buxdojo.js.uncompressed.js 974 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085
  1. require({cache:{
  2. 'url:dijit/templates/CheckedMenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitemcheckbox\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">&#10003;</span>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode,labelNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">&#160;</td>\n</tr>\n",
  3. 'dijit/_base/scroll':function(){
  4. define("dijit/_base/scroll", [
  5. "dojo/window", // windowUtils.scrollIntoView
  6. ".." // export symbol to dijit
  7. ], function(windowUtils, dijit){
  8. // module:
  9. // dijit/_base/scroll
  10. // summary:
  11. // Back compatibility module, new code should use windowUtils directly instead of using this module.
  12. dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  13. // summary:
  14. // Scroll the passed node into view, if it is not already.
  15. // Deprecated, use `windowUtils.scrollIntoView` instead.
  16. windowUtils.scrollIntoView(node, pos);
  17. };
  18. });
  19. },
  20. 'dijit/_TemplatedMixin':function(){
  21. define("dijit/_TemplatedMixin", [
  22. "dojo/_base/lang", // lang.getObject
  23. "dojo/touch",
  24. "./_WidgetBase",
  25. "dojo/string", // string.substitute string.trim
  26. "dojo/cache", // dojo.cache
  27. "dojo/_base/array", // array.forEach
  28. "dojo/_base/declare", // declare
  29. "dojo/dom-construct", // domConstruct.destroy, domConstruct.toDom
  30. "dojo/_base/sniff", // has("ie")
  31. "dojo/_base/unload", // unload.addOnWindowUnload
  32. "dojo/_base/window" // win.doc
  33. ], function(lang, touch, _WidgetBase, string, cache, array, declare, domConstruct, has, unload, win) {
  34. /*=====
  35. var _WidgetBase = dijit._WidgetBase;
  36. =====*/
  37. // module:
  38. // dijit/_TemplatedMixin
  39. // summary:
  40. // Mixin for widgets that are instantiated from a template
  41. var _TemplatedMixin = declare("dijit._TemplatedMixin", null, {
  42. // summary:
  43. // Mixin for widgets that are instantiated from a template
  44. // templateString: [protected] String
  45. // A string that represents the widget template.
  46. // Use in conjunction with dojo.cache() to load from a file.
  47. templateString: null,
  48. // templatePath: [protected deprecated] String
  49. // Path to template (HTML file) for this widget relative to dojo.baseUrl.
  50. // Deprecated: use templateString with require([... "dojo/text!..."], ...) instead
  51. templatePath: null,
  52. // skipNodeCache: [protected] Boolean
  53. // If using a cached widget template nodes poses issues for a
  54. // particular widget class, it can set this property to ensure
  55. // that its template is always re-built from a string
  56. _skipNodeCache: false,
  57. // _earlyTemplatedStartup: Boolean
  58. // A fallback to preserve the 1.0 - 1.3 behavior of children in
  59. // templates having their startup called before the parent widget
  60. // fires postCreate. Defaults to 'false', causing child widgets to
  61. // have their .startup() called immediately before a parent widget
  62. // .startup(), but always after the parent .postCreate(). Set to
  63. // 'true' to re-enable to previous, arguably broken, behavior.
  64. _earlyTemplatedStartup: false,
  65. /*=====
  66. // _attachPoints: [private] String[]
  67. // List of widget attribute names associated with data-dojo-attach-point=... in the
  68. // template, ex: ["containerNode", "labelNode"]
  69. _attachPoints: [],
  70. =====*/
  71. /*=====
  72. // _attachEvents: [private] Handle[]
  73. // List of connections associated with data-dojo-attach-event=... in the
  74. // template
  75. _attachEvents: [],
  76. =====*/
  77. constructor: function(){
  78. this._attachPoints = [];
  79. this._attachEvents = [];
  80. },
  81. _stringRepl: function(tmpl){
  82. // summary:
  83. // Does substitution of ${foo} type properties in template string
  84. // tags:
  85. // private
  86. var className = this.declaredClass, _this = this;
  87. // Cache contains a string because we need to do property replacement
  88. // do the property replacement
  89. return string.substitute(tmpl, this, function(value, key){
  90. if(key.charAt(0) == '!'){ value = lang.getObject(key.substr(1), false, _this); }
  91. if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
  92. if(value == null){ return ""; }
  93. // Substitution keys beginning with ! will skip the transform step,
  94. // in case a user wishes to insert unescaped markup, e.g. ${!foo}
  95. return key.charAt(0) == "!" ? value :
  96. // Safer substitution, see heading "Attribute values" in
  97. // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
  98. value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
  99. }, this);
  100. },
  101. buildRendering: function(){
  102. // summary:
  103. // Construct the UI for this widget from a template, setting this.domNode.
  104. // tags:
  105. // protected
  106. if(!this.templateString){
  107. this.templateString = cache(this.templatePath, {sanitize: true});
  108. }
  109. // Lookup cached version of template, and download to cache if it
  110. // isn't there already. Returns either a DomNode or a string, depending on
  111. // whether or not the template contains ${foo} replacement parameters.
  112. var cached = _TemplatedMixin.getCachedTemplate(this.templateString, this._skipNodeCache);
  113. var node;
  114. if(lang.isString(cached)){
  115. node = domConstruct.toDom(this._stringRepl(cached));
  116. if(node.nodeType != 1){
  117. // Flag common problems such as templates with multiple top level nodes (nodeType == 11)
  118. throw new Error("Invalid template: " + cached);
  119. }
  120. }else{
  121. // if it's a node, all we have to do is clone it
  122. node = cached.cloneNode(true);
  123. }
  124. this.domNode = node;
  125. // Call down to _Widget.buildRendering() to get base classes assigned
  126. // TODO: change the baseClass assignment to _setBaseClassAttr
  127. this.inherited(arguments);
  128. // recurse through the node, looking for, and attaching to, our
  129. // attachment points and events, which should be defined on the template node.
  130. this._attachTemplateNodes(node, function(n,p){ return n.getAttribute(p); });
  131. this._beforeFillContent(); // hook for _WidgetsInTemplateMixin
  132. this._fillContent(this.srcNodeRef);
  133. },
  134. _beforeFillContent: function(){
  135. },
  136. _fillContent: function(/*DomNode*/ source){
  137. // summary:
  138. // Relocate source contents to templated container node.
  139. // this.containerNode must be able to receive children, or exceptions will be thrown.
  140. // tags:
  141. // protected
  142. var dest = this.containerNode;
  143. if(source && dest){
  144. while(source.hasChildNodes()){
  145. dest.appendChild(source.firstChild);
  146. }
  147. }
  148. },
  149. _attachTemplateNodes: function(rootNode, getAttrFunc){
  150. // summary:
  151. // Iterate through the template and attach functions and nodes accordingly.
  152. // Alternately, if rootNode is an array of widgets, then will process data-dojo-attach-point
  153. // etc. for those widgets.
  154. // description:
  155. // Map widget properties and functions to the handlers specified in
  156. // the dom node and it's descendants. This function iterates over all
  157. // nodes and looks for these properties:
  158. // * dojoAttachPoint/data-dojo-attach-point
  159. // * dojoAttachEvent/data-dojo-attach-event
  160. // rootNode: DomNode|Widget[]
  161. // the node to search for properties. All children will be searched.
  162. // getAttrFunc: Function
  163. // a function which will be used to obtain property for a given
  164. // DomNode/Widget
  165. // tags:
  166. // private
  167. var nodes = lang.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
  168. var x = lang.isArray(rootNode) ? 0 : -1;
  169. for(; x<nodes.length; x++){
  170. var baseNode = (x == -1) ? rootNode : nodes[x];
  171. if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){
  172. continue;
  173. }
  174. // Process data-dojo-attach-point
  175. var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point");
  176. if(attachPoint){
  177. var point, points = attachPoint.split(/\s*,\s*/);
  178. while((point = points.shift())){
  179. if(lang.isArray(this[point])){
  180. this[point].push(baseNode);
  181. }else{
  182. this[point]=baseNode;
  183. }
  184. this._attachPoints.push(point);
  185. }
  186. }
  187. // Process data-dojo-attach-event
  188. var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event");
  189. if(attachEvent){
  190. // NOTE: we want to support attributes that have the form
  191. // "domEvent: nativeEvent; ..."
  192. var event, events = attachEvent.split(/\s*,\s*/);
  193. var trim = lang.trim;
  194. while((event = events.shift())){
  195. if(event){
  196. var thisFunc = null;
  197. if(event.indexOf(":") != -1){
  198. // oh, if only JS had tuple assignment
  199. var funcNameArr = event.split(":");
  200. event = trim(funcNameArr[0]);
  201. thisFunc = trim(funcNameArr[1]);
  202. }else{
  203. event = trim(event);
  204. }
  205. if(!thisFunc){
  206. thisFunc = event;
  207. }
  208. // Map "press", "move" and "release" to keys.touch, keys.move, keys.release
  209. this._attachEvents.push(this.connect(baseNode, touch[event] || event, thisFunc));
  210. }
  211. }
  212. }
  213. }
  214. },
  215. destroyRendering: function(){
  216. // Delete all attach points to prevent IE6 memory leaks.
  217. array.forEach(this._attachPoints, function(point){
  218. delete this[point];
  219. }, this);
  220. this._attachPoints = [];
  221. // And same for event handlers
  222. array.forEach(this._attachEvents, this.disconnect, this);
  223. this._attachEvents = [];
  224. this.inherited(arguments);
  225. }
  226. });
  227. // key is templateString; object is either string or DOM tree
  228. _TemplatedMixin._templateCache = {};
  229. _TemplatedMixin.getCachedTemplate = function(templateString, alwaysUseString){
  230. // summary:
  231. // Static method to get a template based on the templatePath or
  232. // templateString key
  233. // templateString: String
  234. // The template
  235. // alwaysUseString: Boolean
  236. // Don't cache the DOM tree for this template, even if it doesn't have any variables
  237. // returns: Mixed
  238. // Either string (if there are ${} variables that need to be replaced) or just
  239. // a DOM tree (if the node can be cloned directly)
  240. // is it already cached?
  241. var tmplts = _TemplatedMixin._templateCache;
  242. var key = templateString;
  243. var cached = tmplts[key];
  244. if(cached){
  245. try{
  246. // 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
  247. if(!cached.ownerDocument || cached.ownerDocument == win.doc){
  248. // string or node of the same document
  249. return cached;
  250. }
  251. }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
  252. domConstruct.destroy(cached);
  253. }
  254. templateString = string.trim(templateString);
  255. if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
  256. // there are variables in the template so all we can do is cache the string
  257. return (tmplts[key] = templateString); //String
  258. }else{
  259. // there are no variables in the template so we can cache the DOM tree
  260. var node = domConstruct.toDom(templateString);
  261. if(node.nodeType != 1){
  262. throw new Error("Invalid template: " + templateString);
  263. }
  264. return (tmplts[key] = node); //Node
  265. }
  266. };
  267. if(has("ie")){
  268. unload.addOnWindowUnload(function(){
  269. var cache = _TemplatedMixin._templateCache;
  270. for(var key in cache){
  271. var value = cache[key];
  272. if(typeof value == "object"){ // value is either a string or a DOM node template
  273. domConstruct.destroy(value);
  274. }
  275. delete cache[key];
  276. }
  277. });
  278. }
  279. // These arguments can be specified for widgets which are used in templates.
  280. // Since any widget can be specified as sub widgets in template, mix it
  281. // into the base widget class. (This is a hack, but it's effective.)
  282. lang.extend(_WidgetBase,{
  283. dojoAttachEvent: "",
  284. dojoAttachPoint: ""
  285. });
  286. return _TemplatedMixin;
  287. });
  288. },
  289. 'dojox/string/tokenize':function(){
  290. define("dojox/string/tokenize", [
  291. "dojo/_base/lang",
  292. "dojo/_base/sniff"
  293. ], function(lang, has){
  294. var tokenize = lang.getObject("dojox.string", true).tokenize;
  295. tokenize = function(/*String*/ str, /*RegExp*/ re, /*Function?*/ parseDelim, /*Object?*/ instance){
  296. // summary:
  297. // Split a string by a regular expression with the ability to capture the delimeters
  298. // parseDelim:
  299. // Each group (excluding the 0 group) is passed as a parameter. If the function returns
  300. // a value, it's added to the list of tokens.
  301. // instance:
  302. // Used as the "this" instance when calling parseDelim
  303. var tokens = [];
  304. var match, content, lastIndex = 0;
  305. while(match = re.exec(str)){
  306. content = str.slice(lastIndex, re.lastIndex - match[0].length);
  307. if(content.length){
  308. tokens.push(content);
  309. }
  310. if(parseDelim){
  311. if(has("opera")){
  312. var copy = match.slice(0);
  313. while(copy.length < match.length){
  314. copy.push(null);
  315. }
  316. match = copy;
  317. }
  318. var parsed = parseDelim.apply(instance, match.slice(1).concat(tokens.length));
  319. if(typeof parsed != "undefined"){
  320. tokens.push(parsed);
  321. }
  322. }
  323. lastIndex = re.lastIndex;
  324. }
  325. content = str.slice(lastIndex);
  326. if(content.length){
  327. tokens.push(content);
  328. }
  329. return tokens;
  330. };
  331. return tokenize;
  332. });
  333. },
  334. 'dijit/_Templated':function(){
  335. define("dijit/_Templated", [
  336. "./_WidgetBase",
  337. "./_TemplatedMixin",
  338. "./_WidgetsInTemplateMixin",
  339. "dojo/_base/array", // array.forEach
  340. "dojo/_base/declare", // declare
  341. "dojo/_base/lang", // lang.extend lang.isArray
  342. "dojo/_base/kernel" // kernel.deprecated
  343. ], function(_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, array, declare, lang, kernel){
  344. /*=====
  345. var _WidgetBase = dijit._WidgetBase;
  346. var _TemplatedMixin = dijit._TemplatedMixin;
  347. var _WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
  348. =====*/
  349. // module:
  350. // dijit/_Templated
  351. // summary:
  352. // Deprecated mixin for widgets that are instantiated from a template.
  353. // These arguments can be specified for widgets which are used in templates.
  354. // Since any widget can be specified as sub widgets in template, mix it
  355. // into the base widget class. (This is a hack, but it's effective.)
  356. lang.extend(_WidgetBase, {
  357. waiRole: "",
  358. waiState:""
  359. });
  360. return declare("dijit._Templated", [_TemplatedMixin, _WidgetsInTemplateMixin], {
  361. // summary:
  362. // Deprecated mixin for widgets that are instantiated from a template.
  363. // Widgets should use _TemplatedMixin plus if necessary _WidgetsInTemplateMixin instead.
  364. // widgetsInTemplate: [protected] Boolean
  365. // Should we parse the template to find widgets that might be
  366. // declared in markup inside it? False by default.
  367. widgetsInTemplate: false,
  368. constructor: function(){
  369. kernel.deprecated(this.declaredClass + ": dijit._Templated deprecated, use dijit._TemplatedMixin and if necessary dijit._WidgetsInTemplateMixin", "", "2.0");
  370. },
  371. _attachTemplateNodes: function(rootNode, getAttrFunc){
  372. this.inherited(arguments);
  373. // Do deprecated waiRole and waiState
  374. var nodes = lang.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
  375. var x = lang.isArray(rootNode) ? 0 : -1;
  376. for(; x<nodes.length; x++){
  377. var baseNode = (x == -1) ? rootNode : nodes[x];
  378. // waiRole, waiState
  379. var role = getAttrFunc(baseNode, "waiRole");
  380. if(role){
  381. baseNode.setAttribute("role", role);
  382. }
  383. var values = getAttrFunc(baseNode, "waiState");
  384. if(values){
  385. array.forEach(values.split(/\s*,\s*/), function(stateValue){
  386. if(stateValue.indexOf('-') != -1){
  387. var pair = stateValue.split('-');
  388. baseNode.setAttribute("aria-"+pair[0], pair[1]);
  389. }
  390. });
  391. }
  392. }
  393. }
  394. });
  395. });
  396. },
  397. 'dijit/_CssStateMixin':function(){
  398. define("dijit/_CssStateMixin", [
  399. "dojo/touch",
  400. "dojo/_base/array", // array.forEach array.map
  401. "dojo/_base/declare", // declare
  402. "dojo/dom-class", // domClass.toggle
  403. "dojo/_base/lang", // lang.hitch
  404. "dojo/_base/window" // win.body
  405. ], function(touch, array, declare, domClass, lang, win){
  406. // module:
  407. // dijit/_CssStateMixin
  408. // summary:
  409. // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
  410. // state changes, and also higher-level state changes such becoming disabled or selected.
  411. return declare("dijit._CssStateMixin", [], {
  412. // summary:
  413. // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
  414. // state changes, and also higher-level state changes such becoming disabled or selected.
  415. //
  416. // description:
  417. // By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically
  418. // maintain CSS classes on the widget root node (this.domNode) depending on hover,
  419. // active, focus, etc. state. Ex: with a baseClass of dijitButton, it will apply the classes
  420. // dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it.
  421. //
  422. // It also sets CSS like dijitButtonDisabled based on widget semantic state.
  423. //
  424. // By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons
  425. // within the widget).
  426. // cssStateNodes: [protected] Object
  427. // List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus
  428. //.
  429. // Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names
  430. // (like "dijitUpArrowButton"). Example:
  431. // | {
  432. // | "upArrowButton": "dijitUpArrowButton",
  433. // | "downArrowButton": "dijitDownArrowButton"
  434. // | }
  435. // The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it
  436. // is hovered, etc.
  437. cssStateNodes: {},
  438. // hovering: [readonly] Boolean
  439. // True if cursor is over this widget
  440. hovering: false,
  441. // active: [readonly] Boolean
  442. // True if mouse was pressed while over this widget, and hasn't been released yet
  443. active: false,
  444. _applyAttributes: function(){
  445. // This code would typically be in postCreate(), but putting in _applyAttributes() for
  446. // performance: so the class changes happen before DOM is inserted into the document.
  447. // Change back to postCreate() in 2.0. See #11635.
  448. this.inherited(arguments);
  449. // Automatically monitor mouse events (essentially :hover and :active) on this.domNode
  450. array.forEach(["onmouseenter", "onmouseleave", touch.press], function(e){
  451. this.connect(this.domNode, e, "_cssMouseEvent");
  452. }, this);
  453. // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node
  454. array.forEach(["disabled", "readOnly", "checked", "selected", "focused", "state", "hovering", "active"], function(attr){
  455. this.watch(attr, lang.hitch(this, "_setStateClass"));
  456. }, this);
  457. // Events on sub nodes within the widget
  458. for(var ap in this.cssStateNodes){
  459. this._trackMouseState(this[ap], this.cssStateNodes[ap]);
  460. }
  461. // Set state initially; there's probably no hover/active/focus state but widget might be
  462. // disabled/readonly/checked/selected so we want to set CSS classes for those conditions.
  463. this._setStateClass();
  464. },
  465. _cssMouseEvent: function(/*Event*/ event){
  466. // summary:
  467. // Sets hovering and active properties depending on mouse state,
  468. // which triggers _setStateClass() to set appropriate CSS classes for this.domNode.
  469. if(!this.disabled){
  470. switch(event.type){
  471. case "mouseenter":
  472. case "mouseover": // generated on non-IE browsers even though we connected to mouseenter
  473. this._set("hovering", true);
  474. this._set("active", this._mouseDown);
  475. break;
  476. case "mouseleave":
  477. case "mouseout": // generated on non-IE browsers even though we connected to mouseleave
  478. this._set("hovering", false);
  479. this._set("active", false);
  480. break;
  481. case "mousedown":
  482. case "touchpress":
  483. this._set("active", true);
  484. this._mouseDown = true;
  485. // Set a global event to handle mouseup, so it fires properly
  486. // even if the cursor leaves this.domNode before the mouse up event.
  487. // Alternately could set active=false on mouseout.
  488. var mouseUpConnector = this.connect(win.body(), touch.release, function(){
  489. this._mouseDown = false;
  490. this._set("active", false);
  491. this.disconnect(mouseUpConnector);
  492. });
  493. break;
  494. }
  495. }
  496. },
  497. _setStateClass: function(){
  498. // summary:
  499. // Update the visual state of the widget by setting the css classes on this.domNode
  500. // (or this.stateNode if defined) by combining this.baseClass with
  501. // various suffixes that represent the current widget state(s).
  502. //
  503. // description:
  504. // In the case where a widget has multiple
  505. // states, it sets the class based on all possible
  506. // combinations. For example, an invalid form widget that is being hovered
  507. // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
  508. //
  509. // The widget may have one or more of the following states, determined
  510. // by this.state, this.checked, this.valid, and this.selected:
  511. // - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
  512. // - Incomplete - ValidationTextBox sets this.state to "Incomplete" if the current input value is not finished yet
  513. // - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
  514. // - Selected - ex: currently selected tab will have this.selected==true
  515. //
  516. // In addition, it may have one or more of the following states,
  517. // based on this.disabled and flags set in _onMouse (this.active, this.hovering) and from focus manager (this.focused):
  518. // - Disabled - if the widget is disabled
  519. // - Active - if the mouse (or space/enter key?) is being pressed down
  520. // - Focused - if the widget has focus
  521. // - Hover - if the mouse is over the widget
  522. // Compute new set of classes
  523. var newStateClasses = this.baseClass.split(" ");
  524. function multiply(modifier){
  525. newStateClasses = newStateClasses.concat(array.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier);
  526. }
  527. if(!this.isLeftToRight()){
  528. // For RTL mode we need to set an addition class like dijitTextBoxRtl.
  529. multiply("Rtl");
  530. }
  531. var checkedState = this.checked == "mixed" ? "Mixed" : (this.checked ? "Checked" : "");
  532. if(this.checked){
  533. multiply(checkedState);
  534. }
  535. if(this.state){
  536. multiply(this.state);
  537. }
  538. if(this.selected){
  539. multiply("Selected");
  540. }
  541. if(this.disabled){
  542. multiply("Disabled");
  543. }else if(this.readOnly){
  544. multiply("ReadOnly");
  545. }else{
  546. if(this.active){
  547. multiply("Active");
  548. }else if(this.hovering){
  549. multiply("Hover");
  550. }
  551. }
  552. if(this.focused){
  553. multiply("Focused");
  554. }
  555. // Remove old state classes and add new ones.
  556. // For performance concerns we only write into domNode.className once.
  557. var tn = this.stateNode || this.domNode,
  558. classHash = {}; // set of all classes (state and otherwise) for node
  559. array.forEach(tn.className.split(" "), function(c){ classHash[c] = true; });
  560. if("_stateClasses" in this){
  561. array.forEach(this._stateClasses, function(c){ delete classHash[c]; });
  562. }
  563. array.forEach(newStateClasses, function(c){ classHash[c] = true; });
  564. var newClasses = [];
  565. for(var c in classHash){
  566. newClasses.push(c);
  567. }
  568. tn.className = newClasses.join(" ");
  569. this._stateClasses = newStateClasses;
  570. },
  571. _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){
  572. // summary:
  573. // Track mouse/focus events on specified node and set CSS class on that node to indicate
  574. // current state. Usually not called directly, but via cssStateNodes attribute.
  575. // description:
  576. // Given class=foo, will set the following CSS class on the node
  577. // - fooActive: if the user is currently pressing down the mouse button while over the node
  578. // - fooHover: if the user is hovering the mouse over the node, but not pressing down a button
  579. // - fooFocus: if the node is focused
  580. //
  581. // Note that it won't set any classes if the widget is disabled.
  582. // node: DomNode
  583. // Should be a sub-node of the widget, not the top node (this.domNode), since the top node
  584. // is handled specially and automatically just by mixing in this class.
  585. // clazz: String
  586. // CSS class name (ex: dijitSliderUpArrow).
  587. // Current state of node (initially false)
  588. // NB: setting specifically to false because domClass.toggle() needs true boolean as third arg
  589. var hovering=false, active=false, focused=false;
  590. var self = this,
  591. cn = lang.hitch(this, "connect", node);
  592. function setClass(){
  593. var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly);
  594. domClass.toggle(node, clazz+"Hover", hovering && !active && !disabled);
  595. domClass.toggle(node, clazz+"Active", active && !disabled);
  596. domClass.toggle(node, clazz+"Focused", focused && !disabled);
  597. }
  598. // Mouse
  599. cn("onmouseenter", function(){
  600. hovering = true;
  601. setClass();
  602. });
  603. cn("onmouseleave", function(){
  604. hovering = false;
  605. active = false;
  606. setClass();
  607. });
  608. cn(touch.press, function(){
  609. active = true;
  610. setClass();
  611. });
  612. cn(touch.release, function(){
  613. active = false;
  614. setClass();
  615. });
  616. // Focus
  617. cn("onfocus", function(){
  618. focused = true;
  619. setClass();
  620. });
  621. cn("onblur", function(){
  622. focused = false;
  623. setClass();
  624. });
  625. // Just in case widget is enabled/disabled while it has focus/hover/active state.
  626. // Maybe this is overkill.
  627. this.watch("disabled", setClass);
  628. this.watch("readOnly", setClass);
  629. }
  630. });
  631. });
  632. },
  633. 'url:dijit/form/templates/ComboButton.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tcellspacing='0' cellpadding='0' role=\"presentation\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonNode\" data-dojo-attach-point=\"buttonNode\" data-dojo-attach-event=\"ondijitclick:_onClick,onkeypress:_onButtonKeyPress\"\n\t\t><div id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" data-dojo-attach-point=\"containerNode\" role=\"presentation\"></div\n\t\t></div\n\t\t></td\n\t\t><td id=\"${id}_arrow\" class='dijitReset dijitRight dijitButtonNode dijitArrowButton'\n\t\t\tdata-dojo-attach-point=\"_popupStateNode,focusNode,_buttonNode\"\n\t\t\tdata-dojo-attach-event=\"onkeypress:_onArrowKeyPress\"\n\t\t\ttitle=\"${optionsTitle}\"\n\t\t\trole=\"button\" aria-haspopup=\"true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">&#9660;</div\n\t\t></td\n\t\t><td style=\"display:none !important;\"\n\t\t\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" data-dojo-attach-point=\"valueNode\"\n\t\t/></td></tr></tbody\n></table>\n",
  634. 'dijit/layout/ScrollingTabController':function(){
  635. require({cache:{
  636. 'url:dijit/layout/templates/ScrollingTabController.html':"<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerMenuButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\"\n\t\t\tdata-dojo-props=\"containerId: '${containerId}', iconClass: 'dijitTabStripMenuIcon',\n\t\t\t\t\tdropDownPosition: ['below-alt', 'above-alt']\"\n\t\t\tdata-dojo-attach-point=\"_menuBtn\" showLabel=\"false\" title=\"\">&#9660;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideLeftIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_leftBtn\" data-dojo-attach-event=\"onClick: doSlideLeft\">&#9664;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideRightIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_rightBtn\" data-dojo-attach-event=\"onClick: doSlideRight\">&#9654;</div>\n\t<div class='dijitTabListWrapper' data-dojo-attach-point='tablistWrapper'>\n\t\t<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'\n\t\t\t\tdata-dojo-attach-point='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>",
  637. 'url:dijit/layout/templates/_ScrollingTabControllerButton.html':"<div data-dojo-attach-event=\"onclick:_onClick\">\n\t<div role=\"presentation\" class=\"dijitTabInnerDiv\" data-dojo-attach-point=\"innerDiv,focusNode\">\n\t\t<div role=\"presentation\" class=\"dijitTabContent dijitButtonContents\" data-dojo-attach-point=\"tabContent\">\n\t\t\t<img role=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t\t<span data-dojo-attach-point=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n\t\t</div>\n\t</div>\n</div>"}});
  638. define("dijit/layout/ScrollingTabController", [
  639. "dojo/_base/array", // array.forEach
  640. "dojo/_base/declare", // declare
  641. "dojo/dom-class", // domClass.add domClass.contains
  642. "dojo/dom-geometry", // domGeometry.contentBox
  643. "dojo/dom-style", // domStyle.style
  644. "dojo/_base/fx", // Animation
  645. "dojo/_base/lang", // lang.hitch
  646. "dojo/query", // query
  647. "dojo/_base/sniff", // has("ie"), has("webkit"), has("quirks")
  648. "../registry", // registry.byId()
  649. "dojo/text!./templates/ScrollingTabController.html",
  650. "dojo/text!./templates/_ScrollingTabControllerButton.html",
  651. "./TabController",
  652. "./utils", // marginBox2contextBox, layoutChildren
  653. "../_WidgetsInTemplateMixin",
  654. "../Menu",
  655. "../MenuItem",
  656. "../form/Button",
  657. "../_HasDropDown",
  658. "dojo/NodeList-dom" // NodeList.style
  659. ], function(array, declare, domClass, domGeometry, domStyle, fx, lang, query, has,
  660. registry, tabControllerTemplate, buttonTemplate, TabController, layoutUtils, _WidgetsInTemplateMixin,
  661. Menu, MenuItem, Button, _HasDropDown){
  662. /*=====
  663. var _WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
  664. var Menu = dijit.Menu;
  665. var _HasDropDown = dijit._HasDropDown;
  666. var TabController = dijit.layout.TabController;
  667. =====*/
  668. // module:
  669. // dijit/layout/ScrollingTabController
  670. // summary:
  671. // Set of tabs with left/right arrow keys and a menu to switch between tabs not
  672. // all fitting on a single row.
  673. var ScrollingTabController = declare("dijit.layout.ScrollingTabController", [TabController, _WidgetsInTemplateMixin], {
  674. // summary:
  675. // Set of tabs with left/right arrow keys and a menu to switch between tabs not
  676. // all fitting on a single row.
  677. // Works only for horizontal tabs (either above or below the content, not to the left
  678. // or right).
  679. // tags:
  680. // private
  681. baseClass: "dijitTabController dijitScrollingTabController",
  682. templateString: tabControllerTemplate,
  683. // useMenu: [const] Boolean
  684. // True if a menu should be used to select tabs when they are too
  685. // wide to fit the TabContainer, false otherwise.
  686. useMenu: true,
  687. // useSlider: [const] Boolean
  688. // True if a slider should be used to select tabs when they are too
  689. // wide to fit the TabContainer, false otherwise.
  690. useSlider: true,
  691. // tabStripClass: [const] String
  692. // The css class to apply to the tab strip, if it is visible.
  693. tabStripClass: "",
  694. widgetsInTemplate: true,
  695. // _minScroll: Number
  696. // The distance in pixels from the edge of the tab strip which,
  697. // if a scroll animation is less than, forces the scroll to
  698. // go all the way to the left/right.
  699. _minScroll: 5,
  700. // Override default behavior mapping class to DOMNode
  701. _setClassAttr: { node: "containerNode", type: "class" },
  702. buildRendering: function(){
  703. this.inherited(arguments);
  704. var n = this.domNode;
  705. this.scrollNode = this.tablistWrapper;
  706. this._initButtons();
  707. if(!this.tabStripClass){
  708. this.tabStripClass = "dijitTabContainer" +
  709. this.tabPosition.charAt(0).toUpperCase() +
  710. this.tabPosition.substr(1).replace(/-.*/, "") +
  711. "None";
  712. domClass.add(n, "tabStrip-disabled")
  713. }
  714. domClass.add(this.tablistWrapper, this.tabStripClass);
  715. },
  716. onStartup: function(){
  717. this.inherited(arguments);
  718. // TabController is hidden until it finishes drawing, to give
  719. // a less visually jumpy instantiation. When it's finished, set visibility to ""
  720. // to that the tabs are hidden/shown depending on the container's visibility setting.
  721. domStyle.set(this.domNode, "visibility", "");
  722. this._postStartup = true;
  723. },
  724. onAddChild: function(page, insertIndex){
  725. this.inherited(arguments);
  726. // changes to the tab button label or iconClass will have changed the width of the
  727. // buttons, so do a resize
  728. array.forEach(["label", "iconClass"], function(attr){
  729. this.pane2watches[page.id].push(
  730. this.pane2button[page.id].watch(attr, lang.hitch(this, function(){
  731. if(this._postStartup && this._dim){
  732. this.resize(this._dim);
  733. }
  734. }))
  735. );
  736. }, this);
  737. // Increment the width of the wrapper when a tab is added
  738. // This makes sure that the buttons never wrap.
  739. // The value 200 is chosen as it should be bigger than most
  740. // Tab button widths.
  741. domStyle.set(this.containerNode, "width",
  742. (domStyle.get(this.containerNode, "width") + 200) + "px");
  743. },
  744. onRemoveChild: function(page, insertIndex){
  745. // null out _selectedTab because we are about to delete that dom node
  746. var button = this.pane2button[page.id];
  747. if(this._selectedTab === button.domNode){
  748. this._selectedTab = null;
  749. }
  750. this.inherited(arguments);
  751. },
  752. _initButtons: function(){
  753. // summary:
  754. // Creates the buttons used to scroll to view tabs that
  755. // may not be visible if the TabContainer is too narrow.
  756. // Make a list of the buttons to display when the tab labels become
  757. // wider than the TabContainer, and hide the other buttons.
  758. // Also gets the total width of the displayed buttons.
  759. this._btnWidth = 0;
  760. this._buttons = query("> .tabStripButton", this.domNode).filter(function(btn){
  761. if((this.useMenu && btn == this._menuBtn.domNode) ||
  762. (this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){
  763. this._btnWidth += domGeometry.getMarginSize(btn).w;
  764. return true;
  765. }else{
  766. domStyle.set(btn, "display", "none");
  767. return false;
  768. }
  769. }, this);
  770. },
  771. _getTabsWidth: function(){
  772. var children = this.getChildren();
  773. if(children.length){
  774. var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode,
  775. rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode;
  776. return rightTab.offsetLeft + domStyle.get(rightTab, "width") - leftTab.offsetLeft;
  777. }else{
  778. return 0;
  779. }
  780. },
  781. _enableBtn: function(width){
  782. // summary:
  783. // Determines if the tabs are wider than the width of the TabContainer, and
  784. // thus that we need to display left/right/menu navigation buttons.
  785. var tabsWidth = this._getTabsWidth();
  786. width = width || domStyle.get(this.scrollNode, "width");
  787. return tabsWidth > 0 && width < tabsWidth;
  788. },
  789. resize: function(dim){
  790. // summary:
  791. // Hides or displays the buttons used to scroll the tab list and launch the menu
  792. // that selects tabs.
  793. // Save the dimensions to be used when a child is renamed.
  794. this._dim = dim;
  795. // Set my height to be my natural height (tall enough for one row of tab labels),
  796. // and my content-box width based on margin-box width specified in dim parameter.
  797. // But first reset scrollNode.height in case it was set by layoutChildren() call
  798. // in a previous run of this method.
  799. this.scrollNode.style.height = "auto";
  800. var cb = this._contentBox = layoutUtils.marginBox2contentBox(this.domNode, {h: 0, w: dim.w});
  801. cb.h = this.scrollNode.offsetHeight;
  802. domGeometry.setContentSize(this.domNode, cb);
  803. // Show/hide the left/right/menu navigation buttons depending on whether or not they
  804. // are needed.
  805. var enable = this._enableBtn(this._contentBox.w);
  806. this._buttons.style("display", enable ? "" : "none");
  807. // Position and size the navigation buttons and the tablist
  808. this._leftBtn.layoutAlign = "left";
  809. this._rightBtn.layoutAlign = "right";
  810. this._menuBtn.layoutAlign = this.isLeftToRight() ? "right" : "left";
  811. layoutUtils.layoutChildren(this.domNode, this._contentBox,
  812. [this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, layoutAlign: "client"}]);
  813. // set proper scroll so that selected tab is visible
  814. if(this._selectedTab){
  815. if(this._anim && this._anim.status() == "playing"){
  816. this._anim.stop();
  817. }
  818. this.scrollNode.scrollLeft = this._convertToScrollLeft(this._getScrollForSelectedTab());
  819. }
  820. // Enable/disabled left right buttons depending on whether or not user can scroll to left or right
  821. this._setButtonClass(this._getScroll());
  822. this._postResize = true;
  823. // Return my size so layoutChildren() can use it.
  824. // Also avoids IE9 layout glitch on browser resize when scroll buttons present
  825. return {h: this._contentBox.h, w: dim.w};
  826. },
  827. _getScroll: function(){
  828. // summary:
  829. // Returns the current scroll of the tabs where 0 means
  830. // "scrolled all the way to the left" and some positive number, based on #
  831. // of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right"
  832. return (this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")) ? this.scrollNode.scrollLeft :
  833. domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width")
  834. + (has("ie") == 8 ? -1 : 1) * this.scrollNode.scrollLeft;
  835. },
  836. _convertToScrollLeft: function(val){
  837. // summary:
  838. // Given a scroll value where 0 means "scrolled all the way to the left"
  839. // and some positive number, based on # of pixels of possible scroll (ex: 1000)
  840. // means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft
  841. // to achieve that scroll.
  842. //
  843. // This method is to adjust for RTL funniness in various browsers and versions.
  844. if(this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")){
  845. return val;
  846. }else{
  847. var maxScroll = domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width");
  848. return (has("ie") == 8 ? -1 : 1) * (val - maxScroll);
  849. }
  850. },
  851. onSelectChild: function(/*dijit._Widget*/ page){
  852. // summary:
  853. // Smoothly scrolls to a tab when it is selected.
  854. var tab = this.pane2button[page.id];
  855. if(!tab || !page){return;}
  856. var node = tab.domNode;
  857. // Save the selection
  858. if(node != this._selectedTab){
  859. this._selectedTab = node;
  860. // Scroll to the selected tab, except on startup, when scrolling is handled in resize()
  861. if(this._postResize){
  862. var sl = this._getScroll();
  863. if(sl > node.offsetLeft ||
  864. sl + domStyle.get(this.scrollNode, "width") <
  865. node.offsetLeft + domStyle.get(node, "width")){
  866. this.createSmoothScroll().play();
  867. }
  868. }
  869. }
  870. this.inherited(arguments);
  871. },
  872. _getScrollBounds: function(){
  873. // summary:
  874. // Returns the minimum and maximum scroll setting to show the leftmost and rightmost
  875. // tabs (respectively)
  876. var children = this.getChildren(),
  877. scrollNodeWidth = domStyle.get(this.scrollNode, "width"), // about 500px
  878. containerWidth = domStyle.get(this.containerNode, "width"), // 50,000px
  879. maxPossibleScroll = containerWidth - scrollNodeWidth, // scrolling until right edge of containerNode visible
  880. tabsWidth = this._getTabsWidth();
  881. if(children.length && tabsWidth > scrollNodeWidth){
  882. // Scrolling should happen
  883. return {
  884. min: this.isLeftToRight() ? 0 : children[children.length-1].domNode.offsetLeft,
  885. max: this.isLeftToRight() ?
  886. (children[children.length-1].domNode.offsetLeft + domStyle.get(children[children.length-1].domNode, "width")) - scrollNodeWidth :
  887. maxPossibleScroll
  888. };
  889. }else{
  890. // No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir)
  891. var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll;
  892. return {
  893. min: onlyScrollPosition,
  894. max: onlyScrollPosition
  895. };
  896. }
  897. },
  898. _getScrollForSelectedTab: function(){
  899. // summary:
  900. // Returns the scroll value setting so that the selected tab
  901. // will appear in the center
  902. var w = this.scrollNode,
  903. n = this._selectedTab,
  904. scrollNodeWidth = domStyle.get(this.scrollNode, "width"),
  905. scrollBounds = this._getScrollBounds();
  906. // TODO: scroll minimal amount (to either right or left) so that
  907. // selected tab is fully visible, and just return if it's already visible?
  908. var pos = (n.offsetLeft + domStyle.get(n, "width")/2) - scrollNodeWidth/2;
  909. pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max);
  910. // TODO:
  911. // If scrolling close to the left side or right side, scroll
  912. // all the way to the left or right. See this._minScroll.
  913. // (But need to make sure that doesn't scroll the tab out of view...)
  914. return pos;
  915. },
  916. createSmoothScroll: function(x){
  917. // summary:
  918. // Creates a dojo._Animation object that smoothly scrolls the tab list
  919. // either to a fixed horizontal pixel value, or to the selected tab.
  920. // description:
  921. // If an number argument is passed to the function, that horizontal
  922. // pixel position is scrolled to. Otherwise the currently selected
  923. // tab is scrolled to.
  924. // x: Integer?
  925. // An optional pixel value to scroll to, indicating distance from left.
  926. // Calculate position to scroll to
  927. if(arguments.length > 0){
  928. // position specified by caller, just make sure it's within bounds
  929. var scrollBounds = this._getScrollBounds();
  930. x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max);
  931. }else{
  932. // scroll to center the current tab
  933. x = this._getScrollForSelectedTab();
  934. }
  935. if(this._anim && this._anim.status() == "playing"){
  936. this._anim.stop();
  937. }
  938. var self = this,
  939. w = this.scrollNode,
  940. anim = new fx.Animation({
  941. beforeBegin: function(){
  942. if(this.curve){ delete this.curve; }
  943. var oldS = w.scrollLeft,
  944. newS = self._convertToScrollLeft(x);
  945. anim.curve = new fx._Line(oldS, newS);
  946. },
  947. onAnimate: function(val){
  948. w.scrollLeft = val;
  949. }
  950. });
  951. this._anim = anim;
  952. // Disable/enable left/right buttons according to new scroll position
  953. this._setButtonClass(x);
  954. return anim; // dojo._Animation
  955. },
  956. _getBtnNode: function(/*Event*/ e){
  957. // summary:
  958. // Gets a button DOM node from a mouse click event.
  959. // e:
  960. // The mouse click event.
  961. var n = e.target;
  962. while(n && !domClass.contains(n, "tabStripButton")){
  963. n = n.parentNode;
  964. }
  965. return n;
  966. },
  967. doSlideRight: function(/*Event*/ e){
  968. // summary:
  969. // Scrolls the menu to the right.
  970. // e:
  971. // The mouse click event.
  972. this.doSlide(1, this._getBtnNode(e));
  973. },
  974. doSlideLeft: function(/*Event*/ e){
  975. // summary:
  976. // Scrolls the menu to the left.
  977. // e:
  978. // The mouse click event.
  979. this.doSlide(-1,this._getBtnNode(e));
  980. },
  981. doSlide: function(/*Number*/ direction, /*DomNode*/ node){
  982. // summary:
  983. // Scrolls the tab list to the left or right by 75% of the widget width.
  984. // direction:
  985. // If the direction is 1, the widget scrolls to the right, if it is
  986. // -1, it scrolls to the left.
  987. if(node && domClass.contains(node, "dijitTabDisabled")){return;}
  988. var sWidth = domStyle.get(this.scrollNode, "width");
  989. var d = (sWidth * 0.75) * direction;
  990. var to = this._getScroll() + d;
  991. this._setButtonClass(to);
  992. this.createSmoothScroll(to).play();
  993. },
  994. _setButtonClass: function(/*Number*/ scroll){
  995. // summary:
  996. // Disables the left scroll button if the tabs are scrolled all the way to the left,
  997. // or the right scroll button in the opposite case.
  998. // scroll: Integer
  999. // amount of horizontal scroll
  1000. var scrollBounds = this._getScrollBounds();
  1001. this._leftBtn.set("disabled", scroll <= scrollBounds.min);
  1002. this._rightBtn.set("disabled", scroll >= scrollBounds.max);
  1003. }
  1004. });
  1005. var ScrollingTabControllerButtonMixin = declare("dijit.layout._ScrollingTabControllerButtonMixin", null, {
  1006. baseClass: "dijitTab tabStripButton",
  1007. templateString: buttonTemplate,
  1008. // Override inherited tabIndex: 0 from dijit.form.Button, because user shouldn't be
  1009. // able to tab to the left/right/menu buttons
  1010. tabIndex: "",
  1011. // Similarly, override FormWidget.isFocusable() because clicking a button shouldn't focus it
  1012. // either (this override avoids focus() call in FormWidget.js)
  1013. isFocusable: function(){ return false; }
  1014. });
  1015. /*=====
  1016. ScrollingTabControllerButtonMixin = dijit.layout._ScrollingTabControllerButtonMixin;
  1017. =====*/
  1018. // Class used in template
  1019. declare("dijit.layout._ScrollingTabControllerButton",
  1020. [Button, ScrollingTabControllerButtonMixin]);
  1021. // Class used in template
  1022. declare(
  1023. "dijit.layout._ScrollingTabControllerMenuButton",
  1024. [Button, _HasDropDown, ScrollingTabControllerButtonMixin],
  1025. {
  1026. // id of the TabContainer itself
  1027. containerId: "",
  1028. // -1 so user can't tab into the button, but so that button can still be focused programatically.
  1029. // Because need to move focus to the button (or somewhere) before the menu is hidden or IE6 will crash.
  1030. tabIndex: "-1",
  1031. isLoaded: function(){
  1032. // recreate menu every time, in case the TabContainer's list of children (or their icons/labels) have changed
  1033. return false;
  1034. },
  1035. loadDropDown: function(callback){
  1036. this.dropDown = new Menu({
  1037. id: this.containerId + "_menu",
  1038. dir: this.dir,
  1039. lang: this.lang,
  1040. textDir: this.textDir
  1041. });
  1042. var container = registry.byId(this.containerId);
  1043. array.forEach(container.getChildren(), function(page){
  1044. var menuItem = new MenuItem({
  1045. id: page.id + "_stcMi",
  1046. label: page.title,
  1047. iconClass: page.iconClass,
  1048. dir: page.dir,
  1049. lang: page.lang,
  1050. textDir: page.textDir,
  1051. onClick: function(){
  1052. container.selectChild(page);
  1053. }
  1054. });
  1055. this.dropDown.addChild(menuItem);
  1056. }, this);
  1057. callback();
  1058. },
  1059. closeDropDown: function(/*Boolean*/ focus){
  1060. this.inherited(arguments);
  1061. if(this.dropDown){
  1062. this.dropDown.destroyRecursive();
  1063. delete this.dropDown;
  1064. }
  1065. }
  1066. });
  1067. return ScrollingTabController;
  1068. });
  1069. },
  1070. 'dijit/place':function(){
  1071. define("dijit/place", [
  1072. "dojo/_base/array", // array.forEach array.map array.some
  1073. "dojo/dom-geometry", // domGeometry.position
  1074. "dojo/dom-style", // domStyle.getComputedStyle
  1075. "dojo/_base/kernel", // kernel.deprecated
  1076. "dojo/_base/window", // win.body
  1077. "./Viewport", // getEffectiveBox
  1078. "." // dijit (defining dijit.place to match API doc)
  1079. ], function(array, domGeometry, domStyle, kernel, win, Viewport, dijit){
  1080. // module:
  1081. // dijit/place
  1082. // summary:
  1083. // Code to place a popup relative to another node
  1084. function _place(/*DomNode*/ node, choices, layoutNode, aroundNodeCoords){
  1085. // summary:
  1086. // Given a list of spots to put node, put it at the first spot where it fits,
  1087. // of if it doesn't fit anywhere then the place with the least overflow
  1088. // choices: Array
  1089. // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
  1090. // Above example says to put the top-left corner of the node at (10,20)
  1091. // layoutNode: Function(node, aroundNodeCorner, nodeCorner, size)
  1092. // for things like tooltip, they are displayed differently (and have different dimensions)
  1093. // based on their orientation relative to the parent. This adjusts the popup based on orientation.
  1094. // It also passes in the available size for the popup, which is useful for tooltips to
  1095. // tell them that their width is limited to a certain amount. layoutNode() may return a value expressing
  1096. // how much the popup had to be modified to fit into the available space. This is used to determine
  1097. // what the best placement is.
  1098. // aroundNodeCoords: Object
  1099. // Size of aroundNode, ex: {w: 200, h: 50}
  1100. // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
  1101. // viewport over document
  1102. var view = Viewport.getEffectiveBox(node.ownerDocument);
  1103. // This won't work if the node is inside a <div style="position: relative">,
  1104. // so reattach it to win.doc.body. (Otherwise, the positioning will be wrong
  1105. // and also it might get cutoff)
  1106. if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
  1107. win.body().appendChild(node);
  1108. }
  1109. var best = null;
  1110. array.some(choices, function(choice){
  1111. var corner = choice.corner;
  1112. var pos = choice.pos;
  1113. var overflow = 0;
  1114. // calculate amount of space available given specified position of node
  1115. var spaceAvailable = {
  1116. w: {
  1117. 'L': view.l + view.w - pos.x,
  1118. 'R': pos.x - view.l,
  1119. 'M': view.w
  1120. }[corner.charAt(1)],
  1121. h: {
  1122. 'T': view.t + view.h - pos.y,
  1123. 'B': pos.y - view.t,
  1124. 'M': view.h
  1125. }[corner.charAt(0)]
  1126. };
  1127. // Clear left/right position settings set earlier so they don't interfere with calculations,
  1128. // specifically when layoutNode() (a.k.a. Tooltip.orient()) measures natural width of Tooltip
  1129. var s = node.style;
  1130. s.left = s.right = "auto";
  1131. // configure node to be displayed in given position relative to button
  1132. // (need to do this in order to get an accurate size for the node, because
  1133. // a tooltip's size changes based on position, due to triangle)
  1134. if(layoutNode){
  1135. var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords);
  1136. overflow = typeof res == "undefined" ? 0 : res;
  1137. }
  1138. // get node's size
  1139. var style = node.style;
  1140. var oldDisplay = style.display;
  1141. var oldVis = style.visibility;
  1142. if(style.display == "none"){
  1143. style.visibility = "hidden";
  1144. style.display = "";
  1145. }
  1146. var bb = domGeometry.position(node);
  1147. style.display = oldDisplay;
  1148. style.visibility = oldVis;
  1149. // coordinates and size of node with specified corner placed at pos,
  1150. // and clipped by viewport
  1151. var
  1152. startXpos = {
  1153. 'L': pos.x,
  1154. 'R': pos.x - bb.w,
  1155. 'M': Math.max(view.l, Math.min(view.l + view.w, pos.x + (bb.w >> 1)) - bb.w) // M orientation is more flexible
  1156. }[corner.charAt(1)],
  1157. startYpos = {
  1158. 'T': pos.y,
  1159. 'B': pos.y - bb.h,
  1160. 'M': Math.max(view.t, Math.min(view.t + view.h, pos.y + (bb.h >> 1)) - bb.h)
  1161. }[corner.charAt(0)],
  1162. startX = Math.max(view.l, startXpos),
  1163. startY = Math.max(view.t, startYpos),
  1164. endX = Math.min(view.l + view.w, startXpos + bb.w),
  1165. endY = Math.min(view.t + view.h, startYpos + bb.h),
  1166. width = endX - startX,
  1167. height = endY - startY;
  1168. overflow += (bb.w - width) + (bb.h - height);
  1169. if(best == null || overflow < best.overflow){
  1170. best = {
  1171. corner: corner,
  1172. aroundCorner: choice.aroundCorner,
  1173. x: startX,
  1174. y: startY,
  1175. w: width,
  1176. h: height,
  1177. overflow: overflow,
  1178. spaceAvailable: spaceAvailable
  1179. };
  1180. }
  1181. return !overflow;
  1182. });
  1183. // In case the best position is not the last one we checked, need to call
  1184. // layoutNode() again.
  1185. if(best.overflow && layoutNode){
  1186. layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords);
  1187. }
  1188. // And then position the node. Do this last, after the layoutNode() above
  1189. // has sized the node, due to browser quirks when the viewport is scrolled
  1190. // (specifically that a Tooltip will shrink to fit as though the window was
  1191. // scrolled to the left).
  1192. var s = node.style;
  1193. s.top = best.y + "px";
  1194. s.left = best.x + "px";
  1195. s.right = "auto"; // needed for FF or else tooltip goes to far left
  1196. return best;
  1197. }
  1198. /*=====
  1199. dijit.place.__Position = function(){
  1200. // x: Integer
  1201. // horizontal coordinate in pixels, relative to document body
  1202. // y: Integer
  1203. // vertical coordinate in pixels, relative to document body
  1204. this.x = x;
  1205. this.y = y;
  1206. };
  1207. =====*/
  1208. /*=====
  1209. dijit.place.__Rectangle = function(){
  1210. // x: Integer
  1211. // horizontal offset in pixels, relative to document body
  1212. // y: Integer
  1213. // vertical offset in pixels, relative to document body
  1214. // w: Integer
  1215. // width in pixels. Can also be specified as "width" for backwards-compatibility.
  1216. // h: Integer
  1217. // height in pixels. Can also be specified as "height" from backwards-compatibility.
  1218. this.x = x;
  1219. this.y = y;
  1220. this.w = w;
  1221. this.h = h;
  1222. };
  1223. =====*/
  1224. return (dijit.place = {
  1225. // summary:
  1226. // Code to place a DOMNode relative to another DOMNode.
  1227. // Load using require(["dijit/place"], function(place){ ... }).
  1228. at: function(node, pos, corners, padding){
  1229. // summary:
  1230. // Positions one of the node's corners at specified position
  1231. // such that node is fully visible in viewport.
  1232. // description:
  1233. // NOTE: node is assumed to be absolutely or relatively positioned.
  1234. // node: DOMNode
  1235. // The node to position
  1236. // pos: dijit.place.__Position
  1237. // Object like {x: 10, y: 20}
  1238. // corners: String[]
  1239. // Array of Strings representing order to try corners in, like ["TR", "BL"].
  1240. // Possible values are:
  1241. // * "BL" - bottom left
  1242. // * "BR" - bottom right
  1243. // * "TL" - top left
  1244. // * "TR" - top right
  1245. // padding: dijit.place.__Position?
  1246. // optional param to set padding, to put some buffer around the element you want to position.
  1247. // example:
  1248. // Try to place node's top right corner at (10,20).
  1249. // If that makes node go (partially) off screen, then try placing
  1250. // bottom left corner at (10,20).
  1251. // | place(node, {x: 10, y: 20}, ["TR", "BL"])
  1252. var choices = array.map(corners, function(corner){
  1253. var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
  1254. if(padding){
  1255. c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
  1256. c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
  1257. }
  1258. return c;
  1259. });
  1260. return _place(node, choices);
  1261. },
  1262. around: function(
  1263. /*DomNode*/ node,
  1264. /*DomNode || dijit.place.__Rectangle*/ anchor,
  1265. /*String[]*/ positions,
  1266. /*Boolean*/ leftToRight,
  1267. /*Function?*/ layoutNode){
  1268. // summary:
  1269. // Position node adjacent or kitty-corner to anchor
  1270. // such that it's fully visible in viewport.
  1271. //
  1272. // description:
  1273. // Place node such that corner of node touches a corner of
  1274. // aroundNode, and that node is fully visible.
  1275. //
  1276. // anchor:
  1277. // Either a DOMNode or a __Rectangle (object with x, y, width, height).
  1278. //
  1279. // positions:
  1280. // Ordered list of positions to try matching up.
  1281. // * before: places drop down to the left of the anchor node/widget, or to the right in the case
  1282. // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
  1283. // with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
  1284. // * after: places drop down to the right of the anchor node/widget, or to the left in the case
  1285. // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
  1286. // with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
  1287. // * before-centered: centers drop down to the left of the anchor node/widget, or to the right
  1288. // in the case of RTL scripts like Hebrew and Arabic
  1289. // * after-centered: centers drop down to the right of the anchor node/widget, or to the left
  1290. // in the case of RTL scripts like Hebrew and Arabic
  1291. // * above-centered: drop down is centered above anchor node
  1292. // * above: drop down goes above anchor node, left sides aligned
  1293. // * above-alt: drop down goes above anchor node, right sides aligned
  1294. // * below-centered: drop down is centered above anchor node
  1295. // * below: drop down goes below anchor node
  1296. // * below-alt: drop down goes below anchor node, right sides aligned
  1297. //
  1298. // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
  1299. // For things like tooltip, they are displayed differently (and have different dimensions)
  1300. // based on their orientation relative to the parent. This adjusts the popup based on orientation.
  1301. //
  1302. // leftToRight:
  1303. // True if widget is LTR, false if widget is RTL. Affects the behavior of "above" and "below"
  1304. // positions slightly.
  1305. //
  1306. // example:
  1307. // | placeAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'});
  1308. // This will try to position node such that node's top-left corner is at the same position
  1309. // as the bottom left corner of the aroundNode (ie, put node below
  1310. // aroundNode, with left edges aligned). If that fails it will try to put
  1311. // the bottom-right corner of node where the top right corner of aroundNode is
  1312. // (ie, put node above aroundNode, with right edges aligned)
  1313. //
  1314. // if around is a DOMNode (or DOMNode id), convert to coordinates
  1315. var aroundNodePos = (typeof anchor == "string" || "offsetWidth" in anchor)
  1316. ? domGeometry.position(anchor, true)
  1317. : anchor;
  1318. // Compute position and size of visible part of anchor (it may be partially hidden by ancestor nodes w/scrollbars)
  1319. if(anchor.parentNode){
  1320. // ignore nodes between position:relative and position:absolute
  1321. var sawPosAbsolute = domStyle.getComputedStyle(anchor).position == "absolute";
  1322. var parent = anchor.parentNode;
  1323. while(parent && parent.nodeType == 1 && parent.nodeName != "BODY"){ //ignoring the body will help performance
  1324. var parentPos = domGeometry.position(parent, true),
  1325. pcs = domStyle.getComputedStyle(parent);
  1326. if(/relative|absolute/.test(pcs.position)){
  1327. sawPosAbsolute = false;
  1328. }
  1329. if(!sawPosAbsolute && /hidden|auto|scroll/.test(pcs.overflow)){
  1330. var bottomYCoord = Math.min(aroundNodePos.y + aroundNodePos.h, parentPos.y + parentPos.h);
  1331. var rightXCoord = Math.min(aroundNodePos.x + aroundNodePos.w, parentPos.x + parentPos.w);
  1332. aroundNodePos.x = Math.max(aroundNodePos.x, parentPos.x);
  1333. aroundNodePos.y = Math.max(aroundNodePos.y, parentPos.y);
  1334. aroundNodePos.h = bottomYCoord - aroundNodePos.y;
  1335. aroundNodePos.w = rightXCoord - aroundNodePos.x;
  1336. }
  1337. if(pcs.position == "absolute"){
  1338. sawPosAbsolute = true;
  1339. }
  1340. parent = parent.parentNode;
  1341. }
  1342. }
  1343. var x = aroundNodePos.x,
  1344. y = aroundNodePos.y,
  1345. width = "w" in aroundNodePos ? aroundNodePos.w : (aroundNodePos.w = aroundNodePos.width),
  1346. height = "h" in aroundNodePos ? aroundNodePos.h : (kernel.deprecated("place.around: dijit.place.__Rectangle: { x:"+x+", y:"+y+", height:"+aroundNodePos.height+", width:"+width+" } has been deprecated. Please use { x:"+x+", y:"+y+", h:"+aroundNodePos.height+", w:"+width+" }", "", "2.0"), aroundNodePos.h = aroundNodePos.height);
  1347. // Convert positions arguments into choices argument for _place()
  1348. var choices = [];
  1349. function push(aroundCorner, corner){
  1350. choices.push({
  1351. aroundCorner: aroundCorner,
  1352. corner: corner,
  1353. pos: {
  1354. x: {
  1355. 'L': x,
  1356. 'R': x + width,
  1357. 'M': x + (width >> 1)
  1358. }[aroundCorner.charAt(1)],
  1359. y: {
  1360. 'T': y,
  1361. 'B': y + height,
  1362. 'M': y + (height >> 1)
  1363. }[aroundCorner.charAt(0)]
  1364. }
  1365. })
  1366. }
  1367. array.forEach(positions, function(pos){
  1368. var ltr = leftToRight;
  1369. switch(pos){
  1370. case "above-centered":
  1371. push("TM", "BM");
  1372. break;
  1373. case "below-centered":
  1374. push("BM", "TM");
  1375. break;
  1376. case "after-centered":
  1377. ltr = !ltr;
  1378. // fall through
  1379. case "before-centered":
  1380. push(ltr ? "ML" : "MR", ltr ? "MR" : "ML");
  1381. break;
  1382. case "after":
  1383. ltr = !ltr;
  1384. // fall through
  1385. case "before":
  1386. push(ltr ? "TL" : "TR", ltr ? "TR" : "TL");
  1387. push(ltr ? "BL" : "BR", ltr ? "BR" : "BL");
  1388. break;
  1389. case "below-alt":
  1390. ltr = !ltr;
  1391. // fall through
  1392. case "below":
  1393. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  1394. push(ltr ? "BL" : "BR", ltr ? "TL" : "TR");
  1395. push(ltr ? "BR" : "BL", ltr ? "TR" : "TL");
  1396. break;
  1397. case "above-alt":
  1398. ltr = !ltr;
  1399. // fall through
  1400. case "above":
  1401. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  1402. push(ltr ? "TL" : "TR", ltr ? "BL" : "BR");
  1403. push(ltr ? "TR" : "TL", ltr ? "BR" : "BL");
  1404. break;
  1405. default:
  1406. // To assist dijit/_base/place, accept arguments of type {aroundCorner: "BL", corner: "TL"}.
  1407. // Not meant to be used directly.
  1408. push(pos.aroundCorner, pos.corner);
  1409. }
  1410. });
  1411. var position = _place(node, choices, layoutNode, {w: width, h: height});
  1412. position.aroundNodePos = aroundNodePos;
  1413. return position;
  1414. }
  1415. });
  1416. });
  1417. },
  1418. 'dijit/_HasDropDown':function(){
  1419. define("dijit/_HasDropDown", [
  1420. "dojo/_base/declare", // declare
  1421. "dojo/_base/Deferred",
  1422. "dojo/_base/event", // event.stop
  1423. "dojo/dom", // dom.isDescendant
  1424. "dojo/dom-attr", // domAttr.set
  1425. "dojo/dom-class", // domClass.add domClass.contains domClass.remove
  1426. "dojo/dom-geometry", // domGeometry.marginBox domGeometry.position
  1427. "dojo/dom-style", // domStyle.set
  1428. "dojo/has",
  1429. "dojo/keys", // keys.DOWN_ARROW keys.ENTER keys.ESCAPE
  1430. "dojo/_base/lang", // lang.hitch lang.isFunction
  1431. "dojo/touch",
  1432. "dojo/_base/window", // win.doc
  1433. "./registry", // registry.byNode()
  1434. "./focus",
  1435. "./popup",
  1436. "./_FocusMixin",
  1437. "./Viewport"
  1438. ], function(declare, Deferred, event,dom, domAttr, domClass, domGeometry, domStyle, has, keys, lang, touch,
  1439. win, registry, focus, popup, _FocusMixin, Viewport){
  1440. /*=====
  1441. var _FocusMixin = dijit._FocusMixin;
  1442. =====*/
  1443. // module:
  1444. // dijit/_HasDropDown
  1445. // summary:
  1446. // Mixin for widgets that need drop down ability.
  1447. return declare("dijit._HasDropDown", _FocusMixin, {
  1448. // summary:
  1449. // Mixin for widgets that need drop down ability.
  1450. // _buttonNode: [protected] DomNode
  1451. // The button/icon/node to click to display the drop down.
  1452. // Can be set via a data-dojo-attach-point assignment.
  1453. // If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
  1454. _buttonNode: null,
  1455. // _arrowWrapperNode: [protected] DomNode
  1456. // Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
  1457. // on where the drop down is set to be positioned.
  1458. // Can be set via a data-dojo-attach-point assignment.
  1459. // If missing, then _buttonNode will be used.
  1460. _arrowWrapperNode: null,
  1461. // _popupStateNode: [protected] DomNode
  1462. // The node to set the popupActive class on.
  1463. // Can be set via a data-dojo-attach-point assignment.
  1464. // If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
  1465. _popupStateNode: null,
  1466. // _aroundNode: [protected] DomNode
  1467. // The node to display the popup around.
  1468. // Can be set via a data-dojo-attach-point assignment.
  1469. // If missing, then domNode will be used.
  1470. _aroundNode: null,
  1471. // dropDown: [protected] Widget
  1472. // The widget to display as a popup. This widget *must* be
  1473. // defined before the startup function is called.
  1474. dropDown: null,
  1475. // autoWidth: [protected] Boolean
  1476. // Set to true to make the drop down at least as wide as this
  1477. // widget. Set to false if the drop down should just be its
  1478. // default width
  1479. autoWidth: true,
  1480. // forceWidth: [protected] Boolean
  1481. // Set to true to make the drop down exactly as wide as this
  1482. // widget. Overrides autoWidth.
  1483. forceWidth: false,
  1484. // maxHeight: [protected] Integer
  1485. // The max height for our dropdown.
  1486. // Any dropdown taller than this will have scrollbars.
  1487. // Set to 0 for no max height, or -1 to limit height to available space in viewport
  1488. maxHeight: 0,
  1489. // dropDownPosition: [const] String[]
  1490. // This variable controls the position of the drop down.
  1491. // It's an array of strings with the following values:
  1492. //
  1493. // * before: places drop down to the left of the target node/widget, or to the right in
  1494. // the case of RTL scripts like Hebrew and Arabic
  1495. // * after: places drop down to the right of the target node/widget, or to the left in
  1496. // the case of RTL scripts like Hebrew and Arabic
  1497. // * above: drop down goes above target node
  1498. // * below: drop down goes below target node
  1499. //
  1500. // The list is positions is tried, in order, until a position is found where the drop down fits
  1501. // within the viewport.
  1502. //
  1503. dropDownPosition: ["below","above"],
  1504. // _stopClickEvents: Boolean
  1505. // When set to false, the click events will not be stopped, in
  1506. // case you want to use them in your subwidget
  1507. _stopClickEvents: true,
  1508. _onDropDownMouseDown: function(/*Event*/ e){
  1509. // summary:
  1510. // Callback when the user mousedown's on the arrow icon
  1511. if(this.disabled || this.readOnly){ return; }
  1512. // Prevent default to stop things like text selection, but don't stop propogation, so that:
  1513. // 1. TimeTextBox etc. can focusthe <input> on mousedown
  1514. // 2. dropDownButtonActive class applied by _CssStateMixin (on button depress)
  1515. // 3. user defined onMouseDown handler fires
  1516. //
  1517. // Also, don't call preventDefault() on MSPointerDown event (on IE10) because that prevents the button
  1518. // from getting focus, and then the focus manager doesn't know what's going on (#17262)
  1519. if(e.type != "MSPointerDown" && e.type != "pointerdown"){
  1520. e.preventDefault();
  1521. }
  1522. this._docHandler = this.connect(win.doc, touch.release, "_onDropDownMouseUp");
  1523. this.toggleDropDown();
  1524. },
  1525. _onDropDownMouseUp: function(/*Event?*/ e){
  1526. // summary:
  1527. // Callback when the user lifts their mouse after mouse down on the arrow icon.
  1528. // If the drop down is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our
  1529. // drop down widget. If the event is missing, then we are not
  1530. // a mouseup event.
  1531. //
  1532. // This is useful for the common mouse movement pattern
  1533. // with native browser <select> nodes:
  1534. // 1. mouse down on the select node (probably on the arrow)
  1535. // 2. move mouse to a menu item while holding down the mouse button
  1536. // 3. mouse up. this selects the menu item as though the user had clicked it.
  1537. if(e && this._docHandler){
  1538. this.disconnect(this._docHandler);
  1539. }
  1540. var dropDown = this.dropDown, overMenu = false;
  1541. if(e && this._opened){
  1542. // This code deals with the corner-case when the drop down covers the original widget,
  1543. // because it's so large. In that case mouse-up shouldn't select a value from the menu.
  1544. // Find out if our target is somewhere in our dropdown widget,
  1545. // but not over our _buttonNode (the clickable node)
  1546. var c = domGeometry.position(this._buttonNode, true);
  1547. if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) ||
  1548. !(e.pageY >= c.y && e.pageY <= c.y + c.h)){
  1549. var t = e.target;
  1550. while(t && !overMenu){
  1551. if(domClass.contains(t, "dijitPopup")){
  1552. overMenu = true;
  1553. }else{
  1554. t = t.parentNode;
  1555. }
  1556. }
  1557. if(overMenu){
  1558. t = e.target;
  1559. if(dropDown.onItemClick){
  1560. var menuItem;
  1561. while(t && !(menuItem = registry.byNode(t))){
  1562. t = t.parentNode;
  1563. }
  1564. if(menuItem && menuItem.onClick && menuItem.getParent){
  1565. menuItem.getParent().onItemClick(menuItem, e);
  1566. }
  1567. }
  1568. return;
  1569. }
  1570. }
  1571. }
  1572. if(this._opened){
  1573. if(dropDown.focus && dropDown.autoFocus !== false){
  1574. // Focus the dropdown widget - do it on a delay so that we
  1575. // don't steal our own focus.
  1576. window.setTimeout(lang.hitch(dropDown, "focus"), 1);
  1577. }
  1578. }else{
  1579. // The drop down arrow icon probably can't receive focus, but widget itself should get focus.
  1580. // setTimeout() needed to make it work on IE (test DateTextBox)
  1581. setTimeout(lang.hitch(this, "focus"), 0);
  1582. }
  1583. if(has("ios")){
  1584. this._justGotMouseUp = true;
  1585. setTimeout(lang.hitch(this, function(){
  1586. this._justGotMouseUp = false;
  1587. }), 0);
  1588. }
  1589. },
  1590. _onDropDownClick: function(/*Event*/ e){
  1591. if(has("ios") && !this._justGotMouseUp){
  1592. // This branch fires on iPhone for ComboBox, because the button node is an <input> and doesn't
  1593. // generate touchstart/touchend events. Pretend we just got a mouse down / mouse up.
  1594. // The if(has("ios") is necessary since IE and desktop safari get spurious onclick events
  1595. // when there are nested tables (specifically, clicking on a table that holds a dijit.form.Select,
  1596. // but not on the Select itself, causes an onclick event on the Select)
  1597. this._onDropDownMouseDown(e);
  1598. this._onDropDownMouseUp(e);
  1599. }
  1600. // The drop down was already opened on mousedown/keydown; just need to call stopEvent().
  1601. if(this._stopClickEvents){
  1602. event.stop(e);
  1603. }
  1604. },
  1605. buildRendering: function(){
  1606. this.inherited(arguments);
  1607. this._buttonNode = this._buttonNode || this.focusNode || this.domNode;
  1608. this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode;
  1609. // Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow
  1610. // based on where drop down will normally appear
  1611. var defaultPos = {
  1612. "after" : this.isLeftToRight() ? "Right" : "Left",
  1613. "before" : this.isLeftToRight() ? "Left" : "Right",
  1614. "above" : "Up",
  1615. "below" : "Down",
  1616. "left" : "Left",
  1617. "right" : "Right"
  1618. }[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down";
  1619. domClass.add(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton");
  1620. },
  1621. postCreate: function(){
  1622. // summary:
  1623. // set up nodes and connect our mouse and keyboard events
  1624. this.inherited(arguments);
  1625. this.connect(this._buttonNode, touch.press, "_onDropDownMouseDown");
  1626. this.connect(this._buttonNode, "onclick", "_onDropDownClick");
  1627. this.connect(this.focusNode, "onkeydown", "_onKey");
  1628. this.connect(this.focusNode, "onkeyup", "_onKeyUp");
  1629. },
  1630. destroy: function(){
  1631. if(this.dropDown){
  1632. // Destroy the drop down, unless it's already been destroyed. This can happen because
  1633. // the drop down is a direct child of <body> even though it's logically my child.
  1634. if(!this.dropDown._destroyed){
  1635. this.dropDown.destroyRecursive();
  1636. }
  1637. delete this.dropDown;
  1638. }
  1639. this.inherited(arguments);
  1640. },
  1641. _onKey: function(/*Event*/ e){
  1642. // summary:
  1643. // Callback when the user presses a key while focused on the button node
  1644. if(this.disabled || this.readOnly){ return; }
  1645. var d = this.dropDown, target = e.target;
  1646. if(d && this._opened && d.handleKey){
  1647. if(d.handleKey(e) === false){
  1648. /* false return code means that the drop down handled the key */
  1649. event.stop(e);
  1650. return;
  1651. }
  1652. }
  1653. if(d && this._opened && e.keyCode == keys.ESCAPE){
  1654. this.closeDropDown();
  1655. event.stop(e);
  1656. }else if(!this._opened &&
  1657. (e.keyCode == keys.DOWN_ARROW ||
  1658. ( (e.keyCode == keys.ENTER || e.keyCode == dojo.keys.SPACE) &&
  1659. //ignore enter and space if the event is for a text input
  1660. ((target.tagName || "").toLowerCase() !== 'input' ||
  1661. (target.type && target.type.toLowerCase() !== 'text'))))){
  1662. // Toggle the drop down, but wait until keyup so that the drop down doesn't
  1663. // get a stray keyup event, or in the case of key-repeat (because user held
  1664. // down key for too long), stray keydown events
  1665. this._toggleOnKeyUp = true;
  1666. event.stop(e);
  1667. }
  1668. },
  1669. _onKeyUp: function(){
  1670. if(this._toggleOnKeyUp){
  1671. delete this._toggleOnKeyUp;
  1672. this.toggleDropDown();
  1673. var d = this.dropDown; // drop down may not exist until toggleDropDown() call
  1674. if(d && d.focus){
  1675. setTimeout(lang.hitch(d, "focus"), 1);
  1676. }
  1677. }
  1678. },
  1679. _onBlur: function(){
  1680. // summary:
  1681. // Called magically when focus has shifted away from this widget and it's dropdown
  1682. // Don't focus on button if the user has explicitly focused on something else (happens
  1683. // when user clicks another control causing the current popup to close)..
  1684. // But if focus is inside of the drop down then reset focus to me, because IE doesn't like
  1685. // it when you display:none a node with focus.
  1686. var focusMe = focus.curNode && this.dropDown && dom.isDescendant(focus.curNode, this.dropDown.domNode);
  1687. this.closeDropDown(focusMe);
  1688. this.inherited(arguments);
  1689. },
  1690. isLoaded: function(){
  1691. // summary:
  1692. // Returns true if the dropdown exists and it's data is loaded. This can
  1693. // be overridden in order to force a call to loadDropDown().
  1694. // tags:
  1695. // protected
  1696. return true;
  1697. },
  1698. loadDropDown: function(/*Function*/ loadCallback){
  1699. // summary:
  1700. // Creates the drop down if it doesn't exist, loads the data
  1701. // if there's an href and it hasn't been loaded yet, and then calls
  1702. // the given callback.
  1703. // tags:
  1704. // protected
  1705. // TODO: for 2.0, change API to return a Deferred, instead of calling loadCallback?
  1706. loadCallback();
  1707. },
  1708. loadAndOpenDropDown: function(){
  1709. // summary:
  1710. // Creates the drop down if it doesn't exist, loads the data
  1711. // if there's an href and it hasn't been loaded yet, and
  1712. // then opens the drop down. This is basically a callback when the
  1713. // user presses the down arrow button to open the drop down.
  1714. // returns: Deferred
  1715. // Deferred for the drop down widget that
  1716. // fires when drop down is created and loaded
  1717. // tags:
  1718. // protected
  1719. var d = new Deferred(),
  1720. afterLoad = lang.hitch(this, function(){
  1721. this.openDropDown();
  1722. d.resolve(this.dropDown);
  1723. });
  1724. if(!this.isLoaded()){
  1725. this.loadDropDown(afterLoad);
  1726. }else{
  1727. afterLoad();
  1728. }
  1729. return d;
  1730. },
  1731. toggleDropDown: function(){
  1732. // summary:
  1733. // Callback when the user presses the down arrow button or presses
  1734. // the down arrow key to open/close the drop down.
  1735. // Toggle the drop-down widget; if it is up, close it, if not, open it
  1736. // tags:
  1737. // protected
  1738. if(this.disabled || this.readOnly){ return; }
  1739. if(!this._opened){
  1740. this.loadAndOpenDropDown();
  1741. }else{
  1742. this.closeDropDown();
  1743. }
  1744. },
  1745. openDropDown: function(){
  1746. // summary:
  1747. // Opens the dropdown for this widget. To be called only when this.dropDown
  1748. // has been created and is ready to display (ie, it's data is loaded).
  1749. // returns:
  1750. // return value of dijit.popup.open()
  1751. // tags:
  1752. // protected
  1753. var dropDown = this.dropDown,
  1754. ddNode = dropDown.domNode,
  1755. aroundNode = this._aroundNode || this.domNode,
  1756. self = this;
  1757. // Prepare our popup's height and honor maxHeight if it exists.
  1758. // TODO: isn't maxHeight dependent on the return value from dijit.popup.open(),
  1759. // ie, dependent on how much space is available (BK)
  1760. if(!this._preparedNode){
  1761. this._preparedNode = true;
  1762. // Check if we have explicitly set width and height on the dropdown widget dom node
  1763. if(ddNode.style.width){
  1764. this._explicitDDWidth = true;
  1765. }
  1766. if(ddNode.style.height){
  1767. this._explicitDDHeight = true;
  1768. }
  1769. }
  1770. // Code for resizing dropdown (height limitation, or increasing width to match my width)
  1771. if(this.maxHeight || this.forceWidth || this.autoWidth){
  1772. var myStyle = {
  1773. display: "",
  1774. visibility: "hidden"
  1775. };
  1776. if(!this._explicitDDWidth){
  1777. myStyle.width = "";
  1778. }
  1779. if(!this._explicitDDHeight){
  1780. myStyle.height = "";
  1781. }
  1782. domStyle.set(ddNode, myStyle);
  1783. // Figure out maximum height allowed (if there is a height restriction)
  1784. var maxHeight = this.maxHeight;
  1785. if(maxHeight == -1){
  1786. // limit height to space available in viewport either above or below my domNode
  1787. // (whichever side has more room)
  1788. var viewport = Viewport.getEffectiveBox(this.ownerDocument),
  1789. position = domGeometry.position(aroundNode, false);
  1790. maxHeight = Math.floor(Math.max(position.y, viewport.h - (position.y + position.h)));
  1791. }
  1792. // Attach dropDown to DOM and make make visibility:hidden rather than display:none
  1793. // so we call startup() and also get the size
  1794. popup.moveOffScreen(dropDown);
  1795. if(dropDown.startup && !dropDown._started){
  1796. dropDown.startup(); // this has to be done after being added to the DOM
  1797. }
  1798. // Get size of drop down, and determine if vertical scroll bar needed
  1799. var mb = domGeometry.getMarginSize(ddNode);
  1800. var overHeight = (maxHeight && mb.h > maxHeight);
  1801. domStyle.set(ddNode, {
  1802. overflow: overHeight ? "auto" : "visible"
  1803. });
  1804. if(overHeight){
  1805. mb.h = maxHeight;
  1806. if("w" in mb){
  1807. mb.w += 16; // room for vertical scrollbar
  1808. }
  1809. }else{
  1810. delete mb.h;
  1811. }
  1812. // Adjust dropdown width to match or be larger than my width
  1813. if(this.forceWidth){
  1814. mb.w = aroundNode.offsetWidth;
  1815. }else if(this.autoWidth){
  1816. mb.w = Math.max(mb.w, aroundNode.offsetWidth);
  1817. }else{
  1818. delete mb.w;
  1819. }
  1820. // And finally, resize the dropdown to calculated height and width
  1821. if(lang.isFunction(dropDown.resize)){
  1822. dropDown.resize(mb);
  1823. }else{
  1824. domGeometry.setMarginBox(ddNode, mb);
  1825. }
  1826. }
  1827. var retVal = popup.open({
  1828. parent: this,
  1829. popup: dropDown,
  1830. around: aroundNode,
  1831. orient: this.dropDownPosition,
  1832. onExecute: function(){
  1833. self.closeDropDown(true);
  1834. },
  1835. onCancel: function(){
  1836. self.closeDropDown(true);
  1837. },
  1838. onClose: function(){
  1839. domAttr.set(self._popupStateNode, "popupActive", false);
  1840. domClass.remove(self._popupStateNode, "dijitHasDropDownOpen");
  1841. self._opened = false;
  1842. }
  1843. });
  1844. domAttr.set(this._popupStateNode, "popupActive", "true");
  1845. domClass.add(self._popupStateNode, "dijitHasDropDownOpen");
  1846. this._opened=true;
  1847. // TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
  1848. return retVal;
  1849. },
  1850. closeDropDown: function(/*Boolean*/ focus){
  1851. // summary:
  1852. // Closes the drop down on this widget
  1853. // focus:
  1854. // If true, refocuses the button widget
  1855. // tags:
  1856. // protected
  1857. if(this._opened){
  1858. if(focus){ this.focus(); }
  1859. popup.close(this.dropDown);
  1860. this._opened = false;
  1861. }
  1862. }
  1863. });
  1864. });
  1865. },
  1866. 'dijit/tree/TreeStoreModel':function(){
  1867. define("dijit/tree/TreeStoreModel", [
  1868. "dojo/_base/array", // array.filter array.forEach array.indexOf array.some
  1869. "dojo/aspect", // aspect.after
  1870. "dojo/_base/declare", // declare
  1871. "dojo/_base/json", // json.stringify
  1872. "dojo/_base/lang" // lang.hitch
  1873. ], function(array, aspect, declare, json, lang){
  1874. // module:
  1875. // dijit/tree/TreeStoreModel
  1876. // summary:
  1877. // Implements dijit.Tree.model connecting to a dojo.data store with a single
  1878. // root item.
  1879. return declare("dijit.tree.TreeStoreModel", null, {
  1880. // summary:
  1881. // Implements dijit.Tree.model connecting to a dojo.data store with a single
  1882. // root item. Any methods passed into the constructor will override
  1883. // the ones defined here.
  1884. // store: dojo.data.Store
  1885. // Underlying store
  1886. store: null,
  1887. // childrenAttrs: String[]
  1888. // One or more attribute names (attributes in the dojo.data item) that specify that item's children
  1889. childrenAttrs: ["children"],
  1890. // newItemIdAttr: String
  1891. // Name of attribute in the Object passed to newItem() that specifies the id.
  1892. //
  1893. // If newItemIdAttr is set then it's used when newItem() is called to see if an
  1894. // item with the same id already exists, and if so just links to the old item
  1895. // (so that the old item ends up with two parents).
  1896. //
  1897. // Setting this to null or "" will make every drop create a new item.
  1898. newItemIdAttr: "id",
  1899. // labelAttr: String
  1900. // If specified, get label for tree node from this attribute, rather
  1901. // than by calling store.getLabel()
  1902. labelAttr: "",
  1903. // root: [readonly] dojo.data.Item
  1904. // Pointer to the root item (read only, not a parameter)
  1905. root: null,
  1906. // query: anything
  1907. // Specifies datastore query to return the root item for the tree.
  1908. // Must only return a single item. Alternately can just pass in pointer
  1909. // to root item.
  1910. // example:
  1911. // | {id:'ROOT'}
  1912. query: null,
  1913. // deferItemLoadingUntilExpand: Boolean
  1914. // Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes
  1915. // until they are expanded. This allows for lazying loading where only one
  1916. // loadItem (and generally one network call, consequently) per expansion
  1917. // (rather than one for each child).
  1918. // This relies on partial loading of the children items; each children item of a
  1919. // fully loaded item should contain the label and info about having children.
  1920. deferItemLoadingUntilExpand: false,
  1921. constructor: function(/* Object */ args){
  1922. // summary:
  1923. // Passed the arguments listed above (store, etc)
  1924. // tags:
  1925. // private
  1926. lang.mixin(this, args);
  1927. this.connects = [];
  1928. var store = this.store;
  1929. if(!store.getFeatures()['dojo.data.api.Identity']){
  1930. throw new Error("dijit.Tree: store must support dojo.data.Identity");
  1931. }
  1932. // if the store supports Notification, subscribe to the notification events
  1933. if(store.getFeatures()['dojo.data.api.Notification']){
  1934. this.connects = this.connects.concat([
  1935. aspect.after(store, "onNew", lang.hitch(this, "onNewItem"), true),
  1936. aspect.after(store, "onDelete", lang.hitch(this, "onDeleteItem"), true),
  1937. aspect.after(store, "onSet", lang.hitch(this, "onSetItem"), true)
  1938. ]);
  1939. }
  1940. },
  1941. destroy: function(){
  1942. var h;
  1943. while(h = this.connects.pop()){ h.remove(); }
  1944. // TODO: should cancel any in-progress processing of getRoot(), getChildren()
  1945. },
  1946. // =======================================================================
  1947. // Methods for traversing hierarchy
  1948. getRoot: function(onItem, onError){
  1949. // summary:
  1950. // Calls onItem with the root item for the tree, possibly a fabricated item.
  1951. // Calls onError on error.
  1952. if(this.root){
  1953. onItem(this.root);
  1954. }else{
  1955. this.store.fetch({
  1956. query: this.query,
  1957. onComplete: lang.hitch(this, function(items){
  1958. if(items.length != 1){
  1959. throw new Error(this.declaredClass + ": query " + json.stringify(this.query) + " returned " + items.length +
  1960. " items, but must return exactly one item");
  1961. }
  1962. this.root = items[0];
  1963. onItem(this.root);
  1964. }),
  1965. onError: onError
  1966. });
  1967. }
  1968. },
  1969. mayHaveChildren: function(/*dojo.data.Item*/ item){
  1970. // summary:
  1971. // Tells if an item has or may have children. Implementing logic here
  1972. // avoids showing +/- expando icon for nodes that we know don't have children.
  1973. // (For efficiency reasons we may not want to check if an element actually
  1974. // has children until user clicks the expando node)
  1975. return array.some(this.childrenAttrs, function(attr){
  1976. return this.store.hasAttribute(item, attr);
  1977. }, this);
  1978. },
  1979. getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
  1980. // summary:
  1981. // Calls onComplete() with array of child items of given parent item, all loaded.
  1982. var store = this.store;
  1983. if(!store.isItemLoaded(parentItem)){
  1984. // The parent is not loaded yet, we must be in deferItemLoadingUntilExpand
  1985. // mode, so we will load it and just return the children (without loading each
  1986. // child item)
  1987. var getChildren = lang.hitch(this, arguments.callee);
  1988. store.loadItem({
  1989. item: parentItem,
  1990. onItem: function(parentItem){
  1991. getChildren(parentItem, onComplete, onError);
  1992. },
  1993. onError: onError
  1994. });
  1995. return;
  1996. }
  1997. // get children of specified item
  1998. var childItems = [];
  1999. for(var i=0; i<this.childrenAttrs.length; i++){
  2000. var vals = store.getValues(parentItem, this.childrenAttrs[i]);
  2001. childItems = childItems.concat(vals);
  2002. }
  2003. // count how many items need to be loaded
  2004. var _waitCount = 0;
  2005. if(!this.deferItemLoadingUntilExpand){
  2006. array.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
  2007. }
  2008. if(_waitCount == 0){
  2009. // all items are already loaded (or we aren't loading them). proceed...
  2010. onComplete(childItems);
  2011. }else{
  2012. // still waiting for some or all of the items to load
  2013. array.forEach(childItems, function(item, idx){
  2014. if(!store.isItemLoaded(item)){
  2015. store.loadItem({
  2016. item: item,
  2017. onItem: function(item){
  2018. childItems[idx] = item;
  2019. if(--_waitCount == 0){
  2020. // all nodes have been loaded, send them to the tree
  2021. onComplete(childItems);
  2022. }
  2023. },
  2024. onError: onError
  2025. });
  2026. }
  2027. });
  2028. }
  2029. },
  2030. // =======================================================================
  2031. // Inspecting items
  2032. isItem: function(/* anything */ something){
  2033. return this.store.isItem(something); // Boolean
  2034. },
  2035. fetchItemByIdentity: function(/* object */ keywordArgs){
  2036. this.store.fetchItemByIdentity(keywordArgs);
  2037. },
  2038. getIdentity: function(/* item */ item){
  2039. return this.store.getIdentity(item); // Object
  2040. },
  2041. getLabel: function(/*dojo.data.Item*/ item){
  2042. // summary:
  2043. // Get the label for an item
  2044. if(this.labelAttr){
  2045. return this.store.getValue(item,this.labelAttr); // String
  2046. }else{
  2047. return this.store.getLabel(item); // String
  2048. }
  2049. },
  2050. // =======================================================================
  2051. // Write interface
  2052. newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
  2053. // summary:
  2054. // Creates a new item. See `dojo.data.api.Write` for details on args.
  2055. // Used in drag & drop when item from external source dropped onto tree.
  2056. // description:
  2057. // Developers will need to override this method if new items get added
  2058. // to parents with multiple children attributes, in order to define which
  2059. // children attribute points to the new item.
  2060. var pInfo = {parent: parent, attribute: this.childrenAttrs[0]}, LnewItem;
  2061. if(this.newItemIdAttr && args[this.newItemIdAttr]){
  2062. // Maybe there's already a corresponding item in the store; if so, reuse it.
  2063. this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){
  2064. if(item){
  2065. // There's already a matching item in store, use it
  2066. this.pasteItem(item, null, parent, true, insertIndex);
  2067. }else{
  2068. // Create new item in the tree, based on the drag source.
  2069. LnewItem=this.store.newItem(args, pInfo);
  2070. if(LnewItem && (insertIndex!=undefined)){
  2071. // Move new item to desired position
  2072. this.pasteItem(LnewItem, parent, parent, false, insertIndex);
  2073. }
  2074. }
  2075. }});
  2076. }else{
  2077. // [as far as we know] there is no id so we must assume this is a new item
  2078. LnewItem=this.store.newItem(args, pInfo);
  2079. if(LnewItem && (insertIndex!=undefined)){
  2080. // Move new item to desired position
  2081. this.pasteItem(LnewItem, parent, parent, false, insertIndex);
  2082. }
  2083. }
  2084. },
  2085. pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
  2086. // summary:
  2087. // Move or copy an item from one parent item to another.
  2088. // Used in drag & drop
  2089. var store = this.store,
  2090. parentAttr = this.childrenAttrs[0]; // name of "children" attr in parent item
  2091. // remove child from source item, and record the attribute that child occurred in
  2092. if(oldParentItem){
  2093. array.forEach(this.childrenAttrs, function(attr){
  2094. if(store.containsValue(oldParentItem, attr, childItem)){
  2095. if(!bCopy){
  2096. var values = array.filter(store.getValues(oldParentItem, attr), function(x){
  2097. return x != childItem;
  2098. });
  2099. store.setValues(oldParentItem, attr, values);
  2100. }
  2101. parentAttr = attr;
  2102. }
  2103. });
  2104. }
  2105. // modify target item's children attribute to include this item
  2106. if(newParentItem){
  2107. if(typeof insertIndex == "number"){
  2108. // call slice() to avoid modifying the original array, confusing the data store
  2109. var childItems = store.getValues(newParentItem, parentAttr).slice();
  2110. childItems.splice(insertIndex, 0, childItem);
  2111. store.setValues(newParentItem, parentAttr, childItems);
  2112. }else{
  2113. store.setValues(newParentItem, parentAttr,
  2114. store.getValues(newParentItem, parentAttr).concat(childItem));
  2115. }
  2116. }
  2117. },
  2118. // =======================================================================
  2119. // Callbacks
  2120. onChange: function(/*dojo.data.Item*/ /*===== item =====*/){
  2121. // summary:
  2122. // Callback whenever an item has changed, so that Tree
  2123. // can update the label, icon, etc. Note that changes
  2124. // to an item's children or parent(s) will trigger an
  2125. // onChildrenChange() so you can ignore those changes here.
  2126. // tags:
  2127. // callback
  2128. },
  2129. onChildrenChange: function(/*===== parent, newChildrenList =====*/){
  2130. // summary:
  2131. // Callback to do notifications about new, updated, or deleted items.
  2132. // parent: dojo.data.Item
  2133. // newChildrenList: dojo.data.Item[]
  2134. // tags:
  2135. // callback
  2136. },
  2137. onDelete: function(/*dojo.data.Item*/ /*===== item =====*/){
  2138. // summary:
  2139. // Callback when an item has been deleted.
  2140. // description:
  2141. // Note that there will also be an onChildrenChange() callback for the parent
  2142. // of this item.
  2143. // tags:
  2144. // callback
  2145. },
  2146. // =======================================================================
  2147. // Events from data store
  2148. onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
  2149. // summary:
  2150. // Handler for when new items appear in the store, either from a drop operation
  2151. // or some other way. Updates the tree view (if necessary).
  2152. // description:
  2153. // If the new item is a child of an existing item,
  2154. // calls onChildrenChange() with the new list of children
  2155. // for that existing item.
  2156. //
  2157. // tags:
  2158. // extension
  2159. // We only care about the new item if it has a parent that corresponds to a TreeNode
  2160. // we are currently displaying
  2161. if(!parentInfo){
  2162. return;
  2163. }
  2164. // Call onChildrenChange() on parent (ie, existing) item with new list of children
  2165. // In the common case, the new list of children is simply parentInfo.newValue or
  2166. // [ parentInfo.newValue ], although if items in the store has multiple
  2167. // child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue,
  2168. // so call getChildren() to be sure to get right answer.
  2169. this.getChildren(parentInfo.item, lang.hitch(this, function(children){
  2170. this.onChildrenChange(parentInfo.item, children);
  2171. }));
  2172. },
  2173. onDeleteItem: function(/*Object*/ item){
  2174. // summary:
  2175. // Handler for delete notifications from underlying store
  2176. this.onDelete(item);
  2177. },
  2178. onSetItem: function(item, attribute /*===== , oldValue, newValue =====*/){
  2179. // summary:
  2180. // Updates the tree view according to changes in the data store.
  2181. // description:
  2182. // Handles updates to an item's children by calling onChildrenChange(), and
  2183. // other updates to an item by calling onChange().
  2184. //
  2185. // See `onNewItem` for more details on handling updates to an item's children.
  2186. // item: Item
  2187. // attribute: attribute-name-string
  2188. // oldValue: object | array
  2189. // newValue: object | array
  2190. // tags:
  2191. // extension
  2192. if(array.indexOf(this.childrenAttrs, attribute) != -1){
  2193. // item's children list changed
  2194. this.getChildren(item, lang.hitch(this, function(children){
  2195. // See comments in onNewItem() about calling getChildren()
  2196. this.onChildrenChange(item, children);
  2197. }));
  2198. }else{
  2199. // item's label/icon/etc. changed.
  2200. this.onChange(item);
  2201. }
  2202. }
  2203. });
  2204. });
  2205. },
  2206. 'dojo/dnd/Selector':function(){
  2207. define("dojo/dnd/Selector", ["../main", "./common", "./Container"], function(dojo) {
  2208. // module:
  2209. // dojo/dnd/Selector
  2210. // summary:
  2211. // TODOC
  2212. /*
  2213. Container item states:
  2214. "" - an item is not selected
  2215. "Selected" - an item is selected
  2216. "Anchor" - an item is selected, and is an anchor for a "shift" selection
  2217. */
  2218. /*=====
  2219. dojo.declare("dojo.dnd.__SelectorArgs", [dojo.dnd.__ContainerArgs], {
  2220. // singular: Boolean
  2221. // allows selection of only one element, if true
  2222. singular: false,
  2223. // autoSync: Boolean
  2224. // autosynchronizes the source with its list of DnD nodes,
  2225. autoSync: false
  2226. });
  2227. =====*/
  2228. dojo.declare("dojo.dnd.Selector", dojo.dnd.Container, {
  2229. // summary:
  2230. // a Selector object, which knows how to select its children
  2231. /*=====
  2232. // selection: Set<String>
  2233. // The set of id's that are currently selected, such that this.selection[id] == 1
  2234. // if the node w/that id is selected. Can iterate over selected node's id's like:
  2235. // | for(var id in this.selection)
  2236. selection: {},
  2237. =====*/
  2238. constructor: function(node, params){
  2239. // summary:
  2240. // constructor of the Selector
  2241. // node: Node||String
  2242. // node or node's id to build the selector on
  2243. // params: dojo.dnd.__SelectorArgs?
  2244. // a dictionary of parameters
  2245. if(!params){ params = {}; }
  2246. this.singular = params.singular;
  2247. this.autoSync = params.autoSync;
  2248. // class-specific variables
  2249. this.selection = {};
  2250. this.anchor = null;
  2251. this.simpleSelection = false;
  2252. // set up events
  2253. this.events.push(
  2254. dojo.connect(this.node, "onmousedown", this, "onMouseDown"),
  2255. dojo.connect(this.node, "onmouseup", this, "onMouseUp"));
  2256. },
  2257. // object attributes (for markup)
  2258. singular: false, // is singular property
  2259. // methods
  2260. getSelectedNodes: function(){
  2261. // summary:
  2262. // returns a list (an array) of selected nodes
  2263. var t = new dojo.NodeList();
  2264. var e = dojo.dnd._empty;
  2265. for(var i in this.selection){
  2266. if(i in e){ continue; }
  2267. t.push(dojo.byId(i));
  2268. }
  2269. return t; // NodeList
  2270. },
  2271. selectNone: function(){
  2272. // summary:
  2273. // unselects all items
  2274. return this._removeSelection()._removeAnchor(); // self
  2275. },
  2276. selectAll: function(){
  2277. // summary:
  2278. // selects all items
  2279. this.forInItems(function(data, id){
  2280. this._addItemClass(dojo.byId(id), "Selected");
  2281. this.selection[id] = 1;
  2282. }, this);
  2283. return this._removeAnchor(); // self
  2284. },
  2285. deleteSelectedNodes: function(){
  2286. // summary:
  2287. // deletes all selected items
  2288. var e = dojo.dnd._empty;
  2289. for(var i in this.selection){
  2290. if(i in e){ continue; }
  2291. var n = dojo.byId(i);
  2292. this.delItem(i);
  2293. dojo.destroy(n);
  2294. }
  2295. this.anchor = null;
  2296. this.selection = {};
  2297. return this; // self
  2298. },
  2299. forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
  2300. // summary:
  2301. // iterates over selected items;
  2302. // see `dojo.dnd.Container.forInItems()` for details
  2303. o = o || dojo.global;
  2304. var s = this.selection, e = dojo.dnd._empty;
  2305. for(var i in s){
  2306. if(i in e){ continue; }
  2307. f.call(o, this.getItem(i), i, this);
  2308. }
  2309. },
  2310. sync: function(){
  2311. // summary:
  2312. // sync up the node list with the data map
  2313. dojo.dnd.Selector.superclass.sync.call(this);
  2314. // fix the anchor
  2315. if(this.anchor){
  2316. if(!this.getItem(this.anchor.id)){
  2317. this.anchor = null;
  2318. }
  2319. }
  2320. // fix the selection
  2321. var t = [], e = dojo.dnd._empty;
  2322. for(var i in this.selection){
  2323. if(i in e){ continue; }
  2324. if(!this.getItem(i)){
  2325. t.push(i);
  2326. }
  2327. }
  2328. dojo.forEach(t, function(i){
  2329. delete this.selection[i];
  2330. }, this);
  2331. return this; // self
  2332. },
  2333. insertNodes: function(addSelected, data, before, anchor){
  2334. // summary:
  2335. // inserts new data items (see `dojo.dnd.Container.insertNodes()` method for details)
  2336. // addSelected: Boolean
  2337. // all new nodes will be added to selected items, if true, no selection change otherwise
  2338. // data: Array
  2339. // a list of data items, which should be processed by the creator function
  2340. // before: Boolean
  2341. // insert before the anchor, if true, and after the anchor otherwise
  2342. // anchor: Node
  2343. // the anchor node to be used as a point of insertion
  2344. var oldCreator = this._normalizedCreator;
  2345. this._normalizedCreator = function(item, hint){
  2346. var t = oldCreator.call(this, item, hint);
  2347. if(addSelected){
  2348. if(!this.anchor){
  2349. this.anchor = t.node;
  2350. this._removeItemClass(t.node, "Selected");
  2351. this._addItemClass(this.anchor, "Anchor");
  2352. }else if(this.anchor != t.node){
  2353. this._removeItemClass(t.node, "Anchor");
  2354. this._addItemClass(t.node, "Selected");
  2355. }
  2356. this.selection[t.node.id] = 1;
  2357. }else{
  2358. this._removeItemClass(t.node, "Selected");
  2359. this._removeItemClass(t.node, "Anchor");
  2360. }
  2361. return t;
  2362. };
  2363. dojo.dnd.Selector.superclass.insertNodes.call(this, data, before, anchor);
  2364. this._normalizedCreator = oldCreator;
  2365. return this; // self
  2366. },
  2367. destroy: function(){
  2368. // summary:
  2369. // prepares the object to be garbage-collected
  2370. dojo.dnd.Selector.superclass.destroy.call(this);
  2371. this.selection = this.anchor = null;
  2372. },
  2373. // mouse events
  2374. onMouseDown: function(e){
  2375. // summary:
  2376. // event processor for onmousedown
  2377. // e: Event
  2378. // mouse event
  2379. if(this.autoSync){ this.sync(); }
  2380. if(!this.current){ return; }
  2381. if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
  2382. this.simpleSelection = true;
  2383. if(e.button === dojo.mouseButtons.LEFT){
  2384. // accept the left button and stop the event
  2385. // for IE we don't stop event when multiple buttons are pressed
  2386. dojo.stopEvent(e);
  2387. }
  2388. return;
  2389. }
  2390. if(!this.singular && e.shiftKey){
  2391. if(!dojo.isCopyKey(e)){
  2392. this._removeSelection();
  2393. }
  2394. var c = this.getAllNodes();
  2395. if(c.length){
  2396. if(!this.anchor){
  2397. this.anchor = c[0];
  2398. this._addItemClass(this.anchor, "Anchor");
  2399. }
  2400. this.selection[this.anchor.id] = 1;
  2401. if(this.anchor != this.current){
  2402. var i = 0;
  2403. for(; i < c.length; ++i){
  2404. var node = c[i];
  2405. if(node == this.anchor || node == this.current){ break; }
  2406. }
  2407. for(++i; i < c.length; ++i){
  2408. var node = c[i];
  2409. if(node == this.anchor || node == this.current){ break; }
  2410. this._addItemClass(node, "Selected");
  2411. this.selection[node.id] = 1;
  2412. }
  2413. this._addItemClass(this.current, "Selected");
  2414. this.selection[this.current.id] = 1;
  2415. }
  2416. }
  2417. }else{
  2418. if(this.singular){
  2419. if(this.anchor == this.current){
  2420. if(dojo.isCopyKey(e)){
  2421. this.selectNone();
  2422. }
  2423. }else{
  2424. this.selectNone();
  2425. this.anchor = this.current;
  2426. this._addItemClass(this.anchor, "Anchor");
  2427. this.selection[this.current.id] = 1;
  2428. }
  2429. }else{
  2430. if(dojo.isCopyKey(e)){
  2431. if(this.anchor == this.current){
  2432. delete this.selection[this.anchor.id];
  2433. this._removeAnchor();
  2434. }else{
  2435. if(this.current.id in this.selection){
  2436. this._removeItemClass(this.current, "Selected");
  2437. delete this.selection[this.current.id];
  2438. }else{
  2439. if(this.anchor){
  2440. this._removeItemClass(this.anchor, "Anchor");
  2441. this._addItemClass(this.anchor, "Selected");
  2442. }
  2443. this.anchor = this.current;
  2444. this._addItemClass(this.current, "Anchor");
  2445. this.selection[this.current.id] = 1;
  2446. }
  2447. }
  2448. }else{
  2449. if(!(this.current.id in this.selection)){
  2450. this.selectNone();
  2451. this.anchor = this.current;
  2452. this._addItemClass(this.current, "Anchor");
  2453. this.selection[this.current.id] = 1;
  2454. }
  2455. }
  2456. }
  2457. }
  2458. dojo.stopEvent(e);
  2459. },
  2460. onMouseUp: function(e){
  2461. // summary:
  2462. // event processor for onmouseup
  2463. // e: Event
  2464. // mouse event
  2465. if(!this.simpleSelection){ return; }
  2466. this.simpleSelection = false;
  2467. this.selectNone();
  2468. if(this.current){
  2469. this.anchor = this.current;
  2470. this._addItemClass(this.anchor, "Anchor");
  2471. this.selection[this.current.id] = 1;
  2472. }
  2473. },
  2474. onMouseMove: function(e){
  2475. // summary:
  2476. // event processor for onmousemove
  2477. // e: Event
  2478. // mouse event
  2479. this.simpleSelection = false;
  2480. },
  2481. // utilities
  2482. onOverEvent: function(){
  2483. // summary:
  2484. // this function is called once, when mouse is over our container
  2485. this.onmousemoveEvent = dojo.connect(this.node, "onmousemove", this, "onMouseMove");
  2486. },
  2487. onOutEvent: function(){
  2488. // summary:
  2489. // this function is called once, when mouse is out of our container
  2490. dojo.disconnect(this.onmousemoveEvent);
  2491. delete this.onmousemoveEvent;
  2492. },
  2493. _removeSelection: function(){
  2494. // summary:
  2495. // unselects all items
  2496. var e = dojo.dnd._empty;
  2497. for(var i in this.selection){
  2498. if(i in e){ continue; }
  2499. var node = dojo.byId(i);
  2500. if(node){ this._removeItemClass(node, "Selected"); }
  2501. }
  2502. this.selection = {};
  2503. return this; // self
  2504. },
  2505. _removeAnchor: function(){
  2506. if(this.anchor){
  2507. this._removeItemClass(this.anchor, "Anchor");
  2508. this.anchor = null;
  2509. }
  2510. return this; // self
  2511. }
  2512. });
  2513. return dojo.dnd.Selector;
  2514. });
  2515. },
  2516. 'dijit/_MenuBase':function(){
  2517. define("dijit/_MenuBase", [
  2518. "./popup",
  2519. "dojo/window",
  2520. "./_Widget",
  2521. "./_KeyNavContainer",
  2522. "./_TemplatedMixin",
  2523. "dojo/_base/declare", // declare
  2524. "dojo/dom", // dom.isDescendant domClass.replace
  2525. "dojo/dom-attr",
  2526. "dojo/dom-class", // domClass.replace
  2527. "dojo/_base/lang", // lang.hitch
  2528. "dojo/_base/array" // array.indexOf
  2529. ], function(pm, winUtils, _Widget, _KeyNavContainer, _TemplatedMixin,
  2530. declare, dom, domAttr, domClass, lang, array){
  2531. /*=====
  2532. var _Widget = dijit._Widget;
  2533. var _TemplatedMixin = dijit._TemplatedMixin;
  2534. var _KeyNavContainer = dijit._KeyNavContainer;
  2535. =====*/
  2536. // module:
  2537. // dijit/_MenuBase
  2538. // summary:
  2539. // Base class for Menu and MenuBar
  2540. return declare("dijit._MenuBase",
  2541. [_Widget, _TemplatedMixin, _KeyNavContainer],
  2542. {
  2543. // summary:
  2544. // Base class for Menu and MenuBar
  2545. // parentMenu: [readonly] Widget
  2546. // pointer to menu that displayed me
  2547. parentMenu: null,
  2548. // popupDelay: Integer
  2549. // number of milliseconds before hovering (without clicking) causes the popup to automatically open.
  2550. popupDelay: 500,
  2551. onExecute: function(){
  2552. // summary:
  2553. // Attach point for notification about when a menu item has been executed.
  2554. // This is an internal mechanism used for Menus to signal to their parent to
  2555. // close them, because they are about to execute the onClick handler. In
  2556. // general developers should not attach to or override this method.
  2557. // tags:
  2558. // protected
  2559. },
  2560. onCancel: function(/*Boolean*/ /*===== closeAll =====*/){
  2561. // summary:
  2562. // Attach point for notification about when the user cancels the current menu
  2563. // This is an internal mechanism used for Menus to signal to their parent to
  2564. // close them. In general developers should not attach to or override this method.
  2565. // tags:
  2566. // protected
  2567. },
  2568. _moveToPopup: function(/*Event*/ evt){
  2569. // summary:
  2570. // This handles the right arrow key (left arrow key on RTL systems),
  2571. // which will either open a submenu, or move to the next item in the
  2572. // ancestor MenuBar
  2573. // tags:
  2574. // private
  2575. if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){
  2576. this.focusedChild._onClick(evt);
  2577. }else{
  2578. var topMenu = this._getTopMenu();
  2579. if(topMenu && topMenu._isMenuBar){
  2580. topMenu.focusNext();
  2581. }
  2582. }
  2583. },
  2584. _onPopupHover: function(/*Event*/ /*===== evt =====*/){
  2585. // summary:
  2586. // This handler is called when the mouse moves over the popup.
  2587. // tags:
  2588. // private
  2589. // if the mouse hovers over a menu popup that is in pending-close state,
  2590. // then stop the close operation.
  2591. // This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker)
  2592. if(this.currentPopup && this.currentPopup._pendingClose_timer){
  2593. var parentMenu = this.currentPopup.parentMenu;
  2594. // highlight the parent menu item pointing to this popup
  2595. if(parentMenu.focusedChild){
  2596. parentMenu.focusedChild._setSelected(false);
  2597. }
  2598. parentMenu.focusedChild = this.currentPopup.from_item;
  2599. parentMenu.focusedChild._setSelected(true);
  2600. // cancel the pending close
  2601. this._stopPendingCloseTimer(this.currentPopup);
  2602. }
  2603. },
  2604. onItemHover: function(/*MenuItem*/ item){
  2605. // summary:
  2606. // Called when cursor is over a MenuItem.
  2607. // tags:
  2608. // protected
  2609. // Don't do anything unless user has "activated" the menu by:
  2610. // 1) clicking it
  2611. // 2) opening it from a parent menu (which automatically focuses it)
  2612. if(this.isActive){
  2613. this.focusChild(item);
  2614. if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){
  2615. this.hover_timer = setTimeout(lang.hitch(this, "_openPopup"), this.popupDelay);
  2616. }
  2617. }
  2618. // if the user is mixing mouse and keyboard navigation,
  2619. // then the menu may not be active but a menu item has focus,
  2620. // but it's not the item that the mouse just hovered over.
  2621. // To avoid both keyboard and mouse selections, use the latest.
  2622. if(this.focusedChild){
  2623. this.focusChild(item);
  2624. }
  2625. this._hoveredChild = item;
  2626. },
  2627. _onChildBlur: function(item){
  2628. // summary:
  2629. // Called when a child MenuItem becomes inactive because focus
  2630. // has been removed from the MenuItem *and* it's descendant menus.
  2631. // tags:
  2632. // private
  2633. this._stopPopupTimer();
  2634. item._setSelected(false);
  2635. // Close all popups that are open and descendants of this menu
  2636. var itemPopup = item.popup;
  2637. if(itemPopup){
  2638. this._stopPendingCloseTimer(itemPopup);
  2639. itemPopup._pendingClose_timer = setTimeout(function(){
  2640. itemPopup._pendingClose_timer = null;
  2641. if(itemPopup.parentMenu){
  2642. itemPopup.parentMenu.currentPopup = null;
  2643. }
  2644. pm.close(itemPopup); // this calls onClose
  2645. }, this.popupDelay);
  2646. }
  2647. },
  2648. onItemUnhover: function(/*MenuItem*/ item){
  2649. // summary:
  2650. // Callback fires when mouse exits a MenuItem
  2651. // tags:
  2652. // protected
  2653. if(this.isActive){
  2654. this._stopPopupTimer();
  2655. }
  2656. if(this._hoveredChild == item){ this._hoveredChild = null; }
  2657. },
  2658. _stopPopupTimer: function(){
  2659. // summary:
  2660. // Cancels the popup timer because the user has stop hovering
  2661. // on the MenuItem, etc.
  2662. // tags:
  2663. // private
  2664. if(this.hover_timer){
  2665. clearTimeout(this.hover_timer);
  2666. this.hover_timer = null;
  2667. }
  2668. },
  2669. _stopPendingCloseTimer: function(/*dijit._Widget*/ popup){
  2670. // summary:
  2671. // Cancels the pending-close timer because the close has been preempted
  2672. // tags:
  2673. // private
  2674. if(popup._pendingClose_timer){
  2675. clearTimeout(popup._pendingClose_timer);
  2676. popup._pendingClose_timer = null;
  2677. }
  2678. },
  2679. _stopFocusTimer: function(){
  2680. // summary:
  2681. // Cancels the pending-focus timer because the menu was closed before focus occured
  2682. // tags:
  2683. // private
  2684. if(this._focus_timer){
  2685. clearTimeout(this._focus_timer);
  2686. this._focus_timer = null;
  2687. }
  2688. },
  2689. _getTopMenu: function(){
  2690. // summary:
  2691. // Returns the top menu in this chain of Menus
  2692. // tags:
  2693. // private
  2694. for(var top=this; top.parentMenu; top=top.parentMenu);
  2695. return top;
  2696. },
  2697. onItemClick: function(/*dijit._Widget*/ item, /*Event*/ evt){
  2698. // summary:
  2699. // Handle clicks on an item.
  2700. // tags:
  2701. // private
  2702. // this can't be done in _onFocus since the _onFocus events occurs asynchronously
  2703. if(typeof this.isShowingNow == 'undefined'){ // non-popup menu
  2704. this._markActive();
  2705. }
  2706. this.focusChild(item);
  2707. if(item.disabled){ return false; }
  2708. if(item.popup){
  2709. this._openPopup();
  2710. }else{
  2711. // before calling user defined handler, close hierarchy of menus
  2712. // and restore focus to place it was when menu was opened
  2713. this.onExecute();
  2714. // user defined handler for click
  2715. item.onClick(evt);
  2716. }
  2717. },
  2718. _openPopup: function(){
  2719. // summary:
  2720. // Open the popup to the side of/underneath the current menu item
  2721. // tags:
  2722. // protected
  2723. this._stopPopupTimer();
  2724. var from_item = this.focusedChild;
  2725. if(!from_item){ return; } // the focused child lost focus since the timer was started
  2726. var popup = from_item.popup;
  2727. if(popup.isShowingNow){ return; }
  2728. if(this.currentPopup){
  2729. this._stopPendingCloseTimer(this.currentPopup);
  2730. pm.close(this.currentPopup);
  2731. }
  2732. popup.parentMenu = this;
  2733. popup.from_item = from_item; // helps finding the parent item that should be focused for this popup
  2734. var self = this;
  2735. pm.open({
  2736. parent: this,
  2737. popup: popup,
  2738. around: from_item.domNode,
  2739. orient: this._orient || ["after", "before"],
  2740. onCancel: function(){ // called when the child menu is canceled
  2741. // set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus
  2742. // which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro)
  2743. self.focusChild(from_item); // put focus back on my node
  2744. self._cleanUp(); // close the submenu (be sure this is done _after_ focus is moved)
  2745. from_item._setSelected(true); // oops, _cleanUp() deselected the item
  2746. self.focusedChild = from_item; // and unset focusedChild
  2747. },
  2748. onExecute: lang.hitch(this, "_cleanUp")
  2749. });
  2750. this.currentPopup = popup;
  2751. // detect mouseovers to handle lazy mouse movements that temporarily focus other menu items
  2752. if(this.popupHoverHandle){
  2753. this.disconnect(this.popupHoverHandle);
  2754. }
  2755. this.popupHoverHandle = this.connect(popup.domNode, "onmouseenter", "_onPopupHover");
  2756. if(popup.focus){
  2757. // If user is opening the popup via keyboard (right arrow, or down arrow for MenuBar),
  2758. // if the cursor happens to collide with the popup, it will generate an onmouseover event
  2759. // even though the mouse wasn't moved. Use a setTimeout() to call popup.focus so that
  2760. // our focus() call overrides the onmouseover event, rather than vice-versa. (#8742)
  2761. popup._focus_timer = setTimeout(lang.hitch(popup, function(){
  2762. this._focus_timer = null;
  2763. this.focus();
  2764. }), 0);
  2765. }
  2766. },
  2767. _markActive: function(){
  2768. // summary:
  2769. // Mark this menu's state as active.
  2770. // Called when this Menu gets focus from:
  2771. // 1) clicking it (mouse or via space/arrow key)
  2772. // 2) being opened by a parent menu.
  2773. // This is not called just from mouse hover.
  2774. // Focusing a menu via TAB does NOT automatically set isActive
  2775. // since TAB is a navigation operation and not a selection one.
  2776. // For Windows apps, pressing the ALT key focuses the menubar
  2777. // menus (similar to TAB navigation) but the menu is not active
  2778. // (ie no dropdown) until an item is clicked.
  2779. this.isActive = true;
  2780. domClass.replace(this.domNode, "dijitMenuActive", "dijitMenuPassive");
  2781. },
  2782. onOpen: function(/*Event*/ /*===== e =====*/){
  2783. // summary:
  2784. // Callback when this menu is opened.
  2785. // This is called by the popup manager as notification that the menu
  2786. // was opened.
  2787. // tags:
  2788. // private
  2789. this.isShowingNow = true;
  2790. this._markActive();
  2791. },
  2792. _markInactive: function(){
  2793. // summary:
  2794. // Mark this menu's state as inactive.
  2795. this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here
  2796. domClass.replace(this.domNode, "dijitMenuPassive", "dijitMenuActive");
  2797. },
  2798. onClose: function(){
  2799. // summary:
  2800. // Callback when this menu is closed.
  2801. // This is called by the popup manager as notification that the menu
  2802. // was closed.
  2803. // tags:
  2804. // private
  2805. this._stopFocusTimer();
  2806. this._markInactive();
  2807. this.isShowingNow = false;
  2808. this.parentMenu = null;
  2809. },
  2810. _closeChild: function(){
  2811. // summary:
  2812. // Called when submenu is clicked or focus is lost. Close hierarchy of menus.
  2813. // tags:
  2814. // private
  2815. this._stopPopupTimer();
  2816. if(this.currentPopup){
  2817. // If focus is on a descendant MenuItem then move focus to me,
  2818. // because IE doesn't like it when you display:none a node with focus,
  2819. // and also so keyboard users don't lose control.
  2820. // Likely, immediately after a user defined onClick handler will move focus somewhere
  2821. // else, like a Dialog.
  2822. if(array.indexOf(this._focusManager.activeStack, this.id) >= 0){
  2823. domAttr.set(this.focusedChild.focusNode, "tabIndex", this.tabIndex);
  2824. this.focusedChild.focusNode.focus();
  2825. }
  2826. // Close all popups that are open and descendants of this menu
  2827. pm.close(this.currentPopup);
  2828. this.currentPopup = null;
  2829. }
  2830. if(this.focusedChild){ // unhighlight the focused item
  2831. this.focusedChild._setSelected(false);
  2832. this.focusedChild._onUnhover();
  2833. this.focusedChild = null;
  2834. }
  2835. },
  2836. _onItemFocus: function(/*MenuItem*/ item){
  2837. // summary:
  2838. // Called when child of this Menu gets focus from:
  2839. // 1) clicking it
  2840. // 2) tabbing into it
  2841. // 3) being opened by a parent menu.
  2842. // This is not called just from mouse hover.
  2843. if(this._hoveredChild && this._hoveredChild != item){
  2844. this._hoveredChild._onUnhover(); // any previous mouse movement is trumped by focus selection
  2845. }
  2846. },
  2847. _onBlur: function(){
  2848. // summary:
  2849. // Called when focus is moved away from this Menu and it's submenus.
  2850. // tags:
  2851. // protected
  2852. this._cleanUp();
  2853. this.inherited(arguments);
  2854. },
  2855. _cleanUp: function(){
  2856. // summary:
  2857. // Called when the user is done with this menu. Closes hierarchy of menus.
  2858. // tags:
  2859. // private
  2860. this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close
  2861. if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose
  2862. this._markInactive();
  2863. }
  2864. }
  2865. });
  2866. });
  2867. },
  2868. 'dijit/focus':function(){
  2869. define("dijit/focus", [
  2870. "dojo/aspect",
  2871. "dojo/_base/declare", // declare
  2872. "dojo/dom", // domAttr.get dom.isDescendant
  2873. "dojo/dom-attr", // domAttr.get dom.isDescendant
  2874. "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy
  2875. "dojo/Evented",
  2876. "dojo/_base/lang", // lang.hitch
  2877. "dojo/on",
  2878. "dojo/domReady",
  2879. "dojo/_base/sniff", // has("ie")
  2880. "dojo/Stateful",
  2881. "dojo/_base/window", // win.body
  2882. "dojo/window", // winUtils.get
  2883. "./a11y", // a11y.isTabNavigable
  2884. "./registry", // registry.byId
  2885. "./main" // to set dijit.focus
  2886. ], function(aspect, declare, dom, domAttr, domConstruct, Evented, lang, on, domReady, has, Stateful, win, winUtils,
  2887. a11y, registry, dijit){
  2888. // module:
  2889. // dijit/focus
  2890. var FocusManager = declare([Stateful, Evented], {
  2891. // summary:
  2892. // Tracks the currently focused node, and which widgets are currently "active".
  2893. // Access via require(["dijit/focus"], function(focus){ ... }).
  2894. //
  2895. // A widget is considered active if it or a descendant widget has focus,
  2896. // or if a non-focusable node of this widget or a descendant was recently clicked.
  2897. //
  2898. // Call focus.watch("curNode", callback) to track the current focused DOMNode,
  2899. // or focus.watch("activeStack", callback) to track the currently focused stack of widgets.
  2900. //
  2901. // Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when
  2902. // when widgets become active/inactive
  2903. //
  2904. // Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist.
  2905. // curNode: DomNode
  2906. // Currently focused item on screen
  2907. curNode: null,
  2908. // activeStack: dijit/_WidgetBase[]
  2909. // List of currently active widgets (focused widget and it's ancestors)
  2910. activeStack: [],
  2911. constructor: function(){
  2912. // Don't leave curNode/prevNode pointing to bogus elements
  2913. var check = lang.hitch(this, function(node){
  2914. if(dom.isDescendant(this.curNode, node)){
  2915. this.set("curNode", null);
  2916. }
  2917. if(dom.isDescendant(this.prevNode, node)){
  2918. this.set("prevNode", null);
  2919. }
  2920. });
  2921. aspect.before(domConstruct, "empty", check);
  2922. aspect.before(domConstruct, "destroy", check);
  2923. },
  2924. registerIframe: function(/*DomNode*/ iframe){
  2925. // summary:
  2926. // Registers listeners on the specified iframe so that any click
  2927. // or focus event on that iframe (or anything in it) is reported
  2928. // as a focus/click event on the `<iframe>` itself.
  2929. // description:
  2930. // Currently only used by editor.
  2931. // returns:
  2932. // Handle with remove() method to deregister.
  2933. return this.registerWin(iframe.contentWindow, iframe);
  2934. },
  2935. registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
  2936. // summary:
  2937. // Registers listeners on the specified window (either the main
  2938. // window or an iframe's window) to detect when the user has clicked somewhere
  2939. // or focused somewhere.
  2940. // description:
  2941. // Users should call registerIframe() instead of this method.
  2942. // targetWindow:
  2943. // If specified this is the window associated with the iframe,
  2944. // i.e. iframe.contentWindow.
  2945. // effectiveNode:
  2946. // If specified, report any focus events inside targetWindow as
  2947. // an event on effectiveNode, rather than on evt.target.
  2948. // returns:
  2949. // Handle with remove() method to deregister.
  2950. // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
  2951. // Listen for blur and focus events on targetWindow's document.
  2952. var _this = this,
  2953. body = targetWindow.document && targetWindow.document.body;
  2954. if(body){
  2955. var mdh = on(body, 'mousedown', function(evt){
  2956. _this._justMouseDowned = true;
  2957. // Use a 13 ms timeout to work-around Chrome resolving too fast and focusout
  2958. // events not seeing that a mousedown just happened when a popup closes.
  2959. // See https://bugs.dojotoolkit.org/ticket/17668
  2960. setTimeout(function(){ _this._justMouseDowned = false; }, 13);
  2961. // workaround weird IE bug where the click is on an orphaned node
  2962. // (first time clicking a Select/DropDownButton inside a TooltipDialog).
  2963. // actually, strangely this is happening on latest chrome too.
  2964. if(evt && evt.target && evt.target.parentNode == null){
  2965. return;
  2966. }
  2967. _this._onTouchNode(effectiveNode || evt.target, "mouse");
  2968. });
  2969. var fih = on(body, 'focusin', function(evt){
  2970. // When you refocus the browser window, IE gives an event with an empty srcElement
  2971. if(!evt.target.tagName) { return; }
  2972. // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
  2973. // ignore those events
  2974. var tag = evt.target.tagName.toLowerCase();
  2975. if(tag == "#document" || tag == "body"){ return; }
  2976. if(a11y.isTabNavigable(evt.target)){
  2977. // If condition doesn't seem quite right, but it is correctly preventing focus events for
  2978. // clicks on disabled buttons.
  2979. _this._onFocusNode(effectiveNode || evt.target);
  2980. }else{
  2981. // Previous code called _onTouchNode() for any activate event on a non-focusable node. Can
  2982. // probably just ignore such an event as it will be handled by onmousedown handler above, but
  2983. // leaving the code for now.
  2984. _this._onTouchNode(effectiveNode || evt.target);
  2985. }
  2986. });
  2987. var foh = on(body, 'focusout', function(evt){
  2988. _this._onBlurNode(effectiveNode || evt.target);
  2989. });
  2990. return {
  2991. remove: function(){
  2992. mdh.remove();
  2993. fih.remove();
  2994. foh.remove();
  2995. mdh = fih = foh = null;
  2996. body = null; // prevent memory leak (apparent circular reference via closure)
  2997. }
  2998. };
  2999. }
  3000. },
  3001. _onBlurNode: function(/*DomNode*/ node){
  3002. // summary:
  3003. // Called when focus leaves a node.
  3004. // Usually ignored, _unless_ it *isn't* followed by touching another node,
  3005. // which indicates that we tabbed off the last field on the page,
  3006. // in which case every widget is marked inactive
  3007. // If the blur event isn't followed by a focus event, it means the user clicked on something unfocusable,
  3008. // so clear focus.
  3009. if(this._clearFocusTimer){
  3010. clearTimeout(this._clearFocusTimer);
  3011. }
  3012. this._clearFocusTimer = setTimeout(lang.hitch(this, function(){
  3013. this.set("prevNode", this.curNode);
  3014. this.set("curNode", null);
  3015. }), 0);
  3016. if(this._justMouseDowned){
  3017. // the mouse down caused a new widget to be marked as active; this blur event
  3018. // is coming late, so ignore it.
  3019. return;
  3020. }
  3021. // If the blur event isn't followed by a focus or touch event then mark all widgets as inactive.
  3022. if(this._clearActiveWidgetsTimer){
  3023. clearTimeout(this._clearActiveWidgetsTimer);
  3024. }
  3025. this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){
  3026. delete this._clearActiveWidgetsTimer;
  3027. this._setStack([]);
  3028. }), 100);
  3029. },
  3030. _onTouchNode: function(/*DomNode*/ node, /*String*/ by){
  3031. // summary:
  3032. // Callback when node is focused or mouse-downed
  3033. // node:
  3034. // The node that was touched.
  3035. // by:
  3036. // "mouse" if the focus/touch was caused by a mouse down event
  3037. // ignore the recent blurNode event
  3038. if(this._clearActiveWidgetsTimer){
  3039. clearTimeout(this._clearActiveWidgetsTimer);
  3040. delete this._clearActiveWidgetsTimer;
  3041. }
  3042. // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
  3043. var newStack=[];
  3044. try{
  3045. while(node){
  3046. var popupParent = domAttr.get(node, "dijitPopupParent");
  3047. if(popupParent){
  3048. node=registry.byId(popupParent).domNode;
  3049. }else if(node.tagName && node.tagName.toLowerCase() == "body"){
  3050. // is this the root of the document or just the root of an iframe?
  3051. if(node === win.body()){
  3052. // node is the root of the main document
  3053. break;
  3054. }
  3055. // otherwise, find the iframe this node refers to (can't access it via parentNode,
  3056. // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
  3057. node=winUtils.get(node.ownerDocument).frameElement;
  3058. }else{
  3059. // if this node is the root node of a widget, then add widget id to stack,
  3060. // except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
  3061. // to support MenuItem)
  3062. var id = node.getAttribute && node.getAttribute("widgetId"),
  3063. widget = id && registry.byId(id);
  3064. if(widget && !(by == "mouse" && widget.get("disabled"))){
  3065. newStack.unshift(id);
  3066. }
  3067. node=node.parentNode;
  3068. }
  3069. }
  3070. }catch(e){ /* squelch */ }
  3071. this._setStack(newStack, by);
  3072. },
  3073. _onFocusNode: function(/*DomNode*/ node){
  3074. // summary:
  3075. // Callback when node is focused
  3076. if(!node){
  3077. return;
  3078. }
  3079. if(node.nodeType == 9){
  3080. // Ignore focus events on the document itself. This is here so that
  3081. // (for example) clicking the up/down arrows of a spinner
  3082. // (which don't get focus) won't cause that widget to blur. (FF issue)
  3083. return;
  3084. }
  3085. // There was probably a blur event right before this event, but since we have a new focus, don't
  3086. // do anything with the blur
  3087. if(this._clearFocusTimer){
  3088. clearTimeout(this._clearFocusTimer);
  3089. delete this._clearFocusTimer;
  3090. }
  3091. this._onTouchNode(node);
  3092. if(node == this.curNode){ return; }
  3093. this.set("prevNode", this.curNode);
  3094. this.set("curNode", node);
  3095. },
  3096. _setStack: function(/*String[]*/ newStack, /*String*/ by){
  3097. // summary:
  3098. // The stack of active widgets has changed. Send out appropriate events and records new stack.
  3099. // newStack:
  3100. // array of widget id's, starting from the top (outermost) widget
  3101. // by:
  3102. // "mouse" if the focus/touch was caused by a mouse down event
  3103. var oldStack = this.activeStack, lastOldIdx = oldStack.length - 1, lastNewIdx = newStack.length - 1;
  3104. if(newStack[lastNewIdx] == oldStack[lastOldIdx]){
  3105. // no changes, return now to avoid spurious notifications about changes to activeStack
  3106. return;
  3107. }
  3108. this.set("activeStack", newStack);
  3109. var widget, i;
  3110. // for all elements that have gone out of focus, set focused=false
  3111. for(i = lastOldIdx; i >= 0 && oldStack[i] != newStack[i]; i--){
  3112. widget = registry.byId(oldStack[i]);
  3113. if(widget){
  3114. widget._hasBeenBlurred = true; // TODO: used by form widgets, should be moved there
  3115. widget.set("focused", false);
  3116. if(widget._focusManager == this){
  3117. widget._onBlur(by);
  3118. }
  3119. this.emit("widget-blur", widget, by);
  3120. }
  3121. }
  3122. // for all element that have come into focus, set focused=true
  3123. for(i++; i <= lastNewIdx; i++){
  3124. widget = registry.byId(newStack[i]);
  3125. if(widget){
  3126. widget.set("focused", true);
  3127. if(widget._focusManager == this){
  3128. widget._onFocus(by);
  3129. }
  3130. this.emit("widget-focus", widget, by);
  3131. }
  3132. }
  3133. },
  3134. focus: function(node){
  3135. // summary:
  3136. // Focus the specified node, suppressing errors if they occur
  3137. if(node){
  3138. try{ node.focus(); }catch(e){/*quiet*/}
  3139. }
  3140. }
  3141. });
  3142. var singleton = new FocusManager();
  3143. // register top window and all the iframes it contains
  3144. domReady(function(){
  3145. var handle = singleton.registerWin(winUtils.get(document));
  3146. if(has("ie")){
  3147. on(window, "unload", function(){
  3148. if(handle){ // because this gets called twice when doh.robot is running
  3149. handle.remove();
  3150. handle = null;
  3151. }
  3152. });
  3153. }
  3154. });
  3155. // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility)
  3156. // as a function to set focus. Remove for 2.0.
  3157. dijit.focus = function(node){
  3158. singleton.focus(node); // indirection here allows dijit/_base/focus.js to override behavior
  3159. };
  3160. for(var attr in singleton){
  3161. if(!/^_/.test(attr)){
  3162. dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr];
  3163. }
  3164. }
  3165. singleton.watch(function(attr, oldVal, newVal){
  3166. dijit.focus[attr] = newVal;
  3167. });
  3168. return singleton;
  3169. });
  3170. },
  3171. 'dojo/i18n':function(){
  3172. define("dojo/i18n", ["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json"],
  3173. function(dojo, require, has, array, config, lang, xhr, json) {
  3174. // module:
  3175. // dojo/i18n
  3176. // summary:
  3177. // This module implements the !dojo/i18n plugin and the v1.6- i18n API
  3178. // description:
  3179. // We choose to include our own plugin to leverage functionality already contained in dojo
  3180. // and thereby reduce the size of the plugin compared to various loader implementations. Also, this
  3181. // allows foreign AMD loaders to be used without their plugins.
  3182. has.add("dojo-preload-i18n-Api",
  3183. // if true, define the preload localizations machinery
  3184. 1
  3185. );
  3186. true || has.add("dojo-v1x-i18n-Api",
  3187. // if true, define the v1.x i18n functions
  3188. 1
  3189. );
  3190. var
  3191. thisModule= dojo.i18n=
  3192. // the dojo.i18n module
  3193. {},
  3194. nlsRe=
  3195. // regexp for reconstructing the master bundle name from parts of the regexp match
  3196. // nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives:
  3197. // ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
  3198. // nlsRe.exec("foo/bar/baz/nls/foo") gives:
  3199. // ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
  3200. // so, if match[5] is blank, it means this is the top bundle definition.
  3201. // courtesy of http://requirejs.org
  3202. /(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,
  3203. getAvailableLocales= function(
  3204. root,
  3205. locale,
  3206. bundlePath,
  3207. bundleName
  3208. ){
  3209. // return a vector of module ids containing all available locales with respect to the target locale
  3210. // For example, assuming:
  3211. // * the root bundle indicates specific bundles for "fr" and "fr-ca",
  3212. // * bundlePath is "myPackage/nls"
  3213. // * bundleName is "myBundle"
  3214. // Then a locale argument of "fr-ca" would return
  3215. // ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"]
  3216. // Notice that bundles are returned least-specific to most-specific, starting with the root.
  3217. //
  3218. // If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales;
  3219. // therefore, assume everything is available and get 404 errors that indicate a particular localization is not available
  3220. //
  3221. for(var result= [bundlePath + bundleName], localeParts= locale.split("-"), current= "", i= 0; i<localeParts.length; i++){
  3222. current+= (current ? "-" : "") + localeParts[i];
  3223. if(!root || root[current]){
  3224. result.push(bundlePath + current + "/" + bundleName);
  3225. }
  3226. }
  3227. return result;
  3228. },
  3229. cache= {},
  3230. getL10nName= dojo.getL10nName = function(moduleName, bundleName, locale){
  3231. locale = locale ? locale.toLowerCase() : dojo.locale;
  3232. moduleName = "dojo/i18n!" + moduleName.replace(/\./g, "/");
  3233. bundleName = bundleName.replace(/\./g, "/");
  3234. return (/root/i.test(locale)) ?
  3235. (moduleName + "/nls/" + bundleName) :
  3236. (moduleName + "/nls/" + locale + "/" + bundleName);
  3237. },
  3238. doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){
  3239. // get the root bundle which instructs which other bundles are required to construct the localized bundle
  3240. require([bundlePathAndName], function(root){
  3241. var current = lang.clone(root.root || root.ROOT),// 1.6 built bundle defined ROOT
  3242. availableLocales= getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName);
  3243. require(availableLocales, function(){
  3244. for (var i= 1; i<availableLocales.length; i++){
  3245. current= lang.mixin(lang.clone(current), arguments[i]);
  3246. }
  3247. // target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested)
  3248. var target= bundlePathAndName + "/" + locale;
  3249. cache[target]= current;
  3250. load();
  3251. });
  3252. });
  3253. },
  3254. normalize = function(id, toAbsMid){
  3255. // id may be relative
  3256. // preload has form *preload*<path>/nls/<module>*<flattened locales> and
  3257. // therefore never looks like a relative
  3258. return /^\./.test(id) ? toAbsMid(id) : id;
  3259. },
  3260. getLocalesToLoad = function(targetLocale){
  3261. var list = config.extraLocale || [];
  3262. list = lang.isArray(list) ? list : [list];
  3263. list.push(targetLocale);
  3264. return list;
  3265. },
  3266. load = function(id, require, load){
  3267. //
  3268. // id is in one of the following formats
  3269. //
  3270. // 1. <path>/nls/<bundle>
  3271. // => load the bundle, localized to config.locale; load all bundles localized to
  3272. // config.extraLocale (if any); return the loaded bundle localized to config.locale.
  3273. //
  3274. // 2. <path>/nls/<locale>/<bundle>
  3275. // => load then return the bundle localized to <locale>
  3276. //
  3277. // 3. *preload*<path>/nls/<module>*<JSON array of available locales>
  3278. // => for config.locale and all config.extraLocale, load all bundles found
  3279. // in the best-matching bundle rollup. A value of 1 is returned, which
  3280. // is meaningless other than to say the plugin is executing the requested
  3281. // preloads
  3282. //
  3283. // In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see
  3284. // normalize. In case 3, it <path> is assumed to be absolue; this is arranged by the builder.
  3285. //
  3286. // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle
  3287. // value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key
  3288. //
  3289. // <path>/nls/<bundle>/<locale>
  3290. //
  3291. // will hold the value. Similarly, then plugin will publish this value to the loader by
  3292. //
  3293. // define("<path>/nls/<bundle>/<locale>", <bundle-value>);
  3294. //
  3295. // Given this algorithm, other machinery can provide fast load paths be preplacing
  3296. // values in the plugin's cache, which is public. When a load is demanded the
  3297. // cache is inspected before starting any loading. Explicitly placing values in the plugin
  3298. // cache is an advanced/experimental feature that should not be needed; use at your own risk.
  3299. //
  3300. // For the normal AMD algorithm, the root bundle is loaded first, which instructs the
  3301. // plugin what additional localized bundles are required for a particular locale. These
  3302. // additional locales are loaded and a mix of the root and each progressively-specific
  3303. // locale is returned. For example:
  3304. //
  3305. // 1. The client demands "dojo/i18n!some/path/nls/someBundle
  3306. //
  3307. // 2. The loader demands load(some/path/nls/someBundle)
  3308. //
  3309. // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
  3310. //
  3311. // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations
  3312. // are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin
  3313. // requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle"
  3314. //
  3315. // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle
  3316. // ab-cd-ef as...
  3317. //
  3318. // mixin(mixin(mixin({}, require("some/path/nls/someBundle"),
  3319. // require("some/path/nls/ab/someBundle")),
  3320. // require("some/path/nls/ab-cd-ef/someBundle"));
  3321. //
  3322. // This value is inserted into the cache and published to the loader at the
  3323. // key/module-id some/path/nls/someBundle/ab-cd-ef.
  3324. //
  3325. // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests
  3326. // (further preload requests will be serviced) until all ongoing preloading has completed.
  3327. //
  3328. // The preload signature instructs the plugin that a special rollup module is available that contains
  3329. // one or more flattened, localized bundles. The JSON array of available locales indicates which locales
  3330. // are available. Here is an example:
  3331. //
  3332. // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
  3333. //
  3334. // This indicates the following rollup modules are available:
  3335. //
  3336. // some/path/nls/someModule_ROOT
  3337. // some/path/nls/someModule_ab
  3338. // some/path/nls/someModule_ab-cd-ef
  3339. //
  3340. // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash.
  3341. // For example, assume someModule contained the bundles some/bundle/path/someBundle and
  3342. // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as folllows:
  3343. //
  3344. // define({
  3345. // some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>,
  3346. // some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>,
  3347. // });
  3348. //
  3349. // E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
  3350. //
  3351. // require(["some/path/nls/someModule_ab"], function(rollup){
  3352. // for(var p in rollup){
  3353. // var id = p + "/ab",
  3354. // cache[id] = rollup[p];
  3355. // define(id, rollup[p]);
  3356. // }
  3357. // });
  3358. //
  3359. // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
  3360. // load accordingly.
  3361. //
  3362. // The builder will write such rollups for every layer if a non-empty localeList profile property is
  3363. // provided. Further, the builder will include the following cache entry in the cache associated with
  3364. // any layer.
  3365. //
  3366. // "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);}
  3367. //
  3368. // The *now special cache module instructs the loader to apply the provided function to context-require
  3369. // with respect to the particular layer being defined. This causes the plugin to hold all normal service
  3370. // requests until all preloading is complete.
  3371. //
  3372. // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case
  3373. // where the target locale has a single segment and a layer depends on a single bundle:
  3374. //
  3375. // Without Preloads:
  3376. //
  3377. // 1. Layer loads root bundle.
  3378. // 2. bundle is demanded; plugin loads single localized bundle.
  3379. //
  3380. // With Preloads:
  3381. //
  3382. // 1. Layer causes preloading of target bundle.
  3383. // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
  3384. //
  3385. // In each case a single transaction is required to load the target bundle. In cases where multiple bundles
  3386. // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas
  3387. // the normal path requires an additional transaction for each additional bundle/locale-segment. However all
  3388. // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading
  3389. // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false.
  3390. //
  3391. if(has("dojo-preload-i18n-Api")){
  3392. var split = id.split("*"),
  3393. preloadDemand = split[1]=="preload";
  3394. if(preloadDemand){
  3395. if(!cache[id]){
  3396. // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but
  3397. // who knows what over-aggressive human optimizers may attempt
  3398. cache[id] = 1;
  3399. preloadL10n(split[2], json.parse(split[3]), 1);
  3400. }
  3401. // don't stall the loader!
  3402. load(1);
  3403. }
  3404. if(preloadDemand || waitForPreloads(id, require, load)){
  3405. return;
  3406. }
  3407. }
  3408. var match= nlsRe.exec(id),
  3409. bundlePath= match[1] + "/",
  3410. bundleName= match[5] || match[4],
  3411. bundlePathAndName= bundlePath + bundleName,
  3412. localeSpecified = (match[5] && match[4]),
  3413. targetLocale= localeSpecified || dojo.locale,
  3414. loadTarget= bundlePathAndName + "/" + targetLocale,
  3415. loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale),
  3416. remaining = loadList.length,
  3417. finish = function(){
  3418. if(!--remaining){
  3419. load(lang.delegate(cache[loadTarget]));
  3420. }
  3421. };
  3422. array.forEach(loadList, function(locale){
  3423. var target = bundlePathAndName + "/" + locale;
  3424. if(has("dojo-preload-i18n-Api")){
  3425. checkForLegacyModules(target);
  3426. }
  3427. if(!cache[target]){
  3428. doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish);
  3429. }else{
  3430. finish();
  3431. }
  3432. });
  3433. };
  3434. if(has("dojo-unit-tests")){
  3435. var unitTests = thisModule.unitTests = [];
  3436. }
  3437. if(has("dojo-preload-i18n-Api") || 1){
  3438. var normalizeLocale = thisModule.normalizeLocale= function(locale){
  3439. var result = locale ? locale.toLowerCase() : dojo.locale;
  3440. return result == "root" ? "ROOT" : result;
  3441. },
  3442. isXd = function(mid){
  3443. return (1 && 1) ?
  3444. require.isXdUrl(require.toUrl(mid + ".js")) :
  3445. true;
  3446. },
  3447. preloading = 0,
  3448. preloadWaitQueue = [],
  3449. preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean*/ guaranteedAmdFormat){
  3450. // summary:
  3451. // Load available flattened resource bundles associated with a particular module for dojo.locale and all dojo.config.extraLocale (if any)
  3452. //
  3453. // descirption:
  3454. // Only called by built layer files. The entire locale hierarchy is loaded. For example,
  3455. // if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6-
  3456. // in that the v1.6- would lonly load ab-cd...which was *always* flattened.
  3457. //
  3458. // If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm
  3459. // and the extra possible extra transaction.
  3460. //
  3461. function forEachLocale(locale, func){
  3462. // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy
  3463. var parts = locale.split("-");
  3464. while(parts.length){
  3465. if(func(parts.join("-"))){
  3466. return true;
  3467. }
  3468. parts.pop();
  3469. }
  3470. return func("ROOT");
  3471. }
  3472. function preload(locale){
  3473. locale = normalizeLocale(locale);
  3474. forEachLocale(locale, function(loc){
  3475. if(array.indexOf(localesGenerated, loc)>=0){
  3476. var mid = bundlePrefix.replace(/\./g, "/")+"_"+loc;
  3477. preloading++;
  3478. (isXd(mid) || guaranteedAmdFormat ? require : syncRequire)([mid], function(rollup){
  3479. for(var p in rollup){
  3480. cache[p + "/" + loc] = rollup[p];
  3481. }
  3482. --preloading;
  3483. while(!preloading && preloadWaitQueue.length){
  3484. load.apply(null, preloadWaitQueue.shift());
  3485. }
  3486. });
  3487. return true;
  3488. }
  3489. return false;
  3490. });
  3491. }
  3492. preload();
  3493. array.forEach(dojo.config.extraLocale, preload);
  3494. },
  3495. waitForPreloads = function(id, require, load){
  3496. if(preloading){
  3497. preloadWaitQueue.push([id, require, load]);
  3498. }
  3499. return preloading;
  3500. };
  3501. }
  3502. if(1){
  3503. // this code path assumes the dojo loader and won't work with a standard AMD loader
  3504. var evalBundle=
  3505. // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
  3506. new Function(
  3507. "__bundle", // the bundle to evalutate
  3508. "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space
  3509. "__mid", // the mid that __bundle is intended to define
  3510. // returns one of:
  3511. // 1 => the bundle was an AMD bundle
  3512. // a legacy bundle object that is the value of __mid
  3513. // instance of Error => could not figure out how to evaluate bundle
  3514. // used to detect when __bundle calls define
  3515. "var define = function(){define.called = 1;},"
  3516. + " require = function(){define.called = 1;};"
  3517. + "try{"
  3518. + "define.called = 0;"
  3519. + "eval(__bundle);"
  3520. + "if(define.called==1)"
  3521. // bundle called define; therefore signal it's an AMD bundle
  3522. + "return 1;"
  3523. + "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"
  3524. // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space
  3525. + "return __checkForLegacyModules;"
  3526. + "}catch(e){}"
  3527. // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
  3528. // either way, re-eval *after* surrounding with parentheses
  3529. + "try{"
  3530. + "return eval('('+__bundle+')');"
  3531. + "}catch(e){"
  3532. + "return e;"
  3533. + "}"
  3534. ),
  3535. syncRequire= function(deps, callback){
  3536. var results= [];
  3537. array.forEach(deps, function(mid){
  3538. var url= require.toUrl(mid + ".js");
  3539. function load(text){
  3540. var result = evalBundle(text, checkForLegacyModules, mid);
  3541. if(result===1){
  3542. // the bundle was an AMD module; re-inject it through the normal AMD path
  3543. // we gotta do this since it could be an anonymous module and simply evaluating
  3544. // the text here won't provide the loader with the context to know what
  3545. // module is being defined()'d. With browser caching, this should be free; further
  3546. // this entire code path can be circumvented by using the AMD format to begin with
  3547. require([mid], function(bundle){
  3548. results.push(cache[url]= bundle);
  3549. });
  3550. }else{
  3551. if(result instanceof Error){
  3552. console.error("failed to evaluate i18n bundle; url=" + url, result);
  3553. result = {};
  3554. }
  3555. // nls/<locale>/<bundle-name> indicates not the root.
  3556. results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1}));
  3557. }
  3558. }
  3559. if(cache[url]){
  3560. results.push(cache[url]);
  3561. }else{
  3562. var bundle = require.syncLoadNls(mid);
  3563. // need to check for legacy module here because there might be a legacy module for a
  3564. // less specific locale (which was not looked up during the first checkForLegacyModules
  3565. // call in load()).
  3566. // Also need to reverse the locale and the module name in the mid because syncRequire
  3567. // deps parameters uses the AMD style package/nls/locale/module while legacy code uses
  3568. // package/nls/module/locale.
  3569. if(!bundle){
  3570. bundle = checkForLegacyModules(mid.replace(/nls\/([^\/]*)\/([^\/]*)$/, "nls/$2/$1"));
  3571. }
  3572. if(bundle){
  3573. results.push(bundle);
  3574. }else{
  3575. if(!xhr){
  3576. try{
  3577. require.getText(url, true, load);
  3578. }catch(e){
  3579. results.push(cache[url]= {});
  3580. }
  3581. }else{
  3582. xhr.get({
  3583. url:url,
  3584. sync:true,
  3585. load:load,
  3586. error:function(){
  3587. results.push(cache[url]= {});
  3588. }
  3589. });
  3590. }
  3591. }
  3592. }
  3593. });
  3594. callback && callback.apply(null, results);
  3595. },
  3596. checkForLegacyModules = function(target){
  3597. // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache
  3598. for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){}
  3599. if(object){
  3600. result = object[names[i]];
  3601. if(!result){
  3602. // fallback for incorrect bundle build of 1.6
  3603. result = object[names[i].replace(/-/g,"_")];
  3604. }
  3605. if(result){
  3606. cache[target] = result;
  3607. }
  3608. }
  3609. return result;
  3610. };
  3611. thisModule.getLocalization= function(moduleName, bundleName, locale){
  3612. var result,
  3613. l10nName= getL10nName(moduleName, bundleName, locale).substring(10);
  3614. load(l10nName, (!isXd(l10nName) ? syncRequire : require), function(result_){ result= result_; });
  3615. return result;
  3616. };
  3617. if(has("dojo-unit-tests")){
  3618. unitTests.push(function(doh){
  3619. doh.register("tests.i18n.unit", function(t){
  3620. var check;
  3621. check = evalBundle("{prop:1}");
  3622. t.is({prop:1}, check); t.is(undefined, check[1]);
  3623. check = evalBundle("({prop:1})");
  3624. t.is({prop:1}, check); t.is(undefined, check[1]);
  3625. check = evalBundle("{'prop-x':1}");
  3626. t.is({'prop-x':1}, check); t.is(undefined, check[1]);
  3627. check = evalBundle("({'prop-x':1})");
  3628. t.is({'prop-x':1}, check); t.is(undefined, check[1]);
  3629. check = evalBundle("define({'prop-x':1})");
  3630. t.is(1, check);
  3631. check = evalBundle("this is total nonsense and should throw an error");
  3632. t.is(check instanceof Error, true);
  3633. });
  3634. });
  3635. }
  3636. }
  3637. return lang.mixin(thisModule, {
  3638. dynamic:true,
  3639. normalize:normalize,
  3640. load:load,
  3641. cache:cache
  3642. });
  3643. });
  3644. },
  3645. 'dijit/hccss':function(){
  3646. define("dijit/hccss", [
  3647. "require", // require.toUrl
  3648. "dojo/_base/config", // config.blankGif
  3649. "dojo/dom-class", // domClass.add domConstruct.create domStyle.getComputedStyle
  3650. "dojo/dom-construct", // domClass.add domConstruct.create domStyle.getComputedStyle
  3651. "dojo/dom-style", // domClass.add domConstruct.create domStyle.getComputedStyle
  3652. "dojo/ready", // ready
  3653. "dojo/_base/sniff", // has("ie") has("mozilla")
  3654. "dojo/_base/window" // win.body
  3655. ], function(require, config, domClass, domConstruct, domStyle, ready, has, win){
  3656. // module:
  3657. // dijit/hccss
  3658. // summary:
  3659. // Test if computer is in high contrast mode, and sets dijit_a11y flag on <body> if it is.
  3660. if(has("ie") || has("mozilla")){ // NOTE: checking in Safari messes things up
  3661. // priority is 90 to run ahead of parser priority of 100
  3662. ready(90, function(){
  3663. // summary:
  3664. // Detects if we are in high-contrast mode or not
  3665. // create div for testing if high contrast mode is on or images are turned off
  3666. var div = domConstruct.create("div",{
  3667. id: "a11yTestNode",
  3668. style:{
  3669. cssText:'border: 1px solid;'
  3670. + 'border-color:red green;'
  3671. + 'position: absolute;'
  3672. + 'height: 5px;'
  3673. + 'top: -999px;'
  3674. + 'background-image: url("' + (config.blankGif || require.toUrl("dojo/resources/blank.gif")) + '");'
  3675. }
  3676. }, win.body());
  3677. // test it
  3678. var cs = domStyle.getComputedStyle(div);
  3679. if(cs){
  3680. var bkImg = cs.backgroundImage;
  3681. var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
  3682. if(needsA11y){
  3683. domClass.add(win.body(), "dijit_a11y");
  3684. }
  3685. if(has("ie")){
  3686. div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014
  3687. }else{
  3688. win.body().removeChild(div);
  3689. }
  3690. }
  3691. });
  3692. }
  3693. });
  3694. },
  3695. 'dijit/tree/ForestStoreModel':function(){
  3696. define("dijit/tree/ForestStoreModel", [
  3697. "dojo/_base/array", // array.indexOf array.some
  3698. "dojo/_base/declare", // declare
  3699. "dojo/_base/lang", // lang.hitch
  3700. "dojo/_base/window", // win.global
  3701. "./TreeStoreModel"
  3702. ], function(array, declare, lang, win, TreeStoreModel){
  3703. /*=====
  3704. var TreeStoreModel = dijit.tree.TreeStoreModel;
  3705. =====*/
  3706. // module:
  3707. // dijit/tree/ForestStoreModel
  3708. // summary:
  3709. // Interface between a dijit.Tree and a dojo.data store that doesn't have a root item,
  3710. // a.k.a. a store that has multiple "top level" items.
  3711. return declare("dijit.tree.ForestStoreModel", TreeStoreModel, {
  3712. // summary:
  3713. // Interface between a dijit.Tree and a dojo.data store that doesn't have a root item,
  3714. // a.k.a. a store that has multiple "top level" items.
  3715. //
  3716. // description
  3717. // Use this class to wrap a dojo.data store, making all the items matching the specified query
  3718. // appear as children of a fabricated "root item". If no query is specified then all the
  3719. // items returned by fetch() on the underlying store become children of the root item.
  3720. // This class allows dijit.Tree to assume a single root item, even if the store doesn't have one.
  3721. //
  3722. // When using this class the developer must override a number of methods according to their app and
  3723. // data, including:
  3724. // - onNewRootItem
  3725. // - onAddToRoot
  3726. // - onLeaveRoot
  3727. // - onNewItem
  3728. // - onSetItem
  3729. // Parameters to constructor
  3730. // rootId: String
  3731. // ID of fabricated root item
  3732. rootId: "$root$",
  3733. // rootLabel: String
  3734. // Label of fabricated root item
  3735. rootLabel: "ROOT",
  3736. // query: String
  3737. // Specifies the set of children of the root item.
  3738. // example:
  3739. // | {type:'continent'}
  3740. query: null,
  3741. // End of parameters to constructor
  3742. constructor: function(params){
  3743. // summary:
  3744. // Sets up variables, etc.
  3745. // tags:
  3746. // private
  3747. // Make dummy root item
  3748. this.root = {
  3749. store: this,
  3750. root: true,
  3751. id: params.rootId,
  3752. label: params.rootLabel,
  3753. children: params.rootChildren // optional param
  3754. };
  3755. },
  3756. // =======================================================================
  3757. // Methods for traversing hierarchy
  3758. mayHaveChildren: function(/*dojo.data.Item*/ item){
  3759. // summary:
  3760. // Tells if an item has or may have children. Implementing logic here
  3761. // avoids showing +/- expando icon for nodes that we know don't have children.
  3762. // (For efficiency reasons we may not want to check if an element actually
  3763. // has children until user clicks the expando node)
  3764. // tags:
  3765. // extension
  3766. return item === this.root || this.inherited(arguments);
  3767. },
  3768. getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){
  3769. // summary:
  3770. // Calls onComplete() with array of child items of given parent item, all loaded.
  3771. if(parentItem === this.root){
  3772. if(this.root.children){
  3773. // already loaded, just return
  3774. callback(this.root.children);
  3775. }else{
  3776. this.store.fetch({
  3777. query: this.query,
  3778. onComplete: lang.hitch(this, function(items){
  3779. this.root.children = items;
  3780. callback(items);
  3781. }),
  3782. onError: onError
  3783. });
  3784. }
  3785. }else{
  3786. this.inherited(arguments);
  3787. }
  3788. },
  3789. // =======================================================================
  3790. // Inspecting items
  3791. isItem: function(/* anything */ something){
  3792. return (something === this.root) ? true : this.inherited(arguments);
  3793. },
  3794. fetchItemByIdentity: function(/* object */ keywordArgs){
  3795. if(keywordArgs.identity == this.root.id){
  3796. var scope = keywordArgs.scope?keywordArgs.scope:win.global;
  3797. if(keywordArgs.onItem){
  3798. keywordArgs.onItem.call(scope, this.root);
  3799. }
  3800. }else{
  3801. this.inherited(arguments);
  3802. }
  3803. },
  3804. getIdentity: function(/* item */ item){
  3805. return (item === this.root) ? this.root.id : this.inherited(arguments);
  3806. },
  3807. getLabel: function(/* item */ item){
  3808. return (item === this.root) ? this.root.label : this.inherited(arguments);
  3809. },
  3810. // =======================================================================
  3811. // Write interface
  3812. newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
  3813. // summary:
  3814. // Creates a new item. See dojo.data.api.Write for details on args.
  3815. // Used in drag & drop when item from external source dropped onto tree.
  3816. if(parent === this.root){
  3817. this.onNewRootItem(args);
  3818. return this.store.newItem(args);
  3819. }else{
  3820. return this.inherited(arguments);
  3821. }
  3822. },
  3823. onNewRootItem: function(/* dojo.dnd.Item */ /*===== args =====*/){
  3824. // summary:
  3825. // User can override this method to modify a new element that's being
  3826. // added to the root of the tree, for example to add a flag like root=true
  3827. },
  3828. pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
  3829. // summary:
  3830. // Move or copy an item from one parent item to another.
  3831. // Used in drag & drop
  3832. if(oldParentItem === this.root){
  3833. if(!bCopy){
  3834. // It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
  3835. // this.query... thus triggering an onChildrenChange() event to notify the Tree
  3836. // that this element is no longer a child of the root node
  3837. this.onLeaveRoot(childItem);
  3838. }
  3839. }
  3840. this.inherited(arguments, [childItem,
  3841. oldParentItem === this.root ? null : oldParentItem,
  3842. newParentItem === this.root ? null : newParentItem,
  3843. bCopy,
  3844. insertIndex
  3845. ]);
  3846. if(newParentItem === this.root){
  3847. // It's onAddToRoot()'s responsibility to modify the item so it matches
  3848. // this.query... thus triggering an onChildrenChange() event to notify the Tree
  3849. // that this element is now a child of the root node
  3850. this.onAddToRoot(childItem);
  3851. }
  3852. },
  3853. // =======================================================================
  3854. // Handling for top level children
  3855. onAddToRoot: function(/* item */ item){
  3856. // summary:
  3857. // Called when item added to root of tree; user must override this method
  3858. // to modify the item so that it matches the query for top level items
  3859. // example:
  3860. // | store.setValue(item, "root", true);
  3861. // tags:
  3862. // extension
  3863. console.log(this, ": item ", item, " added to root");
  3864. },
  3865. onLeaveRoot: function(/* item */ item){
  3866. // summary:
  3867. // Called when item removed from root of tree; user must override this method
  3868. // to modify the item so it doesn't match the query for top level items
  3869. // example:
  3870. // | store.unsetAttribute(item, "root");
  3871. // tags:
  3872. // extension
  3873. console.log(this, ": item ", item, " removed from root");
  3874. },
  3875. // =======================================================================
  3876. // Events from data store
  3877. _requeryTop: function(){
  3878. // reruns the query for the children of the root node,
  3879. // sending out an onSet notification if those children have changed
  3880. var oldChildren = this.root.children || [];
  3881. this.store.fetch({
  3882. query: this.query,
  3883. onComplete: lang.hitch(this, function(newChildren){
  3884. this.root.children = newChildren;
  3885. // If the list of children or the order of children has changed...
  3886. if(oldChildren.length != newChildren.length ||
  3887. array.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
  3888. this.onChildrenChange(this.root, newChildren);
  3889. }
  3890. })
  3891. });
  3892. },
  3893. onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
  3894. // summary:
  3895. // Handler for when new items appear in the store. Developers should override this
  3896. // method to be more efficient based on their app/data.
  3897. // description:
  3898. // Note that the default implementation requeries the top level items every time
  3899. // a new item is created, since any new item could be a top level item (even in
  3900. // addition to being a child of another item, since items can have multiple parents).
  3901. //
  3902. // If developers can detect which items are possible top level items (based on the item and the
  3903. // parentInfo parameters), they should override this method to only call _requeryTop() for top
  3904. // level items. Often all top level items have parentInfo==null, but
  3905. // that will depend on which store you use and what your data is like.
  3906. // tags:
  3907. // extension
  3908. this._requeryTop();
  3909. this.inherited(arguments);
  3910. },
  3911. onDeleteItem: function(/*Object*/ item){
  3912. // summary:
  3913. // Handler for delete notifications from underlying store
  3914. // check if this was a child of root, and if so send notification that root's children
  3915. // have changed
  3916. if(array.indexOf(this.root.children, item) != -1){
  3917. this._requeryTop();
  3918. }
  3919. this.inherited(arguments);
  3920. },
  3921. onSetItem: function(/* item */ item,
  3922. /* attribute-name-string */ attribute,
  3923. /* object | array */ oldValue,
  3924. /* object | array */ newValue){
  3925. // summary:
  3926. // Updates the tree view according to changes to an item in the data store.
  3927. // Developers should override this method to be more efficient based on their app/data.
  3928. // description:
  3929. // Handles updates to an item's children by calling onChildrenChange(), and
  3930. // other updates to an item by calling onChange().
  3931. //
  3932. // Also, any change to any item re-executes the query for the tree's top-level items,
  3933. // since this modified item may have started/stopped matching the query for top level items.
  3934. //
  3935. // If possible, developers should override this function to only call _requeryTop() when
  3936. // the change to the item has caused it to stop/start being a top level item in the tree.
  3937. // tags:
  3938. // extension
  3939. this._requeryTop();
  3940. this.inherited(arguments);
  3941. }
  3942. });
  3943. });
  3944. },
  3945. 'dojo/parser':function(){
  3946. define(
  3947. "dojo/parser", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/config", "./_base/html", "./_base/window", "./_base/url",
  3948. "./_base/json", "./aspect", "./date/stamp", "./has", "./query", "./on", "./ready"],
  3949. function(dojo, dlang, darray, config, dhtml, dwindow, _Url, djson, aspect, dates, has, query, don, ready){
  3950. // module:
  3951. // dojo/parser
  3952. // summary:
  3953. // The Dom/Widget parsing package
  3954. new Date("X"); // workaround for #11279, new Date("") == NaN
  3955. if (1) {
  3956. var form = document.createElement("form");
  3957. // Test if DOMNode.attributes only lists the attributes the user specified, not attributes w/default values.
  3958. has.add("dom-attributes-explicit", form.attributes.length == 0);
  3959. // IE8 will erroneously list a few attributes that weren't specified,
  3960. // but we know to skip them because they have a specified flag which is false
  3961. has.add("dom-attributes-specified-flag", form.attributes.length < 40);
  3962. // Otherwise, it's IE6-7 form.attributes will list hundreds of values, need to do outerHTML instead.
  3963. }
  3964. dojo.parser = new function(){
  3965. // summary:
  3966. // The Dom/Widget parsing package
  3967. var _nameMap = {
  3968. // Map from widget name (ex: "dijit.form.Button") to structure mapping
  3969. // lowercase version of attribute names to the version in the widget ex:
  3970. // {
  3971. // label: "label",
  3972. // onclick: "onClick"
  3973. // }
  3974. };
  3975. function getNameMap(proto){
  3976. // summary:
  3977. // Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"}
  3978. var map = {};
  3979. for(var name in proto){
  3980. if(name.charAt(0)=="_"){ continue; } // skip internal properties
  3981. map[name.toLowerCase()] = name;
  3982. }
  3983. return map;
  3984. }
  3985. // Widgets like BorderContainer add properties to _Widget via dojo.extend().
  3986. // If BorderContainer is loaded after _Widget's parameter list has been cached,
  3987. // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
  3988. aspect.after(dlang, "extend", function(){
  3989. _nameMap = {};
  3990. }, true);
  3991. // Map from widget name (ex: "dijit.form.Button") to a map of { "list-of-mixins": ctor }
  3992. // if "list-of-mixins" is "__type" this is the raw type without mixins
  3993. var _ctorMap = {};
  3994. function getCtor(type){
  3995. var map = _ctorMap[type] || (_ctorMap[type] = {});
  3996. return map["__type"] || (map["__type"] = (dlang.getObject(type) || require(type)));
  3997. }
  3998. this._functionFromScript = function(script, attrData){
  3999. // summary:
  4000. // Convert a <script type="dojo/method" args="a, b, c"> ... </script>
  4001. // into a function
  4002. // script: DOMNode
  4003. // The <script> DOMNode
  4004. // attrData: String
  4005. // For HTML5 compliance, searches for attrData + "args" (typically
  4006. // "data-dojo-args") instead of "args"
  4007. var preamble = "";
  4008. var suffix = "";
  4009. var argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args"));
  4010. if(argsStr){
  4011. darray.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
  4012. preamble += "var "+part+" = arguments["+idx+"]; ";
  4013. });
  4014. }
  4015. var withStr = script.getAttribute("with");
  4016. if(withStr && withStr.length){
  4017. darray.forEach(withStr.split(/\s*,\s*/), function(part){
  4018. preamble += "with("+part+"){";
  4019. suffix += "}";
  4020. });
  4021. }
  4022. return new Function(preamble+script.innerHTML+suffix);
  4023. };
  4024. this.instantiate = /*====== dojo.parser.instantiate= ======*/ function(nodes, mixin, options) {
  4025. // summary:
  4026. // Takes array of nodes, and turns them into class instances and
  4027. // potentially calls a startup method to allow them to connect with
  4028. // any children.
  4029. // nodes: Array
  4030. // Array of DOM nodes
  4031. // mixin: Object?
  4032. // An object that will be mixed in with each node in the array.
  4033. // Values in the mixin will override values in the node, if they
  4034. // exist.
  4035. // options: Object?
  4036. // An object used to hold kwArgs for instantiation.
  4037. // See parse.options argument for details.
  4038. mixin = mixin || {};
  4039. options = options || {};
  4040. var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
  4041. attrData = "data-" + (options.scope || dojo._scopeName) + "-",// typically "data-dojo-"
  4042. dataDojoType = attrData + "type"; // typically "data-dojo-type"
  4043. var list = [];
  4044. darray.forEach(nodes, function(node){
  4045. var type = dojoType in mixin ? mixin[dojoType] : node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
  4046. if(type){
  4047. list.push({
  4048. node: node,
  4049. "type": type
  4050. });
  4051. }
  4052. });
  4053. // Instantiate the nodes and return the objects
  4054. return this._instantiate(list, mixin, options);
  4055. };
  4056. this._instantiate = /*====== dojo.parser.instantiate= ======*/ function(nodes, mixin, options){
  4057. // summary:
  4058. // Takes array of objects representing nodes, and turns them into class instances and
  4059. // potentially calls a startup method to allow them to connect with
  4060. // any children.
  4061. // nodes: Array
  4062. // Array of objects like
  4063. // | {
  4064. // | type: "dijit.form.Button",
  4065. // | node: DOMNode,
  4066. // | scripts: [ ... ], // array of <script type="dojo/..."> children of node
  4067. // | inherited: { ... } // settings inherited from ancestors like dir, theme, etc.
  4068. // | }
  4069. // mixin: Object
  4070. // An object that will be mixed in with each node in the array.
  4071. // Values in the mixin will override values in the node, if they
  4072. // exist.
  4073. // options: Object
  4074. // An options object used to hold kwArgs for instantiation.
  4075. // See parse.options argument for details.
  4076. var thelist = [];
  4077. // Precompute names of special attributes we are looking for
  4078. // TODO: for 2.0 default to data-dojo- regardless of scopeName (or maybe scopeName won't exist in 2.0)
  4079. var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
  4080. attrData = "data-" + (options.scope || dojo._scopeName) + "-",// typically "data-dojo-"
  4081. dataDojoType = attrData + "type", // typically "data-dojo-type"
  4082. dataDojoProps = attrData + "props", // typically "data-dojo-props"
  4083. dataDojoAttachPoint = attrData + "attach-point",
  4084. dataDojoAttachEvent = attrData + "attach-event",
  4085. dataDojoId = attrData + "id",
  4086. dataDojoMixins = attrData + "mixins";
  4087. // And make hash to quickly check if a given attribute is special, and to map the name to something friendly
  4088. var specialAttrs = {};
  4089. darray.forEach([dataDojoProps, dataDojoType, dojoType, dataDojoId, "jsId", dataDojoAttachPoint,
  4090. dataDojoAttachEvent, "dojoAttachPoint", "dojoAttachEvent", "class", "style", dataDojoMixins], function(name){
  4091. specialAttrs[name.toLowerCase()] = name.replace(options.scope, "dojo");
  4092. });
  4093. function extend(type, mixins){
  4094. return type.createSubclass && type.createSubclass(mixins) || type.extend.apply(type, mixins);
  4095. }
  4096. darray.forEach(nodes, function(obj){
  4097. if(!obj){ return; }
  4098. var node = obj.node,
  4099. type = obj.type,
  4100. mixins = node.getAttribute(dataDojoMixins), ctor;
  4101. if(mixins){
  4102. var map = _ctorMap[type];
  4103. // remove whitespaces
  4104. mixins = mixins.replace(/ /g, "");
  4105. ctor = map && map[mixins];
  4106. if(!ctor){
  4107. // first get ctor for raw type (& create _ctorMap[type] if needed (should not be))
  4108. ctor = getCtor(type);
  4109. // then do the mixin
  4110. ctor = _ctorMap[type][mixins] = extend(ctor, darray.map(mixins.split(","), getCtor));
  4111. }
  4112. }else{
  4113. ctor = getCtor(type);
  4114. }
  4115. var proto = ctor && ctor.prototype;
  4116. // Setup hash to hold parameter settings for this widget. Start with the parameter
  4117. // settings inherited from ancestors ("dir" and "lang").
  4118. // Inherited setting may later be overridden by explicit settings on node itself.
  4119. var params = {};
  4120. if(options.defaults){
  4121. // settings for the document itself (or whatever subtree is being parsed)
  4122. dlang.mixin(params, options.defaults);
  4123. }
  4124. if(obj.inherited){
  4125. // settings from dir=rtl or lang=... on a node above this node
  4126. dlang.mixin(params, obj.inherited);
  4127. }
  4128. // Get list of attributes explicitly listed in the markup
  4129. var attributes;
  4130. if(has("dom-attributes-explicit")){
  4131. // Standard path to get list of user specified attributes
  4132. attributes = node.attributes;
  4133. }else if(has("dom-attributes-specified-flag")){
  4134. // Special processing needed for IE8, to skip a few faux values in attributes[]
  4135. attributes = darray.filter(node.attributes, function(a){ return a.specified;});
  4136. }else{
  4137. // Special path for IE6-7, avoid (sometimes >100) bogus entries in node.attributes
  4138. var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false),
  4139. attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*\s*/, "").replace(/\s*>.*$/, "");
  4140. attributes = darray.map(attrs.split(/\s+/), function(name){
  4141. var lcName = name.toLowerCase();
  4142. return {
  4143. name: name,
  4144. // getAttribute() doesn't work for button.value, returns innerHTML of button.
  4145. // but getAttributeNode().value doesn't work for the form.encType or li.value
  4146. value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ?
  4147. node.getAttribute(lcName) : node.getAttributeNode(lcName).value
  4148. };
  4149. });
  4150. }
  4151. // Read in attributes and process them, including data-dojo-props, data-dojo-type,
  4152. // dojoAttachPoint, etc., as well as normal foo=bar attributes.
  4153. var i=0, item;
  4154. while(item = attributes[i++]){
  4155. var name = item.name,
  4156. lcName = name.toLowerCase(),
  4157. value = item.value;
  4158. if(lcName in specialAttrs){
  4159. switch(specialAttrs[lcName]){
  4160. // Data-dojo-props. Save for later to make sure it overrides direct foo=bar settings
  4161. case "data-dojo-props":
  4162. var extra = value;
  4163. break;
  4164. // data-dojo-id or jsId. TODO: drop jsId in 2.0
  4165. case "data-dojo-id":
  4166. case "jsId":
  4167. var jsname = value;
  4168. break;
  4169. // For the benefit of _Templated
  4170. case "data-dojo-attach-point":
  4171. case "dojoAttachPoint":
  4172. params.dojoAttachPoint = value;
  4173. break;
  4174. case "data-dojo-attach-event":
  4175. case "dojoAttachEvent":
  4176. params.dojoAttachEvent = value;
  4177. break;
  4178. // Special parameter handling needed for IE
  4179. case "class":
  4180. params["class"] = node.className;
  4181. break;
  4182. case "style":
  4183. params["style"] = node.style && node.style.cssText;
  4184. break;
  4185. }
  4186. }else{
  4187. // Normal attribute, ex: value="123"
  4188. // Find attribute in widget corresponding to specified name.
  4189. // May involve case conversion, ex: onclick --> onClick
  4190. if(!(name in proto)){
  4191. var map = (_nameMap[type] || (_nameMap[type] = getNameMap(proto)));
  4192. name = map[lcName] || name;
  4193. }
  4194. // Set params[name] to value, doing type conversion
  4195. if(name in proto){
  4196. switch(typeof proto[name]){
  4197. case "string":
  4198. params[name] = value;
  4199. break;
  4200. case "number":
  4201. params[name] = value.length ? Number(value) : NaN;
  4202. break;
  4203. case "boolean":
  4204. // for checked/disabled value might be "" or "checked". interpret as true.
  4205. params[name] = value.toLowerCase() != "false";
  4206. break;
  4207. case "function":
  4208. if(value === "" || value.search(/[^\w\.]+/i) != -1){
  4209. // The user has specified some text for a function like "return x+5"
  4210. params[name] = new Function(value);
  4211. }else{
  4212. // The user has specified the name of a function like "myOnClick"
  4213. // or a single word function "return"
  4214. params[name] = dlang.getObject(value, false) || new Function(value);
  4215. }
  4216. break;
  4217. default:
  4218. var pVal = proto[name];
  4219. params[name] =
  4220. (pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) : // array
  4221. (pVal instanceof Date) ?
  4222. (value == "" ? new Date("") : // the NaN of dates
  4223. value == "now" ? new Date() : // current date
  4224. dates.fromISOString(value)) :
  4225. (pVal instanceof dojo._Url) ? (dojo.baseUrl + value) :
  4226. djson.fromJson(value);
  4227. }
  4228. }else{
  4229. params[name] = value;
  4230. }
  4231. }
  4232. }
  4233. // Mix things found in data-dojo-props into the params, overriding any direct settings
  4234. if(extra){
  4235. try{
  4236. extra = djson.fromJson.call(options.propsThis, "{" + extra + "}");
  4237. dlang.mixin(params, extra);
  4238. }catch(e){
  4239. // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
  4240. throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
  4241. }
  4242. }
  4243. // Any parameters specified in "mixin" override everything else.
  4244. dlang.mixin(params, mixin);
  4245. var scripts = obj.scripts || (ctor && (ctor._noScript || proto._noScript) ? [] :
  4246. query("> script[type^='dojo/']", node));
  4247. // Process <script type="dojo/*"> script tags
  4248. // <script type="dojo/method" event="foo"> tags are added to params, and passed to
  4249. // the widget on instantiation.
  4250. // <script type="dojo/method"> tags (with no event) are executed after instantiation
  4251. // <script type="dojo/connect" data-dojo-event="foo"> tags are dojo.connected after instantiation
  4252. // <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation
  4253. // <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation
  4254. // note: dojo/* script tags cannot exist in self closing widgets, like <input />
  4255. var connects = [], // functions to connect after instantiation
  4256. calls = [], // functions to call after instantiation
  4257. watch = [], //functions to watch after instantiation
  4258. on = []; //functions to on after instantiation
  4259. if(scripts){
  4260. for(i=0; i<scripts.length; i++){
  4261. var script = scripts[i];
  4262. node.removeChild(script);
  4263. // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead
  4264. var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")),
  4265. prop = script.getAttribute(attrData + "prop"),
  4266. scriptType = script.getAttribute("type"),
  4267. nf = this._functionFromScript(script, attrData);
  4268. if(event){
  4269. if(scriptType == "dojo/connect"){
  4270. connects.push({event: event, func: nf});
  4271. }else if(scriptType == "dojo/on"){
  4272. on.push({event: event, func: nf});
  4273. }else{
  4274. params[event] = nf;
  4275. }
  4276. }else if(scriptType == "dojo/watch"){
  4277. watch.push({prop: prop, func: nf});
  4278. }else{
  4279. calls.push(nf);
  4280. }
  4281. }
  4282. }
  4283. // create the instance
  4284. var markupFactory = ctor.markupFactory || proto.markupFactory;
  4285. var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node);
  4286. thelist.push(instance);
  4287. // map it to the JS namespace if that makes sense
  4288. if(jsname){
  4289. dlang.setObject(jsname, instance);
  4290. }
  4291. // process connections and startup functions
  4292. for(i=0; i<connects.length; i++){
  4293. aspect.after(instance, connects[i].event, dojo.hitch(instance, connects[i].func), true);
  4294. }
  4295. for(i=0; i<calls.length; i++){
  4296. calls[i].call(instance);
  4297. }
  4298. for(i=0; i<watch.length; i++){
  4299. instance.watch(watch[i].prop, watch[i].func);
  4300. }
  4301. for(i=0; i<on.length; i++){
  4302. don(instance, on[i].event, on[i].func);
  4303. }
  4304. }, this);
  4305. // Call startup on each top level instance if it makes sense (as for
  4306. // widgets). Parent widgets will recursively call startup on their
  4307. // (non-top level) children
  4308. if(!mixin._started){
  4309. darray.forEach(thelist, function(instance){
  4310. if( !options.noStart && instance &&
  4311. dlang.isFunction(instance.startup) &&
  4312. !instance._started
  4313. ){
  4314. instance.startup();
  4315. }
  4316. });
  4317. }
  4318. return thelist;
  4319. };
  4320. this.scan = /*====== dojo.parser.scan= ======*/ function(root, options){
  4321. // summary:
  4322. // Scan a DOM tree and return an array of objects representing the DOMNodes
  4323. // that need to be turned into widgets.
  4324. // description:
  4325. // Search specified node (or document root node) recursively for class instances
  4326. // and return an array of objects that represent potential widgets to be
  4327. // instantiated. Searches for either data-dojo-type="MID" or dojoType="MID" where
  4328. // "MID" is a module ID like "dijit/form/Button" or a fully qualified Class name
  4329. // like "dijit.form.Button".
  4330. //
  4331. // See parser.parse() for details of markup.
  4332. // root: DomNode?
  4333. // A default starting root node from which to start the parsing. Can be
  4334. // omitted, defaulting to the entire document. If omitted, the `options`
  4335. // object can be passed in this place. If the `options` object has a
  4336. // `rootNode` member, that is used.
  4337. // options: Object
  4338. // a kwArgs options object, see parse() for details
  4339. // Output list
  4340. var list = [];
  4341. var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
  4342. attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-"
  4343. dataDojoType = attrData + "type", // typically "data-dojo-type"
  4344. dataDojoTextDir = attrData + "textdir"; // typically "data-dojo-textdir"
  4345. // Info on DOMNode currently being processed
  4346. var node = root.firstChild;
  4347. // Info on parent of DOMNode currently being processed
  4348. // - inherited: dir, lang, and textDir setting of parent, or inherited by parent
  4349. // - parent: pointer to identical structure for my parent (or null if no parent)
  4350. // - scripts: if specified, collects <script type="dojo/..."> type nodes from children
  4351. var inherited = options.inherited;
  4352. if(!inherited){
  4353. function findAncestorAttr(node, attr){
  4354. return (node.getAttribute && node.getAttribute(attr)) ||
  4355. (node !== dwindow.doc && node !== dwindow.doc.documentElement && node.parentNode ? findAncestorAttr(node.parentNode, attr) : null);
  4356. }
  4357. inherited = {
  4358. dir: findAncestorAttr(root, "dir"),
  4359. lang: findAncestorAttr(root, "lang"),
  4360. textDir: findAncestorAttr(root, dataDojoTextDir)
  4361. };
  4362. for(var key in inherited){
  4363. if(!inherited[key]){ delete inherited[key]; }
  4364. }
  4365. }
  4366. var parent = {
  4367. inherited: inherited
  4368. };
  4369. // For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect)
  4370. var scripts;
  4371. // when true, only look for <script type="dojo/..."> tags, and don't recurse to children
  4372. var scriptsOnly;
  4373. function getEffective(parent){
  4374. // summary:
  4375. // Get effective dir, lang, textDir settings for specified obj
  4376. // (matching "parent" object structure above), and do caching.
  4377. // Take care not to return null entries.
  4378. if(!parent.inherited){
  4379. parent.inherited = {};
  4380. var node = parent.node,
  4381. grandparent = getEffective(parent.parent);
  4382. var inherited = {
  4383. dir: node.getAttribute("dir") || grandparent.dir,
  4384. lang: node.getAttribute("lang") || grandparent.lang,
  4385. textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir
  4386. };
  4387. for(var key in inherited){
  4388. if(inherited[key]){
  4389. parent.inherited[key] = inherited[key];
  4390. }
  4391. }
  4392. }
  4393. return parent.inherited;
  4394. }
  4395. // DFS on DOM tree, collecting nodes with data-dojo-type specified.
  4396. while(true){
  4397. if(!node){
  4398. // Finished this level, continue to parent's next sibling
  4399. if(!parent || !parent.node){
  4400. break;
  4401. }
  4402. node = parent.node.nextSibling;
  4403. scripts = parent.scripts;
  4404. scriptsOnly = false;
  4405. parent = parent.parent;
  4406. continue;
  4407. }
  4408. if(node.nodeType != 1){
  4409. // Text or comment node, skip to next sibling
  4410. node = node.nextSibling;
  4411. continue;
  4412. }
  4413. if(scripts && node.nodeName.toLowerCase() == "script"){
  4414. // Save <script type="dojo/..."> for parent, then continue to next sibling
  4415. type = node.getAttribute("type");
  4416. if(type && /^dojo\/\w/i.test(type)){
  4417. scripts.push(node);
  4418. }
  4419. node = node.nextSibling;
  4420. continue;
  4421. }
  4422. if(scriptsOnly){
  4423. node = node.nextSibling;
  4424. continue;
  4425. }
  4426. // Check for data-dojo-type attribute, fallback to backward compatible dojoType
  4427. var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
  4428. // Short circuit for leaf nodes containing nothing [but text]
  4429. var firstChild = node.firstChild;
  4430. if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){
  4431. node = node.nextSibling;
  4432. continue;
  4433. }
  4434. // Setup data structure to save info on current node for when we return from processing descendant nodes
  4435. var current = {
  4436. node: node,
  4437. scripts: scripts,
  4438. parent: parent
  4439. };
  4440. // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate
  4441. // Note: won't find classes declared via dojo.Declaration, so use try/catch to avoid throw from require()
  4442. // We don't care yet about mixins ctors, we check script stop only on main class
  4443. var ctor;
  4444. try{
  4445. ctor = type && getCtor(type);
  4446. }catch(e){
  4447. }
  4448. var childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children
  4449. if(type){
  4450. list.push({
  4451. "type": type,
  4452. node: node,
  4453. scripts: childScripts,
  4454. inherited: getEffective(current) // dir & lang settings for current node, explicit or inherited
  4455. });
  4456. }
  4457. // Recurse, collecting <script type="dojo/..."> children, and also looking for
  4458. // descendant nodes with dojoType specified (unless the widget has the stopParser flag).
  4459. // When finished with children, go to my next sibling.
  4460. node = firstChild;
  4461. scripts = childScripts;
  4462. scriptsOnly = ctor && ctor.prototype.stopParser && !(options.template);
  4463. parent = current;
  4464. }
  4465. return list;
  4466. };
  4467. this.parse = /*====== dojo.parser.parse= ======*/ function(rootNode, options){
  4468. // summary:
  4469. // Scan the DOM for class instances, and instantiate them.
  4470. //
  4471. // description:
  4472. // Search specified node (or root node) recursively for class instances,
  4473. // and instantiate them. Searches for either data-dojo-type="Class" or
  4474. // dojoType="Class" where "Class" is a a fully qualified class name,
  4475. // like `dijit.form.Button`
  4476. //
  4477. // Using `data-dojo-type`:
  4478. // Attributes using can be mixed into the parameters used to instantiate the
  4479. // Class by using a `data-dojo-props` attribute on the node being converted.
  4480. // `data-dojo-props` should be a string attribute to be converted from JSON.
  4481. //
  4482. // Using `dojoType`:
  4483. // Attributes are read from the original domNode and converted to appropriate
  4484. // types by looking up the Class prototype values. This is the default behavior
  4485. // from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will
  4486. // go away in Dojo 2.0.
  4487. //
  4488. // rootNode: DomNode?
  4489. // A default starting root node from which to start the parsing. Can be
  4490. // omitted, defaulting to the entire document. If omitted, the `options`
  4491. // object can be passed in this place. If the `options` object has a
  4492. // `rootNode` member, that is used.
  4493. //
  4494. // options: Object?
  4495. // A hash of options.
  4496. //
  4497. // * noStart: Boolean?
  4498. // when set will prevent the parser from calling .startup()
  4499. // when locating the nodes.
  4500. // * rootNode: DomNode?
  4501. // identical to the function's `rootNode` argument, though
  4502. // allowed to be passed in via this `options object.
  4503. // * template: Boolean
  4504. // If true, ignores ContentPane's stopParser flag and parses contents inside of
  4505. // a ContentPane inside of a template. This allows dojoAttachPoint on widgets/nodes
  4506. // nested inside the ContentPane to work.
  4507. // * inherited: Object
  4508. // Hash possibly containing dir and lang settings to be applied to
  4509. // parsed widgets, unless there's another setting on a sub-node that overrides
  4510. // * scope: String
  4511. // Root for attribute names to search for. If scopeName is dojo,
  4512. // will search for data-dojo-type (or dojoType). For backwards compatibility
  4513. // reasons defaults to dojo._scopeName (which is "dojo" except when
  4514. // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
  4515. // * propsThis: Object
  4516. // If specified, "this" referenced from data-dojo-props will refer to propsThis.
  4517. // Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin`
  4518. //
  4519. // example:
  4520. // Parse all widgets on a page:
  4521. // | dojo.parser.parse();
  4522. //
  4523. // example:
  4524. // Parse all classes within the node with id="foo"
  4525. // | dojo.parser.parse(dojo.byId('foo'));
  4526. //
  4527. // example:
  4528. // Parse all classes in a page, but do not call .startup() on any
  4529. // child
  4530. // | dojo.parser.parse({ noStart: true })
  4531. //
  4532. // example:
  4533. // Parse all classes in a node, but do not call .startup()
  4534. // | dojo.parser.parse(someNode, { noStart:true });
  4535. // | // or
  4536. // | dojo.parser.parse({ noStart:true, rootNode: someNode });
  4537. // determine the root node and options based on the passed arguments.
  4538. var root;
  4539. if(!options && rootNode && rootNode.rootNode){
  4540. options = rootNode;
  4541. root = options.rootNode;
  4542. }else if(rootNode && dlang.isObject(rootNode) && !("nodeType" in rootNode)){
  4543. options = rootNode;
  4544. }else{
  4545. root = rootNode;
  4546. }
  4547. root = root ? dhtml.byId(root) : dwindow.body();
  4548. options = options || {};
  4549. // List of all nodes on page w/dojoType specified
  4550. var list = this.scan(root, options);
  4551. // go build the object instances
  4552. var mixin = options.template ? {template: true} : {};
  4553. return this._instantiate(list, mixin, options); // Array
  4554. };
  4555. }();
  4556. //Register the parser callback. It should be the first callback
  4557. //after the a11y test.
  4558. if(config.parseOnLoad){
  4559. ready(100, dojo.parser, "parse");
  4560. }
  4561. return dojo.parser;
  4562. });
  4563. },
  4564. 'dojox/html/_base':function(){
  4565. define("dojox/html/_base", [
  4566. "dojo/_base/kernel",
  4567. "dojo/_base/lang",
  4568. "dojo/_base/xhr",
  4569. "dojo/_base/window",
  4570. "dojo/_base/sniff",
  4571. "dojo/_base/url",
  4572. "dojo/dom-construct",
  4573. "dojo/html",
  4574. "dojo/_base/declare"
  4575. ], function (dojo, lang, xhrUtil, windowUtil, has, _Url, domConstruct, htmlUtil) {
  4576. /*
  4577. Status: dont know where this will all live exactly
  4578. Need to pull in the implementation of the various helper methods
  4579. Some can be static method, others maybe methods of the ContentSetter (?)
  4580. Gut the ContentPane, replace its _setContent with our own call to dojox.html.set()
  4581. */
  4582. var html = dojo.getObject("dojox.html", true);
  4583. if(has("ie")){
  4584. var alphaImageLoader = /(AlphaImageLoader\([^)]*?src=(['"]))(?![a-z]+:|\/)([^\r\n;}]+?)(\2[^)]*\)\s*[;}]?)/g;
  4585. }
  4586. // css at-rules must be set before any css declarations according to CSS spec
  4587. // match:
  4588. // @import 'http://dojotoolkit.org/dojo.css';
  4589. // @import 'you/never/thought/' print;
  4590. // @import url("it/would/work") tv, screen;
  4591. // @import url(/did/you/now.css);
  4592. // but not:
  4593. // @namespace dojo "http://dojotoolkit.org/dojo.css"; /* namespace URL should always be a absolute URI */
  4594. // @charset 'utf-8';
  4595. // @media print{ #menuRoot {display:none;} }
  4596. // we adjust all paths that dont start on '/' or contains ':'
  4597. //(?![a-z]+:|\/)
  4598. var cssPaths = /(?:(?:@import\s*(['"])(?![a-z]+:|\/)([^\r\n;{]+?)\1)|url\(\s*(['"]?)(?![a-z]+:|\/)([^\r\n;]+?)\3\s*\))([a-z, \s]*[;}]?)/g;
  4599. var adjustCssPaths = html._adjustCssPaths = function(cssUrl, cssText){
  4600. // summary:
  4601. // adjusts relative paths in cssText to be relative to cssUrl
  4602. // a path is considered relative if it doesn't start with '/' and not contains ':'
  4603. // description:
  4604. // Say we fetch a HTML page from level1/page.html
  4605. // It has some inline CSS:
  4606. // @import "css/page.css" tv, screen;
  4607. // ...
  4608. // background-image: url(images/aplhaimage.png);
  4609. //
  4610. // as we fetched this HTML and therefore this CSS
  4611. // from level1/page.html, these paths needs to be adjusted to:
  4612. // @import 'level1/css/page.css' tv, screen;
  4613. // ...
  4614. // background-image: url(level1/images/alphaimage.png);
  4615. //
  4616. // In IE it will also adjust relative paths in AlphaImageLoader()
  4617. // filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/alphaimage.png');
  4618. // will be adjusted to:
  4619. // filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='level1/images/alphaimage.png');
  4620. //
  4621. // Please note that any relative paths in AlphaImageLoader in external css files wont work, as
  4622. // the paths in AlphaImageLoader is MUST be declared relative to the HTML page,
  4623. // not relative to the CSS file that declares it
  4624. if(!cssText || !cssUrl){ return; }
  4625. // support the ImageAlphaFilter if it exists, most people use it in IE 6 for transparent PNGs
  4626. // We are NOT going to kill it in IE 7 just because the PNGs work there. Somebody might have
  4627. // other uses for it.
  4628. // If user want to disable css filter in IE6 he/she should
  4629. // unset filter in a declaration that just IE 6 doesn't understands
  4630. // like * > .myselector { filter:none; }
  4631. if(alphaImageLoader){
  4632. cssText = cssText.replace(alphaImageLoader, function(ignore, pre, delim, url, post){
  4633. return pre + (new _Url(cssUrl, './'+url).toString()) + post;
  4634. });
  4635. }
  4636. return cssText.replace(cssPaths, function(ignore, delimStr, strUrl, delimUrl, urlUrl, media){
  4637. if(strUrl){
  4638. return '@import "' + (new _Url(cssUrl, './'+strUrl).toString()) + '"' + media;
  4639. }else{
  4640. return 'url(' + (new _Url(cssUrl, './'+urlUrl).toString()) + ')' + media;
  4641. }
  4642. });
  4643. };
  4644. // attributepaths one tag can have multiple paths, example:
  4645. // <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
  4646. // <img style='filter:progid...AlphaImageLoader(src="noticeTheSrcHereRunsThroughHtmlSrc")' src="img">
  4647. var htmlAttrPaths = /(<[a-z][a-z0-9]*\s[^>]*)(?:(href|src)=(['"]?)([^>]*?)\3|style=(['"]?)([^>]*?)\5)([^>]*>)/gi;
  4648. var adjustHtmlPaths = html._adjustHtmlPaths = function(htmlUrl, cont){
  4649. var url = htmlUrl || "./";
  4650. return cont.replace(htmlAttrPaths,
  4651. function(tag, start, name, delim, relUrl, delim2, cssText, end){
  4652. return start + (name ?
  4653. (name + '=' + delim + (new _Url(url, relUrl).toString()) + delim)
  4654. : ('style=' + delim2 + adjustCssPaths(url, cssText) + delim2)
  4655. ) + end;
  4656. }
  4657. );
  4658. };
  4659. var snarfStyles = html._snarfStyles = function (/*String*/cssUrl, /*String*/cont, /*Array*/styles){
  4660. /**************** cut out all <style> and <link rel="stylesheet" href=".."> **************/
  4661. // also return any attributes from this tag (might be a media attribute)
  4662. // if cssUrl is set it will adjust paths accordingly
  4663. styles.attributes = [];
  4664. return cont.replace(/(?:<style([^>]*)>([\s\S]*?)<\/style>|<link\s+(?=[^>]*rel=['"]?stylesheet)([^>]*?href=(['"])([^>]*?)\4[^>\/]*)\/?>)/gi,
  4665. function(ignore, styleAttr, cssText, linkAttr, delim, href){
  4666. // trim attribute
  4667. var i, attr = (styleAttr||linkAttr||"").replace(/^\s*([\s\S]*?)\s*$/i, "$1");
  4668. if(cssText){
  4669. i = styles.push(cssUrl ? adjustCssPaths(cssUrl, cssText) : cssText);
  4670. }else{
  4671. i = styles.push('@import "' + href + '";');
  4672. attr = attr.replace(/\s*(?:rel|href)=(['"])?[^\s]*\1\s*/gi, ""); // remove rel=... and href=...
  4673. }
  4674. if(attr){
  4675. attr = attr.split(/\s+/);// split on both "\n", "\t", " " etc
  4676. var atObj = {}, tmp;
  4677. for(var j = 0, e = attr.length; j < e; j++){
  4678. tmp = attr[j].split('='); // split name='value'
  4679. atObj[tmp[0]] = tmp[1].replace(/^\s*['"]?([\s\S]*?)['"]?\s*$/, "$1"); // trim and remove ''
  4680. }
  4681. styles.attributes[i - 1] = atObj;
  4682. }
  4683. return "";
  4684. }
  4685. );
  4686. };
  4687. var snarfScripts = html._snarfScripts = function(cont, byRef){
  4688. // summary
  4689. // strips out script tags from cont
  4690. // invoke with
  4691. // byRef = {errBack:function(){/*add your download error code here*/, downloadRemote: true(default false)}}
  4692. // byRef will have {code: 'jscode'} when this scope leaves
  4693. byRef.code = "";
  4694. //Update script tags nested in comments so that the script tag collector doesn't pick
  4695. //them up.
  4696. cont = cont.replace(/<[!][-][-](.|\s)*?[-][-]>/g,
  4697. function(comment){
  4698. return comment.replace(/<(\/?)script\b/ig,"&lt;$1Script");
  4699. }
  4700. );
  4701. function download(src){
  4702. if(byRef.downloadRemote){
  4703. // console.debug('downloading',src);
  4704. //Fix up src, in case there were entity character encodings in it.
  4705. //Probably only need to worry about a subset.
  4706. src = src.replace(/&([a-z0-9#]+);/g, function(m, name) {
  4707. switch(name) {
  4708. case "amp" : return "&";
  4709. case "gt" : return ">";
  4710. case "lt" : return "<";
  4711. default:
  4712. return name.charAt(0)=="#" ? String.fromCharCode(name.substring(1)) : "&"+name+";";
  4713. }
  4714. });
  4715. xhrUtil.get({
  4716. url: src,
  4717. sync: true,
  4718. load: function(code){
  4719. byRef.code += code+";";
  4720. },
  4721. error: byRef.errBack
  4722. });
  4723. }
  4724. }
  4725. // match <script>, <script type="text/..., but not <script type="dojo(/method)...
  4726. return cont.replace(/<script\s*(?![^>]*type=['"]?(?:dojo\/|text\/html\b))(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi,
  4727. function(ignore, delim, src, code){
  4728. if(src){
  4729. download(src);
  4730. }else{
  4731. byRef.code += code;
  4732. }
  4733. return "";
  4734. }
  4735. );
  4736. };
  4737. var evalInGlobal = html.evalInGlobal = function(code, appendNode){
  4738. // we do our own eval here as dojo.eval doesn't eval in global crossbrowser
  4739. // This work X browser but but it relies on a DOM
  4740. // plus it doesn't return anything, thats unrelevant here but not for dojo core
  4741. appendNode = appendNode || windowUtil.doc.body;
  4742. var n = appendNode.ownerDocument.createElement('script');
  4743. n.type = "text/javascript";
  4744. appendNode.appendChild(n);
  4745. n.text = code; // DOM 1 says this should work
  4746. };
  4747. html._ContentSetter = dojo.declare(/*===== "dojox.html._ContentSetter", =====*/ htmlUtil._ContentSetter, {
  4748. // adjustPaths: Boolean
  4749. // Adjust relative paths in html string content to point to this page
  4750. // Only useful if you grab content from a another folder than the current one
  4751. adjustPaths: false,
  4752. referencePath: ".",
  4753. renderStyles: false,
  4754. executeScripts: false,
  4755. scriptHasHooks: false,
  4756. scriptHookReplacement: null,
  4757. _renderStyles: function(styles){
  4758. // insert css from content into document head
  4759. this._styleNodes = [];
  4760. var st, att, cssText, doc = this.node.ownerDocument;
  4761. var head = doc.getElementsByTagName('head')[0];
  4762. for(var i = 0, e = styles.length; i < e; i++){
  4763. cssText = styles[i]; att = styles.attributes[i];
  4764. st = doc.createElement('style');
  4765. st.setAttribute("type", "text/css"); // this is required in CSS spec!
  4766. for(var x in att){
  4767. st.setAttribute(x, att[x]);
  4768. }
  4769. this._styleNodes.push(st);
  4770. head.appendChild(st); // must insert into DOM before setting cssText
  4771. if(st.styleSheet){ // IE
  4772. st.styleSheet.cssText = cssText;
  4773. }else{ // w3c
  4774. st.appendChild(doc.createTextNode(cssText));
  4775. }
  4776. }
  4777. },
  4778. empty: function() {
  4779. this.inherited("empty", arguments);
  4780. // empty out the styles array from any previous use
  4781. this._styles = [];
  4782. },
  4783. onBegin: function() {
  4784. // summary
  4785. // Called after instantiation, but before set();
  4786. // It allows modification of any of the object properties - including the node and content
  4787. // provided - before the set operation actually takes place
  4788. // This implementation extends that of dojo.html._ContentSetter
  4789. // to add handling for adjustPaths, renderStyles on the html string content before it is set
  4790. this.inherited("onBegin", arguments);
  4791. var cont = this.content,
  4792. node = this.node;
  4793. var styles = this._styles;// init vars
  4794. if(lang.isString(cont)){
  4795. if(this.adjustPaths && this.referencePath){
  4796. cont = adjustHtmlPaths(this.referencePath, cont);
  4797. }
  4798. if(this.renderStyles || this.cleanContent){
  4799. cont = snarfStyles(this.referencePath, cont, styles);
  4800. }
  4801. // because of a bug in IE, script tags that is first in html hierarchy doesnt make it into the DOM
  4802. // when content is innerHTML'ed, so we can't use dojo.query to retrieve scripts from DOM
  4803. if(this.executeScripts){
  4804. var _t = this;
  4805. var byRef = {
  4806. downloadRemote: true,
  4807. errBack:function(e){
  4808. _t._onError.call(_t, 'Exec', 'Error downloading remote script in "'+_t.id+'"', e);
  4809. }
  4810. };
  4811. cont = snarfScripts(cont, byRef);
  4812. this._code = byRef.code;
  4813. }
  4814. }
  4815. this.content = cont;
  4816. },
  4817. onEnd: function() {
  4818. // summary
  4819. // Called after set(), when the new content has been pushed into the node
  4820. // It provides an opportunity for post-processing before handing back the node to the caller
  4821. // This implementation extends that of dojo.html._ContentSetter
  4822. var code = this._code,
  4823. styles = this._styles;
  4824. // clear old stylenodes from the DOM
  4825. // these were added by the last set call
  4826. // (in other words, if you dont keep and reuse the ContentSetter for a particular node
  4827. // .. you'll have no practical way to do this)
  4828. if(this._styleNodes && this._styleNodes.length){
  4829. while(this._styleNodes.length){
  4830. domConstruct.destroy(this._styleNodes.pop());
  4831. }
  4832. }
  4833. // render new style nodes
  4834. if(this.renderStyles && styles && styles.length){
  4835. this._renderStyles(styles);
  4836. }
  4837. if(this.executeScripts && code){
  4838. if(this.cleanContent){
  4839. // clean JS from html comments and other crap that browser
  4840. // parser takes care of in a normal page load
  4841. code = code.replace(/(<!--|(?:\/\/)?-->|<!\[CDATA\[|\]\]>)/g, '');
  4842. }
  4843. if(this.scriptHasHooks){
  4844. // replace _container_ with this.scriptHookReplace()
  4845. // the scriptHookReplacement can be a string
  4846. // or a function, which when invoked returns the string you want to substitute in
  4847. code = code.replace(/_container_(?!\s*=[^=])/g, this.scriptHookReplacement);
  4848. }
  4849. try{
  4850. evalInGlobal(code, this.node);
  4851. }catch(e){
  4852. this._onError('Exec', 'Error eval script in '+this.id+', '+e.message, e);
  4853. }
  4854. }
  4855. this.inherited("onEnd", arguments);
  4856. },
  4857. tearDown: function() {
  4858. this.inherited(arguments);
  4859. delete this._styles;
  4860. // only tear down -or another set() - will explicitly throw away the
  4861. // references to the style nodes we added
  4862. if(this._styleNodes && this._styleNodes.length){
  4863. while(this._styleNodes.length){
  4864. domConstruct.destroy(this._styleNodes.pop());
  4865. }
  4866. }
  4867. delete this._styleNodes;
  4868. // reset the defaults from the prototype
  4869. // XXX: not sure if this is the correct intended behaviour, it was originally
  4870. // dojo.getObject(this.declaredClass).prototype which will not work with anonymous
  4871. // modules
  4872. dojo.mixin(this, html._ContentSetter.prototype);
  4873. }
  4874. });
  4875. html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
  4876. // TODO: add all the other options
  4877. // summary:
  4878. // inserts (replaces) the given content into the given node
  4879. // node:
  4880. // the parent element that will receive the content
  4881. // cont:
  4882. // the content to be set on the parent element.
  4883. // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
  4884. // params:
  4885. // Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
  4886. // example:
  4887. // A safe string/node/nodelist content replacement/injection with hooks for extension
  4888. // Example Usage:
  4889. // dojo.html.set(node, "some string");
  4890. // dojo.html.set(node, contentNode, {options});
  4891. // dojo.html.set(node, myNode.childNodes, {options});
  4892. if(!params){
  4893. // simple and fast
  4894. return htmlUtil._setNodeContent(node, cont, true);
  4895. }else{
  4896. // more options but slower
  4897. var op = new html._ContentSetter(dojo.mixin(
  4898. params,
  4899. { content: cont, node: node }
  4900. ));
  4901. return op.set();
  4902. }
  4903. };
  4904. return html;
  4905. });
  4906. },
  4907. 'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">&#9660;</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-point=\"valueNode\" role=\"presentation\"\n/></span>\n",
  4908. 'dojo/dnd/Manager':function(){
  4909. define("dojo/dnd/Manager", ["../main", "../Evented", "./common", "./autoscroll", "./Avatar"], function(dojo, Evented) {
  4910. // module:
  4911. // dojo/dnd/Manager
  4912. // summary:
  4913. // TODOC
  4914. var Manager = dojo.declare("dojo.dnd.Manager", [Evented], {
  4915. // summary:
  4916. // the manager of DnD operations (usually a singleton)
  4917. constructor: function(){
  4918. this.avatar = null;
  4919. this.source = null;
  4920. this.nodes = [];
  4921. this.copy = true;
  4922. this.target = null;
  4923. this.canDropFlag = false;
  4924. this.events = [];
  4925. },
  4926. // avatar's offset from the mouse
  4927. OFFSET_X: 16,
  4928. OFFSET_Y: 16,
  4929. // methods
  4930. overSource: function(source){
  4931. // summary:
  4932. // called when a source detected a mouse-over condition
  4933. // source: Object
  4934. // the reporter
  4935. if(this.avatar){
  4936. this.target = (source && source.targetState != "Disabled") ? source : null;
  4937. this.canDropFlag = Boolean(this.target);
  4938. this.avatar.update();
  4939. }
  4940. dojo.publish("/dnd/source/over", [source]);
  4941. },
  4942. outSource: function(source){
  4943. // summary:
  4944. // called when a source detected a mouse-out condition
  4945. // source: Object
  4946. // the reporter
  4947. if(this.avatar){
  4948. if(this.target == source){
  4949. this.target = null;
  4950. this.canDropFlag = false;
  4951. this.avatar.update();
  4952. dojo.publish("/dnd/source/over", [null]);
  4953. }
  4954. }else{
  4955. dojo.publish("/dnd/source/over", [null]);
  4956. }
  4957. },
  4958. startDrag: function(source, nodes, copy){
  4959. // summary:
  4960. // called to initiate the DnD operation
  4961. // source: Object
  4962. // the source which provides items
  4963. // nodes: Array
  4964. // the list of transferred items
  4965. // copy: Boolean
  4966. // copy items, if true, move items otherwise
  4967. this.source = source;
  4968. this.nodes = nodes;
  4969. this.copy = Boolean(copy); // normalizing to true boolean
  4970. this.avatar = this.makeAvatar();
  4971. dojo.body().appendChild(this.avatar.node);
  4972. dojo.publish("/dnd/start", [source, nodes, this.copy]);
  4973. this.events = [
  4974. dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
  4975. dojo.connect(dojo.doc, "onmouseup", this, "onMouseUp"),
  4976. dojo.connect(dojo.doc, "onkeydown", this, "onKeyDown"),
  4977. dojo.connect(dojo.doc, "onkeyup", this, "onKeyUp"),
  4978. // cancel text selection and text dragging
  4979. dojo.connect(dojo.doc, "ondragstart", dojo.stopEvent),
  4980. dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent)
  4981. ];
  4982. var c = "dojoDnd" + (copy ? "Copy" : "Move");
  4983. dojo.addClass(dojo.body(), c);
  4984. },
  4985. canDrop: function(flag){
  4986. // summary:
  4987. // called to notify if the current target can accept items
  4988. var canDropFlag = Boolean(this.target && flag);
  4989. if(this.canDropFlag != canDropFlag){
  4990. this.canDropFlag = canDropFlag;
  4991. this.avatar.update();
  4992. }
  4993. },
  4994. stopDrag: function(){
  4995. // summary:
  4996. // stop the DnD in progress
  4997. dojo.removeClass(dojo.body(), ["dojoDndCopy", "dojoDndMove"]);
  4998. dojo.forEach(this.events, dojo.disconnect);
  4999. this.events = [];
  5000. this.avatar.destroy();
  5001. this.avatar = null;
  5002. this.source = this.target = null;
  5003. this.nodes = [];
  5004. },
  5005. makeAvatar: function(){
  5006. // summary:
  5007. // makes the avatar; it is separate to be overwritten dynamically, if needed
  5008. return new dojo.dnd.Avatar(this);
  5009. },
  5010. updateAvatar: function(){
  5011. // summary:
  5012. // updates the avatar; it is separate to be overwritten dynamically, if needed
  5013. this.avatar.update();
  5014. },
  5015. // mouse event processors
  5016. onMouseMove: function(e){
  5017. // summary:
  5018. // event processor for onmousemove
  5019. // e: Event
  5020. // mouse event
  5021. var a = this.avatar;
  5022. if(a){
  5023. dojo.dnd.autoScrollNodes(e);
  5024. //dojo.dnd.autoScroll(e);
  5025. var s = a.node.style;
  5026. s.left = (e.pageX + this.OFFSET_X) + "px";
  5027. s.top = (e.pageY + this.OFFSET_Y) + "px";
  5028. var copy = Boolean(this.source.copyState(dojo.isCopyKey(e)));
  5029. if(this.copy != copy){
  5030. this._setCopyStatus(copy);
  5031. }
  5032. }
  5033. },
  5034. onMouseUp: function(e){
  5035. // summary:
  5036. // event processor for onmouseup
  5037. // e: Event
  5038. // mouse event
  5039. if(this.avatar){
  5040. if(this.target && this.canDropFlag){
  5041. var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))),
  5042. params = [this.source, this.nodes, copy, this.target, e];
  5043. dojo.publish("/dnd/drop/before", params);
  5044. dojo.publish("/dnd/drop", params);
  5045. }else{
  5046. dojo.publish("/dnd/cancel");
  5047. }
  5048. this.stopDrag();
  5049. }
  5050. },
  5051. // keyboard event processors
  5052. onKeyDown: function(e){
  5053. // summary:
  5054. // event processor for onkeydown:
  5055. // watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
  5056. // e: Event
  5057. // keyboard event
  5058. if(this.avatar){
  5059. switch(e.keyCode){
  5060. case dojo.keys.CTRL:
  5061. var copy = Boolean(this.source.copyState(true));
  5062. if(this.copy != copy){
  5063. this._setCopyStatus(copy);
  5064. }
  5065. break;
  5066. case dojo.keys.ESCAPE:
  5067. dojo.publish("/dnd/cancel");
  5068. this.stopDrag();
  5069. break;
  5070. }
  5071. }
  5072. },
  5073. onKeyUp: function(e){
  5074. // summary:
  5075. // event processor for onkeyup, watching for CTRL for copy/move status
  5076. // e: Event
  5077. // keyboard event
  5078. if(this.avatar && e.keyCode == dojo.keys.CTRL){
  5079. var copy = Boolean(this.source.copyState(false));
  5080. if(this.copy != copy){
  5081. this._setCopyStatus(copy);
  5082. }
  5083. }
  5084. },
  5085. // utilities
  5086. _setCopyStatus: function(copy){
  5087. // summary:
  5088. // changes the copy status
  5089. // copy: Boolean
  5090. // the copy status
  5091. this.copy = copy;
  5092. this.source._markDndStatus(this.copy);
  5093. this.updateAvatar();
  5094. dojo.replaceClass(dojo.body(),
  5095. "dojoDnd" + (this.copy ? "Copy" : "Move"),
  5096. "dojoDnd" + (this.copy ? "Move" : "Copy"));
  5097. }
  5098. });
  5099. // dojo.dnd._manager:
  5100. // The manager singleton variable. Can be overwritten if needed.
  5101. dojo.dnd._manager = null;
  5102. Manager.manager = dojo.dnd.manager = function(){
  5103. // summary:
  5104. // Returns the current DnD manager. Creates one if it is not created yet.
  5105. if(!dojo.dnd._manager){
  5106. dojo.dnd._manager = new dojo.dnd.Manager();
  5107. }
  5108. return dojo.dnd._manager; // Object
  5109. };
  5110. return Manager;
  5111. });
  5112. },
  5113. 'dijit/form/ToggleButton':function(){
  5114. define("dijit/form/ToggleButton", [
  5115. "dojo/_base/declare", // declare
  5116. "dojo/_base/kernel", // kernel.deprecated
  5117. "./Button",
  5118. "./_ToggleButtonMixin"
  5119. ], function(declare, kernel, Button, _ToggleButtonMixin){
  5120. /*=====
  5121. var Button = dijit.form.Button;
  5122. var _ToggleButtonMixin = dijit.form._ToggleButtonMixin;
  5123. =====*/
  5124. // module:
  5125. // dijit/form/ToggleButton
  5126. // summary:
  5127. // A templated button widget that can be in two states (checked or not).
  5128. return declare("dijit.form.ToggleButton", [Button, _ToggleButtonMixin], {
  5129. // summary:
  5130. // A templated button widget that can be in two states (checked or not).
  5131. // Can be base class for things like tabs or checkbox or radio buttons
  5132. baseClass: "dijitToggleButton",
  5133. setChecked: function(/*Boolean*/ checked){
  5134. // summary:
  5135. // Deprecated. Use set('checked', true/false) instead.
  5136. kernel.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0");
  5137. this.set('checked', checked);
  5138. }
  5139. });
  5140. });
  5141. },
  5142. 'dojo/date/stamp':function(){
  5143. define("dojo/date/stamp", ["../_base/kernel", "../_base/lang", "../_base/array"], function(dojo, lang, array) {
  5144. // module:
  5145. // dojo/date/stamp
  5146. // summary:
  5147. // TODOC
  5148. lang.getObject("date.stamp", true, dojo);
  5149. // Methods to convert dates to or from a wire (string) format using well-known conventions
  5150. dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
  5151. // summary:
  5152. // Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
  5153. //
  5154. // description:
  5155. // Accepts a string formatted according to a profile of ISO8601 as defined by
  5156. // [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
  5157. // Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
  5158. // The following combinations are valid:
  5159. //
  5160. // * dates only
  5161. // | * yyyy
  5162. // | * yyyy-MM
  5163. // | * yyyy-MM-dd
  5164. // * times only, with an optional time zone appended
  5165. // | * THH:mm
  5166. // | * THH:mm:ss
  5167. // | * THH:mm:ss.SSS
  5168. // * and "datetimes" which could be any combination of the above
  5169. //
  5170. // timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
  5171. // Assumes the local time zone if not specified. Does not validate. Improperly formatted
  5172. // input may return null. Arguments which are out of bounds will be handled
  5173. // by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
  5174. // Only years between 100 and 9999 are supported.
  5175. //
  5176. // formattedString:
  5177. // A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
  5178. //
  5179. // defaultTime:
  5180. // Used for defaults for fields omitted in the formattedString.
  5181. // Uses 1970-01-01T00:00:00.0Z by default.
  5182. if(!dojo.date.stamp._isoRegExp){
  5183. dojo.date.stamp._isoRegExp =
  5184. //TODO: could be more restrictive and check for 00-59, etc.
  5185. /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
  5186. }
  5187. var match = dojo.date.stamp._isoRegExp.exec(formattedString),
  5188. result = null;
  5189. if(match){
  5190. match.shift();
  5191. if(match[1]){match[1]--;} // Javascript Date months are 0-based
  5192. if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
  5193. if(defaultTime){
  5194. // mix in defaultTime. Relatively expensive, so use || operators for the fast path of defaultTime === 0
  5195. defaultTime = new Date(defaultTime);
  5196. array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
  5197. return defaultTime["get" + prop]();
  5198. }), function(value, index){
  5199. match[index] = match[index] || value;
  5200. });
  5201. }
  5202. 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
  5203. if(match[0] < 100){
  5204. result.setFullYear(match[0] || 1970);
  5205. }
  5206. var offset = 0,
  5207. zoneSign = match[7] && match[7].charAt(0);
  5208. if(zoneSign != 'Z'){
  5209. offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
  5210. if(zoneSign != '-'){ offset *= -1; }
  5211. }
  5212. if(zoneSign){
  5213. offset -= result.getTimezoneOffset();
  5214. }
  5215. if(offset){
  5216. result.setTime(result.getTime() + offset * 60000);
  5217. }
  5218. }
  5219. return result; // Date or null
  5220. };
  5221. /*=====
  5222. dojo.date.stamp.__Options = function(){
  5223. // selector: String
  5224. // "date" or "time" for partial formatting of the Date object.
  5225. // Both date and time will be formatted by default.
  5226. // zulu: Boolean
  5227. // if true, UTC/GMT is used for a timezone
  5228. // milliseconds: Boolean
  5229. // if true, output milliseconds
  5230. this.selector = selector;
  5231. this.zulu = zulu;
  5232. this.milliseconds = milliseconds;
  5233. }
  5234. =====*/
  5235. dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
  5236. // summary:
  5237. // Format a Date object as a string according a subset of the ISO-8601 standard
  5238. //
  5239. // description:
  5240. // When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
  5241. // The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
  5242. // Does not check bounds. Only years between 100 and 9999 are supported.
  5243. //
  5244. // dateObject:
  5245. // A Date object
  5246. var _ = function(n){ return (n < 10) ? "0" + n : n; };
  5247. options = options || {};
  5248. var formattedDate = [],
  5249. getter = options.zulu ? "getUTC" : "get",
  5250. date = "";
  5251. if(options.selector != "time"){
  5252. var year = dateObject[getter+"FullYear"]();
  5253. date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
  5254. }
  5255. formattedDate.push(date);
  5256. if(options.selector != "date"){
  5257. var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
  5258. var millis = dateObject[getter+"Milliseconds"]();
  5259. if(options.milliseconds){
  5260. time += "."+ (millis < 100 ? "0" : "") + _(millis);
  5261. }
  5262. if(options.zulu){
  5263. time += "Z";
  5264. }else if(options.selector != "time"){
  5265. var timezoneOffset = dateObject.getTimezoneOffset();
  5266. var absOffset = Math.abs(timezoneOffset);
  5267. time += (timezoneOffset > 0 ? "-" : "+") +
  5268. _(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
  5269. }
  5270. formattedDate.push(time);
  5271. }
  5272. return formattedDate.join('T'); // String
  5273. };
  5274. return dojo.date.stamp;
  5275. });
  5276. },
  5277. 'dojo/Stateful':function(){
  5278. define("dojo/Stateful", ["./_base/declare", "./_base/lang", "./_base/array"], function(declare, lang, array) {
  5279. // module:
  5280. // dojo/Stateful
  5281. // summary:
  5282. // TODOC
  5283. return declare("dojo.Stateful", null, {
  5284. // summary:
  5285. // Base class for objects that provide named properties with optional getter/setter
  5286. // control and the ability to watch for property changes
  5287. // example:
  5288. // | var obj = new dojo.Stateful();
  5289. // | obj.watch("foo", function(){
  5290. // | console.log("foo changed to " + this.get("foo"));
  5291. // | });
  5292. // | obj.set("foo","bar");
  5293. postscript: function(mixin){
  5294. if(mixin){
  5295. lang.mixin(this, mixin);
  5296. }
  5297. },
  5298. get: function(/*String*/name){
  5299. // summary:
  5300. // Get a property on a Stateful instance.
  5301. // name:
  5302. // The property to get.
  5303. // returns:
  5304. // The property value on this Stateful instance.
  5305. // description:
  5306. // Get a named property on a Stateful object. The property may
  5307. // potentially be retrieved via a getter method in subclasses. In the base class
  5308. // this just retrieves the object's property.
  5309. // For example:
  5310. // | stateful = new dojo.Stateful({foo: 3});
  5311. // | stateful.get("foo") // returns 3
  5312. // | stateful.foo // returns 3
  5313. return this[name]; //Any
  5314. },
  5315. set: function(/*String*/name, /*Object*/value){
  5316. // summary:
  5317. // Set a property on a Stateful instance
  5318. // name:
  5319. // The property to set.
  5320. // value:
  5321. // The value to set in the property.
  5322. // returns:
  5323. // The function returns this dojo.Stateful instance.
  5324. // description:
  5325. // Sets named properties on a stateful object and notifies any watchers of
  5326. // the property. A programmatic setter may be defined in subclasses.
  5327. // For example:
  5328. // | stateful = new dojo.Stateful();
  5329. // | stateful.watch(function(name, oldValue, value){
  5330. // | // this will be called on the set below
  5331. // | }
  5332. // | stateful.set(foo, 5);
  5333. //
  5334. // set() may also be called with a hash of name/value pairs, ex:
  5335. // | myObj.set({
  5336. // | foo: "Howdy",
  5337. // | bar: 3
  5338. // | })
  5339. // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
  5340. if(typeof name === "object"){
  5341. for(var x in name){
  5342. if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
  5343. this.set(x, name[x]);
  5344. }
  5345. }
  5346. return this;
  5347. }
  5348. var oldValue = this[name];
  5349. this[name] = value;
  5350. if(this._watchCallbacks){
  5351. this._watchCallbacks(name, oldValue, value);
  5352. }
  5353. return this; //dojo.Stateful
  5354. },
  5355. watch: function(/*String?*/name, /*Function*/callback){
  5356. // summary:
  5357. // Watches a property for changes
  5358. // name:
  5359. // Indicates the property to watch. This is optional (the callback may be the
  5360. // only parameter), and if omitted, all the properties will be watched
  5361. // returns:
  5362. // An object handle for the watch. The unwatch method of this object
  5363. // can be used to discontinue watching this property:
  5364. // | var watchHandle = obj.watch("foo", callback);
  5365. // | watchHandle.unwatch(); // callback won't be called now
  5366. // callback:
  5367. // The function to execute when the property changes. This will be called after
  5368. // the property has been changed. The callback will be called with the |this|
  5369. // set to the instance, the first argument as the name of the property, the
  5370. // second argument as the old value and the third argument as the new value.
  5371. var callbacks = this._watchCallbacks;
  5372. if(!callbacks){
  5373. var self = this;
  5374. callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
  5375. var notify = function(propertyCallbacks){
  5376. if(propertyCallbacks){
  5377. propertyCallbacks = propertyCallbacks.slice();
  5378. for(var i = 0, l = propertyCallbacks.length; i < l; i++){
  5379. propertyCallbacks[i].call(self, name, oldValue, value);
  5380. }
  5381. }
  5382. };
  5383. notify(callbacks['_' + name]);
  5384. if(!ignoreCatchall){
  5385. notify(callbacks["*"]); // the catch-all
  5386. }
  5387. }; // we use a function instead of an object so it will be ignored by JSON conversion
  5388. }
  5389. if(!callback && typeof name === "function"){
  5390. callback = name;
  5391. name = "*";
  5392. }else{
  5393. // prepend with dash to prevent name conflicts with function (like "name" property)
  5394. name = '_' + name;
  5395. }
  5396. var propertyCallbacks = callbacks[name];
  5397. if(typeof propertyCallbacks !== "object"){
  5398. propertyCallbacks = callbacks[name] = [];
  5399. }
  5400. propertyCallbacks.push(callback);
  5401. return {
  5402. unwatch: function(){
  5403. propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
  5404. }
  5405. }; //Object
  5406. }
  5407. });
  5408. });
  5409. },
  5410. 'dojox/layout/FloatingPane':function(){
  5411. require({cache:{
  5412. 'url:dojox/layout/resources/FloatingPane.html':"<div class=\"dojoxFloatingPane\" id=\"${id}\">\n\t<div tabindex=\"0\" role=\"button\" class=\"dojoxFloatingPaneTitle\" dojoAttachPoint=\"focusNode\">\n\t\t<span dojoAttachPoint=\"closeNode\" dojoAttachEvent=\"onclick: close\" class=\"dojoxFloatingCloseIcon\"></span>\n\t\t<span dojoAttachPoint=\"maxNode\" dojoAttachEvent=\"onclick: maximize\" class=\"dojoxFloatingMaximizeIcon\">&thinsp;</span>\n\t\t<span dojoAttachPoint=\"restoreNode\" dojoAttachEvent=\"onclick: _restore\" class=\"dojoxFloatingRestoreIcon\">&thinsp;</span>\t\n\t\t<span dojoAttachPoint=\"dockNode\" dojoAttachEvent=\"onclick: minimize\" class=\"dojoxFloatingMinimizeIcon\">&thinsp;</span>\n\t\t<span dojoAttachPoint=\"titleNode\" class=\"dijitInline dijitTitleNode\"></span>\n\t</div>\n\t<div dojoAttachPoint=\"canvas\" class=\"dojoxFloatingPaneCanvas\">\n\t\t<div dojoAttachPoint=\"containerNode\" role=\"region\" tabindex=\"-1\" class=\"${contentClass}\">\n\t\t</div>\n\t\t<span dojoAttachPoint=\"resizeHandle\" class=\"dojoxFloatingResizeHandle\"></span>\n\t</div>\n</div>\n"}});
  5413. define("dojox/layout/FloatingPane", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/window","dojo/_base/declare",
  5414. "dojo/_base/fx","dojo/_base/connect","dojo/_base/array","dojo/_base/sniff",
  5415. "dojo/window","dojo/dom","dojo/dom-class","dojo/dom-geometry","dojo/dom-construct",
  5416. "dijit/_TemplatedMixin","dijit/_Widget","dijit/BackgroundIframe","dojo/dnd/Moveable",
  5417. "./ContentPane","./ResizeHandle","dojo/text!./resources/FloatingPane.html"], function(
  5418. kernel, lang, winUtil, declare, baseFx, connectUtil, arrayUtil,
  5419. has, windowLib, dom, domClass, domGeom, domConstruct, TemplatedMixin, Widget, BackgroundIframe,
  5420. Moveable, ContentPane, ResizeHandle, template){
  5421. /*=====
  5422. var Widget = dijit._Widget;
  5423. var TemplatedMixin = dijit._TemplatedMixin;
  5424. var ContentPane = dojox.layout.ContentPane;
  5425. =====*/
  5426. kernel.experimental("dojox.layout.FloatingPane");
  5427. var FloatingPane = declare("dojox.layout.FloatingPane", [ ContentPane, TemplatedMixin ],{
  5428. // summary:
  5429. // A non-modal Floating window.
  5430. //
  5431. // description:
  5432. // Makes a `dojox.layout.ContentPane` float and draggable by it's title [similar to TitlePane]
  5433. // and over-rides onClick to onDblClick for wipeIn/Out of containerNode
  5434. // provides minimize(dock) / show() and hide() methods, and resize [almost]
  5435. //
  5436. // closable: Boolean
  5437. // Allow closure of this Node
  5438. closable: true,
  5439. // dockable: Boolean
  5440. // Allow minimizing of pane if true
  5441. dockable: true,
  5442. // resizable: Boolean
  5443. // Allow resizing of pane true if true
  5444. resizable: false,
  5445. // maxable: Boolean
  5446. // Horrible param name for "Can you maximize this floating pane?"
  5447. maxable: false,
  5448. // resizeAxis: String
  5449. // One of: x | xy | y to limit pane's sizing direction
  5450. resizeAxis: "xy",
  5451. // title: String
  5452. // Title to use in the header
  5453. title: "",
  5454. // dockTo: DomNode?
  5455. // if empty, will create private layout.Dock that scrolls with viewport
  5456. // on bottom span of viewport.
  5457. dockTo: "",
  5458. // duration: Integer
  5459. // Time is MS to spend toggling in/out node
  5460. duration: 400,
  5461. /*=====
  5462. // iconSrc: String
  5463. // [not implemented yet] will be either icon in titlepane to left
  5464. // of Title, and/or icon show when docked in a fisheye-like dock
  5465. // or maybe dockIcon would be better?
  5466. iconSrc: null,
  5467. =====*/
  5468. // contentClass: String
  5469. // The className to give to the inner node which has the content
  5470. contentClass: "dojoxFloatingPaneContent",
  5471. // animation holders for toggle
  5472. _showAnim: null,
  5473. _hideAnim: null,
  5474. // node in the dock (if docked)
  5475. _dockNode: null,
  5476. // privates:
  5477. _restoreState: {},
  5478. _allFPs: [],
  5479. _startZ: 100,
  5480. templateString: template,
  5481. attributeMap: lang.delegate(Widget.prototype.attributeMap, {
  5482. title: { type:"innerHTML", node:"titleNode" }
  5483. }),
  5484. postCreate: function(){
  5485. this.inherited(arguments);
  5486. new Moveable(this.domNode,{ handle: this.focusNode });
  5487. //this._listener = dojo.subscribe("/dnd/move/start",this,"bringToTop");
  5488. if(!this.dockable){ this.dockNode.style.display = "none"; }
  5489. if(!this.closable){ this.closeNode.style.display = "none"; }
  5490. if(!this.maxable){
  5491. this.maxNode.style.display = "none";
  5492. this.restoreNode.style.display = "none";
  5493. }
  5494. if(!this.resizable){
  5495. this.resizeHandle.style.display = "none";
  5496. }else{
  5497. this.domNode.style.width = domGeom.getMarginBox(this.domNode).w + "px";
  5498. }
  5499. this._allFPs.push(this);
  5500. this.domNode.style.position = "absolute";
  5501. this.bgIframe = new BackgroundIframe(this.domNode);
  5502. this._naturalState = domGeom.position(this.domNode);
  5503. },
  5504. startup: function(){
  5505. if(this._started){ return; }
  5506. this.inherited(arguments);
  5507. if(this.resizable){
  5508. if(has("ie")){
  5509. this.canvas.style.overflow = "auto";
  5510. }else{
  5511. this.containerNode.style.overflow = "auto";
  5512. }
  5513. this._resizeHandle = new ResizeHandle({
  5514. targetId: this.id,
  5515. resizeAxis: this.resizeAxis
  5516. },this.resizeHandle);
  5517. }
  5518. if(this.dockable){
  5519. // FIXME: argh.
  5520. var tmpName = this.dockTo;
  5521. if(this.dockTo){
  5522. this.dockTo = dijit.byId(this.dockTo);
  5523. }else{
  5524. this.dockTo = dijit.byId('dojoxGlobalFloatingDock');
  5525. }
  5526. if(!this.dockTo){
  5527. var tmpId, tmpNode;
  5528. // we need to make our dock node, and position it against
  5529. // .dojoxDockDefault .. this is a lot. either dockto="node"
  5530. // and fail if node doesn't exist or make the global one
  5531. // once, and use it on empty OR invalid dockTo="" node?
  5532. if(tmpName){
  5533. tmpId = tmpName;
  5534. tmpNode = dom.byId(tmpName);
  5535. }else{
  5536. tmpNode = domConstruct.create('div', null, winUtil.body());
  5537. domClass.add(tmpNode,"dojoxFloatingDockDefault");
  5538. tmpId = 'dojoxGlobalFloatingDock';
  5539. }
  5540. this.dockTo = new Dock({ id: tmpId, autoPosition: "south" }, tmpNode);
  5541. this.dockTo.startup();
  5542. }
  5543. if((this.domNode.style.display == "none")||(this.domNode.style.visibility == "hidden")){
  5544. // If the FP is created dockable and non-visible, start up docked.
  5545. this.minimize();
  5546. }
  5547. }
  5548. this.connect(this.focusNode,"onmousedown","bringToTop");
  5549. this.connect(this.domNode, "onmousedown","bringToTop");
  5550. // Initial resize to give child the opportunity to lay itself out
  5551. this.resize(domGeom.position(this.domNode));
  5552. this._started = true;
  5553. },
  5554. setTitle: function(/* String */ title){
  5555. // summary: Update the Title bar with a new string
  5556. kernel.deprecated("pane.setTitle", "Use pane.set('title', someTitle)", "2.0");
  5557. this.set("title", title);
  5558. },
  5559. close: function(){
  5560. // summary: Close and destroy this widget
  5561. if(!this.closable){ return; }
  5562. connectUtil.unsubscribe(this._listener);
  5563. this.hide(lang.hitch(this,function(){
  5564. this.destroyRecursive();
  5565. }));
  5566. },
  5567. hide: function(/* Function? */ callback){
  5568. // summary: Close, but do not destroy this FloatingPane
  5569. baseFx.fadeOut({
  5570. node:this.domNode,
  5571. duration:this.duration,
  5572. onEnd: lang.hitch(this,function() {
  5573. this.domNode.style.display = "none";
  5574. this.domNode.style.visibility = "hidden";
  5575. if(this.dockTo && this.dockable){
  5576. this.dockTo._positionDock(null);
  5577. }
  5578. if(callback){
  5579. callback();
  5580. }
  5581. })
  5582. }).play();
  5583. },
  5584. show: function(/* Function? */callback){
  5585. // summary: Show the FloatingPane
  5586. var anim = baseFx.fadeIn({node:this.domNode, duration:this.duration,
  5587. beforeBegin: lang.hitch(this,function(){
  5588. this.domNode.style.display = "";
  5589. this.domNode.style.visibility = "visible";
  5590. if (this.dockTo && this.dockable) { this.dockTo._positionDock(null); }
  5591. if (typeof callback == "function") { callback(); }
  5592. this._isDocked = false;
  5593. if (this._dockNode) {
  5594. this._dockNode.destroy();
  5595. this._dockNode = null;
  5596. }
  5597. })
  5598. }).play();
  5599. this.resize(domGeom.position(this.domNode));
  5600. this._onShow(); // lazy load trigger
  5601. },
  5602. minimize: function(){
  5603. // summary: Hide and dock the FloatingPane
  5604. if(!this._isDocked){ this.hide(lang.hitch(this,"_dock")); }
  5605. },
  5606. maximize: function(){
  5607. // summary: Make this FloatingPane full-screen (viewport)
  5608. if(this._maximized){ return; }
  5609. this._naturalState = domGeom.position(this.domNode);
  5610. if(this._isDocked){
  5611. this.show();
  5612. setTimeout(lang.hitch(this,"maximize"),this.duration);
  5613. }
  5614. domClass.add(this.focusNode,"floatingPaneMaximized");
  5615. this.resize(windowLib.getBox());
  5616. this._maximized = true;
  5617. },
  5618. _restore: function(){
  5619. if(this._maximized){
  5620. this.resize(this._naturalState);
  5621. domClass.remove(this.focusNode,"floatingPaneMaximized");
  5622. this._maximized = false;
  5623. }
  5624. },
  5625. _dock: function(){
  5626. if(!this._isDocked && this.dockable){
  5627. this._dockNode = this.dockTo.addNode(this);
  5628. this._isDocked = true;
  5629. }
  5630. },
  5631. resize: function(/* Object */dim){
  5632. // summary: Size the FloatingPane and place accordingly
  5633. dim = dim || this._naturalState;
  5634. this._naturalState = dim;
  5635. // From the ResizeHandle we only get width and height information
  5636. var dns = this.domNode.style;
  5637. if("t" in dim){ dns.top = dim.t + "px"; }
  5638. else if("y" in dim){ dns.top = dim.y + "px"; }
  5639. if("l" in dim){ dns.left = dim.l + "px"; }
  5640. else if("x" in dim){ dns.left = dim.x + "px"; }
  5641. dns.width = dim.w + "px";
  5642. dns.height = dim.h + "px";
  5643. // Now resize canvas
  5644. var mbCanvas = { l: 0, t: 0, w: dim.w, h: (dim.h - this.focusNode.offsetHeight) };
  5645. domGeom.setMarginBox(this.canvas, mbCanvas);
  5646. // If the single child can resize, forward resize event to it so it can
  5647. // fit itself properly into the content area
  5648. this._checkIfSingleChild();
  5649. if(this._singleChild && this._singleChild.resize){
  5650. this._singleChild.resize(mbCanvas);
  5651. }
  5652. },
  5653. bringToTop: function(){
  5654. // summary: bring this FloatingPane above all other panes
  5655. var windows = arrayUtil.filter(
  5656. this._allFPs,
  5657. function(i){
  5658. return i !== this;
  5659. },
  5660. this);
  5661. windows.sort(function(a, b){
  5662. return a.domNode.style.zIndex - b.domNode.style.zIndex;
  5663. });
  5664. windows.push(this);
  5665. arrayUtil.forEach(windows, function(w, x){
  5666. w.domNode.style.zIndex = this._startZ + (x * 2);
  5667. domClass.remove(w.domNode, "dojoxFloatingPaneFg");
  5668. }, this);
  5669. domClass.add(this.domNode, "dojoxFloatingPaneFg");
  5670. },
  5671. destroy: function(){
  5672. // summary: Destroy this FloatingPane completely
  5673. this._allFPs.splice(arrayUtil.indexOf(this._allFPs, this), 1);
  5674. if(this._resizeHandle){
  5675. this._resizeHandle.destroy();
  5676. }
  5677. this.inherited(arguments);
  5678. }
  5679. });
  5680. var Dock = declare("dojox.layout.Dock",[Widget, TemplatedMixin],{
  5681. // summary:
  5682. // A widget that attaches to a node and keeps track of incoming / outgoing FloatingPanes
  5683. // and handles layout
  5684. templateString: '<div class="dojoxDock"><ul dojoAttachPoint="containerNode" class="dojoxDockList"></ul></div>',
  5685. // private _docked: array of panes currently in our dock
  5686. _docked: [],
  5687. _inPositioning: false,
  5688. autoPosition: false,
  5689. addNode: function(refNode){
  5690. // summary: Instert a dockNode refernce into the dock
  5691. var div = domConstruct.create('li', null, this.containerNode),
  5692. node = new DockNode({
  5693. title: refNode.title,
  5694. paneRef: refNode
  5695. }, div)
  5696. ;
  5697. node.startup();
  5698. return node;
  5699. },
  5700. startup: function(){
  5701. if (this.id == "dojoxGlobalFloatingDock" || this.isFixedDock) {
  5702. // attach window.onScroll, and a position like in presentation/dialog
  5703. this.connect(window, 'onresize', "_positionDock");
  5704. this.connect(window, 'onscroll', "_positionDock");
  5705. if(has("ie")){
  5706. this.connect(this.domNode, "onresize", "_positionDock");
  5707. }
  5708. }
  5709. this._positionDock(null);
  5710. this.inherited(arguments);
  5711. },
  5712. _positionDock: function(/* Event? */e){
  5713. if(!this._inPositioning){
  5714. if(this.autoPosition == "south"){
  5715. // Give some time for scrollbars to appear/disappear
  5716. setTimeout(lang.hitch(this, function() {
  5717. this._inPositiononing = true;
  5718. var viewport = windowLib.getBox();
  5719. var s = this.domNode.style;
  5720. s.left = viewport.l + "px";
  5721. s.width = (viewport.w-2) + "px";
  5722. s.top = (viewport.h + viewport.t) - this.domNode.offsetHeight + "px";
  5723. this._inPositioning = false;
  5724. }), 125);
  5725. }
  5726. }
  5727. }
  5728. });
  5729. var DockNode = declare("dojox.layout._DockNode",[Widget, TemplatedMixin],{
  5730. // summary:
  5731. // dojox.layout._DockNode is a private widget used to keep track of
  5732. // which pane is docked.
  5733. //
  5734. // title: String
  5735. // Shown in dock icon. should read parent iconSrc?
  5736. title: "",
  5737. // paneRef: Widget
  5738. // reference to the FloatingPane we reprasent in any given dock
  5739. paneRef: null,
  5740. templateString:
  5741. '<li dojoAttachEvent="onclick: restore" class="dojoxDockNode">'+
  5742. '<span dojoAttachPoint="restoreNode" class="dojoxDockRestoreButton" dojoAttachEvent="onclick: restore"></span>'+
  5743. '<span class="dojoxDockTitleNode" dojoAttachPoint="titleNode">${title}</span>'+
  5744. '</li>',
  5745. restore: function(){
  5746. // summary: remove this dock item from parent dock, and call show() on reffed floatingpane
  5747. this.paneRef.show();
  5748. this.paneRef.bringToTop();
  5749. this.destroy();
  5750. }
  5751. });
  5752. return FloatingPane;
  5753. });
  5754. },
  5755. 'dijit/form/ComboButton':function(){
  5756. require({cache:{
  5757. 'url:dijit/form/templates/ComboButton.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tcellspacing='0' cellpadding='0' role=\"presentation\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonNode\" data-dojo-attach-point=\"buttonNode\" data-dojo-attach-event=\"ondijitclick:_onClick,onkeypress:_onButtonKeyPress\"\n\t\t><div id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" data-dojo-attach-point=\"containerNode\" role=\"presentation\"></div\n\t\t></div\n\t\t></td\n\t\t><td id=\"${id}_arrow\" class='dijitReset dijitRight dijitButtonNode dijitArrowButton'\n\t\t\tdata-dojo-attach-point=\"_popupStateNode,focusNode,_buttonNode\"\n\t\t\tdata-dojo-attach-event=\"onkeypress:_onArrowKeyPress\"\n\t\t\ttitle=\"${optionsTitle}\"\n\t\t\trole=\"button\" aria-haspopup=\"true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">&#9660;</div\n\t\t></td\n\t\t><td style=\"display:none !important;\"\n\t\t\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" data-dojo-attach-point=\"valueNode\"\n\t\t/></td></tr></tbody\n></table>\n"}});
  5758. define("dijit/form/ComboButton", [
  5759. "dojo/_base/declare", // declare
  5760. "dojo/_base/event", // event.stop
  5761. "dojo/keys", // keys
  5762. "../focus", // focus.focus()
  5763. "./DropDownButton",
  5764. "dojo/text!./templates/ComboButton.html"
  5765. ], function(declare, event, keys, focus, DropDownButton, template){
  5766. /*=====
  5767. var DropDownButton = dijit.form.DropDownButton;
  5768. =====*/
  5769. // module:
  5770. // dijit/form/ComboButton
  5771. // summary:
  5772. // A combination button and drop-down button.
  5773. return declare("dijit.form.ComboButton", DropDownButton, {
  5774. // summary:
  5775. // A combination button and drop-down button.
  5776. // Users can click one side to "press" the button, or click an arrow
  5777. // icon to display the drop down.
  5778. //
  5779. // example:
  5780. // | <button data-dojo-type="dijit.form.ComboButton" onClick="...">
  5781. // | <span>Hello world</span>
  5782. // | <div data-dojo-type="dijit.Menu">...</div>
  5783. // | </button>
  5784. //
  5785. // example:
  5786. // | var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});
  5787. // | dojo.body().appendChild(button1.domNode);
  5788. //
  5789. templateString: template,
  5790. // Map widget attributes to DOMNode attributes.
  5791. _setIdAttr: "", // override _FormWidgetMixin which puts id on the focusNode
  5792. _setTabIndexAttr: ["focusNode", "titleNode"],
  5793. _setTitleAttr: "titleNode",
  5794. // optionsTitle: String
  5795. // Text that describes the options menu (accessibility)
  5796. optionsTitle: "",
  5797. baseClass: "dijitComboButton",
  5798. // Set classes like dijitButtonContentsHover or dijitArrowButtonActive depending on
  5799. // mouse action over specified node
  5800. cssStateNodes: {
  5801. "buttonNode": "dijitButtonNode",
  5802. "titleNode": "dijitButtonContents",
  5803. "_popupStateNode": "dijitDownArrowButton"
  5804. },
  5805. _focusedNode: null,
  5806. _onButtonKeyPress: function(/*Event*/ evt){
  5807. // summary:
  5808. // Handler for right arrow key when focus is on left part of button
  5809. if(evt.charOrCode == keys[this.isLeftToRight() ? "RIGHT_ARROW" : "LEFT_ARROW"]){
  5810. focus.focus(this._popupStateNode);
  5811. event.stop(evt);
  5812. }
  5813. },
  5814. _onArrowKeyPress: function(/*Event*/ evt){
  5815. // summary:
  5816. // Handler for left arrow key when focus is on right part of button
  5817. if(evt.charOrCode == keys[this.isLeftToRight() ? "LEFT_ARROW" : "RIGHT_ARROW"]){
  5818. focus.focus(this.titleNode);
  5819. event.stop(evt);
  5820. }
  5821. },
  5822. focus: function(/*String*/ position){
  5823. // summary:
  5824. // Focuses this widget to according to position, if specified,
  5825. // otherwise on arrow node
  5826. // position:
  5827. // "start" or "end"
  5828. if(!this.disabled){
  5829. focus.focus(position == "start" ? this.titleNode : this._popupStateNode);
  5830. }
  5831. }
  5832. });
  5833. });
  5834. },
  5835. 'dojox/xml/parser':function(){
  5836. define("dojox/xml/parser", ['dojo/_base/kernel', 'dojo/_base/lang', 'dojo/_base/array', 'dojo/_base/window', 'dojo/_base/sniff'], function(dojo){
  5837. dojo.getObject("xml.parser", true, dojox);
  5838. //DOM type to int value for reference.
  5839. //Ints make for more compact code than full constant names.
  5840. //ELEMENT_NODE = 1;
  5841. //ATTRIBUTE_NODE = 2;
  5842. //TEXT_NODE = 3;
  5843. //CDATA_SECTION_NODE = 4;
  5844. //ENTITY_REFERENCE_NODE = 5;
  5845. //ENTITY_NODE = 6;
  5846. //PROCESSING_INSTRUCTION_NODE = 7;
  5847. //COMMENT_NODE = 8;
  5848. //DOCUMENT_NODE = 9;
  5849. //DOCUMENT_TYPE_NODE = 10;
  5850. //DOCUMENT_FRAGMENT_NODE = 11;
  5851. //NOTATION_NODE = 12;
  5852. dojox.xml.parser.parse = function(/*String?*/ str, /*String?*/ mimetype){
  5853. // summary:
  5854. // cross-browser implementation of creating an XML document object from null, empty string, and XML text..
  5855. //
  5856. // str:
  5857. // Optional text to create the document from. If not provided, an empty XML document will be created.
  5858. // If str is empty string "", then a new empty document will be created.
  5859. // mimetype:
  5860. // Optional mimetype of the text. Typically, this is text/xml. Will be defaulted to text/xml if not provided.
  5861. var _document = dojo.doc;
  5862. var doc;
  5863. mimetype = mimetype || "text/xml";
  5864. if(str && dojo.trim(str) && "DOMParser" in dojo.global){
  5865. //Handle parsing the text on Mozilla based browsers etc..
  5866. var parser = new DOMParser();
  5867. doc = parser.parseFromString(str, mimetype);
  5868. var de = doc.documentElement;
  5869. var errorNS = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
  5870. if(de.nodeName == "parsererror" && de.namespaceURI == errorNS){
  5871. var sourceText = de.getElementsByTagNameNS(errorNS, 'sourcetext')[0];
  5872. if(sourceText){
  5873. sourceText = sourceText.firstChild.data;
  5874. }
  5875. throw new Error("Error parsing text " + de.firstChild.data + " \n" + sourceText);
  5876. }
  5877. return doc;
  5878. }else if("ActiveXObject" in dojo.global){
  5879. //Handle IE.
  5880. var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
  5881. var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
  5882. dojo.some(dp, function(p){
  5883. try{
  5884. doc = new ActiveXObject(p);
  5885. }catch(e){ return false; }
  5886. return true;
  5887. });
  5888. if(str && doc){
  5889. doc.async = false;
  5890. doc.loadXML(str);
  5891. var pe = doc.parseError;
  5892. if(pe.errorCode !== 0){
  5893. throw new Error("Line: " + pe.line + "\n" +
  5894. "Col: " + pe.linepos + "\n" +
  5895. "Reason: " + pe.reason + "\n" +
  5896. "Error Code: " + pe.errorCode + "\n" +
  5897. "Source: " + pe.srcText);
  5898. }
  5899. }
  5900. if(doc){
  5901. return doc; //DOMDocument
  5902. }
  5903. }else if(_document.implementation && _document.implementation.createDocument){
  5904. if(str && dojo.trim(str) && _document.createElement){
  5905. //Everyone else that we couldn't get to work. Fallback case.
  5906. // FIXME: this may change all tags to uppercase!
  5907. var tmp = _document.createElement("xml");
  5908. tmp.innerHTML = str;
  5909. var xmlDoc = _document.implementation.createDocument("foo", "", null);
  5910. dojo.forEach(tmp.childNodes, function(child){
  5911. xmlDoc.importNode(child, true);
  5912. });
  5913. return xmlDoc; // DOMDocument
  5914. }else{
  5915. return _document.implementation.createDocument("", "", null); // DOMDocument
  5916. }
  5917. }
  5918. return null; // null
  5919. };
  5920. dojox.xml.parser.textContent = function(/*Node*/node, /*String?*/text){
  5921. // summary:
  5922. // Implementation of the DOM Level 3 attribute; scan node for text
  5923. // description:
  5924. // Implementation of the DOM Level 3 attribute; scan node for text
  5925. // This function can also update the text of a node by replacing all child
  5926. // content of the node.
  5927. // node:
  5928. // The node to get the text off of or set the text on.
  5929. // text:
  5930. // Optional argument of the text to apply to the node.
  5931. if(arguments.length>1){
  5932. var _document = node.ownerDocument || dojo.doc; //Preference is to get the node owning doc first or it may fail
  5933. dojox.xml.parser.replaceChildren(node, _document.createTextNode(text));
  5934. return text; // String
  5935. }else{
  5936. if(node.textContent !== undefined){ //FF 1.5 -- remove?
  5937. return node.textContent; // String
  5938. }
  5939. var _result = "";
  5940. if(node){
  5941. dojo.forEach(node.childNodes, function(child){
  5942. switch(child.nodeType){
  5943. case 1: // ELEMENT_NODE
  5944. case 5: // ENTITY_REFERENCE_NODE
  5945. _result += dojox.xml.parser.textContent(child);
  5946. break;
  5947. case 3: // TEXT_NODE
  5948. case 2: // ATTRIBUTE_NODE
  5949. case 4: // CDATA_SECTION_NODE
  5950. _result += child.nodeValue;
  5951. }
  5952. });
  5953. }
  5954. return _result; // String
  5955. }
  5956. };
  5957. dojox.xml.parser.replaceChildren = function(/*Element*/node, /*Node || Array*/ newChildren){
  5958. // summary:
  5959. // Removes all children of node and appends newChild. All the existing
  5960. // children will be destroyed.
  5961. // description:
  5962. // Removes all children of node and appends newChild. All the existing
  5963. // children will be destroyed.
  5964. // node:
  5965. // The node to modify the children on
  5966. // newChildren:
  5967. // The children to add to the node. It can either be a single Node or an
  5968. // array of Nodes.
  5969. var nodes = [];
  5970. if(dojo.isIE){
  5971. dojo.forEach(node.childNodes, function(child){
  5972. nodes.push(child);
  5973. });
  5974. }
  5975. dojox.xml.parser.removeChildren(node);
  5976. dojo.forEach(nodes, dojo.destroy);
  5977. if(!dojo.isArray(newChildren)){
  5978. node.appendChild(newChildren);
  5979. }else{
  5980. dojo.forEach(newChildren, function(child){
  5981. node.appendChild(child);
  5982. });
  5983. }
  5984. };
  5985. dojox.xml.parser.removeChildren = function(/*Element*/node){
  5986. // summary:
  5987. // removes all children from node and returns the count of children removed.
  5988. // The children nodes are not destroyed. Be sure to call dojo.destroy on them
  5989. // after they are not used anymore.
  5990. // node:
  5991. // The node to remove all the children from.
  5992. var count = node.childNodes.length;
  5993. while(node.hasChildNodes()){
  5994. node.removeChild(node.firstChild);
  5995. }
  5996. return count; // int
  5997. };
  5998. dojox.xml.parser.innerXML = function(/*Node*/node){
  5999. // summary:
  6000. // Implementation of MS's innerXML function.
  6001. // node:
  6002. // The node from which to generate the XML text representation.
  6003. if(node.innerXML){
  6004. return node.innerXML; // String
  6005. }else if(node.xml){
  6006. return node.xml; // String
  6007. }else if(typeof XMLSerializer != "undefined"){
  6008. return (new XMLSerializer()).serializeToString(node); // String
  6009. }
  6010. return null;
  6011. };
  6012. return dojox.xml.parser;
  6013. });
  6014. },
  6015. 'url:dijit/layout/templates/_ScrollingTabControllerButton.html':"<div data-dojo-attach-event=\"onclick:_onClick\">\n\t<div role=\"presentation\" class=\"dijitTabInnerDiv\" data-dojo-attach-point=\"innerDiv,focusNode\">\n\t\t<div role=\"presentation\" class=\"dijitTabContent dijitButtonContents\" data-dojo-attach-point=\"tabContent\">\n\t\t\t<img role=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t\t<span data-dojo-attach-point=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n\t\t</div>\n\t</div>\n</div>",
  6016. 'url:dijit/layout/templates/_TabButton.html':"<div role=\"presentation\" data-dojo-attach-point=\"titleNode\" data-dojo-attach-event='onclick:onClick'>\n <div role=\"presentation\" class='dijitTabInnerDiv' data-dojo-attach-point='innerDiv'>\n <div role=\"presentation\" class='dijitTabContent' data-dojo-attach-point='tabContent'>\n \t<div role=\"presentation\" data-dojo-attach-point='focusNode'>\n\t\t <img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitTabButtonIcon\" data-dojo-attach-point='iconNode' />\n\t\t <span data-dojo-attach-point='containerNode' class='tabLabel'></span>\n\t\t <span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" data-dojo-attach-point='closeNode'\n\t\t \t\tdata-dojo-attach-event='onclick: onClickCloseButton' role=\"presentation\">\n\t\t <span data-dojo-attach-point='closeText' class='dijitTabCloseText'>[x]</span\n\t\t ></span>\n\t\t\t</div>\n </div>\n </div>\n</div>\n",
  6017. 'dijit/_base/window':function(){
  6018. define("dijit/_base/window", [
  6019. "dojo/window", // windowUtils.get
  6020. ".." // export symbol to dijit
  6021. ], function(windowUtils, dijit){
  6022. // module:
  6023. // dijit/_base/window
  6024. // summary:
  6025. // Back compatibility module, new code should use windowUtils directly instead of using this module.
  6026. dijit.getDocumentWindow = function(doc){
  6027. return windowUtils.get(doc);
  6028. };
  6029. });
  6030. },
  6031. 'dijit/PopupMenuItem':function(){
  6032. define("dijit/PopupMenuItem", [
  6033. "dojo/_base/declare", // declare
  6034. "dojo/dom-style", // domStyle.set
  6035. "dojo/query", // query
  6036. "dojo/_base/window", // win.body
  6037. "./registry", // registry.byNode
  6038. "./MenuItem",
  6039. "./hccss"
  6040. ], function(declare, domStyle, query, win, registry, MenuItem){
  6041. /*=====
  6042. var MenuItem = dijit.MenuItem;
  6043. =====*/
  6044. // module:
  6045. // dijit/PopupMenuItem
  6046. // summary:
  6047. // An item in a Menu that spawn a drop down (usually a drop down menu)
  6048. return declare("dijit.PopupMenuItem", MenuItem, {
  6049. // summary:
  6050. // An item in a Menu that spawn a drop down (usually a drop down menu)
  6051. _fillContent: function(){
  6052. // summary:
  6053. // When Menu is declared in markup, this code gets the menu label and
  6054. // the popup widget from the srcNodeRef.
  6055. // description:
  6056. // srcNodeRefinnerHTML contains both the menu item text and a popup widget
  6057. // The first part holds the menu item text and the second part is the popup
  6058. // example:
  6059. // | <div data-dojo-type="dijit.PopupMenuItem">
  6060. // | <span>pick me</span>
  6061. // | <popup> ... </popup>
  6062. // | </div>
  6063. // tags:
  6064. // protected
  6065. if(this.srcNodeRef){
  6066. var nodes = query("*", this.srcNodeRef);
  6067. this.inherited(arguments, [nodes[0]]);
  6068. // save pointer to srcNode so we can grab the drop down widget after it's instantiated
  6069. this.dropDownContainer = this.srcNodeRef;
  6070. }
  6071. },
  6072. startup: function(){
  6073. if(this._started){ return; }
  6074. this.inherited(arguments);
  6075. // we didn't copy the dropdown widget from the this.srcNodeRef, so it's in no-man's
  6076. // land now. move it to win.doc.body.
  6077. if(!this.popup){
  6078. var node = query("[widgetId]", this.dropDownContainer)[0];
  6079. this.popup = registry.byNode(node);
  6080. }
  6081. win.body().appendChild(this.popup.domNode);
  6082. this.popup.startup();
  6083. this.popup.domNode.style.display="none";
  6084. if(this.arrowWrapper){
  6085. domStyle.set(this.arrowWrapper, "visibility", "");
  6086. }
  6087. this.focusNode.setAttribute("aria-haspopup", "true");
  6088. },
  6089. destroyDescendants: function(/*Boolean*/ preserveDom){
  6090. if(this.popup){
  6091. // Destroy the popup, unless it's already been destroyed. This can happen because
  6092. // the popup is a direct child of <body> even though it's logically my child.
  6093. if(!this.popup._destroyed){
  6094. this.popup.destroyRecursive(preserveDom);
  6095. }
  6096. delete this.popup;
  6097. }
  6098. this.inherited(arguments);
  6099. }
  6100. });
  6101. });
  6102. },
  6103. 'dojox/data/QueryReadStore':function(){
  6104. define("dojox/data/QueryReadStore", ["dojo", "dojox", "dojo/data/util/sorter", "dojo/string"], function(dojo, dojox) {
  6105. dojo.declare("dojox.data.QueryReadStore",
  6106. null,
  6107. {
  6108. // summary:
  6109. // This class provides a store that is mainly intended to be used
  6110. // for loading data dynamically from the server, used i.e. for
  6111. // retreiving chunks of data from huge data stores on the server (by server-side filtering!).
  6112. // Upon calling the fetch() method of this store the data are requested from
  6113. // the server if they are not yet loaded for paging (or cached).
  6114. //
  6115. // For example used for a combobox which works on lots of data. It
  6116. // can be used to retreive the data partially upon entering the
  6117. // letters "ac" it returns only items like "action", "acting", etc.
  6118. //
  6119. // note:
  6120. // The field name "id" in a query is reserved for looking up data
  6121. // by id. This is necessary as before the first fetch, the store
  6122. // has no way of knowing which field the server will declare as
  6123. // identifier.
  6124. //
  6125. // example:
  6126. // | // The parameter "query" contains the data that are sent to the server.
  6127. // | var store = new dojox.data.QueryReadStore({url:'/search.php'});
  6128. // | store.fetch({query:{name:'a'}, queryOptions:{ignoreCase:false}});
  6129. //
  6130. // | // Since "serverQuery" is given, it overrules and those data are
  6131. // | // sent to the server.
  6132. // | var store = new dojox.data.QueryReadStore({url:'/search.php'});
  6133. // | store.fetch({serverQuery:{name:'a'}, queryOptions:{ignoreCase:false}});
  6134. //
  6135. // | <div dojoType="dojox.data.QueryReadStore"
  6136. // | jsId="store2"
  6137. // | url="../tests/stores/QueryReadStore.php"
  6138. // | requestMethod="post"></div>
  6139. // | <div dojoType="dojox.grid.data.DojoData"
  6140. // | jsId="model2"
  6141. // | store="store2"
  6142. // | sortFields="[{attribute: 'name', descending: true}]"
  6143. // | rowsPerPage="30"></div>
  6144. // | <div dojoType="dojox.Grid" id="grid2"
  6145. // | model="model2"
  6146. // | structure="gridLayout"
  6147. // | style="height:300px; width:800px;"></div>
  6148. //
  6149. // todo:
  6150. // - there is a bug in the paging, when i set start:2, count:5 after an initial fetch() and doClientPaging:true
  6151. // it returns 6 elemetns, though count=5, try it in QueryReadStore.html
  6152. // - add optional caching
  6153. // - when the first query searched for "a" and the next for a subset of
  6154. // the first, i.e. "ab" then we actually dont need a server request, if
  6155. // we have client paging, we just need to filter the items we already have
  6156. // that might also be tooo much logic
  6157. url:"",
  6158. requestMethod:"get",
  6159. //useCache:false,
  6160. // We use the name in the errors, once the name is fixed hardcode it, may be.
  6161. _className:"dojox.data.QueryReadStore",
  6162. // This will contain the items we have loaded from the server.
  6163. // The contents of this array is optimized to satisfy all read-api requirements
  6164. // and for using lesser storage, so the keys and their content need some explaination:
  6165. // this._items[0].i - the item itself
  6166. // this._items[0].r - a reference to the store, so we can identify the item
  6167. // securly. We set this reference right after receiving the item from the
  6168. // server.
  6169. _items:[],
  6170. // Store the last query that triggered xhr request to the server.
  6171. // So we can compare if the request changed and if we shall reload
  6172. // (this also depends on other factors, such as is caching used, etc).
  6173. _lastServerQuery:null,
  6174. // Store how many rows we have so that we can pass it to a clientPaging handler
  6175. _numRows:-1,
  6176. // Store a hash of the last server request. Actually I introduced this
  6177. // for testing, so I can check if no unnecessary requests were issued for
  6178. // client-side-paging.
  6179. lastRequestHash:null,
  6180. // summary:
  6181. // By default every request for paging is sent to the server.
  6182. doClientPaging:false,
  6183. // summary:
  6184. // By default all the sorting is done serverside before the data is returned
  6185. // which is the proper place to be doing it for really large datasets.
  6186. doClientSorting:false,
  6187. // Items by identify for Identify API
  6188. _itemsByIdentity:null,
  6189. // Identifier used
  6190. _identifier:null,
  6191. _features: {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true},
  6192. _labelAttr: "label",
  6193. constructor: function(/* Object */ params){
  6194. dojo.mixin(this,params);
  6195. },
  6196. getValue: function(/* item */ item, /* attribute-name-string */ attribute, /* value? */ defaultValue){
  6197. // According to the Read API comments in getValue() and exception is
  6198. // thrown when an item is not an item or the attribute not a string!
  6199. this._assertIsItem(item);
  6200. if(!dojo.isString(attribute)){
  6201. throw new Error(this._className+".getValue(): Invalid attribute, string expected!");
  6202. }
  6203. if(!this.hasAttribute(item, attribute)){
  6204. // read api says: return defaultValue "only if *item* does not have a value for *attribute*."
  6205. // Is this the case here? The attribute doesn't exist, but a defaultValue, sounds reasonable.
  6206. if(defaultValue){
  6207. return defaultValue;
  6208. }
  6209. }
  6210. return item.i[attribute];
  6211. },
  6212. getValues: function(/* item */ item, /* attribute-name-string */ attribute){
  6213. this._assertIsItem(item);
  6214. var ret = [];
  6215. if(this.hasAttribute(item, attribute)){
  6216. ret.push(item.i[attribute]);
  6217. }
  6218. return ret;
  6219. },
  6220. getAttributes: function(/* item */ item){
  6221. this._assertIsItem(item);
  6222. var ret = [];
  6223. for(var i in item.i){
  6224. ret.push(i);
  6225. }
  6226. return ret;
  6227. },
  6228. hasAttribute: function(/* item */ item, /* attribute-name-string */ attribute){
  6229. // summary:
  6230. // See dojo.data.api.Read.hasAttribute()
  6231. return this.isItem(item) && typeof item.i[attribute]!="undefined";
  6232. },
  6233. containsValue: function(/* item */ item, /* attribute-name-string */ attribute, /* anything */ value){
  6234. var values = this.getValues(item, attribute);
  6235. var len = values.length;
  6236. for(var i=0; i<len; i++){
  6237. if(values[i] == value){
  6238. return true;
  6239. }
  6240. }
  6241. return false;
  6242. },
  6243. isItem: function(/* anything */ something){
  6244. // Some basic tests, that are quick and easy to do here.
  6245. // >>> var store = new dojox.data.QueryReadStore({});
  6246. // >>> store.isItem("");
  6247. // false
  6248. //
  6249. // >>> var store = new dojox.data.QueryReadStore({});
  6250. // >>> store.isItem({});
  6251. // false
  6252. //
  6253. // >>> var store = new dojox.data.QueryReadStore({});
  6254. // >>> store.isItem(0);
  6255. // false
  6256. //
  6257. // >>> var store = new dojox.data.QueryReadStore({});
  6258. // >>> store.isItem({name:"me", label:"me too"});
  6259. // false
  6260. //
  6261. if(something){
  6262. return typeof something.r != "undefined" && something.r == this;
  6263. }
  6264. return false;
  6265. },
  6266. isItemLoaded: function(/* anything */ something){
  6267. // Currently we dont have any state that tells if an item is loaded or not
  6268. // if the item exists its also loaded.
  6269. // This might change when we start working with refs inside items ...
  6270. return this.isItem(something);
  6271. },
  6272. loadItem: function(/* object */ args){
  6273. if(this.isItemLoaded(args.item)){
  6274. return;
  6275. }
  6276. // Actually we have nothing to do here, or at least I dont know what to do here ...
  6277. },
  6278. fetch:function(/* Object? */ request){
  6279. // summary:
  6280. // See dojo.data.util.simpleFetch.fetch() this is just a copy and I adjusted
  6281. // only the paging, since it happens on the server if doClientPaging is
  6282. // false, thx to http://trac.dojotoolkit.org/ticket/4761 reporting this.
  6283. // Would be nice to be able to use simpleFetch() to reduce copied code,
  6284. // but i dont know how yet. Ideas please!
  6285. request = request || {};
  6286. if(!request.store){
  6287. request.store = this;
  6288. }
  6289. var self = this;
  6290. var _errorHandler = function(errorData, requestObject){
  6291. if(requestObject.onError){
  6292. var scope = requestObject.scope || dojo.global;
  6293. requestObject.onError.call(scope, errorData, requestObject);
  6294. }
  6295. };
  6296. var _fetchHandler = function(items, requestObject, numRows){
  6297. var oldAbortFunction = requestObject.abort || null;
  6298. var aborted = false;
  6299. var startIndex = requestObject.start?requestObject.start:0;
  6300. if(self.doClientPaging == false){
  6301. // For client paging we dont need no slicing of the result.
  6302. startIndex = 0;
  6303. }
  6304. var endIndex = requestObject.count?(startIndex + requestObject.count):items.length;
  6305. requestObject.abort = function(){
  6306. aborted = true;
  6307. if(oldAbortFunction){
  6308. oldAbortFunction.call(requestObject);
  6309. }
  6310. };
  6311. var scope = requestObject.scope || dojo.global;
  6312. if(!requestObject.store){
  6313. requestObject.store = self;
  6314. }
  6315. if(requestObject.onBegin){
  6316. requestObject.onBegin.call(scope, numRows, requestObject);
  6317. }
  6318. if(requestObject.sort && self.doClientSorting){
  6319. items.sort(dojo.data.util.sorter.createSortFunction(requestObject.sort, self));
  6320. }
  6321. if(requestObject.onItem){
  6322. for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){
  6323. var item = items[i];
  6324. if(!aborted){
  6325. requestObject.onItem.call(scope, item, requestObject);
  6326. }
  6327. }
  6328. }
  6329. if(requestObject.onComplete && !aborted){
  6330. var subset = null;
  6331. if(!requestObject.onItem){
  6332. subset = items.slice(startIndex, endIndex);
  6333. }
  6334. requestObject.onComplete.call(scope, subset, requestObject);
  6335. }
  6336. };
  6337. this._fetchItems(request, _fetchHandler, _errorHandler);
  6338. return request; // Object
  6339. },
  6340. getFeatures: function(){
  6341. return this._features;
  6342. },
  6343. close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
  6344. // I have no idea if this is really needed ...
  6345. },
  6346. getLabel: function(/* item */ item){
  6347. // summary:
  6348. // See dojo.data.api.Read.getLabel()
  6349. if(this._labelAttr && this.isItem(item)){
  6350. return this.getValue(item, this._labelAttr); //String
  6351. }
  6352. return undefined; //undefined
  6353. },
  6354. getLabelAttributes: function(/* item */ item){
  6355. // summary:
  6356. // See dojo.data.api.Read.getLabelAttributes()
  6357. if(this._labelAttr){
  6358. return [this._labelAttr]; //array
  6359. }
  6360. return null; //null
  6361. },
  6362. _xhrFetchHandler: function(data, request, fetchHandler, errorHandler){
  6363. data = this._filterResponse(data);
  6364. if(data.label){
  6365. this._labelAttr = data.label;
  6366. }
  6367. var numRows = data.numRows || -1;
  6368. this._items = [];
  6369. // Store a ref to "this" in each item, so we can simply check if an item
  6370. // really origins form here (idea is from ItemFileReadStore, I just don't know
  6371. // how efficient the real storage use, garbage collection effort, etc. is).
  6372. dojo.forEach(data.items,function(e){
  6373. this._items.push({i:e, r:this});
  6374. },this);
  6375. var identifier = data.identifier;
  6376. this._itemsByIdentity = {};
  6377. if(identifier){
  6378. this._identifier = identifier;
  6379. var i;
  6380. for(i = 0; i < this._items.length; ++i){
  6381. var item = this._items[i].i;
  6382. var identity = item[identifier];
  6383. if(!this._itemsByIdentity[identity]){
  6384. this._itemsByIdentity[identity] = item;
  6385. }else{
  6386. throw new Error(this._className+": The json data as specified by: [" + this.url + "] is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]");
  6387. }
  6388. }
  6389. }else{
  6390. this._identifier = Number;
  6391. for(i = 0; i < this._items.length; ++i){
  6392. this._items[i].n = i;
  6393. }
  6394. }
  6395. // TODO actually we should do the same as dojo.data.ItemFileReadStore._getItemsFromLoadedData() to sanitize
  6396. // (does it really sanititze them) and store the data optimal. should we? for security reasons???
  6397. numRows = this._numRows = (numRows === -1) ? this._items.length : numRows;
  6398. fetchHandler(this._items, request, numRows);
  6399. this._numRows = numRows;
  6400. },
  6401. _fetchItems: function(request, fetchHandler, errorHandler){
  6402. // summary:
  6403. // The request contains the data as defined in the Read-API.
  6404. // Additionally there is following keyword "serverQuery".
  6405. //
  6406. // The *serverQuery* parameter, optional.
  6407. // This parameter contains the data that will be sent to the server.
  6408. // If this parameter is not given the parameter "query"'s
  6409. // data are sent to the server. This is done for some reasons:
  6410. // - to specify explicitly which data are sent to the server, they
  6411. // might also be a mix of what is contained in "query", "queryOptions"
  6412. // and the paging parameters "start" and "count" or may be even
  6413. // completely different things.
  6414. // - don't modify the request.query data, so the interface using this
  6415. // store can rely on unmodified data, as the combobox dijit currently
  6416. // does it, it compares if the query has changed
  6417. // - request.query is required by the Read-API
  6418. //
  6419. // I.e. the following examples might be sent via GET:
  6420. // fetch({query:{name:"abc"}, queryOptions:{ignoreCase:true}})
  6421. // the URL will become: /url.php?name=abc
  6422. //
  6423. // fetch({serverQuery:{q:"abc", c:true}, query:{name:"abc"}, queryOptions:{ignoreCase:true}})
  6424. // the URL will become: /url.php?q=abc&c=true
  6425. // // The serverQuery-parameter has overruled the query-parameter
  6426. // // but the query parameter stays untouched, but is not sent to the server!
  6427. // // The serverQuery contains more data than the query, so they might differ!
  6428. //
  6429. var serverQuery = request.serverQuery || request.query || {};
  6430. //Need to add start and count
  6431. if(!this.doClientPaging){
  6432. serverQuery.start = request.start || 0;
  6433. // Count might not be sent if not given.
  6434. if(request.count){
  6435. serverQuery.count = request.count;
  6436. }
  6437. }
  6438. if(!this.doClientSorting && request.sort){
  6439. var sortInfo = [];
  6440. dojo.forEach(request.sort, function(sort){
  6441. if(sort && sort.attribute){
  6442. sortInfo.push((sort.descending ? "-" : "") + sort.attribute);
  6443. }
  6444. });
  6445. serverQuery.sort = sortInfo.join(',');
  6446. }
  6447. // Compare the last query and the current query by simply json-encoding them,
  6448. // so we dont have to do any deep object compare ... is there some dojo.areObjectsEqual()???
  6449. if(this.doClientPaging && this._lastServerQuery !== null &&
  6450. dojo.toJson(serverQuery) == dojo.toJson(this._lastServerQuery)
  6451. ){
  6452. this._numRows = (this._numRows === -1) ? this._items.length : this._numRows;
  6453. fetchHandler(this._items, request, this._numRows);
  6454. }else{
  6455. var xhrFunc = this.requestMethod.toLowerCase() == "post" ? dojo.xhrPost : dojo.xhrGet;
  6456. var xhrHandler = xhrFunc({url:this.url, handleAs:"json-comment-optional", content:serverQuery, failOk: true});
  6457. request.abort = function(){
  6458. xhrHandler.cancel();
  6459. };
  6460. xhrHandler.addCallback(dojo.hitch(this, function(data){
  6461. this._xhrFetchHandler(data, request, fetchHandler, errorHandler);
  6462. }));
  6463. xhrHandler.addErrback(function(error){
  6464. errorHandler(error, request);
  6465. });
  6466. // Generate the hash using the time in milliseconds and a randon number.
  6467. // Since Math.randon() returns something like: 0.23453463, we just remove the "0."
  6468. // probably just for esthetic reasons :-).
  6469. this.lastRequestHash = new Date().getTime()+"-"+String(Math.random()).substring(2);
  6470. this._lastServerQuery = dojo.mixin({}, serverQuery);
  6471. }
  6472. },
  6473. _filterResponse: function(data){
  6474. // summary:
  6475. // If the data from servers needs to be processed before it can be processed by this
  6476. // store, then this function should be re-implemented in subclass. This default
  6477. // implementation just return the data unchanged.
  6478. // data:
  6479. // The data received from server
  6480. return data;
  6481. },
  6482. _assertIsItem: function(/* item */ item){
  6483. // summary:
  6484. // It throws an error if item is not valid, so you can call it in every method that needs to
  6485. // throw an error when item is invalid.
  6486. // item:
  6487. // The item to test for being contained by the store.
  6488. if(!this.isItem(item)){
  6489. throw new Error(this._className+": Invalid item argument.");
  6490. }
  6491. },
  6492. _assertIsAttribute: function(/* attribute-name-string */ attribute){
  6493. // summary:
  6494. // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
  6495. // attribute:
  6496. // The attribute to test for being contained by the store.
  6497. if(typeof attribute !== "string"){
  6498. throw new Error(this._className+": Invalid attribute argument ('"+attribute+"').");
  6499. }
  6500. },
  6501. fetchItemByIdentity: function(/* Object */ keywordArgs){
  6502. // summary:
  6503. // See dojo.data.api.Identity.fetchItemByIdentity()
  6504. // See if we have already loaded the item with that id
  6505. // In case there hasn't been a fetch yet, _itemsByIdentity is null
  6506. // and thus a fetch will be triggered below.
  6507. if(this._itemsByIdentity){
  6508. var item = this._itemsByIdentity[keywordArgs.identity];
  6509. if(!(item === undefined)){
  6510. if(keywordArgs.onItem){
  6511. var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
  6512. keywordArgs.onItem.call(scope, {i:item, r:this});
  6513. }
  6514. return;
  6515. }
  6516. }
  6517. // Otherwise we need to go remote
  6518. // Set up error handler
  6519. var _errorHandler = function(errorData, requestObject){
  6520. var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
  6521. if(keywordArgs.onError){
  6522. keywordArgs.onError.call(scope, errorData);
  6523. }
  6524. };
  6525. // Set up fetch handler
  6526. var _fetchHandler = function(items, requestObject){
  6527. var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
  6528. try{
  6529. // There is supposed to be only one result
  6530. var item = null;
  6531. if(items && items.length == 1){
  6532. item = items[0];
  6533. }
  6534. // If no item was found, item is still null and we'll
  6535. // fire the onItem event with the null here
  6536. if(keywordArgs.onItem){
  6537. keywordArgs.onItem.call(scope, item);
  6538. }
  6539. }catch(error){
  6540. if(keywordArgs.onError){
  6541. keywordArgs.onError.call(scope, error);
  6542. }
  6543. }
  6544. };
  6545. // Construct query
  6546. var request = {serverQuery:{id:keywordArgs.identity}};
  6547. // Dispatch query
  6548. this._fetchItems(request, _fetchHandler, _errorHandler);
  6549. },
  6550. getIdentity: function(/* item */ item){
  6551. // summary:
  6552. // See dojo.data.api.Identity.getIdentity()
  6553. var identifier = null;
  6554. if(this._identifier === Number){
  6555. identifier = item.n; // Number
  6556. }else{
  6557. identifier = item.i[this._identifier];
  6558. }
  6559. return identifier;
  6560. },
  6561. getIdentityAttributes: function(/* item */ item){
  6562. // summary:
  6563. // See dojo.data.api.Identity.getIdentityAttributes()
  6564. return [this._identifier];
  6565. }
  6566. }
  6567. );
  6568. return dojox.data.QueryReadStore;
  6569. });
  6570. },
  6571. 'dojo/dnd/AutoSource':function(){
  6572. define("dojo/dnd/AutoSource", [ "./Source" ], function(Source){
  6573. /*===== Source = dojo.dnd.Source =====*/
  6574. return dojo.declare("dojo.dnd.AutoSource", Source, {
  6575. // summary:
  6576. // a source that syncs its DnD nodes by default
  6577. constructor: function(node, params){
  6578. // summary:
  6579. // constructor of the AutoSource --- see the Source constructor for details
  6580. this.autoSync = true;
  6581. }
  6582. });
  6583. });
  6584. },
  6585. 'dijit/main':function(){
  6586. define("dijit/main", [
  6587. "dojo/_base/kernel"
  6588. ], function(dojo){
  6589. // module:
  6590. // dijit
  6591. // summary:
  6592. // The dijit package main module
  6593. return dojo.dijit;
  6594. });
  6595. },
  6596. 'dijit/_OnDijitClickMixin':function(){
  6597. define("dijit/_OnDijitClickMixin", [
  6598. "dojo/on",
  6599. "dojo/_base/array", // array.forEach
  6600. "dojo/keys", // keys.ENTER keys.SPACE
  6601. "dojo/_base/declare", // declare
  6602. "dojo/_base/sniff", // has("ie")
  6603. "dojo/_base/unload", // unload.addOnWindowUnload
  6604. "dojo/_base/window" // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent
  6605. ], function(on, array, keys, declare, has, unload, win){
  6606. // module:
  6607. // dijit/_OnDijitClickMixin
  6608. // summary:
  6609. // Mixin so you can pass "ondijitclick" to this.connect() method,
  6610. // as a way to handle clicks by mouse, or by keyboard (SPACE/ENTER key)
  6611. // Keep track of where the last keydown event was, to help avoid generating
  6612. // spurious ondijitclick events when:
  6613. // 1. focus is on a <button> or <a>
  6614. // 2. user presses then releases the ENTER key
  6615. // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
  6616. // 4. onkeyup event fires, causing the ondijitclick handler to fire
  6617. var lastKeyDownNode = null;
  6618. if(has("ie") < 9){
  6619. (function(){
  6620. var keydownCallback = function(evt){
  6621. lastKeyDownNode = evt.srcElement;
  6622. };
  6623. win.doc.attachEvent('onkeydown', keydownCallback);
  6624. unload.addOnWindowUnload(function(){
  6625. win.doc.detachEvent('onkeydown', keydownCallback);
  6626. });
  6627. })();
  6628. }else{
  6629. win.doc.addEventListener('keydown', function(evt){
  6630. lastKeyDownNode = evt.target;
  6631. }, true);
  6632. }
  6633. // Custom a11yclick (a.k.a. ondijitclick) event
  6634. var a11yclick = function(node, listener){
  6635. if(/input|button/i.test(node.nodeName)){
  6636. // pass through, the browser already generates click event on SPACE/ENTER key
  6637. return on(node, "click", listener);
  6638. }else{
  6639. // Don't fire the click event unless both the keydown and keyup occur on this node.
  6640. // Avoids problems where focus shifted to this node or away from the node on keydown,
  6641. // either causing this node to process a stray keyup event, or causing another node
  6642. // to get a stray keyup event.
  6643. function clickKey(/*Event*/ e){
  6644. return (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE) &&
  6645. !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey;
  6646. }
  6647. var handles = [
  6648. on(node, "keypress", function(e){
  6649. //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
  6650. if(clickKey(e)){
  6651. // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
  6652. lastKeyDownNode = e.target;
  6653. // Prevent viewport scrolling on space key in IE<9.
  6654. // (Reproducible on test_Button.html on any of the first dijit.form.Button examples)
  6655. // Do this onkeypress rather than onkeydown because onkeydown.preventDefault() will
  6656. // suppress the onkeypress event, breaking _HasDropDown
  6657. e.preventDefault();
  6658. }
  6659. }),
  6660. on(node, "keyup", function(e){
  6661. //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
  6662. if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey
  6663. //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
  6664. lastKeyDownNode = null;
  6665. listener.call(this, e);
  6666. }
  6667. }),
  6668. on(node, "click", function(e){
  6669. // and connect for mouse clicks too (or touch-clicks on mobile)
  6670. listener.call(this, e);
  6671. })
  6672. ];
  6673. return {
  6674. remove: function(){
  6675. array.forEach(handles, function(h){ h.remove(); });
  6676. }
  6677. };
  6678. }
  6679. };
  6680. return declare("dijit._OnDijitClickMixin", null, {
  6681. connect: function(
  6682. /*Object|null*/ obj,
  6683. /*String|Function*/ event,
  6684. /*String|Function*/ method){
  6685. // summary:
  6686. // Connects specified obj/event to specified method of this object
  6687. // and registers for disconnect() on widget destroy.
  6688. // description:
  6689. // Provide widget-specific analog to connect.connect, except with the
  6690. // implicit use of this widget as the target object.
  6691. // This version of connect also provides a special "ondijitclick"
  6692. // event which triggers on a click or space or enter keyup.
  6693. // Events connected with `this.connect` are disconnected upon
  6694. // destruction.
  6695. // returns:
  6696. // A handle that can be passed to `disconnect` in order to disconnect before
  6697. // the widget is destroyed.
  6698. // example:
  6699. // | var btn = new dijit.form.Button();
  6700. // | // when foo.bar() is called, call the listener we're going to
  6701. // | // provide in the scope of btn
  6702. // | btn.connect(foo, "bar", function(){
  6703. // | console.debug(this.toString());
  6704. // | });
  6705. // tags:
  6706. // protected
  6707. return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]);
  6708. }
  6709. });
  6710. });
  6711. },
  6712. 'dojo/dnd/autoscroll':function(){
  6713. define("dojo/dnd/autoscroll", ["../main", "../window"], function(dojo) {
  6714. // module:
  6715. // dojo/dnd/autoscroll
  6716. // summary:
  6717. // TODOC
  6718. dojo.getObject("dnd", true, dojo);
  6719. dojo.dnd.getViewport = dojo.window.getBox;
  6720. dojo.dnd.V_TRIGGER_AUTOSCROLL = 32;
  6721. dojo.dnd.H_TRIGGER_AUTOSCROLL = 32;
  6722. dojo.dnd.V_AUTOSCROLL_VALUE = 16;
  6723. dojo.dnd.H_AUTOSCROLL_VALUE = 16;
  6724. dojo.dnd.autoScroll = function(e){
  6725. // summary:
  6726. // a handler for onmousemove event, which scrolls the window, if
  6727. // necesary
  6728. // e: Event
  6729. // onmousemove event
  6730. // FIXME: needs more docs!
  6731. var v = dojo.window.getBox(), dx = 0, dy = 0;
  6732. if(e.clientX < dojo.dnd.H_TRIGGER_AUTOSCROLL){
  6733. dx = -dojo.dnd.H_AUTOSCROLL_VALUE;
  6734. }else if(e.clientX > v.w - dojo.dnd.H_TRIGGER_AUTOSCROLL){
  6735. dx = dojo.dnd.H_AUTOSCROLL_VALUE;
  6736. }
  6737. if(e.clientY < dojo.dnd.V_TRIGGER_AUTOSCROLL){
  6738. dy = -dojo.dnd.V_AUTOSCROLL_VALUE;
  6739. }else if(e.clientY > v.h - dojo.dnd.V_TRIGGER_AUTOSCROLL){
  6740. dy = dojo.dnd.V_AUTOSCROLL_VALUE;
  6741. }
  6742. window.scrollBy(dx, dy);
  6743. };
  6744. dojo.dnd._validNodes = {"div": 1, "p": 1, "td": 1};
  6745. dojo.dnd._validOverflow = {"auto": 1, "scroll": 1};
  6746. dojo.dnd.autoScrollNodes = function(e){
  6747. // summary:
  6748. // a handler for onmousemove event, which scrolls the first avaialble
  6749. // Dom element, it falls back to dojo.dnd.autoScroll()
  6750. // e: Event
  6751. // onmousemove event
  6752. // FIXME: needs more docs!
  6753. var b, t, w, h, rx, ry, dx = 0, dy = 0, oldLeft, oldTop;
  6754. for(var n = e.target; n;){
  6755. if(n.nodeType == 1 && (n.tagName.toLowerCase() in dojo.dnd._validNodes)){
  6756. var s = dojo.getComputedStyle(n),
  6757. overflow = (s.overflow.toLowerCase() in dojo.dnd._validOverflow),
  6758. overflowX = (s.overflowX.toLowerCase() in dojo.dnd._validOverflow),
  6759. overflowY = (s.overflowY.toLowerCase() in dojo.dnd._validOverflow);
  6760. if(overflow || overflowX || overflowY){
  6761. b = dojo._getContentBox(n, s);
  6762. t = dojo.position(n, true);
  6763. }
  6764. // overflow-x
  6765. if(overflow || overflowX){
  6766. w = Math.min(dojo.dnd.H_TRIGGER_AUTOSCROLL, b.w / 2);
  6767. rx = e.pageX - t.x;
  6768. if(dojo.isWebKit || dojo.isOpera){
  6769. // FIXME: this code should not be here, it should be taken into account
  6770. // either by the event fixing code, or the dojo.position()
  6771. // FIXME: this code doesn't work on Opera 9.5 Beta
  6772. rx += dojo.body().scrollLeft;
  6773. }
  6774. dx = 0;
  6775. if(rx > 0 && rx < b.w){
  6776. if(rx < w){
  6777. dx = -w;
  6778. }else if(rx > b.w - w){
  6779. dx = w;
  6780. }
  6781. oldLeft = n.scrollLeft;
  6782. n.scrollLeft = n.scrollLeft + dx;
  6783. }
  6784. }
  6785. // overflow-y
  6786. if(overflow || overflowY){
  6787. //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
  6788. h = Math.min(dojo.dnd.V_TRIGGER_AUTOSCROLL, b.h / 2);
  6789. ry = e.pageY - t.y;
  6790. if(dojo.isWebKit || dojo.isOpera){
  6791. // FIXME: this code should not be here, it should be taken into account
  6792. // either by the event fixing code, or the dojo.position()
  6793. // FIXME: this code doesn't work on Opera 9.5 Beta
  6794. ry += dojo.body().scrollTop;
  6795. }
  6796. dy = 0;
  6797. if(ry > 0 && ry < b.h){
  6798. if(ry < h){
  6799. dy = -h;
  6800. }else if(ry > b.h - h){
  6801. dy = h;
  6802. }
  6803. oldTop = n.scrollTop;
  6804. n.scrollTop = n.scrollTop + dy;
  6805. }
  6806. }
  6807. if(dx || dy){ return; }
  6808. }
  6809. try{
  6810. n = n.parentNode;
  6811. }catch(x){
  6812. n = null;
  6813. }
  6814. }
  6815. dojo.dnd.autoScroll(e);
  6816. };
  6817. return dojo.dnd;
  6818. });
  6819. },
  6820. 'url:dijit/templates/TreeNode.html':"<div class=\"dijitTreeNode\" role=\"presentation\"\n\t><div data-dojo-attach-point=\"rowNode\" class=\"dijitTreeRow\" role=\"presentation\" data-dojo-attach-event=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick\"\n\t\t><img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"expandoNode\" class=\"dijitTreeExpando\" role=\"presentation\"\n\t\t/><span data-dojo-attach-point=\"expandoNodeText\" class=\"dijitExpandoText\" role=\"presentation\"\n\t\t></span\n\t\t><span data-dojo-attach-point=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" role=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"labelNode\" class=\"dijitTreeLabel\" role=\"treeitem\" tabindex=\"-1\" aria-selected=\"false\" data-dojo-attach-event=\"onfocus:_onLabelFocus\"></span>\n\t\t</span\n\t></div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitTreeContainer\" role=\"presentation\" style=\"display: none;\"></div>\n</div>\n",
  6821. 'url:dijit/templates/Tree.html':"<div class=\"dijitTree dijitTreeContainer\" role=\"tree\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" data-dojo-attach-point=\"indentDetector\"></div>\n</div>\n",
  6822. 'dojo/cookie':function(){
  6823. define("dojo/cookie", ["./_base/kernel", "./regexp"], function(dojo, regexp) {
  6824. // module:
  6825. // dojo/cookie
  6826. // summary:
  6827. // TODOC
  6828. /*=====
  6829. dojo.__cookieProps = function(){
  6830. // expires: Date|String|Number?
  6831. // If a number, the number of days from today at which the cookie
  6832. // will expire. If a date, the date past which the cookie will expire.
  6833. // If expires is in the past, the cookie will be deleted.
  6834. // If expires is omitted or is 0, the cookie will expire when the browser closes.
  6835. // path: String?
  6836. // The path to use for the cookie.
  6837. // domain: String?
  6838. // The domain to use for the cookie.
  6839. // secure: Boolean?
  6840. // Whether to only send the cookie on secure connections
  6841. this.expires = expires;
  6842. this.path = path;
  6843. this.domain = domain;
  6844. this.secure = secure;
  6845. }
  6846. =====*/
  6847. dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){
  6848. // summary:
  6849. // Get or set a cookie.
  6850. // description:
  6851. // If one argument is passed, returns the value of the cookie
  6852. // For two or more arguments, acts as a setter.
  6853. // name:
  6854. // Name of the cookie
  6855. // value:
  6856. // Value for the cookie
  6857. // props:
  6858. // Properties for the cookie
  6859. // example:
  6860. // set a cookie with the JSON-serialized contents of an object which
  6861. // will expire 5 days from now:
  6862. // | dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });
  6863. //
  6864. // example:
  6865. // de-serialize a cookie back into a JavaScript object:
  6866. // | var config = dojo.fromJson(dojo.cookie("configObj"));
  6867. //
  6868. // example:
  6869. // delete a cookie:
  6870. // | dojo.cookie("configObj", null, {expires: -1});
  6871. var c = document.cookie, ret;
  6872. if(arguments.length == 1){
  6873. var matches = c.match(new RegExp("(?:^|; )" + regexp.escapeString(name) + "=([^;]*)"));
  6874. ret = matches ? decodeURIComponent(matches[1]) : undefined;
  6875. }else{
  6876. props = props || {};
  6877. // FIXME: expires=0 seems to disappear right away, not on close? (FF3) Change docs?
  6878. var exp = props.expires;
  6879. if(typeof exp == "number"){
  6880. var d = new Date();
  6881. d.setTime(d.getTime() + exp*24*60*60*1000);
  6882. exp = props.expires = d;
  6883. }
  6884. if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); }
  6885. value = encodeURIComponent(value);
  6886. var updatedCookie = name + "=" + value, propName;
  6887. for(propName in props){
  6888. updatedCookie += "; " + propName;
  6889. var propValue = props[propName];
  6890. if(propValue !== true){ updatedCookie += "=" + propValue; }
  6891. }
  6892. document.cookie = updatedCookie;
  6893. }
  6894. return ret; // String|undefined
  6895. };
  6896. dojo.cookie.isSupported = function(){
  6897. // summary:
  6898. // Use to determine if the current browser supports cookies or not.
  6899. //
  6900. // Returns true if user allows cookies.
  6901. // Returns false if user doesn't allow cookies.
  6902. if(!("cookieEnabled" in navigator)){
  6903. this("__djCookieTest__", "CookiesAllowed");
  6904. navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed";
  6905. if(navigator.cookieEnabled){
  6906. this("__djCookieTest__", "", {expires: -1});
  6907. }
  6908. }
  6909. return navigator.cookieEnabled;
  6910. };
  6911. return dojo.cookie;
  6912. });
  6913. },
  6914. 'dojo/cache':function(){
  6915. define("dojo/cache", ["./_base/kernel", "./text"], function(dojo, text){
  6916. // module:
  6917. // dojo/cache
  6918. // summary:
  6919. // The module defines dojo.cache by loading dojo/text.
  6920. //dojo.cache is defined in dojo/text
  6921. return dojo.cache;
  6922. });
  6923. },
  6924. 'dijit/_base/popup':function(){
  6925. define("dijit/_base/popup", [
  6926. "dojo/dom-class", // domClass.contains
  6927. "../popup",
  6928. "../BackgroundIframe" // just loading for back-compat, in case client code is referencing it
  6929. ], function(domClass, popup){
  6930. // module:
  6931. // dijit/_base/popup
  6932. // summary:
  6933. // Old module for popups, new code should use dijit/popup directly
  6934. // Hack support for old API passing in node instead of a widget (to various methods)
  6935. var origCreateWrapper = popup._createWrapper;
  6936. popup._createWrapper = function(widget){
  6937. if(!widget.declaredClass){
  6938. // make fake widget to pass to new API
  6939. widget = {
  6940. _popupWrapper: (widget.parentNode && domClass.contains(widget.parentNode, "dijitPopup")) ?
  6941. widget.parentNode : null,
  6942. domNode: widget,
  6943. destroy: function(){}
  6944. };
  6945. }
  6946. return origCreateWrapper.call(this, widget);
  6947. };
  6948. // Support old format of orient parameter
  6949. var origOpen = popup.open;
  6950. popup.open = function(/*dijit.popup.__OpenArgs*/ args){
  6951. // Convert old hash structure (ex: {"BL": "TL", ...}) of orient to format compatible w/new popup.open() API.
  6952. // Don't do conversion for:
  6953. // - null parameter (that means to use the default positioning)
  6954. // - "R" or "L" strings used to indicate positioning for context menus (when there is no around node)
  6955. // - new format, ex: ["below", "above"]
  6956. // - return value from deprecated dijit.getPopupAroundAlignment() method,
  6957. // ex: ["below", "above"]
  6958. if(args.orient && typeof args.orient != "string" && !("length" in args.orient)){
  6959. var ary = [];
  6960. for(var key in args.orient){
  6961. ary.push({aroundCorner: key, corner: args.orient[key]});
  6962. }
  6963. args.orient = ary;
  6964. }
  6965. return origOpen.call(this, args);
  6966. };
  6967. return popup;
  6968. });
  6969. },
  6970. 'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#x25CF;</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\n/></span>\n",
  6971. 'dojo/_base/url':function(){
  6972. define("dojo/_base/url", ["./kernel"], function(dojo) {
  6973. // module:
  6974. // dojo/url
  6975. // summary:
  6976. // This module contains dojo._Url
  6977. var
  6978. ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
  6979. ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),
  6980. _Url = function(){
  6981. var n = null,
  6982. _a = arguments,
  6983. uri = [_a[0]];
  6984. // resolve uri components relative to each other
  6985. for(var i = 1; i<_a.length; i++){
  6986. if(!_a[i]){ continue; }
  6987. // Safari doesn't support this.constructor so we have to be explicit
  6988. // FIXME: Tracked (and fixed) in Webkit bug 3537.
  6989. // http://bugs.webkit.org/show_bug.cgi?id=3537
  6990. var relobj = new _Url(_a[i]+""),
  6991. uriobj = new _Url(uri[0]+"");
  6992. if(
  6993. relobj.path == "" &&
  6994. !relobj.scheme &&
  6995. !relobj.authority &&
  6996. !relobj.query
  6997. ){
  6998. if(relobj.fragment != n){
  6999. uriobj.fragment = relobj.fragment;
  7000. }
  7001. relobj = uriobj;
  7002. }else if(!relobj.scheme){
  7003. relobj.scheme = uriobj.scheme;
  7004. if(!relobj.authority){
  7005. relobj.authority = uriobj.authority;
  7006. if(relobj.path.charAt(0) != "/"){
  7007. var path = uriobj.path.substring(0,
  7008. uriobj.path.lastIndexOf("/") + 1) + relobj.path;
  7009. var segs = path.split("/");
  7010. for(var j = 0; j < segs.length; j++){
  7011. if(segs[j] == "."){
  7012. // flatten "./" references
  7013. if(j == segs.length - 1){
  7014. segs[j] = "";
  7015. }else{
  7016. segs.splice(j, 1);
  7017. j--;
  7018. }
  7019. }else if(j > 0 && !(j == 1 && segs[0] == "") &&
  7020. segs[j] == ".." && segs[j-1] != ".."){
  7021. // flatten "../" references
  7022. if(j == (segs.length - 1)){
  7023. segs.splice(j, 1);
  7024. segs[j - 1] = "";
  7025. }else{
  7026. segs.splice(j - 1, 2);
  7027. j -= 2;
  7028. }
  7029. }
  7030. }
  7031. relobj.path = segs.join("/");
  7032. }
  7033. }
  7034. }
  7035. uri = [];
  7036. if(relobj.scheme){
  7037. uri.push(relobj.scheme, ":");
  7038. }
  7039. if(relobj.authority){
  7040. uri.push("//", relobj.authority);
  7041. }
  7042. uri.push(relobj.path);
  7043. if(relobj.query){
  7044. uri.push("?", relobj.query);
  7045. }
  7046. if(relobj.fragment){
  7047. uri.push("#", relobj.fragment);
  7048. }
  7049. }
  7050. this.uri = uri.join("");
  7051. // break the uri into its main components
  7052. var r = this.uri.match(ore);
  7053. this.scheme = r[2] || (r[1] ? "" : n);
  7054. this.authority = r[4] || (r[3] ? "" : n);
  7055. this.path = r[5]; // can never be undefined
  7056. this.query = r[7] || (r[6] ? "" : n);
  7057. this.fragment = r[9] || (r[8] ? "" : n);
  7058. if(this.authority != n){
  7059. // server based naming authority
  7060. r = this.authority.match(ire);
  7061. this.user = r[3] || n;
  7062. this.password = r[4] || n;
  7063. this.host = r[6] || r[7]; // ipv6 || ipv4
  7064. this.port = r[9] || n;
  7065. }
  7066. };
  7067. _Url.prototype.toString = function(){ return this.uri; };
  7068. return dojo._Url = _Url;
  7069. });
  7070. },
  7071. 'dojox/main':function(){
  7072. define("dojox/main", ["dojo/_base/kernel"], function(dojo) {
  7073. // module:
  7074. // dojox/main
  7075. // summary:
  7076. // The dojox package main module; dojox package is somewhat unusual in that the main module currently just provides an empty object.
  7077. return dojo.dojox;
  7078. });
  7079. },
  7080. 'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n",
  7081. 'dojo/text':function(){
  7082. define("dojo/text", ["./_base/kernel", "require", "./has", "./_base/xhr"], function(dojo, require, has, xhr){
  7083. // module:
  7084. // dojo/text
  7085. // summary:
  7086. // This module implements the !dojo/text plugin and the dojo.cache API.
  7087. // description:
  7088. // We choose to include our own plugin to leverage functionality already contained in dojo
  7089. // and thereby reduce the size of the plugin compared to various foreign loader implementations.
  7090. // Also, this allows foreign AMD loaders to be used without their plugins.
  7091. //
  7092. // CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous
  7093. // loader. This feature is outside the scope of the CommonJS plugins specification.
  7094. var getText;
  7095. if(1){
  7096. getText= function(url, sync, load){
  7097. xhr("GET", {url:url, sync:!!sync, load:load});
  7098. };
  7099. }else{
  7100. // TODOC: only works for dojo AMD loader
  7101. if(require.getText){
  7102. getText= require.getText;
  7103. }else{
  7104. console.error("dojo/text plugin failed to load because loader does not support getText");
  7105. }
  7106. }
  7107. var
  7108. theCache= {},
  7109. strip= function(text){
  7110. //Strips <?xml ...?> declarations so that external SVG and XML
  7111. //documents can be added to a document without worry. Also, if the string
  7112. //is an HTML document, only the part inside the body tag is returned.
  7113. if(text){
  7114. text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
  7115. var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
  7116. if(matches){
  7117. text= matches[1];
  7118. }
  7119. }else{
  7120. text = "";
  7121. }
  7122. return text;
  7123. },
  7124. notFound = {},
  7125. pending = {},
  7126. result= {
  7127. dynamic:
  7128. // the dojo/text caches it's own resources because of dojo.cache
  7129. true,
  7130. normalize:function(id, toAbsMid){
  7131. // id is something like (path may be relative):
  7132. //
  7133. // "path/to/text.html"
  7134. // "path/to/text.html!strip"
  7135. var parts= id.split("!"),
  7136. url= parts[0];
  7137. return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : "");
  7138. },
  7139. load:function(id, require, load){
  7140. // id is something like (path is always absolute):
  7141. //
  7142. // "path/to/text.html"
  7143. // "path/to/text.html!strip"
  7144. var
  7145. parts= id.split("!"),
  7146. stripFlag= parts.length>1,
  7147. absMid= parts[0],
  7148. url = require.toUrl(parts[0]),
  7149. text = notFound,
  7150. finish = function(text){
  7151. load(stripFlag ? strip(text) : text);
  7152. };
  7153. if(absMid in theCache){
  7154. text = theCache[absMid];
  7155. }else if(url in require.cache){
  7156. text = require.cache[url];
  7157. }else if(url in theCache){
  7158. text = theCache[url];
  7159. }
  7160. if(text===notFound){
  7161. if(pending[url]){
  7162. pending[url].push(finish);
  7163. }else{
  7164. var pendingList = pending[url] = [finish];
  7165. getText(url, !require.async, function(text){
  7166. theCache[absMid]= theCache[url]= text;
  7167. for(var i = 0; i<pendingList.length;){
  7168. pendingList[i++](text);
  7169. }
  7170. delete pending[url];
  7171. });
  7172. }
  7173. }else{
  7174. finish(text);
  7175. }
  7176. }
  7177. };
  7178. dojo.cache= function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
  7179. // * (string string [value]) => (module, url, value)
  7180. // * (object [value]) => (module, value), url defaults to ""
  7181. //
  7182. // * if module is an object, then it must be convertable to a string
  7183. // * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl
  7184. // * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize"
  7185. var key;
  7186. if(typeof module=="string"){
  7187. if(/\//.test(module)){
  7188. // module is a version 1.7+ resolved path
  7189. key = module;
  7190. value = url;
  7191. }else{
  7192. // module is a version 1.6- argument to dojo.moduleUrl
  7193. key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : ""));
  7194. }
  7195. }else{
  7196. key = module + "";
  7197. value = url;
  7198. }
  7199. var
  7200. val = (value != undefined && typeof value != "string") ? value.value : value,
  7201. sanitize = value && value.sanitize;
  7202. if(typeof val == "string"){
  7203. //We have a string, set cache value
  7204. theCache[key] = val;
  7205. return sanitize ? strip(val) : val;
  7206. }else if(val === null){
  7207. //Remove cached value
  7208. delete theCache[key];
  7209. return null;
  7210. }else{
  7211. //Allow cache values to be empty strings. If key property does
  7212. //not exist, fetch it.
  7213. if(!(key in theCache)){
  7214. getText(key, true, function(text){
  7215. theCache[key]= text;
  7216. });
  7217. }
  7218. return sanitize ? strip(theCache[key]) : theCache[key];
  7219. }
  7220. };
  7221. return result;
  7222. /*=====
  7223. dojo.cache = function(module, url, value){
  7224. // summary:
  7225. // A getter and setter for storing the string content associated with the
  7226. // module and url arguments.
  7227. // description:
  7228. // If module is a string that contains slashes, then it is interpretted as a fully
  7229. // resolved path (typically a result returned by require.toUrl), and url should not be
  7230. // provided. This is the preferred signature. If module is a string that does not
  7231. // contain slashes, then url must also be provided and module and url are used to
  7232. // call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated.
  7233. // If value is specified, the cache value for the moduleUrl will be set to
  7234. // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
  7235. // in its internal cache and return that cached value for the URL. To clear
  7236. // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
  7237. // the URL contents, only modules on the same domain of the page can use this capability.
  7238. // The build system can inline the cache values though, to allow for xdomain hosting.
  7239. // module: String||Object
  7240. // If a String with slashes, a fully resolved path; if a String without slashes, the
  7241. // module name to use for the base part of the URL, similar to module argument
  7242. // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
  7243. // generates a valid path for the cache item. For example, a dojo._Url object.
  7244. // url: String
  7245. // The rest of the path to append to the path derived from the module argument. If
  7246. // module is an object, then this second argument should be the "value" argument instead.
  7247. // value: String||Object?
  7248. // If a String, the value to use in the cache for the module/url combination.
  7249. // If an Object, it can have two properties: value and sanitize. The value property
  7250. // should be the value to use in the cache, and sanitize can be set to true or false,
  7251. // to indicate if XML declarations should be removed from the value and if the HTML
  7252. // inside a body tag in the value should be extracted as the real value. The value argument
  7253. // or the value property on the value argument are usually only used by the build system
  7254. // as it inlines cache content.
  7255. // example:
  7256. // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
  7257. // of call is used to avoid an issue with the build system erroneously trying to intern
  7258. // this example. To get the build system to intern your dojo.cache calls, use the
  7259. // "dojo.cache" style of call):
  7260. // | //If template.html contains "<h1>Hello</h1>" that will be
  7261. // | //the value for the text variable.
  7262. // | var text = dojo["cache"]("my.module", "template.html");
  7263. // example:
  7264. // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
  7265. // (the dojo["cache"] style of call is used to avoid an issue with the build system
  7266. // erroneously trying to intern this example. To get the build system to intern your
  7267. // dojo.cache calls, use the "dojo.cache" style of call):
  7268. // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
  7269. // | //text variable will contain just "<h1>Hello</h1>".
  7270. // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
  7271. // example:
  7272. // Same example as previous, but demostrates how an object can be passed in as
  7273. // the first argument, then the value argument can then be the second argument.
  7274. // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
  7275. // | //text variable will contain just "<h1>Hello</h1>".
  7276. // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
  7277. return val; //String
  7278. };
  7279. =====*/
  7280. });
  7281. },
  7282. 'url:dojox/layout/resources/FloatingPane.html':"<div class=\"dojoxFloatingPane\" id=\"${id}\">\n\t<div tabindex=\"0\" role=\"button\" class=\"dojoxFloatingPaneTitle\" dojoAttachPoint=\"focusNode\">\n\t\t<span dojoAttachPoint=\"closeNode\" dojoAttachEvent=\"onclick: close\" class=\"dojoxFloatingCloseIcon\"></span>\n\t\t<span dojoAttachPoint=\"maxNode\" dojoAttachEvent=\"onclick: maximize\" class=\"dojoxFloatingMaximizeIcon\">&thinsp;</span>\n\t\t<span dojoAttachPoint=\"restoreNode\" dojoAttachEvent=\"onclick: _restore\" class=\"dojoxFloatingRestoreIcon\">&thinsp;</span>\t\n\t\t<span dojoAttachPoint=\"dockNode\" dojoAttachEvent=\"onclick: minimize\" class=\"dojoxFloatingMinimizeIcon\">&thinsp;</span>\n\t\t<span dojoAttachPoint=\"titleNode\" class=\"dijitInline dijitTitleNode\"></span>\n\t</div>\n\t<div dojoAttachPoint=\"canvas\" class=\"dojoxFloatingPaneCanvas\">\n\t\t<div dojoAttachPoint=\"containerNode\" role=\"region\" tabindex=\"-1\" class=\"${contentClass}\">\n\t\t</div>\n\t\t<span dojoAttachPoint=\"resizeHandle\" class=\"dojoxFloatingResizeHandle\"></span>\n\t</div>\n</div>\n",
  7283. 'dojo/uacss':function(){
  7284. define("dojo/uacss", ["./dom-geometry", "./_base/lang", "./ready", "./_base/sniff", "./_base/window"],
  7285. function(geometry, lang, ready, has, baseWindow){
  7286. // module:
  7287. // dojo/uacss
  7288. // summary:
  7289. // Applies pre-set CSS classes to the top-level HTML node, based on:
  7290. // - browser (ex: dj_ie)
  7291. // - browser version (ex: dj_ie6)
  7292. // - box model (ex: dj_contentBox)
  7293. // - text direction (ex: dijitRtl)
  7294. //
  7295. // In addition, browser, browser version, and box model are
  7296. // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl.
  7297. var
  7298. html = baseWindow.doc.documentElement,
  7299. ie = has("ie"),
  7300. opera = has("opera"),
  7301. maj = Math.floor,
  7302. ff = has("ff"),
  7303. boxModel = geometry.boxModel.replace(/-/,''),
  7304. classes = {
  7305. "dj_quirks": has("quirks"),
  7306. // NOTE: Opera not supported by dijit
  7307. "dj_opera": opera,
  7308. "dj_khtml": has("khtml"),
  7309. "dj_webkit": has("webkit"),
  7310. "dj_safari": has("safari"),
  7311. "dj_chrome": has("chrome"),
  7312. "dj_gecko": has("mozilla")
  7313. }; // no dojo unsupported browsers
  7314. if(ie){
  7315. classes["dj_ie"] = true;
  7316. classes["dj_ie" + maj(ie)] = true;
  7317. classes["dj_iequirks"] = has("quirks");
  7318. }
  7319. if(ff){
  7320. classes["dj_ff" + maj(ff)] = true;
  7321. }
  7322. classes["dj_" + boxModel] = true;
  7323. // apply browser, browser version, and box model class names
  7324. var classStr = "";
  7325. for(var clz in classes){
  7326. if(classes[clz]){
  7327. classStr += clz + " ";
  7328. }
  7329. }
  7330. html.className = lang.trim(html.className + " " + classStr);
  7331. // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
  7332. // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).
  7333. // priority is 90 to run ahead of parser priority of 100
  7334. ready(90, function(){
  7335. if(!geometry.isBodyLtr()){
  7336. var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ");
  7337. html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "));
  7338. }
  7339. });
  7340. return has;
  7341. });
  7342. },
  7343. 'dojo/string':function(){
  7344. define("dojo/string", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
  7345. // module:
  7346. // dojo/string
  7347. // summary:
  7348. // TODOC
  7349. lang.getObject("string", true, dojo);
  7350. /*=====
  7351. dojo.string = {
  7352. // summary: String utilities for Dojo
  7353. };
  7354. =====*/
  7355. dojo.string.rep = function(/*String*/str, /*Integer*/num){
  7356. // summary:
  7357. // Efficiently replicate a string `n` times.
  7358. // str:
  7359. // the string to replicate
  7360. // num:
  7361. // number of times to replicate the string
  7362. if(num <= 0 || !str){ return ""; }
  7363. var buf = [];
  7364. for(;;){
  7365. if(num & 1){
  7366. buf.push(str);
  7367. }
  7368. if(!(num >>= 1)){ break; }
  7369. str += str;
  7370. }
  7371. return buf.join(""); // String
  7372. };
  7373. dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
  7374. // summary:
  7375. // Pad a string to guarantee that it is at least `size` length by
  7376. // filling with the character `ch` at either the start or end of the
  7377. // string. Pads at the start, by default.
  7378. // text:
  7379. // the string to pad
  7380. // size:
  7381. // length to provide padding
  7382. // ch:
  7383. // character to pad, defaults to '0'
  7384. // end:
  7385. // adds padding at the end if true, otherwise pads at start
  7386. // example:
  7387. // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++".
  7388. // | dojo.string.pad("Dojo", 10, "+", true);
  7389. if(!ch){
  7390. ch = '0';
  7391. }
  7392. var out = String(text),
  7393. pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
  7394. return end ? out + pad : pad + out; // String
  7395. };
  7396. dojo.string.substitute = function( /*String*/ template,
  7397. /*Object|Array*/map,
  7398. /*Function?*/ transform,
  7399. /*Object?*/ thisObject){
  7400. // summary:
  7401. // Performs parameterized substitutions on a string. Throws an
  7402. // exception if any parameter is unmatched.
  7403. // template:
  7404. // a string with expressions in the form `${key}` to be replaced or
  7405. // `${key:format}` which specifies a format function. keys are case-sensitive.
  7406. // map:
  7407. // hash to search for substitutions
  7408. // transform:
  7409. // a function to process all parameters before substitution takes
  7410. // place, e.g. mylib.encodeXML
  7411. // thisObject:
  7412. // where to look for optional format function; default to the global
  7413. // namespace
  7414. // example:
  7415. // Substitutes two expressions in a string from an Array or Object
  7416. // | // returns "File 'foo.html' is not found in directory '/temp'."
  7417. // | // by providing substitution data in an Array
  7418. // | dojo.string.substitute(
  7419. // | "File '${0}' is not found in directory '${1}'.",
  7420. // | ["foo.html","/temp"]
  7421. // | );
  7422. // |
  7423. // | // also returns "File 'foo.html' is not found in directory '/temp'."
  7424. // | // but provides substitution data in an Object structure. Dotted
  7425. // | // notation may be used to traverse the structure.
  7426. // | dojo.string.substitute(
  7427. // | "File '${name}' is not found in directory '${info.dir}'.",
  7428. // | { name: "foo.html", info: { dir: "/temp" } }
  7429. // | );
  7430. // example:
  7431. // Use a transform function to modify the values:
  7432. // | // returns "file 'foo.html' is not found in directory '/temp'."
  7433. // | dojo.string.substitute(
  7434. // | "${0} is not found in ${1}.",
  7435. // | ["foo.html","/temp"],
  7436. // | function(str){
  7437. // | // try to figure out the type
  7438. // | var prefix = (str.charAt(0) == "/") ? "directory": "file";
  7439. // | return prefix + " '" + str + "'";
  7440. // | }
  7441. // | );
  7442. // example:
  7443. // Use a formatter
  7444. // | // returns "thinger -- howdy"
  7445. // | dojo.string.substitute(
  7446. // | "${0:postfix}", ["thinger"], null, {
  7447. // | postfix: function(value, key){
  7448. // | return value + " -- howdy";
  7449. // | }
  7450. // | }
  7451. // | );
  7452. thisObject = thisObject || dojo.global;
  7453. transform = transform ?
  7454. lang.hitch(thisObject, transform) : function(v){ return v; };
  7455. return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
  7456. function(match, key, format){
  7457. var value = lang.getObject(key, false, map);
  7458. if(format){
  7459. value = lang.getObject(format, false, thisObject).call(thisObject, value, key);
  7460. }
  7461. return transform(value, key).toString();
  7462. }); // String
  7463. };
  7464. /*=====
  7465. dojo.string.trim = function(str){
  7466. // summary:
  7467. // Trims whitespace from both sides of the string
  7468. // str: String
  7469. // String to be trimmed
  7470. // returns: String
  7471. // Returns the trimmed string
  7472. // description:
  7473. // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
  7474. // The short yet performant version of this function is dojo.trim(),
  7475. // which is part of Dojo base. Uses String.prototype.trim instead, if available.
  7476. return ""; // String
  7477. }
  7478. =====*/
  7479. dojo.string.trim = String.prototype.trim ?
  7480. lang.trim : // aliasing to the native function
  7481. function(str){
  7482. str = str.replace(/^\s+/, '');
  7483. for(var i = str.length - 1; i >= 0; i--){
  7484. if(/\S/.test(str.charAt(i))){
  7485. str = str.substring(0, i + 1);
  7486. break;
  7487. }
  7488. }
  7489. return str;
  7490. };
  7491. return dojo.string;
  7492. });
  7493. },
  7494. 'url:dijit/templates/MenuSeparator.html':"<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>",
  7495. 'dijit/Tooltip':function(){
  7496. require({cache:{
  7497. 'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\n></div>\n"}});
  7498. define("dijit/Tooltip", [
  7499. "dojo/_base/array", // array.forEach array.indexOf array.map
  7500. "dojo/_base/declare", // declare
  7501. "dojo/_base/fx", // fx.fadeIn fx.fadeOut
  7502. "dojo/dom", // dom.byId
  7503. "dojo/dom-class", // domClass.add
  7504. "dojo/dom-geometry", // domGeometry.position
  7505. "dojo/dom-style", // domStyle.set, domStyle.get
  7506. "dojo/_base/lang", // lang.hitch lang.isArrayLike
  7507. "dojo/_base/sniff", // has("ie")
  7508. "dojo/_base/window", // win.body
  7509. "./_base/manager", // manager.defaultDuration
  7510. "./place",
  7511. "./_Widget",
  7512. "./_TemplatedMixin",
  7513. "./BackgroundIframe",
  7514. "dojo/text!./templates/Tooltip.html",
  7515. "." // sets dijit.showTooltip etc. for back-compat
  7516. ], function(array, declare, fx, dom, domClass, domGeometry, domStyle, lang, has, win,
  7517. manager, place, _Widget, _TemplatedMixin, BackgroundIframe, template, dijit){
  7518. /*=====
  7519. var _Widget = dijit._Widget;
  7520. var BackgroundIframe = dijit.BackgroundIframe;
  7521. var _TemplatedMixin = dijit._TemplatedMixin;
  7522. =====*/
  7523. // module:
  7524. // dijit/Tooltip
  7525. // summary:
  7526. // Defines dijit.Tooltip widget (to display a tooltip), showTooltip()/hideTooltip(), and _MasterTooltip
  7527. var MasterTooltip = declare("dijit._MasterTooltip", [_Widget, _TemplatedMixin], {
  7528. // summary:
  7529. // Internal widget that holds the actual tooltip markup,
  7530. // which occurs once per page.
  7531. // Called by Tooltip widgets which are just containers to hold
  7532. // the markup
  7533. // tags:
  7534. // protected
  7535. // duration: Integer
  7536. // Milliseconds to fade in/fade out
  7537. duration: manager.defaultDuration,
  7538. templateString: template,
  7539. postCreate: function(){
  7540. win.body().appendChild(this.domNode);
  7541. this.bgIframe = new BackgroundIframe(this.domNode);
  7542. // Setup fade-in and fade-out functions.
  7543. this.fadeIn = fx.fadeIn({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onShow") });
  7544. this.fadeOut = fx.fadeOut({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onHide") });
  7545. },
  7546. show: function(innerHTML, aroundNode, position, rtl, textDir){
  7547. // summary:
  7548. // Display tooltip w/specified contents to right of specified node
  7549. // (To left if there's no space on the right, or if rtl == true)
  7550. // innerHTML: String
  7551. // Contents of the tooltip
  7552. // aroundNode: DomNode || dijit.__Rectangle
  7553. // Specifies that tooltip should be next to this node / area
  7554. // position: String[]?
  7555. // List of positions to try to position tooltip (ex: ["right", "above"])
  7556. // rtl: Boolean?
  7557. // Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true
  7558. // means "rtl"; specifies GUI direction, not text direction.
  7559. // textDir: String?
  7560. // Corresponds to `WidgetBase.textdir` attribute; specifies direction of text.
  7561. if(this.aroundNode && this.aroundNode === aroundNode && this.containerNode.innerHTML == innerHTML){
  7562. return;
  7563. }
  7564. // reset width; it may have been set by orient() on a previous tooltip show()
  7565. this.domNode.width = "auto";
  7566. if(this.fadeOut.status() == "playing"){
  7567. // previous tooltip is being hidden; wait until the hide completes then show new one
  7568. this._onDeck=arguments;
  7569. return;
  7570. }
  7571. this.containerNode.innerHTML=innerHTML;
  7572. if(textDir){
  7573. this.set("textDir", textDir);
  7574. }
  7575. this.containerNode.align = rtl? "right" : "left"; //fix the text alignment
  7576. var pos = place.around(this.domNode, aroundNode,
  7577. position && position.length ? position : Tooltip.defaultPosition, !rtl, lang.hitch(this, "orient"));
  7578. // Position the tooltip connector for middle alignment.
  7579. // This could not have been done in orient() since the tooltip wasn't positioned at that time.
  7580. var aroundNodeCoords = pos.aroundNodePos;
  7581. if(pos.corner.charAt(0) == 'M' && pos.aroundCorner.charAt(0) == 'M'){
  7582. this.connectorNode.style.top = aroundNodeCoords.y + ((aroundNodeCoords.h - this.connectorNode.offsetHeight) >> 1) - pos.y + "px";
  7583. this.connectorNode.style.left = "";
  7584. }else if(pos.corner.charAt(1) == 'M' && pos.aroundCorner.charAt(1) == 'M'){
  7585. this.connectorNode.style.left = aroundNodeCoords.x + ((aroundNodeCoords.w - this.connectorNode.offsetWidth) >> 1) - pos.x + "px";
  7586. }
  7587. // show it
  7588. domStyle.set(this.domNode, "opacity", 0);
  7589. this.fadeIn.play();
  7590. this.isShowingNow = true;
  7591. this.aroundNode = aroundNode;
  7592. },
  7593. orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ tooltipCorner, /*Object*/ spaceAvailable, /*Object*/ aroundNodeCoords){
  7594. // summary:
  7595. // Private function to set CSS for tooltip node based on which position it's in.
  7596. // This is called by the dijit popup code. It will also reduce the tooltip's
  7597. // width to whatever width is available
  7598. // tags:
  7599. // protected
  7600. this.connectorNode.style.top = ""; //reset to default
  7601. // Adjust for space taking by tooltip connector.
  7602. // Take care not to modify the original spaceAvailable arg as that confuses the caller (dijit.place).
  7603. var heightAvailable = spaceAvailable.h,
  7604. widthAvailable = spaceAvailable.w;
  7605. if(aroundCorner.charAt(1) != tooltipCorner.charAt(1)){
  7606. // left/right tooltip
  7607. widthAvailable -= this.connectorNode.offsetWidth;
  7608. }else{
  7609. // above/below tooltip
  7610. heightAvailable -= this.connectorNode.offsetHeight;
  7611. }
  7612. node.className = "dijitTooltip " +
  7613. {
  7614. "MR-ML": "dijitTooltipRight",
  7615. "ML-MR": "dijitTooltipLeft",
  7616. "TM-BM": "dijitTooltipAbove",
  7617. "BM-TM": "dijitTooltipBelow",
  7618. "BL-TL": "dijitTooltipBelow dijitTooltipABLeft",
  7619. "TL-BL": "dijitTooltipAbove dijitTooltipABLeft",
  7620. "BR-TR": "dijitTooltipBelow dijitTooltipABRight",
  7621. "TR-BR": "dijitTooltipAbove dijitTooltipABRight",
  7622. "BR-BL": "dijitTooltipRight",
  7623. "BL-BR": "dijitTooltipLeft"
  7624. }[aroundCorner + "-" + tooltipCorner];
  7625. // reduce tooltip's width to the amount of width available, so that it doesn't overflow screen
  7626. this.domNode.style.width = "auto";
  7627. var size = domGeometry.getContentBox(this.domNode);
  7628. var width = Math.min((Math.max(widthAvailable,1)), size.w);
  7629. var widthWasReduced = width < size.w;
  7630. this.domNode.style.width = width+"px";
  7631. // Reposition the tooltip connector.
  7632. if(tooltipCorner.charAt(0) == 'B' && aroundCorner.charAt(0) == 'B'){
  7633. var bb = domGeometry.position(node);
  7634. var tooltipConnectorHeight = this.connectorNode.offsetHeight;
  7635. if(bb.h > heightAvailable){
  7636. // The tooltip starts at the top of the page and will extend past the aroundNode
  7637. var aroundNodePlacement = heightAvailable - ((aroundNodeCoords.h + tooltipConnectorHeight) >> 1);
  7638. this.connectorNode.style.top = aroundNodePlacement + "px";
  7639. this.connectorNode.style.bottom = "";
  7640. }else{
  7641. // Align center of connector with center of aroundNode, except don't let bottom
  7642. // of connector extend below bottom of tooltip content, or top of connector
  7643. // extend past top of tooltip content
  7644. this.connectorNode.style.bottom = Math.min(
  7645. Math.max(aroundNodeCoords.h/2 - tooltipConnectorHeight/2, 0),
  7646. bb.h - tooltipConnectorHeight) + "px";
  7647. this.connectorNode.style.top = "";
  7648. }
  7649. }else{
  7650. // reset the tooltip back to the defaults
  7651. this.connectorNode.style.top = "";
  7652. this.connectorNode.style.bottom = "";
  7653. }
  7654. return Math.max(0, size.w - widthAvailable);
  7655. },
  7656. _onShow: function(){
  7657. // summary:
  7658. // Called at end of fade-in operation
  7659. // tags:
  7660. // protected
  7661. if(has("ie")){
  7662. // the arrow won't show up on a node w/an opacity filter
  7663. this.domNode.style.filter="";
  7664. }
  7665. },
  7666. hide: function(aroundNode){
  7667. // summary:
  7668. // Hide the tooltip
  7669. if(this._onDeck && this._onDeck[1] == aroundNode){
  7670. // this hide request is for a show() that hasn't even started yet;
  7671. // just cancel the pending show()
  7672. this._onDeck=null;
  7673. }else if(this.aroundNode === aroundNode){
  7674. // this hide request is for the currently displayed tooltip
  7675. this.fadeIn.stop();
  7676. this.isShowingNow = false;
  7677. this.aroundNode = null;
  7678. this.fadeOut.play();
  7679. }else{
  7680. // just ignore the call, it's for a tooltip that has already been erased
  7681. }
  7682. },
  7683. _onHide: function(){
  7684. // summary:
  7685. // Called at end of fade-out operation
  7686. // tags:
  7687. // protected
  7688. this.domNode.style.cssText=""; // to position offscreen again
  7689. this.containerNode.innerHTML="";
  7690. if(this._onDeck){
  7691. // a show request has been queued up; do it now
  7692. this.show.apply(this, this._onDeck);
  7693. this._onDeck=null;
  7694. }
  7695. },
  7696. _setAutoTextDir: function(/*Object*/node){
  7697. // summary:
  7698. // Resolve "auto" text direction for children nodes
  7699. // tags:
  7700. // private
  7701. this.applyTextDir(node, has("ie") ? node.outerText : node.textContent);
  7702. array.forEach(node.children, function(child){this._setAutoTextDir(child); }, this);
  7703. },
  7704. _setTextDirAttr: function(/*String*/ textDir){
  7705. // summary:
  7706. // Setter for textDir.
  7707. // description:
  7708. // Users shouldn't call this function; they should be calling
  7709. // set('textDir', value)
  7710. // tags:
  7711. // private
  7712. this._set("textDir", textDir);
  7713. if (textDir == "auto"){
  7714. this._setAutoTextDir(this.containerNode);
  7715. }else{
  7716. this.containerNode.dir = this.textDir;
  7717. }
  7718. }
  7719. });
  7720. dijit.showTooltip = function(innerHTML, aroundNode, position, rtl, textDir){
  7721. // summary:
  7722. // Static method to display tooltip w/specified contents in specified position.
  7723. // See description of dijit.Tooltip.defaultPosition for details on position parameter.
  7724. // If position is not specified then dijit.Tooltip.defaultPosition is used.
  7725. // innerHTML: String
  7726. // Contents of the tooltip
  7727. // aroundNode: dijit.__Rectangle
  7728. // Specifies that tooltip should be next to this node / area
  7729. // position: String[]?
  7730. // List of positions to try to position tooltip (ex: ["right", "above"])
  7731. // rtl: Boolean?
  7732. // Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true
  7733. // means "rtl"; specifies GUI direction, not text direction.
  7734. // textDir: String?
  7735. // Corresponds to `WidgetBase.textdir` attribute; specifies direction of text.
  7736. // after/before don't work, but they used to, so for back-compat convert them to after-centered, before-centered
  7737. if(position){
  7738. position = array.map(position, function(val){
  7739. return {after: "after-centered", before: "before-centered"}[val] || val;
  7740. });
  7741. }
  7742. if(!Tooltip._masterTT){ dijit._masterTT = Tooltip._masterTT = new MasterTooltip(); }
  7743. return Tooltip._masterTT.show(innerHTML, aroundNode, position, rtl, textDir);
  7744. };
  7745. dijit.hideTooltip = function(aroundNode){
  7746. // summary:
  7747. // Static method to hide the tooltip displayed via showTooltip()
  7748. return Tooltip._masterTT && Tooltip._masterTT.hide(aroundNode);
  7749. };
  7750. var Tooltip = declare("dijit.Tooltip", _Widget, {
  7751. // summary:
  7752. // Pops up a tooltip (a help message) when you hover over a node.
  7753. // label: String
  7754. // Text to display in the tooltip.
  7755. // Specified as innerHTML when creating the widget from markup.
  7756. label: "",
  7757. // showDelay: Integer
  7758. // Number of milliseconds to wait after hovering over/focusing on the object, before
  7759. // the tooltip is displayed.
  7760. showDelay: 400,
  7761. // connectId: String|String[]
  7762. // Id of domNode(s) to attach the tooltip to.
  7763. // When user hovers over specified dom node, the tooltip will appear.
  7764. connectId: [],
  7765. // position: String[]
  7766. // See description of `dijit.Tooltip.defaultPosition` for details on position parameter.
  7767. position: [],
  7768. _setConnectIdAttr: function(/*String|String[]*/ newId){
  7769. // summary:
  7770. // Connect to specified node(s)
  7771. // Remove connections to old nodes (if there are any)
  7772. array.forEach(this._connections || [], function(nested){
  7773. array.forEach(nested, lang.hitch(this, "disconnect"));
  7774. }, this);
  7775. // Make array of id's to connect to, excluding entries for nodes that don't exist yet, see startup()
  7776. this._connectIds = array.filter(lang.isArrayLike(newId) ? newId : (newId ? [newId] : []),
  7777. function(id){ return dom.byId(id); });
  7778. // Make connections
  7779. this._connections = array.map(this._connectIds, function(id){
  7780. var node = dom.byId(id);
  7781. return [
  7782. this.connect(node, "onmouseenter", "_onHover"),
  7783. this.connect(node, "onmouseleave", "_onUnHover"),
  7784. this.connect(node, "onfocus", "_onHover"),
  7785. this.connect(node, "onblur", "_onUnHover")
  7786. ];
  7787. }, this);
  7788. this._set("connectId", newId);
  7789. },
  7790. addTarget: function(/*DOMNODE || String*/ node){
  7791. // summary:
  7792. // Attach tooltip to specified node if it's not already connected
  7793. // TODO: remove in 2.0 and just use set("connectId", ...) interface
  7794. var id = node.id || node;
  7795. if(array.indexOf(this._connectIds, id) == -1){
  7796. this.set("connectId", this._connectIds.concat(id));
  7797. }
  7798. },
  7799. removeTarget: function(/*DomNode || String*/ node){
  7800. // summary:
  7801. // Detach tooltip from specified node
  7802. // TODO: remove in 2.0 and just use set("connectId", ...) interface
  7803. var id = node.id || node, // map from DOMNode back to plain id string
  7804. idx = array.indexOf(this._connectIds, id);
  7805. if(idx >= 0){
  7806. // remove id (modifies original this._connectIds but that's OK in this case)
  7807. this._connectIds.splice(idx, 1);
  7808. this.set("connectId", this._connectIds);
  7809. }
  7810. },
  7811. buildRendering: function(){
  7812. this.inherited(arguments);
  7813. domClass.add(this.domNode,"dijitTooltipData");
  7814. },
  7815. startup: function(){
  7816. this.inherited(arguments);
  7817. // If this tooltip was created in a template, or for some other reason the specified connectId[s]
  7818. // didn't exist during the widget's initialization, then connect now.
  7819. var ids = this.connectId;
  7820. array.forEach(lang.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
  7821. },
  7822. _onHover: function(/*Event*/ e){
  7823. // summary:
  7824. // Despite the name of this method, it actually handles both hover and focus
  7825. // events on the target node, setting a timer to show the tooltip.
  7826. // tags:
  7827. // private
  7828. if(!this._showTimer){
  7829. var target = e.target;
  7830. this._showTimer = setTimeout(lang.hitch(this, function(){this.open(target)}), this.showDelay);
  7831. }
  7832. },
  7833. _onUnHover: function(/*Event*/ /*===== e =====*/){
  7834. // summary:
  7835. // Despite the name of this method, it actually handles both mouseleave and blur
  7836. // events on the target node, hiding the tooltip.
  7837. // tags:
  7838. // private
  7839. // keep a tooltip open if the associated element still has focus (even though the
  7840. // mouse moved away)
  7841. if(this._focus){ return; }
  7842. if(this._showTimer){
  7843. clearTimeout(this._showTimer);
  7844. delete this._showTimer;
  7845. }
  7846. this.close();
  7847. },
  7848. open: function(/*DomNode*/ target){
  7849. // summary:
  7850. // Display the tooltip; usually not called directly.
  7851. // tags:
  7852. // private
  7853. if(this._showTimer){
  7854. clearTimeout(this._showTimer);
  7855. delete this._showTimer;
  7856. }
  7857. Tooltip.show(this.label || this.domNode.innerHTML, target, this.position, !this.isLeftToRight(), this.textDir);
  7858. this._connectNode = target;
  7859. this.onShow(target, this.position);
  7860. },
  7861. close: function(){
  7862. // summary:
  7863. // Hide the tooltip or cancel timer for show of tooltip
  7864. // tags:
  7865. // private
  7866. if(this._connectNode){
  7867. // if tooltip is currently shown
  7868. Tooltip.hide(this._connectNode);
  7869. delete this._connectNode;
  7870. this.onHide();
  7871. }
  7872. if(this._showTimer){
  7873. // if tooltip is scheduled to be shown (after a brief delay)
  7874. clearTimeout(this._showTimer);
  7875. delete this._showTimer;
  7876. }
  7877. },
  7878. onShow: function(/*===== target, position =====*/){
  7879. // summary:
  7880. // Called when the tooltip is shown
  7881. // tags:
  7882. // callback
  7883. },
  7884. onHide: function(){
  7885. // summary:
  7886. // Called when the tooltip is hidden
  7887. // tags:
  7888. // callback
  7889. },
  7890. uninitialize: function(){
  7891. this.close();
  7892. this.inherited(arguments);
  7893. }
  7894. });
  7895. Tooltip._MasterTooltip = MasterTooltip; // for monkey patching
  7896. Tooltip.show = dijit.showTooltip; // export function through module return value
  7897. Tooltip.hide = dijit.hideTooltip; // export function through module return value
  7898. // dijit.Tooltip.defaultPosition: String[]
  7899. // This variable controls the position of tooltips, if the position is not specified to
  7900. // the Tooltip widget or *TextBox widget itself. It's an array of strings with the values
  7901. // possible for `dijit/place::around()`. The recommended values are:
  7902. //
  7903. // * before-centered: centers tooltip to the left of the anchor node/widget, or to the right
  7904. // in the case of RTL scripts like Hebrew and Arabic
  7905. // * after-centered: centers tooltip to the right of the anchor node/widget, or to the left
  7906. // in the case of RTL scripts like Hebrew and Arabic
  7907. // * above-centered: tooltip is centered above anchor node
  7908. // * below-centered: tooltip is centered above anchor node
  7909. //
  7910. // The list is positions is tried, in order, until a position is found where the tooltip fits
  7911. // within the viewport.
  7912. //
  7913. // Be careful setting this parameter. A value of "above-centered" may work fine until the user scrolls
  7914. // the screen so that there's no room above the target node. Nodes with drop downs, like
  7915. // DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure
  7916. // that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there
  7917. // is only room below (or above) the target node, but not both.
  7918. Tooltip.defaultPosition = ["after-centered", "before-centered"];
  7919. return Tooltip;
  7920. });
  7921. },
  7922. 'dijit/form/DropDownButton':function(){
  7923. require({cache:{
  7924. 'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">&#9660;</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-point=\"valueNode\" role=\"presentation\"\n/></span>\n"}});
  7925. define("dijit/form/DropDownButton", [
  7926. "dojo/_base/declare", // declare
  7927. "dojo/_base/lang", // hitch
  7928. "dojo/query", // query
  7929. "../registry", // registry.byNode
  7930. "../popup", // dijit.popup2.hide
  7931. "./Button",
  7932. "../_Container",
  7933. "../_HasDropDown",
  7934. "dojo/text!./templates/DropDownButton.html"
  7935. ], function(declare, lang, query, registry, popup, Button, _Container, _HasDropDown, template){
  7936. /*=====
  7937. Button = dijit.form.Button;
  7938. _Container = dijit._Container;
  7939. _HasDropDown = dijit._HasDropDown;
  7940. =====*/
  7941. // module:
  7942. // dijit/form/DropDownButton
  7943. // summary:
  7944. // A button with a drop down
  7945. return declare("dijit.form.DropDownButton", [Button, _Container, _HasDropDown], {
  7946. // summary:
  7947. // A button with a drop down
  7948. //
  7949. // example:
  7950. // | <button data-dojo-type="dijit.form.DropDownButton">
  7951. // | Hello world
  7952. // | <div data-dojo-type="dijit.Menu">...</div>
  7953. // | </button>
  7954. //
  7955. // example:
  7956. // | var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
  7957. // | win.body().appendChild(button1);
  7958. //
  7959. baseClass : "dijitDropDownButton",
  7960. templateString: template,
  7961. _fillContent: function(){
  7962. // Overrides Button._fillContent().
  7963. //
  7964. // My inner HTML contains both the button contents and a drop down widget, like
  7965. // <DropDownButton> <span>push me</span> <Menu> ... </Menu> </DropDownButton>
  7966. // The first node is assumed to be the button content. The widget is the popup.
  7967. if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
  7968. //FIXME: figure out how to filter out the widget and use all remaining nodes as button
  7969. // content, not just nodes[0]
  7970. var nodes = query("*", this.srcNodeRef);
  7971. this.inherited(arguments, [nodes[0]]);
  7972. // save pointer to srcNode so we can grab the drop down widget after it's instantiated
  7973. this.dropDownContainer = this.srcNodeRef;
  7974. }
  7975. },
  7976. startup: function(){
  7977. if(this._started){ return; }
  7978. // the child widget from srcNodeRef is the dropdown widget. Insert it in the page DOM,
  7979. // make it invisible, and store a reference to pass to the popup code.
  7980. if(!this.dropDown && this.dropDownContainer){
  7981. var dropDownNode = query("[widgetId]", this.dropDownContainer)[0];
  7982. this.dropDown = registry.byNode(dropDownNode);
  7983. delete this.dropDownContainer;
  7984. }
  7985. if(this.dropDown){
  7986. popup.hide(this.dropDown);
  7987. }
  7988. this.inherited(arguments);
  7989. },
  7990. isLoaded: function(){
  7991. // Returns whether or not we are loaded - if our dropdown has an href,
  7992. // then we want to check that.
  7993. var dropDown = this.dropDown;
  7994. return (!!dropDown && (!dropDown.href || dropDown.isLoaded));
  7995. },
  7996. loadDropDown: function(/*Function*/ callback){
  7997. // Default implementation assumes that drop down already exists,
  7998. // but hasn't loaded it's data (ex: ContentPane w/href).
  7999. // App must override if the drop down is lazy-created.
  8000. var dropDown = this.dropDown;
  8001. var handler = dropDown.on("load", lang.hitch(this, function(){
  8002. handler.remove();
  8003. callback();
  8004. }));
  8005. dropDown.refresh(); // tell it to load
  8006. },
  8007. isFocusable: function(){
  8008. // Overridden so that focus is handled by the _HasDropDown mixin, not by
  8009. // the _FormWidget mixin.
  8010. return this.inherited(arguments) && !this._mouseDown;
  8011. }
  8012. });
  8013. });
  8014. },
  8015. 'dijit/form/_FormValueMixin':function(){
  8016. define("dijit/form/_FormValueMixin", [
  8017. "dojo/_base/declare", // declare
  8018. "dojo/dom-attr", // domAttr.set
  8019. "dojo/keys", // keys.ESCAPE
  8020. "dojo/_base/sniff", // has("ie"), has("quirks")
  8021. "./_FormWidgetMixin"
  8022. ], function(declare, domAttr, keys, has, _FormWidgetMixin){
  8023. /*=====
  8024. var _FormWidgetMixin = dijit.form._FormWidgetMixin;
  8025. =====*/
  8026. // module:
  8027. // dijit/form/_FormValueMixin
  8028. // summary:
  8029. // Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
  8030. return declare("dijit.form._FormValueMixin", _FormWidgetMixin, {
  8031. // summary:
  8032. // Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
  8033. // description:
  8034. // Each _FormValueMixin represents a single input value, and has a (possibly hidden) <input> element,
  8035. // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
  8036. // works as expected.
  8037. // readOnly: Boolean
  8038. // Should this widget respond to user input?
  8039. // In markup, this is specified as "readOnly".
  8040. // Similar to disabled except readOnly form values are submitted.
  8041. readOnly: false,
  8042. _setReadOnlyAttr: function(/*Boolean*/ value){
  8043. domAttr.set(this.focusNode, 'readOnly', value);
  8044. this._set("readOnly", value);
  8045. },
  8046. postCreate: function(){
  8047. this.inherited(arguments);
  8048. if(has("ie")){ // IE won't stop the event with keypress
  8049. this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
  8050. }
  8051. // Update our reset value if it hasn't yet been set (because this.set()
  8052. // is only called when there *is* a value)
  8053. if(this._resetValue === undefined){
  8054. this._lastValueReported = this._resetValue = this.value;
  8055. }
  8056. },
  8057. _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  8058. // summary:
  8059. // Hook so set('value', value) works.
  8060. // description:
  8061. // Sets the value of the widget.
  8062. // If the value has changed, then fire onChange event, unless priorityChange
  8063. // is specified as null (or false?)
  8064. this._handleOnChange(newValue, priorityChange);
  8065. },
  8066. _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  8067. // summary:
  8068. // Called when the value of the widget has changed. Saves the new value in this.value,
  8069. // and calls onChange() if appropriate. See _FormWidget._handleOnChange() for details.
  8070. this._set("value", newValue);
  8071. this.inherited(arguments);
  8072. },
  8073. undo: function(){
  8074. // summary:
  8075. // Restore the value to the last value passed to onChange
  8076. this._setValueAttr(this._lastValueReported, false);
  8077. },
  8078. reset: function(){
  8079. // summary:
  8080. // Reset the widget's value to what it was at initialization time
  8081. this._hasBeenBlurred = false;
  8082. this._setValueAttr(this._resetValue, true);
  8083. },
  8084. _onKeyDown: function(e){
  8085. if(e.keyCode == keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){
  8086. var te;
  8087. if(has("ie") < 9 || (has("ie") && has("quirks"))){
  8088. e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
  8089. te = document.createEventObject();
  8090. te.keyCode = keys.ESCAPE;
  8091. te.shiftKey = e.shiftKey;
  8092. e.srcElement.fireEvent('onkeypress', te);
  8093. }
  8094. }
  8095. }
  8096. });
  8097. });
  8098. },
  8099. 'dojox/layout/ContentPane':function(){
  8100. define("dojox/layout/ContentPane", [
  8101. "dojo/_base/lang",
  8102. "dojo/_base/xhr",
  8103. "dijit/layout/ContentPane",
  8104. "dojox/html/_base",
  8105. "dojo/_base/declare"
  8106. ], function (lang, xhrUtil, ContentPane, htmlUtil, declare) {
  8107. /*===== var ContentPane = dijit.layout.ContentPane =====*/
  8108. return declare("dojox.layout.ContentPane", ContentPane, {
  8109. // summary:
  8110. // An extended version of dijit.layout.ContentPane.
  8111. // Supports infile scripts and external ones declared by <script src=''
  8112. // relative path adjustments (content fetched from a different folder)
  8113. // <style> and <link rel='stylesheet' href='..'> tags,
  8114. // css paths inside cssText is adjusted (if you set adjustPaths = true)
  8115. //
  8116. // NOTE that dojo.require in script in the fetched file isn't recommended
  8117. // Many widgets need to be required at page load to work properly
  8118. // adjustPaths: Boolean
  8119. // Adjust relative paths in html string content to point to this page.
  8120. // Only useful if you grab content from a another folder then the current one
  8121. adjustPaths: false,
  8122. // cleanContent: Boolean
  8123. // summary:
  8124. // cleans content to make it less likely to generate DOM/JS errors.
  8125. // description:
  8126. // useful if you send ContentPane a complete page, instead of a html fragment
  8127. // scans for
  8128. //
  8129. // * title Node, remove
  8130. // * DOCTYPE tag, remove
  8131. cleanContent: false,
  8132. // renderStyles: Boolean
  8133. // trigger/load styles in the content
  8134. renderStyles: false,
  8135. // executeScripts: Boolean
  8136. // Execute (eval) scripts that is found in the content
  8137. executeScripts: true,
  8138. // scriptHasHooks: Boolean
  8139. // replace keyword '_container_' in scripts with 'dijit.byId(this.id)'
  8140. // NOTE this name might change in the near future
  8141. scriptHasHooks: false,
  8142. constructor: function(){
  8143. // init per instance properties, initializer doesn't work here because how things is hooked up in dijit._Widget
  8144. this.ioArgs = {};
  8145. this.ioMethod = xhrUtil.get;
  8146. },
  8147. onExecError: function(e){
  8148. // summary:
  8149. // event callback, called on script error or on java handler error
  8150. // overide and return your own html string if you want a some text
  8151. // displayed within the ContentPane
  8152. },
  8153. _setContent: function(cont){
  8154. // override dijit.layout.ContentPane._setContent, to enable path adjustments
  8155. var setter = this._contentSetter;
  8156. if(! (setter && setter instanceof htmlUtil._ContentSetter)) {
  8157. setter = this._contentSetter = new htmlUtil._ContentSetter({
  8158. node: this.containerNode,
  8159. _onError: lang.hitch(this, this._onError),
  8160. onContentError: lang.hitch(this, function(e){
  8161. // fires if a domfault occurs when we are appending this.errorMessage
  8162. // like for instance if domNode is a UL and we try append a DIV
  8163. var errMess = this.onContentError(e);
  8164. try{
  8165. this.containerNode.innerHTML = errMess;
  8166. }catch(e){
  8167. console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
  8168. }
  8169. })/*,
  8170. _onError */
  8171. });
  8172. };
  8173. // stash the params for the contentSetter to allow inheritance to work for _setContent
  8174. this._contentSetterParams = {
  8175. adjustPaths: Boolean(this.adjustPaths && (this.href||this.referencePath)),
  8176. referencePath: this.href || this.referencePath,
  8177. renderStyles: this.renderStyles,
  8178. executeScripts: this.executeScripts,
  8179. scriptHasHooks: this.scriptHasHooks,
  8180. scriptHookReplacement: "dijit.byId('"+this.id+"')"
  8181. };
  8182. this.inherited("_setContent", arguments);
  8183. },
  8184. // could put back _renderStyles by wrapping/aliasing dojox.html._ContentSetter.prototype._renderStyles
  8185. destroy: function () {
  8186. var setter = this._contentSetter;
  8187. if (setter) {
  8188. setter.tearDown();
  8189. }
  8190. this.inherited(arguments);
  8191. }
  8192. });
  8193. });
  8194. },
  8195. 'dijit/form/_FormWidgetMixin':function(){
  8196. define("dijit/form/_FormWidgetMixin", [
  8197. "dojo/_base/array", // array.forEach
  8198. "dojo/_base/declare", // declare
  8199. "dojo/dom-attr", // domAttr.set
  8200. "dojo/dom-style", // domStyle.get
  8201. "dojo/_base/lang", // lang.hitch lang.isArray
  8202. "dojo/mouse", // mouse.isLeft
  8203. "dojo/_base/sniff", // has("webkit")
  8204. "dojo/_base/window", // win.body
  8205. "dojo/window", // winUtils.scrollIntoView
  8206. "../a11y" // a11y.hasDefaultTabStop
  8207. ], function(array, declare, domAttr, domStyle, lang, mouse, has, win, winUtils, a11y){
  8208. // module:
  8209. // dijit/form/_FormWidgetMixin
  8210. // summary:
  8211. // Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
  8212. // which can be children of a <form> node or a `dijit.form.Form` widget.
  8213. return declare("dijit.form._FormWidgetMixin", null, {
  8214. // summary:
  8215. // Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
  8216. // which can be children of a <form> node or a `dijit.form.Form` widget.
  8217. //
  8218. // description:
  8219. // Represents a single HTML element.
  8220. // All these widgets should have these attributes just like native HTML input elements.
  8221. // You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
  8222. //
  8223. // They also share some common methods.
  8224. // name: [const] String
  8225. // Name used when submitting form; same as "name" attribute or plain HTML elements
  8226. name: "",
  8227. // alt: String
  8228. // Corresponds to the native HTML <input> element's attribute.
  8229. alt: "",
  8230. // value: String
  8231. // Corresponds to the native HTML <input> element's attribute.
  8232. value: "",
  8233. // type: [const] String
  8234. // Corresponds to the native HTML <input> element's attribute.
  8235. type: "text",
  8236. // tabIndex: Integer
  8237. // Order fields are traversed when user hits the tab key
  8238. tabIndex: "0",
  8239. _setTabIndexAttr: "focusNode", // force copy even when tabIndex default value, needed since Button is <span>
  8240. // disabled: Boolean
  8241. // Should this widget respond to user input?
  8242. // In markup, this is specified as "disabled='disabled'", or just "disabled".
  8243. disabled: false,
  8244. // intermediateChanges: Boolean
  8245. // Fires onChange for each value change or only on demand
  8246. intermediateChanges: false,
  8247. // scrollOnFocus: Boolean
  8248. // On focus, should this widget scroll into view?
  8249. scrollOnFocus: true,
  8250. // Override _WidgetBase mapping id to this.domNode, needs to be on focusNode so <label> etc.
  8251. // works with screen reader
  8252. _setIdAttr: "focusNode",
  8253. _setDisabledAttr: function(/*Boolean*/ value){
  8254. this._set("disabled", value);
  8255. domAttr.set(this.focusNode, 'disabled', value);
  8256. if(this.valueNode){
  8257. domAttr.set(this.valueNode, 'disabled', value);
  8258. }
  8259. this.focusNode.setAttribute("aria-disabled", value ? "true" : "false");
  8260. if(value){
  8261. // reset these, because after the domNode is disabled, we can no longer receive
  8262. // mouse related events, see #4200
  8263. this._set("hovering", false);
  8264. this._set("active", false);
  8265. // clear tab stop(s) on this widget's focusable node(s) (ComboBox has two focusable nodes)
  8266. var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex :
  8267. ("_setTabIndexAttr" in this) ? this._setTabIndexAttr : "focusNode";
  8268. array.forEach(lang.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
  8269. var node = this[attachPointName];
  8270. // complex code because tabIndex=-1 on a <div> doesn't work on FF
  8271. if(has("webkit") || a11y.hasDefaultTabStop(node)){ // see #11064 about webkit bug
  8272. node.setAttribute('tabIndex', "-1");
  8273. }else{
  8274. node.removeAttribute('tabIndex');
  8275. }
  8276. }, this);
  8277. }else{
  8278. if(this.tabIndex != ""){
  8279. this.set('tabIndex', this.tabIndex);
  8280. }
  8281. }
  8282. },
  8283. _onFocus: function(/*String*/ by){
  8284. // If user clicks on the widget, even if the mouse is released outside of it,
  8285. // this widget's focusNode should get focus (to mimic native browser hehavior).
  8286. // Browsers often need help to make sure the focus via mouse actually gets to the focusNode.
  8287. if(by == "mouse" && this.isFocusable()){
  8288. // IE exhibits strange scrolling behavior when refocusing a node so only do it when !focused.
  8289. var focusConnector = this.connect(this.focusNode, "onfocus", function(){
  8290. this.disconnect(mouseUpConnector);
  8291. this.disconnect(focusConnector);
  8292. });
  8293. // Set a global event to handle mouseup, so it fires properly
  8294. // even if the cursor leaves this.domNode before the mouse up event.
  8295. var mouseUpConnector = this.connect(win.body(), "onmouseup", function(){
  8296. this.disconnect(mouseUpConnector);
  8297. this.disconnect(focusConnector);
  8298. // if here, then the mousedown did not focus the focusNode as the default action
  8299. if(this.focused){
  8300. this.focus();
  8301. }
  8302. });
  8303. }
  8304. if(this.scrollOnFocus){
  8305. this.defer(function(){ winUtils.scrollIntoView(this.domNode); }); // without defer, the input caret position can change on mouse click
  8306. }
  8307. this.inherited(arguments);
  8308. },
  8309. isFocusable: function(){
  8310. // summary:
  8311. // Tells if this widget is focusable or not. Used internally by dijit.
  8312. // tags:
  8313. // protected
  8314. return !this.disabled && this.focusNode && (domStyle.get(this.domNode, "display") != "none");
  8315. },
  8316. focus: function(){
  8317. // summary:
  8318. // Put focus on this widget
  8319. if(!this.disabled && this.focusNode.focus){
  8320. try{ this.focusNode.focus(); }catch(e){}/*squelch errors from hidden nodes*/
  8321. }
  8322. },
  8323. compare: function(/*anything*/ val1, /*anything*/ val2){
  8324. // summary:
  8325. // Compare 2 values (as returned by get('value') for this widget).
  8326. // tags:
  8327. // protected
  8328. if(typeof val1 == "number" && typeof val2 == "number"){
  8329. return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2;
  8330. }else if(val1 > val2){
  8331. return 1;
  8332. }else if(val1 < val2){
  8333. return -1;
  8334. }else{
  8335. return 0;
  8336. }
  8337. },
  8338. onChange: function(/*===== newValue =====*/){
  8339. // summary:
  8340. // Callback when this widget's value is changed.
  8341. // tags:
  8342. // callback
  8343. },
  8344. // _onChangeActive: [private] Boolean
  8345. // Indicates that changes to the value should call onChange() callback.
  8346. // This is false during widget initialization, to avoid calling onChange()
  8347. // when the initial value is set.
  8348. _onChangeActive: false,
  8349. _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  8350. // summary:
  8351. // Called when the value of the widget is set. Calls onChange() if appropriate
  8352. // newValue:
  8353. // the new value
  8354. // priorityChange:
  8355. // For a slider, for example, dragging the slider is priorityChange==false,
  8356. // but on mouse up, it's priorityChange==true. If intermediateChanges==false,
  8357. // onChange is only called form priorityChange=true events.
  8358. // tags:
  8359. // private
  8360. if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
  8361. // this block executes not for a change, but during initialization,
  8362. // and is used to store away the original value (or for ToggleButton, the original checked state)
  8363. this._resetValue = this._lastValueReported = newValue;
  8364. }
  8365. this._pendingOnChange = this._pendingOnChange
  8366. || (typeof newValue != typeof this._lastValueReported)
  8367. || (this.compare(newValue, this._lastValueReported) != 0);
  8368. if((this.intermediateChanges || priorityChange || priorityChange === undefined) && this._pendingOnChange){
  8369. this._lastValueReported = newValue;
  8370. this._pendingOnChange = false;
  8371. if(this._onChangeActive){
  8372. if(this._onChangeHandle){
  8373. this._onChangeHandle.remove();
  8374. }
  8375. // defer allows hidden value processing to run and
  8376. // also the onChange handler can safely adjust focus, etc
  8377. this._onChangeHandle = this.defer(
  8378. function(){
  8379. this._onChangeHandle = null;
  8380. this.onChange(newValue);
  8381. }); // try to collapse multiple onChange's fired faster than can be processed
  8382. }
  8383. }
  8384. },
  8385. create: function(){
  8386. // Overrides _Widget.create()
  8387. this.inherited(arguments);
  8388. this._onChangeActive = true;
  8389. },
  8390. destroy: function(){
  8391. if(this._onChangeHandle){ // destroy called before last onChange has fired
  8392. this._onChangeHandle.remove();
  8393. this.onChange(this._lastValueReported);
  8394. }
  8395. this.inherited(arguments);
  8396. }
  8397. });
  8398. });
  8399. },
  8400. 'dojo/date':function(){
  8401. define("dojo/date", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
  8402. // module:
  8403. // dojo/date
  8404. // summary:
  8405. // TODOC
  8406. lang.getObject("date", true, dojo);
  8407. /*=====
  8408. dojo.date = {
  8409. // summary: Date manipulation utilities
  8410. }
  8411. =====*/
  8412. dojo.date.getDaysInMonth = function(/*Date*/dateObject){
  8413. // summary:
  8414. // Returns the number of days in the month used by dateObject
  8415. var month = dateObject.getMonth();
  8416. var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  8417. if(month == 1 && dojo.date.isLeapYear(dateObject)){ return 29; } // Number
  8418. return days[month]; // Number
  8419. };
  8420. dojo.date.isLeapYear = function(/*Date*/dateObject){
  8421. // summary:
  8422. // Determines if the year of the dateObject is a leap year
  8423. // description:
  8424. // Leap years are years with an additional day YYYY-02-29, where the
  8425. // year number is a multiple of four with the following exception: If
  8426. // a year is a multiple of 100, then it is only a leap year if it is
  8427. // also a multiple of 400. For example, 1900 was not a leap year, but
  8428. // 2000 is one.
  8429. var year = dateObject.getFullYear();
  8430. return !(year%400) || (!(year%4) && !!(year%100)); // Boolean
  8431. };
  8432. // FIXME: This is not localized
  8433. dojo.date.getTimezoneName = function(/*Date*/dateObject){
  8434. // summary:
  8435. // Get the user's time zone as provided by the browser
  8436. // dateObject:
  8437. // Needed because the timezone may vary with time (daylight savings)
  8438. // description:
  8439. // Try to get time zone info from toString or toLocaleString method of
  8440. // the Date object -- UTC offset is not a time zone. See
  8441. // http://www.twinsun.com/tz/tz-link.htm Note: results may be
  8442. // inconsistent across browsers.
  8443. var str = dateObject.toString(); // Start looking in toString
  8444. var tz = ''; // The result -- return empty string if nothing found
  8445. var match;
  8446. // First look for something in parentheses -- fast lookup, no regex
  8447. var pos = str.indexOf('(');
  8448. if(pos > -1){
  8449. tz = str.substring(++pos, str.indexOf(')'));
  8450. }else{
  8451. // If at first you don't succeed ...
  8452. // If IE knows about the TZ, it appears before the year
  8453. // Capital letters or slash before a 4-digit year
  8454. // at the end of string
  8455. var pat = /([A-Z\/]+) \d{4}$/;
  8456. if((match = str.match(pat))){
  8457. tz = match[1];
  8458. }else{
  8459. // Some browsers (e.g. Safari) glue the TZ on the end
  8460. // of toLocaleString instead of putting it in toString
  8461. str = dateObject.toLocaleString();
  8462. // Capital letters or slash -- end of string,
  8463. // after space
  8464. pat = / ([A-Z\/]+)$/;
  8465. if((match = str.match(pat))){
  8466. tz = match[1];
  8467. }
  8468. }
  8469. }
  8470. // Make sure it doesn't somehow end up return AM or PM
  8471. return (tz == 'AM' || tz == 'PM') ? '' : tz; // String
  8472. };
  8473. // Utility methods to do arithmetic calculations with Dates
  8474. dojo.date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){
  8475. // summary:
  8476. // Compare two date objects by date, time, or both.
  8477. // description:
  8478. // Returns 0 if equal, positive if a > b, else negative.
  8479. // date1:
  8480. // Date object
  8481. // date2:
  8482. // Date object. If not specified, the current Date is used.
  8483. // portion:
  8484. // A string indicating the "date" or "time" portion of a Date object.
  8485. // Compares both "date" and "time" by default. One of the following:
  8486. // "date", "time", "datetime"
  8487. // Extra step required in copy for IE - see #3112
  8488. date1 = new Date(+date1);
  8489. date2 = new Date(+(date2 || new Date()));
  8490. if(portion == "date"){
  8491. // Ignore times and compare dates.
  8492. date1.setHours(0, 0, 0, 0);
  8493. date2.setHours(0, 0, 0, 0);
  8494. }else if(portion == "time"){
  8495. // Ignore dates and compare times.
  8496. date1.setFullYear(0, 0, 0);
  8497. date2.setFullYear(0, 0, 0);
  8498. }
  8499. if(date1 > date2){ return 1; } // int
  8500. if(date1 < date2){ return -1; } // int
  8501. return 0; // int
  8502. };
  8503. dojo.date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){
  8504. // summary:
  8505. // Add to a Date in intervals of different size, from milliseconds to years
  8506. // date: Date
  8507. // Date object to start with
  8508. // interval:
  8509. // A string representing the interval. One of the following:
  8510. // "year", "month", "day", "hour", "minute", "second",
  8511. // "millisecond", "quarter", "week", "weekday"
  8512. // amount:
  8513. // How much to add to the date.
  8514. var sum = new Date(+date); // convert to Number before copying to accomodate IE (#3112)
  8515. var fixOvershoot = false;
  8516. var property = "Date";
  8517. switch(interval){
  8518. case "day":
  8519. break;
  8520. case "weekday":
  8521. //i18n FIXME: assumes Saturday/Sunday weekend, but this is not always true. see dojo.cldr.supplemental
  8522. // Divide the increment time span into weekspans plus leftover days
  8523. // e.g., 8 days is one 5-day weekspan / and two leftover days
  8524. // Can't have zero leftover days, so numbers divisible by 5 get
  8525. // a days value of 5, and the remaining days make up the number of weeks
  8526. var days, weeks;
  8527. var mod = amount % 5;
  8528. if(!mod){
  8529. days = (amount > 0) ? 5 : -5;
  8530. weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);
  8531. }else{
  8532. days = mod;
  8533. weeks = parseInt(amount/5);
  8534. }
  8535. // Get weekday value for orig date param
  8536. var strt = date.getDay();
  8537. // Orig date is Sat / positive incrementer
  8538. // Jump over Sun
  8539. var adj = 0;
  8540. if(strt == 6 && amount > 0){
  8541. adj = 1;
  8542. }else if(strt == 0 && amount < 0){
  8543. // Orig date is Sun / negative incrementer
  8544. // Jump back over Sat
  8545. adj = -1;
  8546. }
  8547. // Get weekday val for the new date
  8548. var trgt = strt + days;
  8549. // New date is on Sat or Sun
  8550. if(trgt == 0 || trgt == 6){
  8551. adj = (amount > 0) ? 2 : -2;
  8552. }
  8553. // Increment by number of weeks plus leftover days plus
  8554. // weekend adjustments
  8555. amount = (7 * weeks) + days + adj;
  8556. break;
  8557. case "year":
  8558. property = "FullYear";
  8559. // Keep increment/decrement from 2/29 out of March
  8560. fixOvershoot = true;
  8561. break;
  8562. case "week":
  8563. amount *= 7;
  8564. break;
  8565. case "quarter":
  8566. // Naive quarter is just three months
  8567. amount *= 3;
  8568. // fallthrough...
  8569. case "month":
  8570. // Reset to last day of month if you overshoot
  8571. fixOvershoot = true;
  8572. property = "Month";
  8573. break;
  8574. // case "hour":
  8575. // case "minute":
  8576. // case "second":
  8577. // case "millisecond":
  8578. default:
  8579. property = "UTC"+interval.charAt(0).toUpperCase() + interval.substring(1) + "s";
  8580. }
  8581. if(property){
  8582. sum["set"+property](sum["get"+property]()+amount);
  8583. }
  8584. if(fixOvershoot && (sum.getDate() < date.getDate())){
  8585. sum.setDate(0);
  8586. }
  8587. return sum; // Date
  8588. };
  8589. dojo.date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){
  8590. // summary:
  8591. // Get the difference in a specific unit of time (e.g., number of
  8592. // months, weeks, days, etc.) between two dates, rounded to the
  8593. // nearest integer.
  8594. // date1:
  8595. // Date object
  8596. // date2:
  8597. // Date object. If not specified, the current Date is used.
  8598. // interval:
  8599. // A string representing the interval. One of the following:
  8600. // "year", "month", "day", "hour", "minute", "second",
  8601. // "millisecond", "quarter", "week", "weekday"
  8602. // Defaults to "day".
  8603. date2 = date2 || new Date();
  8604. interval = interval || "day";
  8605. var yearDiff = date2.getFullYear() - date1.getFullYear();
  8606. var delta = 1; // Integer return value
  8607. switch(interval){
  8608. case "quarter":
  8609. var m1 = date1.getMonth();
  8610. var m2 = date2.getMonth();
  8611. // Figure out which quarter the months are in
  8612. var q1 = Math.floor(m1/3) + 1;
  8613. var q2 = Math.floor(m2/3) + 1;
  8614. // Add quarters for any year difference between the dates
  8615. q2 += (yearDiff * 4);
  8616. delta = q2 - q1;
  8617. break;
  8618. case "weekday":
  8619. var days = Math.round(dojo.date.difference(date1, date2, "day"));
  8620. var weeks = parseInt(dojo.date.difference(date1, date2, "week"));
  8621. var mod = days % 7;
  8622. // Even number of weeks
  8623. if(mod == 0){
  8624. days = weeks*5;
  8625. }else{
  8626. // Weeks plus spare change (< 7 days)
  8627. var adj = 0;
  8628. var aDay = date1.getDay();
  8629. var bDay = date2.getDay();
  8630. weeks = parseInt(days/7);
  8631. mod = days % 7;
  8632. // Mark the date advanced by the number of
  8633. // round weeks (may be zero)
  8634. var dtMark = new Date(date1);
  8635. dtMark.setDate(dtMark.getDate()+(weeks*7));
  8636. var dayMark = dtMark.getDay();
  8637. // Spare change days -- 6 or less
  8638. if(days > 0){
  8639. switch(true){
  8640. // Range starts on Sat
  8641. case aDay == 6:
  8642. adj = -1;
  8643. break;
  8644. // Range starts on Sun
  8645. case aDay == 0:
  8646. adj = 0;
  8647. break;
  8648. // Range ends on Sat
  8649. case bDay == 6:
  8650. adj = -1;
  8651. break;
  8652. // Range ends on Sun
  8653. case bDay == 0:
  8654. adj = -2;
  8655. break;
  8656. // Range contains weekend
  8657. case (dayMark + mod) > 5:
  8658. adj = -2;
  8659. }
  8660. }else if(days < 0){
  8661. switch(true){
  8662. // Range starts on Sat
  8663. case aDay == 6:
  8664. adj = 0;
  8665. break;
  8666. // Range starts on Sun
  8667. case aDay == 0:
  8668. adj = 1;
  8669. break;
  8670. // Range ends on Sat
  8671. case bDay == 6:
  8672. adj = 2;
  8673. break;
  8674. // Range ends on Sun
  8675. case bDay == 0:
  8676. adj = 1;
  8677. break;
  8678. // Range contains weekend
  8679. case (dayMark + mod) < 0:
  8680. adj = 2;
  8681. }
  8682. }
  8683. days += adj;
  8684. days -= (weeks*2);
  8685. }
  8686. delta = days;
  8687. break;
  8688. case "year":
  8689. delta = yearDiff;
  8690. break;
  8691. case "month":
  8692. delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);
  8693. break;
  8694. case "week":
  8695. // Truncate instead of rounding
  8696. // Don't use Math.floor -- value may be negative
  8697. delta = parseInt(dojo.date.difference(date1, date2, "day")/7);
  8698. break;
  8699. case "day":
  8700. delta /= 24;
  8701. // fallthrough
  8702. case "hour":
  8703. delta /= 60;
  8704. // fallthrough
  8705. case "minute":
  8706. delta /= 60;
  8707. // fallthrough
  8708. case "second":
  8709. delta /= 1000;
  8710. // fallthrough
  8711. case "millisecond":
  8712. delta *= date2.getTime() - date1.getTime();
  8713. }
  8714. // Round for fractional values and DST leaps
  8715. return Math.round(delta); // Number (integer)
  8716. };
  8717. return dojo.date;
  8718. });
  8719. },
  8720. 'dijit/layout/_ContentPaneResizeMixin':function(){
  8721. define("dijit/layout/_ContentPaneResizeMixin", [
  8722. "dojo/_base/array", // array.filter array.forEach
  8723. "dojo/_base/declare", // declare
  8724. "dojo/dom-attr", // domAttr.has
  8725. "dojo/dom-class", // domClass.contains domClass.toggle
  8726. "dojo/dom-geometry",// domGeometry.contentBox domGeometry.marginBox
  8727. "dojo/_base/lang", // lang.mixin
  8728. "dojo/query", // query
  8729. "dojo/_base/sniff", // has("ie")
  8730. "dojo/_base/window", // win.global
  8731. "../registry", // registry.byId
  8732. "./utils", // marginBox2contextBox
  8733. "../_Contained"
  8734. ], function(array, declare, domAttr, domClass, domGeometry, lang, query, has, win,
  8735. registry, layoutUtils, _Contained){
  8736. /*=====
  8737. var _Contained = dijit._Contained;
  8738. =====*/
  8739. // module:
  8740. // dijit/layout/_ContentPaneResizeMixin
  8741. // summary:
  8742. // Resize() functionality of ContentPane. If there's a single layout widget
  8743. // child then it will call resize() with the same dimensions as the ContentPane.
  8744. // Otherwise just calls resize on each child.
  8745. return declare("dijit.layout._ContentPaneResizeMixin", null, {
  8746. // summary:
  8747. // Resize() functionality of ContentPane. If there's a single layout widget
  8748. // child then it will call resize() with the same dimensions as the ContentPane.
  8749. // Otherwise just calls resize on each child.
  8750. //
  8751. // Also implements basic startup() functionality, where starting the parent
  8752. // will start the children
  8753. // doLayout: Boolean
  8754. // - false - don't adjust size of children
  8755. // - true - if there is a single visible child widget, set it's size to
  8756. // however big the ContentPane is
  8757. doLayout: true,
  8758. // isLayoutContainer: [protected] Boolean
  8759. // Indicates that this widget will call resize() on it's child widgets
  8760. // when they become visible.
  8761. isLayoutContainer: true,
  8762. startup: function(){
  8763. // summary:
  8764. // See `dijit.layout._LayoutWidget.startup` for description.
  8765. // Although ContentPane doesn't extend _LayoutWidget, it does implement
  8766. // the same API.
  8767. if(this._started){ return; }
  8768. var parent = this.getParent();
  8769. this._childOfLayoutWidget = parent && parent.isLayoutContainer;
  8770. // I need to call resize() on my child/children (when I become visible), unless
  8771. // I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
  8772. this._needLayout = !this._childOfLayoutWidget;
  8773. this.inherited(arguments);
  8774. if(this._isShown()){
  8775. this._onShow();
  8776. }
  8777. if(!this._childOfLayoutWidget){
  8778. // If my parent isn't a layout container, since my style *may be* width=height=100%
  8779. // or something similar (either set directly or via a CSS class),
  8780. // monitor when my size changes so that I can re-layout.
  8781. // For browsers where I can't directly monitor when my size changes,
  8782. // monitor when the viewport changes size, which *may* indicate a size change for me.
  8783. this.connect(has("ie") ? this.domNode : win.global, 'onresize', function(){
  8784. // Using function(){} closure to ensure no arguments to resize.
  8785. this._needLayout = !this._childOfLayoutWidget;
  8786. this.resize();
  8787. });
  8788. }
  8789. },
  8790. _checkIfSingleChild: function(){
  8791. // summary:
  8792. // Test if we have exactly one visible widget as a child,
  8793. // and if so assume that we are a container for that widget,
  8794. // and should propagate startup() and resize() calls to it.
  8795. // Skips over things like data stores since they aren't visible.
  8796. var childNodes = query("> *", this.containerNode).filter(function(node){
  8797. return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
  8798. }),
  8799. childWidgetNodes = childNodes.filter(function(node){
  8800. return domAttr.has(node, "data-dojo-type") || domAttr.has(node, "dojoType") || domAttr.has(node, "widgetId");
  8801. }),
  8802. candidateWidgets = array.filter(childWidgetNodes.map(registry.byNode), function(widget){
  8803. return widget && widget.domNode && widget.resize;
  8804. });
  8805. if(
  8806. // all child nodes are widgets
  8807. childNodes.length == childWidgetNodes.length &&
  8808. // all but one are invisible (like dojo.data)
  8809. candidateWidgets.length == 1
  8810. ){
  8811. this._singleChild = candidateWidgets[0];
  8812. }else{
  8813. delete this._singleChild;
  8814. }
  8815. // So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
  8816. domClass.toggle(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild);
  8817. },
  8818. resize: function(changeSize, resultSize){
  8819. // summary:
  8820. // See `dijit.layout._LayoutWidget.resize` for description.
  8821. // Although ContentPane doesn't extend _LayoutWidget, it does implement
  8822. // the same API.
  8823. // For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
  8824. // never called, so resize() is our trigger to do the initial href download (see [20099]).
  8825. // However, don't load href for closed TitlePanes.
  8826. if(!this._wasShown && this.open !== false){
  8827. this._onShow();
  8828. }
  8829. this._resizeCalled = true;
  8830. this._scheduleLayout(changeSize, resultSize);
  8831. },
  8832. _scheduleLayout: function(changeSize, resultSize){
  8833. // summary:
  8834. // Resize myself, and call resize() on each of my child layout widgets, either now
  8835. // (if I'm currently visible) or when I become visible
  8836. if(this._isShown()){
  8837. this._layout(changeSize, resultSize);
  8838. }else{
  8839. this._needLayout = true;
  8840. this._changeSize = changeSize;
  8841. this._resultSize = resultSize;
  8842. }
  8843. },
  8844. _layout: function(changeSize, resultSize){
  8845. // summary:
  8846. // Resize myself according to optional changeSize/resultSize parameters, like a layout widget.
  8847. // Also, since I am a Container widget, each of my children expects me to
  8848. // call resize() or layout() on them.
  8849. //
  8850. // Should be called on initialization and also whenever we get new content
  8851. // (from an href, or from set('content', ...))... but deferred until
  8852. // the ContentPane is visible
  8853. // Set margin box size, unless it wasn't specified, in which case use current size.
  8854. if(changeSize){
  8855. domGeometry.setMarginBox(this.domNode, changeSize);
  8856. }
  8857. // Compute content box size of containerNode in case we [later] need to size our single child.
  8858. var cn = this.containerNode;
  8859. if(cn === this.domNode){
  8860. // If changeSize or resultSize was passed to this method and this.containerNode ==
  8861. // this.domNode then we can compute the content-box size without querying the node,
  8862. // which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
  8863. var mb = resultSize || {};
  8864. lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
  8865. if(!("h" in mb) || !("w" in mb)){
  8866. mb = lang.mixin(domGeometry.getMarginBox(cn), mb); // just use domGeometry.setMarginBox() to fill in missing values
  8867. }
  8868. this._contentBox = layoutUtils.marginBox2contentBox(cn, mb);
  8869. }else{
  8870. this._contentBox = domGeometry.getContentBox(cn);
  8871. }
  8872. this._layoutChildren();
  8873. delete this._needLayout;
  8874. },
  8875. _layoutChildren: function(){
  8876. // Call _checkIfSingleChild() again in case app has manually mucked w/the content
  8877. // of the ContentPane (rather than changing it through the set("content", ...) API.
  8878. if(this.doLayout){
  8879. this._checkIfSingleChild();
  8880. }
  8881. if(this._singleChild && this._singleChild.resize){
  8882. var cb = this._contentBox || domGeometry.getContentBox(this.containerNode);
  8883. // note: if widget has padding this._contentBox will have l and t set,
  8884. // but don't pass them to resize() or it will doubly-offset the child
  8885. this._singleChild.resize({w: cb.w, h: cb.h});
  8886. }else{
  8887. // All my child widgets are independently sized (rather than matching my size),
  8888. // but I still need to call resize() on each child to make it layout.
  8889. array.forEach(this.getChildren(), function(widget){
  8890. if(widget.resize){
  8891. widget.resize();
  8892. }
  8893. });
  8894. }
  8895. },
  8896. _isShown: function(){
  8897. // summary:
  8898. // Returns true if the content is currently shown.
  8899. // description:
  8900. // If I am a child of a layout widget then it actually returns true if I've ever been visible,
  8901. // not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
  8902. // tree every call, and at least solves the performance problem on page load by deferring loading
  8903. // hidden ContentPanes until they are first shown
  8904. if(this._childOfLayoutWidget){
  8905. // If we are TitlePane, etc - we return that only *IF* we've been resized
  8906. if(this._resizeCalled && "open" in this){
  8907. return this.open;
  8908. }
  8909. return this._resizeCalled;
  8910. }else if("open" in this){
  8911. return this.open; // for TitlePane, etc.
  8912. }else{
  8913. var node = this.domNode, parent = this.domNode.parentNode;
  8914. return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !domClass.contains(node, "dijitHidden") &&
  8915. parent && parent.style && (parent.style.display != 'none');
  8916. }
  8917. },
  8918. _onShow: function(){
  8919. // summary:
  8920. // Called when the ContentPane is made visible
  8921. // description:
  8922. // For a plain ContentPane, this is called on initialization, from startup().
  8923. // If the ContentPane is a hidden pane of a TabContainer etc., then it's
  8924. // called whenever the pane is made visible.
  8925. //
  8926. // Does layout/resize of child widget(s)
  8927. // Need to keep track of whether ContentPane has been shown (which is different than
  8928. // whether or not it's currently visible).
  8929. this._wasShown = true;
  8930. if(this._needLayout){
  8931. // If a layout has been scheduled for when we become visible, do it now
  8932. this._layout(this._changeSize, this._resultSize);
  8933. }
  8934. this.inherited(arguments);
  8935. }
  8936. });
  8937. });
  8938. },
  8939. 'dijit/WidgetSet':function(){
  8940. define("dijit/WidgetSet", [
  8941. "dojo/_base/array", // array.forEach array.map
  8942. "dojo/_base/declare", // declare
  8943. "dojo/_base/window", // win.global
  8944. "./registry" // to add functions to dijit.registry
  8945. ], function(array, declare, win, registry){
  8946. // module:
  8947. // dijit/WidgetSet
  8948. // summary:
  8949. // Legacy registry code. New modules should just use registry.
  8950. // Will be removed in 2.0.
  8951. var WidgetSet = declare("dijit.WidgetSet", null, {
  8952. // summary:
  8953. // A set of widgets indexed by id. A default instance of this class is
  8954. // available as `dijit.registry`
  8955. //
  8956. // example:
  8957. // Create a small list of widgets:
  8958. // | var ws = new dijit.WidgetSet();
  8959. // | ws.add(dijit.byId("one"));
  8960. // | ws.add(dijit.byId("two"));
  8961. // | // destroy both:
  8962. // | ws.forEach(function(w){ w.destroy(); });
  8963. //
  8964. // example:
  8965. // Using dijit.registry:
  8966. // | dijit.registry.forEach(function(w){ /* do something */ });
  8967. constructor: function(){
  8968. this._hash = {};
  8969. this.length = 0;
  8970. },
  8971. add: function(/*dijit._Widget*/ widget){
  8972. // summary:
  8973. // Add a widget to this list. If a duplicate ID is detected, a error is thrown.
  8974. //
  8975. // widget: dijit._Widget
  8976. // Any dijit._Widget subclass.
  8977. if(this._hash[widget.id]){
  8978. throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
  8979. }
  8980. this._hash[widget.id] = widget;
  8981. this.length++;
  8982. },
  8983. remove: function(/*String*/ id){
  8984. // summary:
  8985. // Remove a widget from this WidgetSet. Does not destroy the widget; simply
  8986. // removes the reference.
  8987. if(this._hash[id]){
  8988. delete this._hash[id];
  8989. this.length--;
  8990. }
  8991. },
  8992. forEach: function(/*Function*/ func, /* Object? */thisObj){
  8993. // summary:
  8994. // Call specified function for each widget in this set.
  8995. //
  8996. // func:
  8997. // A callback function to run for each item. Is passed the widget, the index
  8998. // in the iteration, and the full hash, similar to `array.forEach`.
  8999. //
  9000. // thisObj:
  9001. // An optional scope parameter
  9002. //
  9003. // example:
  9004. // Using the default `dijit.registry` instance:
  9005. // | dijit.registry.forEach(function(widget){
  9006. // | console.log(widget.declaredClass);
  9007. // | });
  9008. //
  9009. // returns:
  9010. // Returns self, in order to allow for further chaining.
  9011. thisObj = thisObj || win.global;
  9012. var i = 0, id;
  9013. for(id in this._hash){
  9014. func.call(thisObj, this._hash[id], i++, this._hash);
  9015. }
  9016. return this; // dijit.WidgetSet
  9017. },
  9018. filter: function(/*Function*/ filter, /* Object? */thisObj){
  9019. // summary:
  9020. // Filter down this WidgetSet to a smaller new WidgetSet
  9021. // Works the same as `array.filter` and `NodeList.filter`
  9022. //
  9023. // filter:
  9024. // Callback function to test truthiness. Is passed the widget
  9025. // reference and the pseudo-index in the object.
  9026. //
  9027. // thisObj: Object?
  9028. // Option scope to use for the filter function.
  9029. //
  9030. // example:
  9031. // Arbitrary: select the odd widgets in this list
  9032. // | dijit.registry.filter(function(w, i){
  9033. // | return i % 2 == 0;
  9034. // | }).forEach(function(w){ /* odd ones */ });
  9035. thisObj = thisObj || win.global;
  9036. var res = new WidgetSet(), i = 0, id;
  9037. for(id in this._hash){
  9038. var w = this._hash[id];
  9039. if(filter.call(thisObj, w, i++, this._hash)){
  9040. res.add(w);
  9041. }
  9042. }
  9043. return res; // dijit.WidgetSet
  9044. },
  9045. byId: function(/*String*/ id){
  9046. // summary:
  9047. // Find a widget in this list by it's id.
  9048. // example:
  9049. // Test if an id is in a particular WidgetSet
  9050. // | var ws = new dijit.WidgetSet();
  9051. // | ws.add(dijit.byId("bar"));
  9052. // | var t = ws.byId("bar") // returns a widget
  9053. // | var x = ws.byId("foo"); // returns undefined
  9054. return this._hash[id]; // dijit._Widget
  9055. },
  9056. byClass: function(/*String*/ cls){
  9057. // summary:
  9058. // Reduce this widgetset to a new WidgetSet of a particular `declaredClass`
  9059. //
  9060. // cls: String
  9061. // The Class to scan for. Full dot-notated string.
  9062. //
  9063. // example:
  9064. // Find all `dijit.TitlePane`s in a page:
  9065. // | dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
  9066. var res = new WidgetSet(), id, widget;
  9067. for(id in this._hash){
  9068. widget = this._hash[id];
  9069. if(widget.declaredClass == cls){
  9070. res.add(widget);
  9071. }
  9072. }
  9073. return res; // dijit.WidgetSet
  9074. },
  9075. toArray: function(){
  9076. // summary:
  9077. // Convert this WidgetSet into a true Array
  9078. //
  9079. // example:
  9080. // Work with the widget .domNodes in a real Array
  9081. // | array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
  9082. var ar = [];
  9083. for(var id in this._hash){
  9084. ar.push(this._hash[id]);
  9085. }
  9086. return ar; // dijit._Widget[]
  9087. },
  9088. map: function(/* Function */func, /* Object? */thisObj){
  9089. // summary:
  9090. // Create a new Array from this WidgetSet, following the same rules as `array.map`
  9091. // example:
  9092. // | var nodes = dijit.registry.map(function(w){ return w.domNode; });
  9093. //
  9094. // returns:
  9095. // A new array of the returned values.
  9096. return array.map(this.toArray(), func, thisObj); // Array
  9097. },
  9098. every: function(func, thisObj){
  9099. // summary:
  9100. // A synthetic clone of `array.every` acting explicitly on this WidgetSet
  9101. //
  9102. // func: Function
  9103. // A callback function run for every widget in this list. Exits loop
  9104. // when the first false return is encountered.
  9105. //
  9106. // thisObj: Object?
  9107. // Optional scope parameter to use for the callback
  9108. thisObj = thisObj || win.global;
  9109. var x = 0, i;
  9110. for(i in this._hash){
  9111. if(!func.call(thisObj, this._hash[i], x++, this._hash)){
  9112. return false; // Boolean
  9113. }
  9114. }
  9115. return true; // Boolean
  9116. },
  9117. some: function(func, thisObj){
  9118. // summary:
  9119. // A synthetic clone of `array.some` acting explicitly on this WidgetSet
  9120. //
  9121. // func: Function
  9122. // A callback function run for every widget in this list. Exits loop
  9123. // when the first true return is encountered.
  9124. //
  9125. // thisObj: Object?
  9126. // Optional scope parameter to use for the callback
  9127. thisObj = thisObj || win.global;
  9128. var x = 0, i;
  9129. for(i in this._hash){
  9130. if(func.call(thisObj, this._hash[i], x++, this._hash)){
  9131. return true; // Boolean
  9132. }
  9133. }
  9134. return false; // Boolean
  9135. }
  9136. });
  9137. // Add in 1.x compatibility methods to dijit.registry.
  9138. // These functions won't show up in the API doc but since they are deprecated anyway,
  9139. // that's probably for the best.
  9140. array.forEach(["forEach", "filter", "byClass", "map", "every", "some"], function(func){
  9141. registry[func] = WidgetSet.prototype[func];
  9142. });
  9143. return WidgetSet;
  9144. });
  9145. },
  9146. 'dojo/dnd/Moveable':function(){
  9147. define("dojo/dnd/Moveable", ["../main", "../Evented", "../touch", "./Mover"], function(dojo, Evented, touch) {
  9148. // module:
  9149. // dojo/dnd/Moveable
  9150. // summary:
  9151. // TODOC
  9152. /*=====
  9153. dojo.declare("dojo.dnd.__MoveableArgs", [], {
  9154. // handle: Node||String
  9155. // A node (or node's id), which is used as a mouse handle.
  9156. // If omitted, the node itself is used as a handle.
  9157. handle: null,
  9158. // delay: Number
  9159. // delay move by this number of pixels
  9160. delay: 0,
  9161. // skip: Boolean
  9162. // skip move of form elements
  9163. skip: false,
  9164. // mover: Object
  9165. // a constructor of custom Mover
  9166. mover: dojo.dnd.Mover
  9167. });
  9168. =====*/
  9169. dojo.declare("dojo.dnd.Moveable", [Evented], {
  9170. // object attributes (for markup)
  9171. handle: "",
  9172. delay: 0,
  9173. skip: false,
  9174. constructor: function(node, params){
  9175. // summary:
  9176. // an object, which makes a node moveable
  9177. // node: Node
  9178. // a node (or node's id) to be moved
  9179. // params: dojo.dnd.__MoveableArgs?
  9180. // optional parameters
  9181. this.node = dojo.byId(node);
  9182. if(!params){ params = {}; }
  9183. this.handle = params.handle ? dojo.byId(params.handle) : null;
  9184. if(!this.handle){ this.handle = this.node; }
  9185. this.delay = params.delay > 0 ? params.delay : 0;
  9186. this.skip = params.skip;
  9187. this.mover = params.mover ? params.mover : dojo.dnd.Mover;
  9188. this.events = [
  9189. dojo.connect(this.handle, touch.press, this, "onMouseDown"),
  9190. // cancel text selection and text dragging
  9191. dojo.connect(this.handle, "ondragstart", this, "onSelectStart"),
  9192. dojo.connect(this.handle, "onselectstart", this, "onSelectStart")
  9193. ];
  9194. },
  9195. // markup methods
  9196. markupFactory: function(params, node, ctor){
  9197. return new ctor(node, params);
  9198. },
  9199. // methods
  9200. destroy: function(){
  9201. // summary:
  9202. // stops watching for possible move, deletes all references, so the object can be garbage-collected
  9203. dojo.forEach(this.events, dojo.disconnect);
  9204. this.events = this.node = this.handle = null;
  9205. },
  9206. // mouse event processors
  9207. onMouseDown: function(e){
  9208. // summary:
  9209. // event processor for onmousedown/ontouchstart, creates a Mover for the node
  9210. // e: Event
  9211. // mouse/touch event
  9212. if(this.skip && dojo.dnd.isFormElement(e)){ return; }
  9213. if(this.delay){
  9214. this.events.push(
  9215. dojo.connect(this.handle, touch.move, this, "onMouseMove"),
  9216. dojo.connect(this.handle, touch.release, this, "onMouseUp")
  9217. );
  9218. this._lastX = e.pageX;
  9219. this._lastY = e.pageY;
  9220. }else{
  9221. this.onDragDetected(e);
  9222. }
  9223. dojo.stopEvent(e);
  9224. },
  9225. onMouseMove: function(e){
  9226. // summary:
  9227. // event processor for onmousemove/ontouchmove, used only for delayed drags
  9228. // e: Event
  9229. // mouse/touch event
  9230. if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){
  9231. this.onMouseUp(e);
  9232. this.onDragDetected(e);
  9233. }
  9234. dojo.stopEvent(e);
  9235. },
  9236. onMouseUp: function(e){
  9237. // summary:
  9238. // event processor for onmouseup, used only for delayed drags
  9239. // e: Event
  9240. // mouse event
  9241. for(var i = 0; i < 2; ++i){
  9242. dojo.disconnect(this.events.pop());
  9243. }
  9244. dojo.stopEvent(e);
  9245. },
  9246. onSelectStart: function(e){
  9247. // summary:
  9248. // event processor for onselectevent and ondragevent
  9249. // e: Event
  9250. // mouse event
  9251. if(!this.skip || !dojo.dnd.isFormElement(e)){
  9252. dojo.stopEvent(e);
  9253. }
  9254. },
  9255. // local events
  9256. onDragDetected: function(/* Event */ e){
  9257. // summary:
  9258. // called when the drag is detected;
  9259. // responsible for creation of the mover
  9260. new this.mover(this.node, e, this);
  9261. },
  9262. onMoveStart: function(/* dojo.dnd.Mover */ mover){
  9263. // summary:
  9264. // called before every move operation
  9265. dojo.publish("/dnd/move/start", [mover]);
  9266. dojo.addClass(dojo.body(), "dojoMove");
  9267. dojo.addClass(this.node, "dojoMoveItem");
  9268. },
  9269. onMoveStop: function(/* dojo.dnd.Mover */ mover){
  9270. // summary:
  9271. // called after every move operation
  9272. dojo.publish("/dnd/move/stop", [mover]);
  9273. dojo.removeClass(dojo.body(), "dojoMove");
  9274. dojo.removeClass(this.node, "dojoMoveItem");
  9275. },
  9276. onFirstMove: function(/* dojo.dnd.Mover */ mover, /* Event */ e){
  9277. // summary:
  9278. // called during the very first move notification;
  9279. // can be used to initialize coordinates, can be overwritten.
  9280. // default implementation does nothing
  9281. },
  9282. onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop, /* Event */ e){
  9283. // summary:
  9284. // called during every move notification;
  9285. // should actually move the node; can be overwritten.
  9286. this.onMoving(mover, leftTop);
  9287. var s = mover.node.style;
  9288. s.left = leftTop.l + "px";
  9289. s.top = leftTop.t + "px";
  9290. this.onMoved(mover, leftTop);
  9291. },
  9292. onMoving: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
  9293. // summary:
  9294. // called before every incremental move; can be overwritten.
  9295. // default implementation does nothing
  9296. },
  9297. onMoved: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
  9298. // summary:
  9299. // called after every incremental move; can be overwritten.
  9300. // default implementation does nothing
  9301. }
  9302. });
  9303. return dojo.dnd.Moveable;
  9304. });
  9305. },
  9306. 'dijit/TooltipDialog':function(){
  9307. require({cache:{
  9308. 'url:dijit/templates/TooltipDialog.html':"<div role=\"presentation\" tabIndex=\"-1\">\n\t<div class=\"dijitTooltipContainer\" role=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" data-dojo-attach-point=\"containerNode\" role=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" role=\"presentation\"></div>\n</div>\n"}});
  9309. define("dijit/TooltipDialog", [
  9310. "dojo/_base/declare", // declare
  9311. "dojo/dom-class", // domClass.replace
  9312. "dojo/_base/event", // event.stop
  9313. "dojo/keys", // keys
  9314. "dojo/_base/lang", // lang.hitch
  9315. "./focus",
  9316. "./layout/ContentPane",
  9317. "./_DialogMixin",
  9318. "./form/_FormMixin",
  9319. "./_TemplatedMixin",
  9320. "dojo/text!./templates/TooltipDialog.html",
  9321. "." // exports methods to dijit global
  9322. ], function(declare, domClass, event, keys, lang,
  9323. focus, ContentPane, _DialogMixin, _FormMixin, _TemplatedMixin, template, dijit){
  9324. /*=====
  9325. var ContentPane = dijit.layout.ContentPane;
  9326. var _DialogMixin = dijit._DialogMixin;
  9327. var _FormMixin = dijit.form._FormMixin;
  9328. var _TemplatedMixin = dijit._TemplatedMixin;
  9329. =====*/
  9330. // module:
  9331. // dijit/TooltipDialog
  9332. // summary:
  9333. // Pops up a dialog that appears like a Tooltip
  9334. return declare("dijit.TooltipDialog",
  9335. [ContentPane, _TemplatedMixin, _FormMixin, _DialogMixin], {
  9336. // summary:
  9337. // Pops up a dialog that appears like a Tooltip
  9338. // title: String
  9339. // Description of tooltip dialog (required for a11y)
  9340. title: "",
  9341. // doLayout: [protected] Boolean
  9342. // Don't change this parameter from the default value.
  9343. // This ContentPane parameter doesn't make sense for TooltipDialog, since TooltipDialog
  9344. // is never a child of a layout container, nor can you specify the size of
  9345. // TooltipDialog in order to control the size of an inner widget.
  9346. doLayout: false,
  9347. // autofocus: Boolean
  9348. // A Toggle to modify the default focus behavior of a Dialog, which
  9349. // is to focus on the first dialog element after opening the dialog.
  9350. // False will disable autofocusing. Default: true
  9351. autofocus: true,
  9352. // baseClass: [protected] String
  9353. // The root className to use for the various states of this widget
  9354. baseClass: "dijitTooltipDialog",
  9355. // _firstFocusItem: [private] [readonly] DomNode
  9356. // The pointer to the first focusable node in the dialog.
  9357. // Set by `dijit._DialogMixin._getFocusItems`.
  9358. _firstFocusItem: null,
  9359. // _lastFocusItem: [private] [readonly] DomNode
  9360. // The pointer to which node has focus prior to our dialog.
  9361. // Set by `dijit._DialogMixin._getFocusItems`.
  9362. _lastFocusItem: null,
  9363. templateString: template,
  9364. _setTitleAttr: function(/*String*/ title){
  9365. this.containerNode.title = title;
  9366. this._set("title", title)
  9367. },
  9368. postCreate: function(){
  9369. this.inherited(arguments);
  9370. this.connect(this.containerNode, "onkeypress", "_onKey");
  9371. },
  9372. orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ corner){
  9373. // summary:
  9374. // Configure widget to be displayed in given position relative to the button.
  9375. // This is called from the dijit.popup code, and should not be called
  9376. // directly.
  9377. // tags:
  9378. // protected
  9379. var newC = "dijitTooltipAB" + (corner.charAt(1) == 'L' ? "Left" : "Right")
  9380. + " dijitTooltip"
  9381. + (corner.charAt(0) == 'T' ? "Below" : "Above");
  9382. domClass.replace(this.domNode, newC, this._currentOrientClass || "");
  9383. this._currentOrientClass = newC;
  9384. },
  9385. focus: function(){
  9386. // summary:
  9387. // Focus on first field
  9388. this._getFocusItems(this.containerNode);
  9389. focus.focus(this._firstFocusItem);
  9390. },
  9391. onOpen: function(/*Object*/ pos){
  9392. // summary:
  9393. // Called when dialog is displayed.
  9394. // This is called from the dijit.popup code, and should not be called directly.
  9395. // tags:
  9396. // protected
  9397. this.orient(this.domNode,pos.aroundCorner, pos.corner);
  9398. this._onShow(); // lazy load trigger
  9399. },
  9400. onClose: function(){
  9401. // summary:
  9402. // Called when dialog is hidden.
  9403. // This is called from the dijit.popup code, and should not be called directly.
  9404. // tags:
  9405. // protected
  9406. this.onHide();
  9407. },
  9408. _onKey: function(/*Event*/ evt){
  9409. // summary:
  9410. // Handler for keyboard events
  9411. // description:
  9412. // Keep keyboard focus in dialog; close dialog on escape key
  9413. // tags:
  9414. // private
  9415. var node = evt.target;
  9416. if(evt.charOrCode === keys.TAB){
  9417. this._getFocusItems(this.containerNode);
  9418. }
  9419. var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
  9420. if(evt.charOrCode == keys.ESCAPE){
  9421. // Use setTimeout to avoid crash on IE, see #10396.
  9422. setTimeout(lang.hitch(this, "onCancel"), 0);
  9423. event.stop(evt);
  9424. }else if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === keys.TAB){
  9425. if(!singleFocusItem){
  9426. focus.focus(this._lastFocusItem); // send focus to last item in dialog
  9427. }
  9428. event.stop(evt);
  9429. }else if(node == this._lastFocusItem && evt.charOrCode === keys.TAB && !evt.shiftKey){
  9430. if(!singleFocusItem){
  9431. focus.focus(this._firstFocusItem); // send focus to first item in dialog
  9432. }
  9433. event.stop(evt);
  9434. }else if(evt.charOrCode === keys.TAB){
  9435. // we want the browser's default tab handling to move focus
  9436. // but we don't want the tab to propagate upwards
  9437. evt.stopPropagation();
  9438. }
  9439. }
  9440. });
  9441. });
  9442. },
  9443. 'dijit/typematic':function(){
  9444. define("dijit/typematic", [
  9445. "dojo/_base/array", // array.forEach
  9446. "dojo/_base/connect", // connect.connect
  9447. "dojo/_base/event", // event.stop
  9448. "dojo/_base/kernel", // kernel.deprecated
  9449. "dojo/_base/lang", // lang.mixin, lang.hitch
  9450. "dojo/on",
  9451. "dojo/_base/sniff", // has("ie")
  9452. "." // setting dijit.typematic global
  9453. ], function(array, connect, event, kernel, lang, on, has, dijit){
  9454. // module:
  9455. // dijit/typematic
  9456. // summary:
  9457. // These functions are used to repetitively call a user specified callback
  9458. // method when a specific key or mouse click over a specific DOM node is
  9459. // held down for a specific amount of time.
  9460. // Only 1 such event is allowed to occur on the browser page at 1 time.
  9461. var typematic = (dijit.typematic = {
  9462. // summary:
  9463. // These functions are used to repetitively call a user specified callback
  9464. // method when a specific key or mouse click over a specific DOM node is
  9465. // held down for a specific amount of time.
  9466. // Only 1 such event is allowed to occur on the browser page at 1 time.
  9467. _fireEventAndReload: function(){
  9468. this._timer = null;
  9469. this._callback(++this._count, this._node, this._evt);
  9470. // Schedule next event, timer is at most minDelay (default 10ms) to avoid
  9471. // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
  9472. this._currentTimeout = Math.max(
  9473. this._currentTimeout < 0 ? this._initialDelay :
  9474. (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
  9475. this._minDelay);
  9476. this._timer = setTimeout(lang.hitch(this, "_fireEventAndReload"), this._currentTimeout);
  9477. },
  9478. trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  9479. // summary:
  9480. // Start a timed, repeating callback sequence.
  9481. // If already started, the function call is ignored.
  9482. // This method is not normally called by the user but can be
  9483. // when the normal listener code is insufficient.
  9484. // evt:
  9485. // key or mouse event object to pass to the user callback
  9486. // _this:
  9487. // pointer to the user's widget space.
  9488. // node:
  9489. // the DOM node object to pass the the callback function
  9490. // callback:
  9491. // function to call until the sequence is stopped called with 3 parameters:
  9492. // count:
  9493. // integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
  9494. // node:
  9495. // the DOM node object passed in
  9496. // evt:
  9497. // key or mouse event object
  9498. // obj:
  9499. // user space object used to uniquely identify each typematic sequence
  9500. // subsequentDelay (optional):
  9501. // if > 1, the number of milliseconds until the 3->n events occur
  9502. // or else the fractional time multiplier for the next event's delay, default=0.9
  9503. // initialDelay (optional):
  9504. // the number of milliseconds until the 2nd event occurs, default=500ms
  9505. // minDelay (optional):
  9506. // the maximum delay in milliseconds for event to fire, default=10ms
  9507. if(obj != this._obj){
  9508. this.stop();
  9509. this._initialDelay = initialDelay || 500;
  9510. this._subsequentDelay = subsequentDelay || 0.90;
  9511. this._minDelay = minDelay || 10;
  9512. this._obj = obj;
  9513. this._evt = evt;
  9514. this._node = node;
  9515. this._currentTimeout = -1;
  9516. this._count = -1;
  9517. this._callback = lang.hitch(_this, callback);
  9518. this._fireEventAndReload();
  9519. this._evt = lang.mixin({faux: true}, evt);
  9520. }
  9521. },
  9522. stop: function(){
  9523. // summary:
  9524. // Stop an ongoing timed, repeating callback sequence.
  9525. if(this._timer){
  9526. clearTimeout(this._timer);
  9527. this._timer = null;
  9528. }
  9529. if(this._obj){
  9530. this._callback(-1, this._node, this._evt);
  9531. this._obj = null;
  9532. }
  9533. },
  9534. addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  9535. // summary:
  9536. // Start listening for a specific typematic key.
  9537. // See also the trigger method for other parameters.
  9538. // keyObject:
  9539. // an object defining the key to listen for:
  9540. // charOrCode:
  9541. // the printable character (string) or keyCode (number) to listen for.
  9542. // keyCode:
  9543. // (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
  9544. // charCode:
  9545. // (deprecated - use charOrCode) the charCode (number) to listen for.
  9546. // ctrlKey:
  9547. // desired ctrl key state to initiate the callback sequence:
  9548. // - pressed (true)
  9549. // - released (false)
  9550. // - either (unspecified)
  9551. // altKey:
  9552. // same as ctrlKey but for the alt key
  9553. // shiftKey:
  9554. // same as ctrlKey but for the shift key
  9555. // returns:
  9556. // a connection handle
  9557. if(keyObject.keyCode){
  9558. keyObject.charOrCode = keyObject.keyCode;
  9559. kernel.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
  9560. }else if(keyObject.charCode){
  9561. keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
  9562. kernel.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
  9563. }
  9564. var handles = [
  9565. on(node, connect._keypress, lang.hitch(this, function(evt){
  9566. if(evt.charOrCode == keyObject.charOrCode &&
  9567. (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
  9568. (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) &&
  9569. (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
  9570. (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
  9571. event.stop(evt);
  9572. typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
  9573. }else if(typematic._obj == keyObject){
  9574. typematic.stop();
  9575. }
  9576. })),
  9577. on(node, "keyup", lang.hitch(this, function(){
  9578. if(typematic._obj == keyObject){
  9579. typematic.stop();
  9580. }
  9581. }))
  9582. ];
  9583. return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
  9584. },
  9585. addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  9586. // summary:
  9587. // Start listening for a typematic mouse click.
  9588. // See the trigger method for other parameters.
  9589. // returns:
  9590. // a connection handle
  9591. var handles = [
  9592. on(node, "mousedown", lang.hitch(this, function(evt){
  9593. event.stop(evt);
  9594. typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
  9595. })),
  9596. on(node, "mouseup", lang.hitch(this, function(evt){
  9597. if(this._obj){
  9598. event.stop(evt);
  9599. }
  9600. typematic.stop();
  9601. })),
  9602. on(node, "mouseout", lang.hitch(this, function(evt){
  9603. event.stop(evt);
  9604. typematic.stop();
  9605. })),
  9606. on(node, "mousemove", lang.hitch(this, function(evt){
  9607. evt.preventDefault();
  9608. })),
  9609. on(node, "dblclick", lang.hitch(this, function(evt){
  9610. event.stop(evt);
  9611. if(has("ie") < 9){
  9612. typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
  9613. setTimeout(lang.hitch(this, typematic.stop), 50);
  9614. }
  9615. }))
  9616. ];
  9617. return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
  9618. },
  9619. addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  9620. // summary:
  9621. // Start listening for a specific typematic key and mouseclick.
  9622. // This is a thin wrapper to addKeyListener and addMouseListener.
  9623. // See the addMouseListener and addKeyListener methods for other parameters.
  9624. // mouseNode:
  9625. // the DOM node object to listen on for mouse events.
  9626. // keyNode:
  9627. // the DOM node object to listen on for key events.
  9628. // returns:
  9629. // a connection handle
  9630. var handles = [
  9631. this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay),
  9632. this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay)
  9633. ];
  9634. return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
  9635. }
  9636. });
  9637. return typematic;
  9638. });
  9639. },
  9640. 'dijit/MenuItem':function(){
  9641. require({cache:{
  9642. 'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n"}});
  9643. define("dijit/MenuItem", [
  9644. "dojo/_base/declare", // declare
  9645. "dojo/dom", // dom.setSelectable
  9646. "dojo/dom-attr", // domAttr.set
  9647. "dojo/dom-class", // domClass.toggle
  9648. "dojo/_base/event", // event.stop
  9649. "dojo/_base/kernel", // kernel.deprecated
  9650. "dojo/_base/sniff", // has("ie")
  9651. "./_Widget",
  9652. "./_TemplatedMixin",
  9653. "./_Contained",
  9654. "./_CssStateMixin",
  9655. "dojo/text!./templates/MenuItem.html"
  9656. ], function(declare, dom, domAttr, domClass, event, kernel, has,
  9657. _Widget, _TemplatedMixin, _Contained, _CssStateMixin, template){
  9658. /*=====
  9659. var _Widget = dijit._Widget;
  9660. var _TemplatedMixin = dijit._TemplatedMixin;
  9661. var _Contained = dijit._Contained;
  9662. var _CssStateMixin = dijit._CssStateMixin;
  9663. =====*/
  9664. // module:
  9665. // dijit/MenuItem
  9666. // summary:
  9667. // A line item in a Menu Widget
  9668. return declare("dijit.MenuItem",
  9669. [_Widget, _TemplatedMixin, _Contained, _CssStateMixin],
  9670. {
  9671. // summary:
  9672. // A line item in a Menu Widget
  9673. // Make 3 columns
  9674. // icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
  9675. templateString: template,
  9676. baseClass: "dijitMenuItem",
  9677. // label: String
  9678. // Menu text
  9679. label: '',
  9680. _setLabelAttr: { node: "containerNode", type: "innerHTML" },
  9681. // iconClass: String
  9682. // Class to apply to DOMNode to make it display an icon.
  9683. iconClass: "dijitNoIcon",
  9684. _setIconClassAttr: { node: "iconNode", type: "class" },
  9685. // accelKey: String
  9686. // Text for the accelerator (shortcut) key combination.
  9687. // Note that although Menu can display accelerator keys there
  9688. // is no infrastructure to actually catch and execute these
  9689. // accelerators.
  9690. accelKey: "",
  9691. // disabled: Boolean
  9692. // If true, the menu item is disabled.
  9693. // If false, the menu item is enabled.
  9694. disabled: false,
  9695. _fillContent: function(/*DomNode*/ source){
  9696. // If button label is specified as srcNodeRef.innerHTML rather than
  9697. // this.params.label, handle it here.
  9698. if(source && !("label" in this.params)){
  9699. this.set('label', source.innerHTML);
  9700. }
  9701. },
  9702. buildRendering: function(){
  9703. this.inherited(arguments);
  9704. var label = this.id+"_text";
  9705. domAttr.set(this.containerNode, "id", label);
  9706. if(this.accelKeyNode){
  9707. domAttr.set(this.accelKeyNode, "id", this.id + "_accel");
  9708. label += " " + this.id + "_accel";
  9709. }
  9710. this.domNode.setAttribute("aria-labelledby", label);
  9711. dom.setSelectable(this.domNode, false);
  9712. },
  9713. _onHover: function(){
  9714. // summary:
  9715. // Handler when mouse is moved onto menu item
  9716. // tags:
  9717. // protected
  9718. this.getParent().onItemHover(this);
  9719. },
  9720. _onUnhover: function(){
  9721. // summary:
  9722. // Handler when mouse is moved off of menu item,
  9723. // possibly to a child menu, or maybe to a sibling
  9724. // menuitem or somewhere else entirely.
  9725. // tags:
  9726. // protected
  9727. // if we are unhovering the currently selected item
  9728. // then unselect it
  9729. this.getParent().onItemUnhover(this);
  9730. // When menu is hidden (collapsed) due to clicking a MenuItem and having it execute,
  9731. // FF and IE don't generate an onmouseout event for the MenuItem.
  9732. // So, help out _CssStateMixin in this case.
  9733. this._set("hovering", false);
  9734. },
  9735. _onClick: function(evt){
  9736. // summary:
  9737. // Internal handler for click events on MenuItem.
  9738. // tags:
  9739. // private
  9740. this.getParent().onItemClick(this, evt);
  9741. event.stop(evt);
  9742. },
  9743. onClick: function(/*Event*/){
  9744. // summary:
  9745. // User defined function to handle clicks
  9746. // tags:
  9747. // callback
  9748. },
  9749. focus: function(){
  9750. // summary:
  9751. // Focus on this MenuItem
  9752. try{
  9753. if(has("ie") == 8){
  9754. // needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
  9755. this.containerNode.focus();
  9756. }
  9757. this.focusNode.focus();
  9758. }catch(e){
  9759. // this throws on IE (at least) in some scenarios
  9760. }
  9761. },
  9762. _onFocus: function(){
  9763. // summary:
  9764. // This is called by the focus manager when focus
  9765. // goes to this MenuItem or a child menu.
  9766. // tags:
  9767. // protected
  9768. this._setSelected(true);
  9769. this.getParent()._onItemFocus(this);
  9770. this.inherited(arguments);
  9771. },
  9772. _setSelected: function(selected){
  9773. // summary:
  9774. // Indicate that this node is the currently selected one
  9775. // tags:
  9776. // private
  9777. /***
  9778. * TODO: remove this method and calls to it, when _onBlur() is working for MenuItem.
  9779. * Currently _onBlur() gets called when focus is moved from the MenuItem to a child menu.
  9780. * That's not supposed to happen, but the problem is:
  9781. * In order to allow dijit.popup's getTopPopup() to work,a sub menu's popupParent
  9782. * points to the parent Menu, bypassing the parent MenuItem... thus the
  9783. * MenuItem is not in the chain of active widgets and gets a premature call to
  9784. * _onBlur()
  9785. */
  9786. domClass.toggle(this.domNode, "dijitMenuItemSelected", selected);
  9787. },
  9788. setLabel: function(/*String*/ content){
  9789. // summary:
  9790. // Deprecated. Use set('label', ...) instead.
  9791. // tags:
  9792. // deprecated
  9793. kernel.deprecated("dijit.MenuItem.setLabel() is deprecated. Use set('label', ...) instead.", "", "2.0");
  9794. this.set("label", content);
  9795. },
  9796. setDisabled: function(/*Boolean*/ disabled){
  9797. // summary:
  9798. // Deprecated. Use set('disabled', bool) instead.
  9799. // tags:
  9800. // deprecated
  9801. kernel.deprecated("dijit.Menu.setDisabled() is deprecated. Use set('disabled', bool) instead.", "", "2.0");
  9802. this.set('disabled', disabled);
  9803. },
  9804. _setDisabledAttr: function(/*Boolean*/ value){
  9805. // summary:
  9806. // Hook for attr('disabled', ...) to work.
  9807. // Enable or disable this menu item.
  9808. this.focusNode.setAttribute('aria-disabled', value ? 'true' : 'false');
  9809. this._set("disabled", value);
  9810. },
  9811. _setAccelKeyAttr: function(/*String*/ value){
  9812. // summary:
  9813. // Hook for attr('accelKey', ...) to work.
  9814. // Set accelKey on this menu item.
  9815. this.accelKeyNode.style.display=value?"":"none";
  9816. this.accelKeyNode.innerHTML=value;
  9817. //have to use colSpan to make it work in IE
  9818. domAttr.set(this.containerNode,'colSpan',value?"1":"2");
  9819. this._set("accelKey", value);
  9820. }
  9821. });
  9822. });
  9823. },
  9824. 'dijit/layout/TabController':function(){
  9825. require({cache:{
  9826. 'url:dijit/layout/templates/_TabButton.html':"<div role=\"presentation\" data-dojo-attach-point=\"titleNode\" data-dojo-attach-event='onclick:onClick'>\n <div role=\"presentation\" class='dijitTabInnerDiv' data-dojo-attach-point='innerDiv'>\n <div role=\"presentation\" class='dijitTabContent' data-dojo-attach-point='tabContent'>\n \t<div role=\"presentation\" data-dojo-attach-point='focusNode'>\n\t\t <img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitTabButtonIcon\" data-dojo-attach-point='iconNode' />\n\t\t <span data-dojo-attach-point='containerNode' class='tabLabel'></span>\n\t\t <span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" data-dojo-attach-point='closeNode'\n\t\t \t\tdata-dojo-attach-event='onclick: onClickCloseButton' role=\"presentation\">\n\t\t <span data-dojo-attach-point='closeText' class='dijitTabCloseText'>[x]</span\n\t\t ></span>\n\t\t\t</div>\n </div>\n </div>\n</div>\n"}});
  9827. define("dijit/layout/TabController", [
  9828. "dojo/_base/declare", // declare
  9829. "dojo/dom", // dom.setSelectable
  9830. "dojo/dom-attr", // domAttr.attr
  9831. "dojo/dom-class", // domClass.toggle
  9832. "dojo/i18n", // i18n.getLocalization
  9833. "dojo/_base/lang", // lang.hitch lang.trim
  9834. "./StackController",
  9835. "../Menu",
  9836. "../MenuItem",
  9837. "dojo/text!./templates/_TabButton.html",
  9838. "dojo/i18n!../nls/common"
  9839. ], function(declare, dom, domAttr, domClass, i18n, lang, StackController, Menu, MenuItem, template){
  9840. /*=====
  9841. var StackController = dijit.layout.StackController;
  9842. var Menu = dijit.Menu;
  9843. var MenuItem = dijit.MenuItem;
  9844. =====*/
  9845. // module:
  9846. // dijit/layout/TabController
  9847. // summary:
  9848. // Set of tabs (the things with titles and a close button, that you click to show a tab panel).
  9849. // Used internally by `dijit.layout.TabContainer`.
  9850. var TabButton = declare("dijit.layout._TabButton", StackController.StackButton, {
  9851. // summary:
  9852. // A tab (the thing you click to select a pane).
  9853. // description:
  9854. // Contains the title of the pane, and optionally a close-button to destroy the pane.
  9855. // This is an internal widget and should not be instantiated directly.
  9856. // tags:
  9857. // private
  9858. // baseClass: String
  9859. // The CSS class applied to the domNode.
  9860. baseClass: "dijitTab",
  9861. // Apply dijitTabCloseButtonHover when close button is hovered
  9862. cssStateNodes: {
  9863. closeNode: "dijitTabCloseButton"
  9864. },
  9865. templateString: template,
  9866. // Override _FormWidget.scrollOnFocus.
  9867. // Don't scroll the whole tab container into view when the button is focused.
  9868. scrollOnFocus: false,
  9869. buildRendering: function(){
  9870. this.inherited(arguments);
  9871. dom.setSelectable(this.containerNode, false);
  9872. },
  9873. startup: function(){
  9874. this.inherited(arguments);
  9875. var n = this.domNode;
  9876. // Required to give IE6 a kick, as it initially hides the
  9877. // tabs until they are focused on.
  9878. setTimeout(function(){
  9879. n.className = n.className;
  9880. }, 1);
  9881. },
  9882. _setCloseButtonAttr: function(/*Boolean*/ disp){
  9883. // summary:
  9884. // Hide/show close button
  9885. this._set("closeButton", disp);
  9886. domClass.toggle(this.innerDiv, "dijitClosable", disp);
  9887. this.closeNode.style.display = disp ? "" : "none";
  9888. if(disp){
  9889. var _nlsResources = i18n.getLocalization("dijit", "common");
  9890. if(this.closeNode){
  9891. domAttr.set(this.closeNode,"title", _nlsResources.itemClose);
  9892. }
  9893. // add context menu onto title button
  9894. this._closeMenu = new Menu({
  9895. id: this.id+"_Menu",
  9896. dir: this.dir,
  9897. lang: this.lang,
  9898. textDir: this.textDir,
  9899. targetNodeIds: [this.domNode]
  9900. });
  9901. this._closeMenu.addChild(new MenuItem({
  9902. label: _nlsResources.itemClose,
  9903. dir: this.dir,
  9904. lang: this.lang,
  9905. textDir: this.textDir,
  9906. onClick: lang.hitch(this, "onClickCloseButton")
  9907. }));
  9908. }else{
  9909. if(this._closeMenu){
  9910. this._closeMenu.destroyRecursive();
  9911. delete this._closeMenu;
  9912. }
  9913. }
  9914. },
  9915. _setLabelAttr: function(/*String*/ content){
  9916. // summary:
  9917. // Hook for set('label', ...) to work.
  9918. // description:
  9919. // takes an HTML string.
  9920. // Inherited ToggleButton implementation will Set the label (text) of the button;
  9921. // Need to set the alt attribute of icon on tab buttons if no label displayed
  9922. this.inherited(arguments);
  9923. if(!this.showLabel && !this.params.title){
  9924. this.iconNode.alt = lang.trim(this.containerNode.innerText || this.containerNode.textContent || '');
  9925. }
  9926. },
  9927. destroy: function(){
  9928. if(this._closeMenu){
  9929. this._closeMenu.destroyRecursive();
  9930. delete this._closeMenu;
  9931. }
  9932. this.inherited(arguments);
  9933. }
  9934. });
  9935. var TabController = declare("dijit.layout.TabController", StackController, {
  9936. // summary:
  9937. // Set of tabs (the things with titles and a close button, that you click to show a tab panel).
  9938. // Used internally by `dijit.layout.TabContainer`.
  9939. // description:
  9940. // Lets the user select the currently shown pane in a TabContainer or StackContainer.
  9941. // TabController also monitors the TabContainer, and whenever a pane is
  9942. // added or deleted updates itself accordingly.
  9943. // tags:
  9944. // private
  9945. baseClass: "dijitTabController",
  9946. templateString: "<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'></div>",
  9947. // tabPosition: String
  9948. // Defines where tabs go relative to the content.
  9949. // "top", "bottom", "left-h", "right-h"
  9950. tabPosition: "top",
  9951. // buttonWidget: Constructor
  9952. // The tab widget to create to correspond to each page
  9953. buttonWidget: TabButton,
  9954. _rectifyRtlTabList: function(){
  9955. // summary:
  9956. // For left/right TabContainer when page is RTL mode, rectify the width of all tabs to be equal, otherwise the tab widths are different in IE
  9957. if(0 >= this.tabPosition.indexOf('-h')){ return; }
  9958. if(!this.pane2button){ return; }
  9959. var maxWidth = 0;
  9960. for(var pane in this.pane2button){
  9961. var ow = this.pane2button[pane].innerDiv.scrollWidth;
  9962. maxWidth = Math.max(maxWidth, ow);
  9963. }
  9964. //unify the length of all the tabs
  9965. for(pane in this.pane2button){
  9966. this.pane2button[pane].innerDiv.style.width = maxWidth + 'px';
  9967. }
  9968. }
  9969. });
  9970. TabController.TabButton = TabButton; // for monkey patching
  9971. return TabController;
  9972. });
  9973. },
  9974. 'dojo/cldr/supplemental':function(){
  9975. define("dojo/cldr/supplemental", ["../_base/kernel", "../_base/lang", "../i18n"], function(dojo, lang) {
  9976. // module:
  9977. // dojo/cldr/supplemental
  9978. // summary:
  9979. // TODOC
  9980. lang.getObject("cldr.supplemental", true, dojo);
  9981. dojo.cldr.supplemental.getFirstDayOfWeek = function(/*String?*/locale){
  9982. // summary: Returns a zero-based index for first day of the week
  9983. // description:
  9984. // Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar.
  9985. // e.g. Sunday (returns 0), or Monday (returns 1)
  9986. // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDay
  9987. var firstDay = {/*default is 1=Monday*/
  9988. mv:5,
  9989. ae:6,af:6,bh:6,dj:6,dz:6,eg:6,er:6,et:6,iq:6,ir:6,jo:6,ke:6,kw:6,
  9990. ly:6,ma:6,om:6,qa:6,sa:6,sd:6,so:6,sy:6,tn:6,ye:6,
  9991. ar:0,as:0,az:0,bw:0,ca:0,cn:0,fo:0,ge:0,gl:0,gu:0,hk:0,
  9992. il:0,'in':0,jm:0,jp:0,kg:0,kr:0,la:0,mh:0,mn:0,mo:0,mp:0,
  9993. mt:0,nz:0,ph:0,pk:0,sg:0,th:0,tt:0,tw:0,um:0,us:0,uz:0,
  9994. vi:0,zw:0
  9995. // variant. do not use? gb:0,
  9996. };
  9997. var country = dojo.cldr.supplemental._region(locale);
  9998. var dow = firstDay[country];
  9999. return (dow === undefined) ? 1 : dow; /*Number*/
  10000. };
  10001. dojo.cldr.supplemental._region = function(/*String?*/locale){
  10002. locale = dojo.i18n.normalizeLocale(locale);
  10003. var tags = locale.split('-');
  10004. var region = tags[1];
  10005. if(!region){
  10006. // IE often gives language only (#2269)
  10007. // Arbitrary mappings of language-only locales to a country:
  10008. region = {de:"de", en:"us", es:"es", fi:"fi", fr:"fr", he:"il", hu:"hu", it:"it",
  10009. ja:"jp", ko:"kr", nl:"nl", pt:"br", sv:"se", zh:"cn"}[tags[0]];
  10010. }else if(region.length == 4){
  10011. // The ISO 3166 country code is usually in the second position, unless a
  10012. // 4-letter script is given. See http://www.ietf.org/rfc/rfc4646.txt
  10013. region = tags[2];
  10014. }
  10015. return region;
  10016. };
  10017. dojo.cldr.supplemental.getWeekend = function(/*String?*/locale){
  10018. // summary: Returns a hash containing the start and end days of the weekend
  10019. // description:
  10020. // Returns a hash containing the start and end days of the weekend according to local custom using locale,
  10021. // or by default in the user's locale.
  10022. // e.g. {start:6, end:0}
  10023. // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End}
  10024. var weekendStart = {/*default is 6=Saturday*/
  10025. 'in':0,
  10026. af:4,dz:4,ir:4,om:4,sa:4,ye:4,
  10027. ae:5,bh:5,eg:5,il:5,iq:5,jo:5,kw:5,ly:5,ma:5,qa:5,sd:5,sy:5,tn:5
  10028. };
  10029. var weekendEnd = {/*default is 0=Sunday*/
  10030. af:5,dz:5,ir:5,om:5,sa:5,ye:5,
  10031. ae:6,bh:5,eg:6,il:6,iq:6,jo:6,kw:6,ly:6,ma:6,qa:6,sd:6,sy:6,tn:6
  10032. };
  10033. var country = dojo.cldr.supplemental._region(locale);
  10034. var start = weekendStart[country];
  10035. var end = weekendEnd[country];
  10036. if(start === undefined){start=6;}
  10037. if(end === undefined){end=0;}
  10038. return {start:start, end:end}; /*Object {start,end}*/
  10039. };
  10040. return dojo.cldr.supplemental;
  10041. });
  10042. },
  10043. 'dijit/ToolbarSeparator':function(){
  10044. define("dijit/ToolbarSeparator", [
  10045. "dojo/_base/declare", // declare
  10046. "dojo/dom", // dom.setSelectable
  10047. "./_Widget",
  10048. "./_TemplatedMixin"
  10049. ], function(declare, dom, _Widget, _TemplatedMixin){
  10050. /*=====
  10051. var _Widget = dijit._Widget;
  10052. var _TemplatedMixin = dijit._TemplatedMixin;
  10053. =====*/
  10054. // module:
  10055. // dijit/ToolbarSeparator
  10056. // summary:
  10057. // A spacer between two `dijit.Toolbar` items
  10058. return declare("dijit.ToolbarSeparator", [_Widget, _TemplatedMixin], {
  10059. // summary:
  10060. // A spacer between two `dijit.Toolbar` items
  10061. templateString: '<div class="dijitToolbarSeparator dijitInline" role="presentation"></div>',
  10062. buildRendering: function(){
  10063. this.inherited(arguments);
  10064. dom.setSelectable(this.domNode, false);
  10065. },
  10066. isFocusable: function(){
  10067. // summary:
  10068. // This widget isn't focusable, so pass along that fact.
  10069. // tags:
  10070. // protected
  10071. return false;
  10072. }
  10073. });
  10074. });
  10075. },
  10076. 'dijit/layout/_LayoutWidget':function(){
  10077. define("dijit/layout/_LayoutWidget", [
  10078. "dojo/_base/lang", // lang.mixin
  10079. "../_Widget",
  10080. "../_Container",
  10081. "../_Contained",
  10082. "dojo/_base/declare", // declare
  10083. "dojo/dom-class", // domClass.add domClass.remove
  10084. "dojo/dom-geometry", // domGeometry.marginBox
  10085. "dojo/dom-style", // domStyle.getComputedStyle
  10086. "dojo/_base/sniff", // has("ie")
  10087. "dojo/_base/window" // win.global
  10088. ], function(lang, _Widget, _Container, _Contained,
  10089. declare, domClass, domGeometry, domStyle, has, win){
  10090. /*=====
  10091. var _Widget = dijit._Widget;
  10092. var _Container = dijit._Container;
  10093. var _Contained = dijit._Contained;
  10094. =====*/
  10095. // module:
  10096. // dijit/layout/_LayoutWidget
  10097. // summary:
  10098. // _LayoutWidget Base class for a _Container widget which is responsible for laying out its children.
  10099. // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
  10100. return declare("dijit.layout._LayoutWidget", [_Widget, _Container, _Contained], {
  10101. // summary:
  10102. // Base class for a _Container widget which is responsible for laying out its children.
  10103. // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
  10104. // baseClass: [protected extension] String
  10105. // This class name is applied to the widget's domNode
  10106. // and also may be used to generate names for sub nodes,
  10107. // for example dijitTabContainer-content.
  10108. baseClass: "dijitLayoutContainer",
  10109. // isLayoutContainer: [protected] Boolean
  10110. // Indicates that this widget is going to call resize() on its
  10111. // children widgets, setting their size, when they become visible.
  10112. isLayoutContainer: true,
  10113. buildRendering: function(){
  10114. this.inherited(arguments);
  10115. domClass.add(this.domNode, "dijitContainer");
  10116. },
  10117. startup: function(){
  10118. // summary:
  10119. // Called after all the widgets have been instantiated and their
  10120. // dom nodes have been inserted somewhere under win.doc.body.
  10121. //
  10122. // Widgets should override this method to do any initialization
  10123. // dependent on other widgets existing, and then call
  10124. // this superclass method to finish things off.
  10125. //
  10126. // startup() in subclasses shouldn't do anything
  10127. // size related because the size of the widget hasn't been set yet.
  10128. if(this._started){ return; }
  10129. // Need to call inherited first - so that child widgets get started
  10130. // up correctly
  10131. this.inherited(arguments);
  10132. // If I am a not being controlled by a parent layout widget...
  10133. var parent = this.getParent && this.getParent();
  10134. if(!(parent && parent.isLayoutContainer)){
  10135. // Do recursive sizing and layout of all my descendants
  10136. // (passing in no argument to resize means that it has to glean the size itself)
  10137. this.resize();
  10138. // Since my parent isn't a layout container, and my style *may be* width=height=100%
  10139. // or something similar (either set directly or via a CSS class),
  10140. // monitor when viewport size changes so that I can re-layout.
  10141. this.connect(win.global, 'onresize', function(){
  10142. // Using function(){} closure to ensure no arguments passed to resize().
  10143. this.resize();
  10144. });
  10145. }
  10146. },
  10147. resize: function(changeSize, resultSize){
  10148. // summary:
  10149. // Call this to resize a widget, or after its size has changed.
  10150. // description:
  10151. // Change size mode:
  10152. // When changeSize is specified, changes the marginBox of this widget
  10153. // and forces it to relayout its contents accordingly.
  10154. // changeSize may specify height, width, or both.
  10155. //
  10156. // If resultSize is specified it indicates the size the widget will
  10157. // become after changeSize has been applied.
  10158. //
  10159. // Notification mode:
  10160. // When changeSize is null, indicates that the caller has already changed
  10161. // the size of the widget, or perhaps it changed because the browser
  10162. // window was resized. Tells widget to relayout its contents accordingly.
  10163. //
  10164. // If resultSize is also specified it indicates the size the widget has
  10165. // become.
  10166. //
  10167. // In either mode, this method also:
  10168. // 1. Sets this._borderBox and this._contentBox to the new size of
  10169. // the widget. Queries the current domNode size if necessary.
  10170. // 2. Calls layout() to resize contents (and maybe adjust child widgets).
  10171. //
  10172. // changeSize: Object?
  10173. // Sets the widget to this margin-box size and position.
  10174. // May include any/all of the following properties:
  10175. // | {w: int, h: int, l: int, t: int}
  10176. //
  10177. // resultSize: Object?
  10178. // The margin-box size of this widget after applying changeSize (if
  10179. // changeSize is specified). If caller knows this size and
  10180. // passes it in, we don't need to query the browser to get the size.
  10181. // | {w: int, h: int}
  10182. var node = this.domNode;
  10183. // set margin box size, unless it wasn't specified, in which case use current size
  10184. if(changeSize){
  10185. domGeometry.setMarginBox(node, changeSize);
  10186. }
  10187. // If either height or width wasn't specified by the user, then query node for it.
  10188. // But note that setting the margin box and then immediately querying dimensions may return
  10189. // inaccurate results, so try not to depend on it.
  10190. var mb = resultSize || {};
  10191. lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
  10192. if( !("h" in mb) || !("w" in mb) ){
  10193. mb = lang.mixin(domGeometry.getMarginBox(node), mb); // just use domGeometry.marginBox() to fill in missing values
  10194. }
  10195. // Compute and save the size of my border box and content box
  10196. // (w/out calling domGeometry.getContentBox() since that may fail if size was recently set)
  10197. var cs = domStyle.getComputedStyle(node);
  10198. var me = domGeometry.getMarginExtents(node, cs);
  10199. var be = domGeometry.getBorderExtents(node, cs);
  10200. var bb = (this._borderBox = {
  10201. w: mb.w - (me.w + be.w),
  10202. h: mb.h - (me.h + be.h)
  10203. });
  10204. var pe = domGeometry.getPadExtents(node, cs);
  10205. this._contentBox = {
  10206. l: domStyle.toPixelValue(node, cs.paddingLeft),
  10207. t: domStyle.toPixelValue(node, cs.paddingTop),
  10208. w: bb.w - pe.w,
  10209. h: bb.h - pe.h
  10210. };
  10211. // Callback for widget to adjust size of its children
  10212. this.layout();
  10213. },
  10214. layout: function(){
  10215. // summary:
  10216. // Widgets override this method to size and position their contents/children.
  10217. // When this is called this._contentBox is guaranteed to be set (see resize()).
  10218. //
  10219. // This is called after startup(), and also when the widget's size has been
  10220. // changed.
  10221. // tags:
  10222. // protected extension
  10223. },
  10224. _setupChild: function(/*dijit._Widget*/child){
  10225. // summary:
  10226. // Common setup for initial children and children which are added after startup
  10227. // tags:
  10228. // protected extension
  10229. var cls = this.baseClass + "-child "
  10230. + (child.baseClass ? this.baseClass + "-" + child.baseClass : "");
  10231. domClass.add(child.domNode, cls);
  10232. },
  10233. addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
  10234. // Overrides _Container.addChild() to call _setupChild()
  10235. this.inherited(arguments);
  10236. if(this._started){
  10237. this._setupChild(child);
  10238. }
  10239. },
  10240. removeChild: function(/*dijit._Widget*/ child){
  10241. // Overrides _Container.removeChild() to remove class added by _setupChild()
  10242. var cls = this.baseClass + "-child"
  10243. + (child.baseClass ?
  10244. " " + this.baseClass + "-" + child.baseClass : "");
  10245. domClass.remove(child.domNode, cls);
  10246. this.inherited(arguments);
  10247. }
  10248. });
  10249. });
  10250. },
  10251. 'dojox/uuid/_base':function(){
  10252. define("dojox/uuid/_base", ['dojo/_base/kernel', 'dojo/_base/lang'], function(dojo){
  10253. dojo.getObject("uuid", true, dojox);
  10254. // Public constants:
  10255. dojox.uuid.NIL_UUID = "00000000-0000-0000-0000-000000000000";
  10256. dojox.uuid.version = {
  10257. // Enumeration for the different UUID versions.
  10258. UNKNOWN: 0,
  10259. TIME_BASED: 1,
  10260. DCE_SECURITY: 2,
  10261. NAME_BASED_MD5: 3,
  10262. RANDOM: 4,
  10263. NAME_BASED_SHA1: 5 };
  10264. dojox.uuid.variant = {
  10265. // Enumeration for the different UUID variants.
  10266. NCS: "0",
  10267. DCE: "10",
  10268. MICROSOFT: "110",
  10269. UNKNOWN: "111" };
  10270. dojox.uuid.assert = function(/*Boolean*/ booleanValue, /*String?*/ message){
  10271. // summary:
  10272. // Throws an exception if the assertion fails.
  10273. // description:
  10274. // If the asserted condition is true, this method does nothing. If the
  10275. // condition is false, we throw an error with a error message.
  10276. // booleanValue: Must be true for the assertion to succeed.
  10277. // message: A string describing the assertion.
  10278. // throws: Throws an Error if 'booleanValue' is false.
  10279. if(!booleanValue){
  10280. if(!message){
  10281. message = "An assert statement failed.\n" +
  10282. "The method dojox.uuid.assert() was called with a 'false' value.\n";
  10283. }
  10284. throw new Error(message);
  10285. }
  10286. };
  10287. dojox.uuid.generateNilUuid = function(){
  10288. // summary:
  10289. // This function returns the Nil UUID: "00000000-0000-0000-0000-000000000000".
  10290. // description:
  10291. // The Nil UUID is described in section 4.1.7 of
  10292. // RFC 4122: http://tools.ietf.org/html/rfc4122#section-4.1.7
  10293. // examples:
  10294. // var string = dojox.uuid.generateNilUuid();
  10295. return dojox.uuid.NIL_UUID; // String
  10296. };
  10297. dojox.uuid.isValid = function(/*String*/ uuidString){
  10298. // summary:
  10299. // Returns true if the UUID was initialized with a valid value.
  10300. uuidString = uuidString.toString();
  10301. var valid = (dojo.isString(uuidString) &&
  10302. (uuidString.length == 36) &&
  10303. (uuidString == uuidString.toLowerCase()));
  10304. if(valid){
  10305. var arrayOfParts = uuidString.split("-");
  10306. valid = ((arrayOfParts.length == 5) &&
  10307. (arrayOfParts[0].length == 8) &&
  10308. (arrayOfParts[1].length == 4) &&
  10309. (arrayOfParts[2].length == 4) &&
  10310. (arrayOfParts[3].length == 4) &&
  10311. (arrayOfParts[4].length == 12));
  10312. var HEX_RADIX = 16;
  10313. for (var i in arrayOfParts) {
  10314. var part = arrayOfParts[i];
  10315. var integer = parseInt(part, HEX_RADIX);
  10316. valid = valid && isFinite(integer);
  10317. }
  10318. }
  10319. return valid; // boolean
  10320. };
  10321. dojox.uuid.getVariant = function(/*String*/ uuidString){
  10322. // summary:
  10323. // Returns a variant code that indicates what type of UUID this is.
  10324. // Returns one of the enumerated dojox.uuid.variant values.
  10325. // example:
  10326. // var variant = dojox.uuid.getVariant("3b12f1df-5232-4804-897e-917bf397618a");
  10327. // dojox.uuid.assert(variant == dojox.uuid.variant.DCE);
  10328. // example:
  10329. // "3b12f1df-5232-4804-897e-917bf397618a"
  10330. // ^
  10331. // |
  10332. // (variant "10__" == DCE)
  10333. if(!dojox.uuid._ourVariantLookupTable){
  10334. var variant = dojox.uuid.variant;
  10335. var lookupTable = [];
  10336. lookupTable[0x0] = variant.NCS; // 0000
  10337. lookupTable[0x1] = variant.NCS; // 0001
  10338. lookupTable[0x2] = variant.NCS; // 0010
  10339. lookupTable[0x3] = variant.NCS; // 0011
  10340. lookupTable[0x4] = variant.NCS; // 0100
  10341. lookupTable[0x5] = variant.NCS; // 0101
  10342. lookupTable[0x6] = variant.NCS; // 0110
  10343. lookupTable[0x7] = variant.NCS; // 0111
  10344. lookupTable[0x8] = variant.DCE; // 1000
  10345. lookupTable[0x9] = variant.DCE; // 1001
  10346. lookupTable[0xA] = variant.DCE; // 1010
  10347. lookupTable[0xB] = variant.DCE; // 1011
  10348. lookupTable[0xC] = variant.MICROSOFT; // 1100
  10349. lookupTable[0xD] = variant.MICROSOFT; // 1101
  10350. lookupTable[0xE] = variant.UNKNOWN; // 1110
  10351. lookupTable[0xF] = variant.UNKNOWN; // 1111
  10352. dojox.uuid._ourVariantLookupTable = lookupTable;
  10353. }
  10354. uuidString = uuidString.toString();
  10355. var variantCharacter = uuidString.charAt(19);
  10356. var HEX_RADIX = 16;
  10357. var variantNumber = parseInt(variantCharacter, HEX_RADIX);
  10358. dojox.uuid.assert((variantNumber >= 0) && (variantNumber <= 16));
  10359. return dojox.uuid._ourVariantLookupTable[variantNumber]; // dojox.uuid.variant
  10360. };
  10361. dojox.uuid.getVersion = function(/*String*/ uuidString){
  10362. // summary:
  10363. // Returns a version number that indicates what type of UUID this is.
  10364. // Returns one of the enumerated dojox.uuid.version values.
  10365. // example:
  10366. // var version = dojox.uuid.getVersion("b4308fb0-86cd-11da-a72b-0800200c9a66");
  10367. // dojox.uuid.assert(version == dojox.uuid.version.TIME_BASED);
  10368. // exceptions:
  10369. // Throws an Error if this is not a DCE Variant UUID.
  10370. var errorMessage = "dojox.uuid.getVersion() was not passed a DCE Variant UUID.";
  10371. dojox.uuid.assert(dojox.uuid.getVariant(uuidString) == dojox.uuid.variant.DCE, errorMessage);
  10372. uuidString = uuidString.toString();
  10373. // "b4308fb0-86cd-11da-a72b-0800200c9a66"
  10374. // ^
  10375. // |
  10376. // (version 1 == TIME_BASED)
  10377. var versionCharacter = uuidString.charAt(14);
  10378. var HEX_RADIX = 16;
  10379. var versionNumber = parseInt(versionCharacter, HEX_RADIX);
  10380. return versionNumber; // dojox.uuid.version
  10381. };
  10382. dojox.uuid.getNode = function(/*String*/ uuidString){
  10383. // summary:
  10384. // If this is a version 1 UUID (a time-based UUID), getNode() returns a
  10385. // 12-character string with the "node" or "pseudonode" portion of the UUID,
  10386. // which is the rightmost 12 characters.
  10387. // exceptions:
  10388. // Throws an Error if this is not a version 1 UUID.
  10389. var errorMessage = "dojox.uuid.getNode() was not passed a TIME_BASED UUID.";
  10390. dojox.uuid.assert(dojox.uuid.getVersion(uuidString) == dojox.uuid.version.TIME_BASED, errorMessage);
  10391. uuidString = uuidString.toString();
  10392. var arrayOfStrings = uuidString.split('-');
  10393. var nodeString = arrayOfStrings[4];
  10394. return nodeString; // String (a 12-character string, which will look something like "917bf397618a")
  10395. };
  10396. dojox.uuid.getTimestamp = function(/*String*/ uuidString, /*String?*/ returnType){
  10397. // summary:
  10398. // If this is a version 1 UUID (a time-based UUID), this method returns
  10399. // the timestamp value encoded in the UUID. The caller can ask for the
  10400. // timestamp to be returned either as a JavaScript Date object or as a
  10401. // 15-character string of hex digits.
  10402. // returnType: Any of these five values: "string", String, "hex", "date", Date
  10403. // returns:
  10404. // Returns the timestamp value as a JavaScript Date object or a 15-character string of hex digits.
  10405. // examples:
  10406. // var uuidString = "b4308fb0-86cd-11da-a72b-0800200c9a66";
  10407. // var date, string, hexString;
  10408. // date = dojox.uuid.getTimestamp(uuidString); // returns a JavaScript Date
  10409. // date = dojox.uuid.getTimestamp(uuidString, Date); //
  10410. // string = dojox.uuid.getTimestamp(uuidString, String); // "Mon, 16 Jan 2006 20:21:41 GMT"
  10411. // hexString = dojox.uuid.getTimestamp(uuidString, "hex"); // "1da86cdb4308fb0"
  10412. // exceptions:
  10413. // Throws an Error if this is not a version 1 UUID.
  10414. var errorMessage = "dojox.uuid.getTimestamp() was not passed a TIME_BASED UUID.";
  10415. dojox.uuid.assert(dojox.uuid.getVersion(uuidString) == dojox.uuid.version.TIME_BASED, errorMessage);
  10416. uuidString = uuidString.toString();
  10417. if(!returnType){returnType = null};
  10418. switch(returnType){
  10419. case "string":
  10420. case String:
  10421. return dojox.uuid.getTimestamp(uuidString, Date).toUTCString(); // String (e.g. "Mon, 16 Jan 2006 20:21:41 GMT")
  10422. break;
  10423. case "hex":
  10424. // Return a 15-character string of hex digits containing the
  10425. // timestamp for this UUID, with the high-order bits first.
  10426. var arrayOfStrings = uuidString.split('-');
  10427. var hexTimeLow = arrayOfStrings[0];
  10428. var hexTimeMid = arrayOfStrings[1];
  10429. var hexTimeHigh = arrayOfStrings[2];
  10430. // Chop off the leading "1" character, which is the UUID
  10431. // version number for time-based UUIDs.
  10432. hexTimeHigh = hexTimeHigh.slice(1);
  10433. var timestampAsHexString = hexTimeHigh + hexTimeMid + hexTimeLow;
  10434. dojox.uuid.assert(timestampAsHexString.length == 15);
  10435. return timestampAsHexString; // String (e.g. "1da86cdb4308fb0")
  10436. break;
  10437. case null: // no returnType was specified, so default to Date
  10438. case "date":
  10439. case Date:
  10440. // Return a JavaScript Date object.
  10441. var GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
  10442. var HEX_RADIX = 16;
  10443. var arrayOfParts = uuidString.split('-');
  10444. var timeLow = parseInt(arrayOfParts[0], HEX_RADIX);
  10445. var timeMid = parseInt(arrayOfParts[1], HEX_RADIX);
  10446. var timeHigh = parseInt(arrayOfParts[2], HEX_RADIX);
  10447. var hundredNanosecondIntervalsSince1582 = timeHigh & 0x0FFF;
  10448. hundredNanosecondIntervalsSince1582 <<= 16;
  10449. hundredNanosecondIntervalsSince1582 += timeMid;
  10450. // What we really want to do next is shift left 32 bits, but the
  10451. // result will be too big to fit in an int, so we'll multiply by 2^32,
  10452. // and the result will be a floating point approximation.
  10453. hundredNanosecondIntervalsSince1582 *= 0x100000000;
  10454. hundredNanosecondIntervalsSince1582 += timeLow;
  10455. var millisecondsSince1582 = hundredNanosecondIntervalsSince1582 / 10000;
  10456. // Again, this will be a floating point approximation.
  10457. // We can make things exact later if we need to.
  10458. var secondsPerHour = 60 * 60;
  10459. var hoursBetween1582and1970 = GREGORIAN_CHANGE_OFFSET_IN_HOURS;
  10460. var secondsBetween1582and1970 = hoursBetween1582and1970 * secondsPerHour;
  10461. var millisecondsBetween1582and1970 = secondsBetween1582and1970 * 1000;
  10462. var millisecondsSince1970 = millisecondsSince1582 - millisecondsBetween1582and1970;
  10463. var timestampAsDate = new Date(millisecondsSince1970);
  10464. return timestampAsDate; // Date
  10465. break;
  10466. default:
  10467. // we got passed something other than a valid returnType
  10468. dojox.uuid.assert(false, "dojox.uuid.getTimestamp was not passed a valid returnType: " + returnType);
  10469. break;
  10470. }
  10471. };
  10472. return dojox.uuid;
  10473. });
  10474. },
  10475. 'dojo/back':function(){
  10476. define("dojo/back", ["./_base/kernel", "./_base/lang", "./_base/sniff", "./dom", "./dom-construct", "./_base/window", "require"], function(dojo, lang, sniff, dom, domConstruct, baseWindow, require) {
  10477. // module:
  10478. // dojo/back
  10479. // summary:
  10480. // TODOC
  10481. lang.getObject("back", true, dojo);
  10482. /*=====
  10483. dojo.back = {
  10484. // summary: Browser history management resources
  10485. };
  10486. =====*/
  10487. var back = dojo.back,
  10488. // everyone deals with encoding the hash slightly differently
  10489. getHash = back.getHash = function(){
  10490. var h = window.location.hash;
  10491. if(h.charAt(0) == "#"){ h = h.substring(1); }
  10492. return sniff("mozilla") ? h : decodeURIComponent(h);
  10493. },
  10494. setHash = back.setHash = function(h){
  10495. if(!h){ h = ""; }
  10496. window.location.hash = encodeURIComponent(h);
  10497. historyCounter = history.length;
  10498. };
  10499. var initialHref = (typeof(window) !== "undefined") ? window.location.href : "";
  10500. var initialHash = (typeof(window) !== "undefined") ? getHash() : "";
  10501. var initialState = null;
  10502. var locationTimer = null;
  10503. var bookmarkAnchor = null;
  10504. var historyIframe = null;
  10505. var forwardStack = [];
  10506. var historyStack = [];
  10507. var moveForward = false;
  10508. var changingUrl = false;
  10509. var historyCounter;
  10510. function handleBackButton(){
  10511. //summary: private method. Do not call this directly.
  10512. //The "current" page is always at the top of the history stack.
  10513. var current = historyStack.pop();
  10514. if(!current){ return; }
  10515. var last = historyStack[historyStack.length-1];
  10516. if(!last && historyStack.length == 0){
  10517. last = initialState;
  10518. }
  10519. if(last){
  10520. if(last.kwArgs["back"]){
  10521. last.kwArgs["back"]();
  10522. }else if(last.kwArgs["backButton"]){
  10523. last.kwArgs["backButton"]();
  10524. }else if(last.kwArgs["handle"]){
  10525. last.kwArgs.handle("back");
  10526. }
  10527. }
  10528. forwardStack.push(current);
  10529. }
  10530. back.goBack = handleBackButton;
  10531. function handleForwardButton(){
  10532. //summary: private method. Do not call this directly.
  10533. var last = forwardStack.pop();
  10534. if(!last){ return; }
  10535. if(last.kwArgs["forward"]){
  10536. last.kwArgs.forward();
  10537. }else if(last.kwArgs["forwardButton"]){
  10538. last.kwArgs.forwardButton();
  10539. }else if(last.kwArgs["handle"]){
  10540. last.kwArgs.handle("forward");
  10541. }
  10542. historyStack.push(last);
  10543. }
  10544. back.goForward = handleForwardButton;
  10545. function createState(url, args, hash){
  10546. //summary: private method. Do not call this directly.
  10547. return {"url": url, "kwArgs": args, "urlHash": hash}; //Object
  10548. }
  10549. function getUrlQuery(url){
  10550. //summary: private method. Do not call this directly.
  10551. var segments = url.split("?");
  10552. if(segments.length < 2){
  10553. return null; //null
  10554. }
  10555. else{
  10556. return segments[1]; //String
  10557. }
  10558. }
  10559. function loadIframeHistory(){
  10560. //summary: private method. Do not call this directly.
  10561. var url = (dojo.config["dojoIframeHistoryUrl"] || require.toUrl("./resources/iframe_history.html")) + "?" + (new Date()).getTime();
  10562. moveForward = true;
  10563. if(historyIframe){
  10564. sniff("webkit") ? historyIframe.location = url : window.frames[historyIframe.name].location = url;
  10565. }else{
  10566. //console.warn("dojo.back: Not initialised. You need to call dojo.back.init() from a <script> block that lives inside the <body> tag.");
  10567. }
  10568. return url; //String
  10569. }
  10570. function checkLocation(){
  10571. if(!changingUrl){
  10572. var hsl = historyStack.length;
  10573. var hash = getHash();
  10574. if((hash === initialHash||window.location.href == initialHref)&&(hsl == 1)){
  10575. // FIXME: could this ever be a forward button?
  10576. // we can't clear it because we still need to check for forwards. Ugg.
  10577. // clearInterval(this.locationTimer);
  10578. handleBackButton();
  10579. return;
  10580. }
  10581. // first check to see if we could have gone forward. We always halt on
  10582. // a no-hash item.
  10583. if(forwardStack.length > 0){
  10584. if(forwardStack[forwardStack.length-1].urlHash === hash){
  10585. handleForwardButton();
  10586. return;
  10587. }
  10588. }
  10589. // ok, that didn't work, try someplace back in the history stack
  10590. if((hsl >= 2)&&(historyStack[hsl-2])){
  10591. if(historyStack[hsl-2].urlHash === hash){
  10592. handleBackButton();
  10593. }
  10594. }
  10595. }
  10596. }
  10597. back.init = function(){
  10598. //summary: Initializes the undo stack. This must be called from a <script>
  10599. // block that lives inside the <body> tag to prevent bugs on IE.
  10600. // description:
  10601. // Only call this method before the page's DOM is finished loading. Otherwise
  10602. // it will not work. Be careful with xdomain loading or djConfig.debugAtAllCosts scenarios,
  10603. // in order for this method to work, dojo.back will need to be part of a build layer.
  10604. // prevent reinit
  10605. if(dom.byId("dj_history")){ return; }
  10606. var src = dojo.config["dojoIframeHistoryUrl"] || require.toUrl("./resources/iframe_history.html");
  10607. if (dojo._postLoad) {
  10608. console.error("dojo.back.init() must be called before the DOM has loaded. "
  10609. + "If using xdomain loading or djConfig.debugAtAllCosts, include dojo.back "
  10610. + "in a build layer.");
  10611. } else {
  10612. document.write('<iframe style="border:0;width:1px;height:1px;position:absolute;visibility:hidden;bottom:0;right:0;" name="dj_history" id="dj_history" src="' + src + '"></iframe>');
  10613. }
  10614. };
  10615. back.setInitialState = function(/*Object*/args){
  10616. //summary:
  10617. // Sets the state object and back callback for the very first page
  10618. // that is loaded.
  10619. //description:
  10620. // It is recommended that you call this method as part of an event
  10621. // listener that is registered via dojo.addOnLoad().
  10622. //args: Object
  10623. // See the addToHistory() function for the list of valid args properties.
  10624. initialState = createState(initialHref, args, initialHash);
  10625. };
  10626. //FIXME: Make these doc comments not be awful. At least they're not wrong.
  10627. //FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
  10628. //FIXME: is there a slight race condition in moz using change URL with the timer check and when
  10629. // the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
  10630. /*=====
  10631. dojo.__backArgs = function(kwArgs){
  10632. // back: Function?
  10633. // A function to be called when this state is reached via the user
  10634. // clicking the back button.
  10635. // forward: Function?
  10636. // Upon return to this state from the "back, forward" combination
  10637. // of navigation steps, this function will be called. Somewhat
  10638. // analgous to the semantic of an "onRedo" event handler.
  10639. // changeUrl: Boolean?|String?
  10640. // Boolean indicating whether or not to create a unique hash for
  10641. // this state. If a string is passed instead, it is used as the
  10642. // hash.
  10643. }
  10644. =====*/
  10645. back.addToHistory = function(/*dojo.__backArgs*/ args){
  10646. // summary:
  10647. // adds a state object (args) to the history list.
  10648. // args: dojo.__backArgs
  10649. // The state object that will be added to the history list.
  10650. // description:
  10651. // To support getting back button notifications, the object
  10652. // argument should implement a function called either "back",
  10653. // "backButton", or "handle". The string "back" will be passed as
  10654. // the first and only argument to this callback.
  10655. //
  10656. // To support getting forward button notifications, the object
  10657. // argument should implement a function called either "forward",
  10658. // "forwardButton", or "handle". The string "forward" will be
  10659. // passed as the first and only argument to this callback.
  10660. //
  10661. // If you want the browser location string to change, define "changeUrl" on the object. If the
  10662. // value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
  10663. // identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
  10664. // not evaluate to false, that value will be used as the fragment identifier. For example,
  10665. // if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
  10666. //
  10667. // There are problems with using dojo.back with semantically-named fragment identifiers
  10668. // ("hash values" on an URL). In most browsers it will be hard for dojo.back to know
  10669. // distinguish a back from a forward event in those cases. For back/forward support to
  10670. // work best, the fragment ID should always be a unique value (something using new Date().getTime()
  10671. // for example). If you want to detect hash changes using semantic fragment IDs, then
  10672. // consider using dojo.hash instead (in Dojo 1.4+).
  10673. //
  10674. // example:
  10675. // | dojo.back.addToHistory({
  10676. // | back: function(){ console.log('back pressed'); },
  10677. // | forward: function(){ console.log('forward pressed'); },
  10678. // | changeUrl: true
  10679. // | });
  10680. // BROWSER NOTES:
  10681. // Safari 1.2:
  10682. // back button "works" fine, however it's not possible to actually
  10683. // DETECT that you've moved backwards by inspecting window.location.
  10684. // Unless there is some other means of locating.
  10685. // FIXME: perhaps we can poll on history.length?
  10686. // Safari 2.0.3+ (and probably 1.3.2+):
  10687. // works fine, except when changeUrl is used. When changeUrl is used,
  10688. // Safari jumps all the way back to whatever page was shown before
  10689. // the page that uses dojo.undo.browser support.
  10690. // IE 5.5 SP2:
  10691. // back button behavior is macro. It does not move back to the
  10692. // previous hash value, but to the last full page load. This suggests
  10693. // that the iframe is the correct way to capture the back button in
  10694. // these cases.
  10695. // Don't test this page using local disk for MSIE. MSIE will not create
  10696. // a history list for iframe_history.html if served from a file: URL.
  10697. // The XML served back from the XHR tests will also not be properly
  10698. // created if served from local disk. Serve the test pages from a web
  10699. // server to test in that browser.
  10700. // IE 6.0:
  10701. // same behavior as IE 5.5 SP2
  10702. // Firefox 1.0+:
  10703. // the back button will return us to the previous hash on the same
  10704. // page, thereby not requiring an iframe hack, although we do then
  10705. // need to run a timer to detect inter-page movement.
  10706. //If addToHistory is called, then that means we prune the
  10707. //forward stack -- the user went back, then wanted to
  10708. //start a new forward path.
  10709. forwardStack = [];
  10710. var hash = null;
  10711. var url = null;
  10712. if(!historyIframe){
  10713. if(dojo.config["useXDomain"] && !dojo.config["dojoIframeHistoryUrl"]){
  10714. console.warn("dojo.back: When using cross-domain Dojo builds,"
  10715. + " please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
  10716. + " to the path on your domain to iframe_history.html");
  10717. }
  10718. historyIframe = window.frames["dj_history"];
  10719. }
  10720. if(!bookmarkAnchor){
  10721. bookmarkAnchor = domConstruct.create("a", {style: {display: "none"}}, baseWindow.body());
  10722. }
  10723. if(args["changeUrl"]){
  10724. hash = ""+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
  10725. //If the current hash matches the new one, just replace the history object with
  10726. //this new one. It doesn't make sense to track different state objects for the same
  10727. //logical URL. This matches the browser behavior of only putting in one history
  10728. //item no matter how many times you click on the same #hash link, at least in Firefox
  10729. //and Safari, and there is no reliable way in those browsers to know if a #hash link
  10730. //has been clicked on multiple times. So making this the standard behavior in all browsers
  10731. //so that dojo.back's behavior is the same in all browsers.
  10732. if(historyStack.length == 0 && initialState.urlHash == hash){
  10733. initialState = createState(url, args, hash);
  10734. return;
  10735. }else if(historyStack.length > 0 && historyStack[historyStack.length - 1].urlHash == hash){
  10736. historyStack[historyStack.length - 1] = createState(url, args, hash);
  10737. return;
  10738. }
  10739. changingUrl = true;
  10740. setTimeout(function() {
  10741. setHash(hash);
  10742. changingUrl = false;
  10743. }, 1);
  10744. bookmarkAnchor.href = hash;
  10745. if(sniff("ie")){
  10746. url = loadIframeHistory();
  10747. var oldCB = args["back"]||args["backButton"]||args["handle"];
  10748. //The function takes handleName as a parameter, in case the
  10749. //callback we are overriding was "handle". In that case,
  10750. //we will need to pass the handle name to handle.
  10751. var tcb = function(handleName){
  10752. if(getHash() != ""){
  10753. setTimeout(function() { setHash(hash); }, 1);
  10754. }
  10755. //Use apply to set "this" to args, and to try to avoid memory leaks.
  10756. oldCB.apply(this, [handleName]);
  10757. };
  10758. //Set interceptor function in the right place.
  10759. if(args["back"]){
  10760. args.back = tcb;
  10761. }else if(args["backButton"]){
  10762. args.backButton = tcb;
  10763. }else if(args["handle"]){
  10764. args.handle = tcb;
  10765. }
  10766. var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
  10767. //The function takes handleName as a parameter, in case the
  10768. //callback we are overriding was "handle". In that case,
  10769. //we will need to pass the handle name to handle.
  10770. var tfw = function(handleName){
  10771. if(getHash() != ""){
  10772. setHash(hash);
  10773. }
  10774. if(oldFW){ // we might not actually have one
  10775. //Use apply to set "this" to args, and to try to avoid memory leaks.
  10776. oldFW.apply(this, [handleName]);
  10777. }
  10778. };
  10779. //Set interceptor function in the right place.
  10780. if(args["forward"]){
  10781. args.forward = tfw;
  10782. }else if(args["forwardButton"]){
  10783. args.forwardButton = tfw;
  10784. }else if(args["handle"]){
  10785. args.handle = tfw;
  10786. }
  10787. }else if(!sniff("ie")){
  10788. // start the timer
  10789. if(!locationTimer){
  10790. locationTimer = setInterval(checkLocation, 200);
  10791. }
  10792. }
  10793. }else{
  10794. url = loadIframeHistory();
  10795. }
  10796. historyStack.push(createState(url, args, hash));
  10797. };
  10798. back._iframeLoaded = function(evt, ifrLoc){
  10799. //summary:
  10800. // private method. Do not call this directly.
  10801. var query = getUrlQuery(ifrLoc.href);
  10802. if(query == null){
  10803. // alert("iframeLoaded");
  10804. // we hit the end of the history, so we should go back
  10805. if(historyStack.length == 1){
  10806. handleBackButton();
  10807. }
  10808. return;
  10809. }
  10810. if(moveForward){
  10811. // we were expecting it, so it's not either a forward or backward movement
  10812. moveForward = false;
  10813. return;
  10814. }
  10815. //Check the back stack first, since it is more likely.
  10816. //Note that only one step back or forward is supported.
  10817. if(historyStack.length >= 2 && query == getUrlQuery(historyStack[historyStack.length-2].url)){
  10818. handleBackButton();
  10819. }else if(forwardStack.length > 0 && query == getUrlQuery(forwardStack[forwardStack.length-1].url)){
  10820. handleForwardButton();
  10821. }
  10822. };
  10823. return dojo.back;
  10824. });
  10825. },
  10826. 'dijit/popup':function(){
  10827. define("dijit/popup", [
  10828. "dojo/_base/array", // array.forEach array.some
  10829. "dojo/aspect",
  10830. "dojo/_base/connect", // connect._keypress
  10831. "dojo/_base/declare", // declare
  10832. "dojo/dom", // dom.isDescendant
  10833. "dojo/dom-attr", // domAttr.set
  10834. "dojo/dom-construct", // domConstruct.create domConstruct.destroy
  10835. "dojo/dom-geometry", // domGeometry.isBodyLtr
  10836. "dojo/dom-style", // domStyle.set
  10837. "dojo/_base/event", // event.stop
  10838. "dojo/has",
  10839. "dojo/keys",
  10840. "dojo/_base/lang", // lang.hitch
  10841. "dojo/on",
  10842. "dojo/_base/window", // win.body
  10843. "./place",
  10844. "./BackgroundIframe",
  10845. "." // dijit (defining dijit.popup to match API doc)
  10846. ], function(array, aspect, connect, declare, dom, domAttr, domConstruct, domGeometry, domStyle, event, has, keys, lang, on, win,
  10847. place, BackgroundIframe, dijit){
  10848. // module:
  10849. // dijit/popup
  10850. // summary:
  10851. // Used to show drop downs (ex: the select list of a ComboBox)
  10852. // or popups (ex: right-click context menus)
  10853. /*=====
  10854. dijit.popup.__OpenArgs = function(){
  10855. // popup: Widget
  10856. // widget to display
  10857. // parent: Widget
  10858. // the button etc. that is displaying this popup
  10859. // around: DomNode
  10860. // DOM node (typically a button); place popup relative to this node. (Specify this *or* "x" and "y" parameters.)
  10861. // x: Integer
  10862. // Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
  10863. // y: Integer
  10864. // Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
  10865. // orient: Object|String
  10866. // When the around parameter is specified, orient should be a list of positions to try, ex:
  10867. // | [ "below", "above" ]
  10868. // For backwards compatibility it can also be an (ordered) hash of tuples of the form
  10869. // (around-node-corner, popup-node-corner), ex:
  10870. // | { "BL": "TL", "TL": "BL" }
  10871. // where BL means "bottom left" and "TL" means "top left", etc.
  10872. //
  10873. // dijit.popup.open() tries to position the popup according to each specified position, in order,
  10874. // until the popup appears fully within the viewport.
  10875. //
  10876. // The default value is ["below", "above"]
  10877. //
  10878. // When an (x,y) position is specified rather than an around node, orient is either
  10879. // "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
  10880. // specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
  10881. // fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
  10882. // and the top-right corner.
  10883. // onCancel: Function
  10884. // callback when user has canceled the popup by
  10885. // 1. hitting ESC or
  10886. // 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
  10887. // i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
  10888. // onClose: Function
  10889. // callback whenever this popup is closed
  10890. // onExecute: Function
  10891. // callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
  10892. // padding: dijit.__Position
  10893. // adding a buffer around the opening position. This is only useful when around is not set.
  10894. this.popup = popup;
  10895. this.parent = parent;
  10896. this.around = around;
  10897. this.x = x;
  10898. this.y = y;
  10899. this.orient = orient;
  10900. this.onCancel = onCancel;
  10901. this.onClose = onClose;
  10902. this.onExecute = onExecute;
  10903. this.padding = padding;
  10904. }
  10905. =====*/
  10906. /*=====
  10907. dijit.popup = {
  10908. // summary:
  10909. // Used to show drop downs (ex: the select list of a ComboBox)
  10910. // or popups (ex: right-click context menus).
  10911. //
  10912. // Access via require(["dijit/popup"], function(popup){ ... }).
  10913. moveOffScreen: function(widget){
  10914. // summary:
  10915. // Moves the popup widget off-screen.
  10916. // Do not use this method to hide popups when not in use, because
  10917. // that will create an accessibility issue: the offscreen popup is
  10918. // still in the tabbing order.
  10919. // widget: dijit._WidgetBase
  10920. // The widget
  10921. },
  10922. hide: function(widget){
  10923. // summary:
  10924. // Hide this popup widget (until it is ready to be shown).
  10925. // Initialization for widgets that will be used as popups
  10926. //
  10927. // Also puts widget inside a wrapper DIV (if not already in one)
  10928. //
  10929. // If popup widget needs to layout it should
  10930. // do so when it is made visible, and popup._onShow() is called.
  10931. // widget: dijit._WidgetBase
  10932. // The widget
  10933. },
  10934. open: function(args){
  10935. // summary:
  10936. // Popup the widget at the specified position
  10937. // example:
  10938. // opening at the mouse position
  10939. // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
  10940. // example:
  10941. // opening the widget as a dropdown
  10942. // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
  10943. //
  10944. // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
  10945. // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
  10946. // args: dijit.popup.__OpenArgs
  10947. // Parameters
  10948. return {}; // Object specifying which position was chosen
  10949. },
  10950. close: function(popup){
  10951. // summary:
  10952. // Close specified popup and any popups that it parented.
  10953. // If no popup is specified, closes all popups.
  10954. // widget: dijit._WidgetBase?
  10955. // The widget, optional
  10956. }
  10957. };
  10958. =====*/
  10959. function destroyWrapper(){
  10960. // summary:
  10961. // Function to destroy wrapper when popup widget is destroyed.
  10962. // Left in this scope to avoid memory leak on IE8 on refresh page, see #15206.
  10963. if(this._popupWrapper){
  10964. domConstruct.destroy(this._popupWrapper);
  10965. delete this._popupWrapper;
  10966. }
  10967. }
  10968. var PopupManager = declare(null, {
  10969. // _stack: dijit._Widget[]
  10970. // Stack of currently popped up widgets.
  10971. // (someone opened _stack[0], and then it opened _stack[1], etc.)
  10972. _stack: [],
  10973. // _beginZIndex: Number
  10974. // Z-index of the first popup. (If first popup opens other
  10975. // popups they get a higher z-index.)
  10976. _beginZIndex: 1000,
  10977. _idGen: 1,
  10978. _createWrapper: function(/*Widget*/ widget){
  10979. // summary:
  10980. // Initialization for widgets that will be used as popups.
  10981. // Puts widget inside a wrapper DIV (if not already in one),
  10982. // and returns pointer to that wrapper DIV.
  10983. var wrapper = widget._popupWrapper,
  10984. node = widget.domNode;
  10985. if(!wrapper){
  10986. // Create wrapper <div> for when this widget [in the future] will be used as a popup.
  10987. // This is done early because of IE bugs where creating/moving DOM nodes causes focus
  10988. // to go wonky, see tests/robot/Toolbar.html to reproduce
  10989. wrapper = domConstruct.create("div", {
  10990. "class":"dijitPopup",
  10991. style:{ display: "none"},
  10992. role: "presentation"
  10993. }, win.body());
  10994. wrapper.appendChild(node);
  10995. var s = node.style;
  10996. s.display = "";
  10997. s.visibility = "";
  10998. s.position = "";
  10999. s.top = "0px";
  11000. widget._popupWrapper = wrapper;
  11001. aspect.after(widget, "destroy", destroyWrapper, true);
  11002. }
  11003. return wrapper;
  11004. },
  11005. moveOffScreen: function(/*Widget*/ widget){
  11006. // summary:
  11007. // Moves the popup widget off-screen.
  11008. // Do not use this method to hide popups when not in use, because
  11009. // that will create an accessibility issue: the offscreen popup is
  11010. // still in the tabbing order.
  11011. // Create wrapper if not already there
  11012. var wrapper = this._createWrapper(widget);
  11013. domStyle.set(wrapper, {
  11014. visibility: "hidden",
  11015. top: "-9999px", // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
  11016. display: ""
  11017. });
  11018. },
  11019. hide: function(/*Widget*/ widget){
  11020. // summary:
  11021. // Hide this popup widget (until it is ready to be shown).
  11022. // Initialization for widgets that will be used as popups
  11023. //
  11024. // Also puts widget inside a wrapper DIV (if not already in one)
  11025. //
  11026. // If popup widget needs to layout it should
  11027. // do so when it is made visible, and popup._onShow() is called.
  11028. // Create wrapper if not already there
  11029. var wrapper = this._createWrapper(widget);
  11030. domStyle.set(wrapper, "display", "none");
  11031. },
  11032. getTopPopup: function(){
  11033. // summary:
  11034. // Compute the closest ancestor popup that's *not* a child of another popup.
  11035. // Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
  11036. var stack = this._stack;
  11037. for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
  11038. /* do nothing, just trying to get right value for pi */
  11039. }
  11040. return stack[pi];
  11041. },
  11042. open: function(/*dijit.popup.__OpenArgs*/ args){
  11043. // summary:
  11044. // Popup the widget at the specified position
  11045. //
  11046. // example:
  11047. // opening at the mouse position
  11048. // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
  11049. //
  11050. // example:
  11051. // opening the widget as a dropdown
  11052. // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
  11053. //
  11054. // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
  11055. // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
  11056. var stack = this._stack,
  11057. widget = args.popup,
  11058. orient = args.orient || ["below", "below-alt", "above", "above-alt"],
  11059. ltr = args.parent ? args.parent.isLeftToRight() : domGeometry.isBodyLtr(),
  11060. around = args.around,
  11061. id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
  11062. // If we are opening a new popup that isn't a child of a currently opened popup, then
  11063. // close currently opened popup(s). This should happen automatically when the old popups
  11064. // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198].
  11065. while(stack.length && (!args.parent || !dom.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){
  11066. this.close(stack[stack.length-1].widget);
  11067. }
  11068. // Get pointer to popup wrapper, and create wrapper if it doesn't exist
  11069. var wrapper = this._createWrapper(widget);
  11070. domAttr.set(wrapper, {
  11071. id: id,
  11072. style: {
  11073. zIndex: this._beginZIndex + stack.length
  11074. },
  11075. "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
  11076. dijitPopupParent: args.parent ? args.parent.id : ""
  11077. });
  11078. if(has("bgIframe") && !widget.bgIframe){
  11079. // setting widget.bgIframe triggers cleanup in _Widget.destroy()
  11080. widget.bgIframe = new BackgroundIframe(wrapper);
  11081. }
  11082. // position the wrapper node and make it visible
  11083. var best = around ?
  11084. place.around(wrapper, around, orient, ltr, widget.orient ? lang.hitch(widget, "orient") : null) :
  11085. place.at(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
  11086. wrapper.style.display = "";
  11087. wrapper.style.visibility = "visible";
  11088. widget.domNode.style.visibility = "visible"; // counteract effects from _HasDropDown
  11089. var handlers = [];
  11090. // provide default escape and tab key handling
  11091. // (this will work for any widget, not just menu)
  11092. handlers.push(on(wrapper, connect._keypress, lang.hitch(this, function(evt){
  11093. if(evt.charOrCode == keys.ESCAPE && args.onCancel){
  11094. event.stop(evt);
  11095. args.onCancel();
  11096. }else if(evt.charOrCode === keys.TAB){
  11097. event.stop(evt);
  11098. var topPopup = this.getTopPopup();
  11099. if(topPopup && topPopup.onCancel){
  11100. topPopup.onCancel();
  11101. }
  11102. }
  11103. })));
  11104. // watch for cancel/execute events on the popup and notify the caller
  11105. // (for a menu, "execute" means clicking an item)
  11106. if(widget.onCancel && args.onCancel){
  11107. handlers.push(widget.on("cancel", args.onCancel));
  11108. }
  11109. handlers.push(widget.on(widget.onExecute ? "execute" : "change", lang.hitch(this, function(){
  11110. var topPopup = this.getTopPopup();
  11111. if(topPopup && topPopup.onExecute){
  11112. topPopup.onExecute();
  11113. }
  11114. })));
  11115. stack.push({
  11116. widget: widget,
  11117. parent: args.parent,
  11118. onExecute: args.onExecute,
  11119. onCancel: args.onCancel,
  11120. onClose: args.onClose,
  11121. handlers: handlers
  11122. });
  11123. if(widget.onOpen){
  11124. // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
  11125. widget.onOpen(best);
  11126. }
  11127. return best;
  11128. },
  11129. close: function(/*Widget?*/ popup){
  11130. // summary:
  11131. // Close specified popup and any popups that it parented.
  11132. // If no popup is specified, closes all popups.
  11133. var stack = this._stack;
  11134. // Basically work backwards from the top of the stack closing popups
  11135. // until we hit the specified popup, but IIRC there was some issue where closing
  11136. // a popup would cause others to close too. Thus if we are trying to close B in [A,B,C]
  11137. // closing C might close B indirectly and then the while() condition will run where stack==[A]...
  11138. // so the while condition is constructed defensively.
  11139. while((popup && array.some(stack, function(elem){return elem.widget == popup;})) ||
  11140. (!popup && stack.length)){
  11141. var top = stack.pop(),
  11142. widget = top.widget,
  11143. onClose = top.onClose;
  11144. if(widget.onClose){
  11145. // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
  11146. widget.onClose();
  11147. }
  11148. var h;
  11149. while(h = top.handlers.pop()){ h.remove(); }
  11150. // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc.
  11151. if(widget && widget.domNode){
  11152. this.hide(widget);
  11153. }
  11154. if(onClose){
  11155. onClose();
  11156. }
  11157. }
  11158. }
  11159. });
  11160. return (dijit.popup = new PopupManager());
  11161. });
  11162. },
  11163. 'dijit/_base/manager':function(){
  11164. define("dijit/_base/manager", [
  11165. "dojo/_base/array",
  11166. "dojo/_base/config", // defaultDuration
  11167. "../registry",
  11168. ".." // for setting exports to dijit namespace
  11169. ], function(array, config, registry, dijit){
  11170. // module:
  11171. // dijit/_base/manager
  11172. // summary:
  11173. // Shim to methods on registry, plus a few other declarations.
  11174. // New code should access dijit/registry directly when possible.
  11175. /*=====
  11176. dijit.byId = function(id){
  11177. // summary:
  11178. // Returns a widget by it's id, or if passed a widget, no-op (like dom.byId())
  11179. // id: String|dijit._Widget
  11180. return registry.byId(id); // dijit._Widget
  11181. };
  11182. dijit.getUniqueId = function(widgetType){
  11183. // summary:
  11184. // Generates a unique id for a given widgetType
  11185. // widgetType: String
  11186. return registry.getUniqueId(widgetType); // String
  11187. };
  11188. dijit.findWidgets = function(root){
  11189. // summary:
  11190. // Search subtree under root returning widgets found.
  11191. // Doesn't search for nested widgets (ie, widgets inside other widgets).
  11192. // root: DOMNode
  11193. return registry.findWidgets(root);
  11194. };
  11195. dijit._destroyAll = function(){
  11196. // summary:
  11197. // Code to destroy all widgets and do other cleanup on page unload
  11198. return registry._destroyAll();
  11199. };
  11200. dijit.byNode = function(node){
  11201. // summary:
  11202. // Returns the widget corresponding to the given DOMNode
  11203. // node: DOMNode
  11204. return registry.byNode(node); // dijit._Widget
  11205. };
  11206. dijit.getEnclosingWidget = function(node){
  11207. // summary:
  11208. // Returns the widget whose DOM tree contains the specified DOMNode, or null if
  11209. // the node is not contained within the DOM tree of any widget
  11210. // node: DOMNode
  11211. return registry.getEnclosingWidget(node);
  11212. };
  11213. =====*/
  11214. array.forEach(["byId", "getUniqueId", "findWidgets", "_destroyAll", "byNode", "getEnclosingWidget"], function(name){
  11215. dijit[name] = registry[name];
  11216. });
  11217. /*=====
  11218. dojo.mixin(dijit, {
  11219. // defaultDuration: Integer
  11220. // The default fx.animation speed (in ms) to use for all Dijit
  11221. // transitional fx.animations, unless otherwise specified
  11222. // on a per-instance basis. Defaults to 200, overrided by
  11223. // `djConfig.defaultDuration`
  11224. defaultDuration: 200
  11225. });
  11226. =====*/
  11227. dijit.defaultDuration = config["defaultDuration"] || 200;
  11228. return dijit;
  11229. });
  11230. },
  11231. 'dijit/layout/StackController':function(){
  11232. define("dijit/layout/StackController", [
  11233. "dojo/_base/array", // array.forEach array.indexOf array.map
  11234. "dojo/_base/declare", // declare
  11235. "dojo/_base/event", // event.stop
  11236. "dojo/keys", // keys
  11237. "dojo/_base/lang", // lang.getObject
  11238. "dojo/_base/sniff", // has("ie")
  11239. "../focus", // focus.focus()
  11240. "../registry", // registry.byId
  11241. "../_Widget",
  11242. "../_TemplatedMixin",
  11243. "../_Container",
  11244. "../form/ToggleButton",
  11245. "dojo/i18n!../nls/common"
  11246. ], function(array, declare, event, keys, lang, has,
  11247. focus, registry, _Widget, _TemplatedMixin, _Container, ToggleButton){
  11248. /*=====
  11249. var _Widget = dijit._Widget;
  11250. var _TemplatedMixin = dijit._TemplatedMixin;
  11251. var _Container = dijit._Container;
  11252. var ToggleButton = dijit.form.ToggleButton;
  11253. =====*/
  11254. // module:
  11255. // dijit/layout/StackController
  11256. // summary:
  11257. // Set of buttons to select a page in a `dijit.layout.StackContainer`
  11258. var StackButton = declare("dijit.layout._StackButton", ToggleButton, {
  11259. // summary:
  11260. // Internal widget used by StackContainer.
  11261. // description:
  11262. // The button-like or tab-like object you click to select or delete a page
  11263. // tags:
  11264. // private
  11265. // Override _FormWidget.tabIndex.
  11266. // StackContainer buttons are not in the tab order by default.
  11267. // Probably we should be calling this.startupKeyNavChildren() instead.
  11268. tabIndex: "-1",
  11269. // closeButton: Boolean
  11270. // When true, display close button for this tab
  11271. closeButton: false,
  11272. _setCheckedAttr: function(/*Boolean*/ value, /*Boolean?*/ priorityChange){
  11273. this.inherited(arguments);
  11274. this.focusNode.removeAttribute("aria-pressed");
  11275. },
  11276. buildRendering: function(/*Event*/ evt){
  11277. this.inherited(arguments);
  11278. (this.focusNode || this.domNode).setAttribute("role", "tab");
  11279. },
  11280. onClick: function(/*Event*/ /*===== evt =====*/){
  11281. // summary:
  11282. // This is for TabContainer where the tabs are <span> rather than button,
  11283. // so need to set focus explicitly (on some browsers)
  11284. // Note that you shouldn't override this method, but you can connect to it.
  11285. focus.focus(this.focusNode);
  11286. // ... now let StackController catch the event and tell me what to do
  11287. },
  11288. onClickCloseButton: function(/*Event*/ evt){
  11289. // summary:
  11290. // StackContainer connects to this function; if your widget contains a close button
  11291. // then clicking it should call this function.
  11292. // Note that you shouldn't override this method, but you can connect to it.
  11293. evt.stopPropagation();
  11294. }
  11295. });
  11296. var StackController = declare("dijit.layout.StackController", [_Widget, _TemplatedMixin, _Container], {
  11297. // summary:
  11298. // Set of buttons to select a page in a `dijit.layout.StackContainer`
  11299. // description:
  11300. // Monitors the specified StackContainer, and whenever a page is
  11301. // added, deleted, or selected, updates itself accordingly.
  11302. baseClass: "dijitStackController",
  11303. templateString: "<span role='tablist' data-dojo-attach-event='onkeypress'></span>",
  11304. // containerId: [const] String
  11305. // The id of the page container that I point to
  11306. containerId: "",
  11307. // buttonWidget: [const] Constructor
  11308. // The button widget to create to correspond to each page
  11309. buttonWidget: StackButton,
  11310. constructor: function(){
  11311. this.pane2button = {}; // mapping from pane id to buttons
  11312. this.pane2connects = {}; // mapping from pane id to this.connect() handles
  11313. this.pane2watches = {}; // mapping from pane id to watch() handles
  11314. },
  11315. postCreate: function(){
  11316. this.inherited(arguments);
  11317. // Listen to notifications from StackContainer
  11318. this.subscribe(this.containerId+"-startup", "onStartup");
  11319. this.subscribe(this.containerId+"-addChild", "onAddChild");
  11320. this.subscribe(this.containerId+"-removeChild", "onRemoveChild");
  11321. this.subscribe(this.containerId+"-selectChild", "onSelectChild");
  11322. this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress");
  11323. },
  11324. onStartup: function(/*Object*/ info){
  11325. // summary:
  11326. // Called after StackContainer has finished initializing
  11327. // tags:
  11328. // private
  11329. array.forEach(info.children, this.onAddChild, this);
  11330. if(info.selected){
  11331. // Show button corresponding to selected pane (unless selected
  11332. // is null because there are no panes)
  11333. this.onSelectChild(info.selected);
  11334. }
  11335. },
  11336. destroy: function(){
  11337. for(var pane in this.pane2button){
  11338. this.onRemoveChild(registry.byId(pane));
  11339. }
  11340. this.inherited(arguments);
  11341. },
  11342. onAddChild: function(/*dijit._Widget*/ page, /*Integer?*/ insertIndex){
  11343. // summary:
  11344. // Called whenever a page is added to the container.
  11345. // Create button corresponding to the page.
  11346. // tags:
  11347. // private
  11348. // create an instance of the button widget
  11349. // (remove typeof buttonWidget == string support in 2.0)
  11350. var cls = lang.isString(this.buttonWidget) ? lang.getObject(this.buttonWidget) : this.buttonWidget;
  11351. var button = new cls({
  11352. id: this.id + "_" + page.id,
  11353. label: page.title,
  11354. dir: page.dir,
  11355. lang: page.lang,
  11356. textDir: page.textDir,
  11357. showLabel: page.showTitle,
  11358. iconClass: page.iconClass,
  11359. closeButton: page.closable,
  11360. title: page.tooltip
  11361. });
  11362. button.focusNode.setAttribute("aria-selected", "false");
  11363. // map from page attribute to corresponding tab button attribute
  11364. var pageAttrList = ["title", "showTitle", "iconClass", "closable", "tooltip"],
  11365. buttonAttrList = ["label", "showLabel", "iconClass", "closeButton", "title"];
  11366. // watch() so events like page title changes are reflected in tab button
  11367. this.pane2watches[page.id] = array.map(pageAttrList, function(pageAttr, idx){
  11368. return page.watch(pageAttr, function(name, oldVal, newVal){
  11369. button.set(buttonAttrList[idx], newVal);
  11370. });
  11371. });
  11372. // connections so that clicking a tab button selects the corresponding page
  11373. this.pane2connects[page.id] = [
  11374. this.connect(button, 'onClick', lang.hitch(this,"onButtonClick", page)),
  11375. this.connect(button, 'onClickCloseButton', lang.hitch(this,"onCloseButtonClick", page))
  11376. ];
  11377. this.addChild(button, insertIndex);
  11378. this.pane2button[page.id] = button;
  11379. page.controlButton = button; // this value might be overwritten if two tabs point to same container
  11380. if(!this._currentChild){ // put the first child into the tab order
  11381. button.focusNode.setAttribute("tabIndex", "0");
  11382. button.focusNode.setAttribute("aria-selected", "true");
  11383. this._currentChild = page;
  11384. }
  11385. // make sure all tabs have the same length
  11386. if(!this.isLeftToRight() && has("ie") && this._rectifyRtlTabList){
  11387. this._rectifyRtlTabList();
  11388. }
  11389. },
  11390. onRemoveChild: function(/*dijit._Widget*/ page){
  11391. // summary:
  11392. // Called whenever a page is removed from the container.
  11393. // Remove the button corresponding to the page.
  11394. // tags:
  11395. // private
  11396. if(this._currentChild === page){ this._currentChild = null; }
  11397. // disconnect/unwatch connections/watches related to page being removed
  11398. array.forEach(this.pane2connects[page.id], lang.hitch(this, "disconnect"));
  11399. delete this.pane2connects[page.id];
  11400. array.forEach(this.pane2watches[page.id], function(w){ w.unwatch(); });
  11401. delete this.pane2watches[page.id];
  11402. var button = this.pane2button[page.id];
  11403. if(button){
  11404. this.removeChild(button);
  11405. delete this.pane2button[page.id];
  11406. button.destroy();
  11407. }
  11408. delete page.controlButton;
  11409. },
  11410. onSelectChild: function(/*dijit._Widget*/ page){
  11411. // summary:
  11412. // Called when a page has been selected in the StackContainer, either by me or by another StackController
  11413. // tags:
  11414. // private
  11415. if(!page){ return; }
  11416. if(this._currentChild){
  11417. var oldButton=this.pane2button[this._currentChild.id];
  11418. oldButton.set('checked', false);
  11419. oldButton.focusNode.setAttribute("aria-selected", "false");
  11420. oldButton.focusNode.setAttribute("tabIndex", "-1");
  11421. }
  11422. var newButton=this.pane2button[page.id];
  11423. newButton.set('checked', true);
  11424. newButton.focusNode.setAttribute("aria-selected", "true");
  11425. this._currentChild = page;
  11426. newButton.focusNode.setAttribute("tabIndex", "0");
  11427. var container = registry.byId(this.containerId);
  11428. container.containerNode.setAttribute("aria-labelledby", newButton.id);
  11429. },
  11430. onButtonClick: function(/*dijit._Widget*/ page){
  11431. // summary:
  11432. // Called whenever one of my child buttons is pressed in an attempt to select a page
  11433. // tags:
  11434. // private
  11435. if(this._currentChild.id === page.id) {
  11436. //In case the user clicked the checked button, keep it in the checked state because it remains to be the selected stack page.
  11437. var button=this.pane2button[page.id];
  11438. button.set('checked', true);
  11439. }
  11440. var container = registry.byId(this.containerId);
  11441. container.selectChild(page);
  11442. },
  11443. onCloseButtonClick: function(/*dijit._Widget*/ page){
  11444. // summary:
  11445. // Called whenever one of my child buttons [X] is pressed in an attempt to close a page
  11446. // tags:
  11447. // private
  11448. var container = registry.byId(this.containerId);
  11449. container.closeChild(page);
  11450. if(this._currentChild){
  11451. var b = this.pane2button[this._currentChild.id];
  11452. if(b){
  11453. focus.focus(b.focusNode || b.domNode);
  11454. }
  11455. }
  11456. },
  11457. // TODO: this is a bit redundant with forward, back api in StackContainer
  11458. adjacent: function(/*Boolean*/ forward){
  11459. // summary:
  11460. // Helper for onkeypress to find next/previous button
  11461. // tags:
  11462. // private
  11463. if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; }
  11464. // find currently focused button in children array
  11465. var children = this.getChildren();
  11466. var current = array.indexOf(children, this.pane2button[this._currentChild.id]);
  11467. // pick next button to focus on
  11468. var offset = forward ? 1 : children.length - 1;
  11469. return children[ (current + offset) % children.length ]; // dijit._Widget
  11470. },
  11471. onkeypress: function(/*Event*/ e){
  11472. // summary:
  11473. // Handle keystrokes on the page list, for advancing to next/previous button
  11474. // and closing the current page if the page is closable.
  11475. // tags:
  11476. // private
  11477. if(this.disabled || e.altKey ){ return; }
  11478. var forward = null;
  11479. if(e.ctrlKey || !e._djpage){
  11480. switch(e.charOrCode){
  11481. case keys.LEFT_ARROW:
  11482. case keys.UP_ARROW:
  11483. if(!e._djpage){ forward = false; }
  11484. break;
  11485. case keys.PAGE_UP:
  11486. if(e.ctrlKey){ forward = false; }
  11487. break;
  11488. case keys.RIGHT_ARROW:
  11489. case keys.DOWN_ARROW:
  11490. if(!e._djpage){ forward = true; }
  11491. break;
  11492. case keys.PAGE_DOWN:
  11493. if(e.ctrlKey){ forward = true; }
  11494. break;
  11495. case keys.HOME:
  11496. case keys.END:
  11497. var children = this.getChildren();
  11498. if(children && children.length){
  11499. children[e.charOrCode == keys.HOME ? 0 : children.length-1].onClick();
  11500. }
  11501. event.stop(e);
  11502. break;
  11503. case keys.DELETE:
  11504. if(this._currentChild.closable){
  11505. this.onCloseButtonClick(this._currentChild);
  11506. }
  11507. event.stop(e);
  11508. break;
  11509. default:
  11510. if(e.ctrlKey){
  11511. if(e.charOrCode === keys.TAB){
  11512. this.adjacent(!e.shiftKey).onClick();
  11513. event.stop(e);
  11514. }else if(e.charOrCode == "w"){
  11515. if(this._currentChild.closable){
  11516. this.onCloseButtonClick(this._currentChild);
  11517. }
  11518. event.stop(e); // avoid browser tab closing.
  11519. }
  11520. }
  11521. }
  11522. // handle next/previous page navigation (left/right arrow, etc.)
  11523. if(forward !== null){
  11524. this.adjacent(forward).onClick();
  11525. event.stop(e);
  11526. }
  11527. }
  11528. },
  11529. onContainerKeyPress: function(/*Object*/ info){
  11530. // summary:
  11531. // Called when there was a keypress on the container
  11532. // tags:
  11533. // private
  11534. info.e._djpage = info.page;
  11535. this.onkeypress(info.e);
  11536. }
  11537. });
  11538. StackController.StackButton = StackButton; // for monkey patching
  11539. return StackController;
  11540. });
  11541. },
  11542. 'url:dijit/templates/TooltipDialog.html':"<div role=\"presentation\" tabIndex=\"-1\">\n\t<div class=\"dijitTooltipContainer\" role=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" data-dojo-attach-point=\"containerNode\" role=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" role=\"presentation\"></div>\n</div>\n",
  11543. 'dojo/dnd/Mover':function(){
  11544. define("dojo/dnd/Mover", ["../main", "../Evented", "../touch", "./common", "./autoscroll"], function(dojo, Evented, touch) {
  11545. // module:
  11546. // dojo/dnd/Mover
  11547. // summary:
  11548. // TODOC
  11549. dojo.declare("dojo.dnd.Mover", [Evented], {
  11550. constructor: function(node, e, host){
  11551. // summary:
  11552. // an object which makes a node follow the mouse, or touch-drag on touch devices.
  11553. // Used as a default mover, and as a base class for custom movers.
  11554. // node: Node
  11555. // a node (or node's id) to be moved
  11556. // e: Event
  11557. // a mouse event, which started the move;
  11558. // only pageX and pageY properties are used
  11559. // host: Object?
  11560. // object which implements the functionality of the move,
  11561. // and defines proper events (onMoveStart and onMoveStop)
  11562. this.node = dojo.byId(node);
  11563. this.marginBox = {l: e.pageX, t: e.pageY};
  11564. this.mouseButton = e.button;
  11565. var h = (this.host = host), d = node.ownerDocument;
  11566. this.events = [
  11567. // At the start of a drag, onFirstMove is called, and then the following two
  11568. // connects are disconnected
  11569. dojo.connect(d, touch.move, this, "onFirstMove"),
  11570. // These are called continually during the drag
  11571. dojo.connect(d, touch.move, this, "onMouseMove"),
  11572. // And these are called at the end of the drag
  11573. dojo.connect(d, touch.release, this, "onMouseUp"),
  11574. // cancel text selection and text dragging
  11575. dojo.connect(d, "ondragstart", dojo.stopEvent),
  11576. dojo.connect(d.body, "onselectstart", dojo.stopEvent)
  11577. ];
  11578. // notify that the move has started
  11579. if(h && h.onMoveStart){
  11580. h.onMoveStart(this);
  11581. }
  11582. },
  11583. // mouse event processors
  11584. onMouseMove: function(e){
  11585. // summary:
  11586. // event processor for onmousemove/ontouchmove
  11587. // e: Event
  11588. // mouse/touch event
  11589. dojo.dnd.autoScroll(e);
  11590. var m = this.marginBox;
  11591. this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e);
  11592. dojo.stopEvent(e);
  11593. },
  11594. onMouseUp: function(e){
  11595. if(dojo.isWebKit && dojo.isMac && this.mouseButton == 2 ?
  11596. e.button == 0 : this.mouseButton == e.button){ // TODO Should condition be met for touch devices, too?
  11597. this.destroy();
  11598. }
  11599. dojo.stopEvent(e);
  11600. },
  11601. // utilities
  11602. onFirstMove: function(e){
  11603. // summary:
  11604. // makes the node absolute; it is meant to be called only once.
  11605. // relative and absolutely positioned nodes are assumed to use pixel units
  11606. var s = this.node.style, l, t, h = this.host;
  11607. switch(s.position){
  11608. case "relative":
  11609. case "absolute":
  11610. // assume that left and top values are in pixels already
  11611. l = Math.round(parseFloat(s.left)) || 0;
  11612. t = Math.round(parseFloat(s.top)) || 0;
  11613. break;
  11614. default:
  11615. s.position = "absolute"; // enforcing the absolute mode
  11616. var m = dojo.marginBox(this.node);
  11617. // event.pageX/pageY (which we used to generate the initial
  11618. // margin box) includes padding and margin set on the body.
  11619. // However, setting the node's position to absolute and then
  11620. // doing dojo.marginBox on it *doesn't* take that additional
  11621. // space into account - so we need to subtract the combined
  11622. // padding and margin. We use getComputedStyle and
  11623. // _getMarginBox/_getContentBox to avoid the extra lookup of
  11624. // the computed style.
  11625. var b = dojo.doc.body;
  11626. var bs = dojo.getComputedStyle(b);
  11627. var bm = dojo._getMarginBox(b, bs);
  11628. var bc = dojo._getContentBox(b, bs);
  11629. l = m.l - (bc.l - bm.l);
  11630. t = m.t - (bc.t - bm.t);
  11631. break;
  11632. }
  11633. this.marginBox.l = l - this.marginBox.l;
  11634. this.marginBox.t = t - this.marginBox.t;
  11635. if(h && h.onFirstMove){
  11636. h.onFirstMove(this, e);
  11637. }
  11638. // Disconnect onmousemove and ontouchmove events that call this function
  11639. dojo.disconnect(this.events.shift());
  11640. },
  11641. destroy: function(){
  11642. // summary:
  11643. // stops the move, deletes all references, so the object can be garbage-collected
  11644. dojo.forEach(this.events, dojo.disconnect);
  11645. // undo global settings
  11646. var h = this.host;
  11647. if(h && h.onMoveStop){
  11648. h.onMoveStop(this);
  11649. }
  11650. // destroy objects
  11651. this.events = this.node = this.host = null;
  11652. }
  11653. });
  11654. return dojo.dnd.Mover;
  11655. });
  11656. },
  11657. 'dijit/layout/TabContainer':function(){
  11658. define("dijit/layout/TabContainer", [
  11659. "dojo/_base/lang", // lang.getObject
  11660. "dojo/_base/declare", // declare
  11661. "./_TabContainerBase",
  11662. "./TabController",
  11663. "./ScrollingTabController"
  11664. ], function(lang, declare, _TabContainerBase, TabController, ScrollingTabController){
  11665. /*=====
  11666. var _TabContainerBase = dijit.layout._TabContainerBase;
  11667. var TabController = dijit.layout.TabController;
  11668. var ScrollingTabController = dijit.layout.ScrollingTabController;
  11669. =====*/
  11670. // module:
  11671. // dijit/layout/TabContainer
  11672. // summary:
  11673. // A Container with tabs to select each child (only one of which is displayed at a time).
  11674. return declare("dijit.layout.TabContainer", _TabContainerBase, {
  11675. // summary:
  11676. // A Container with tabs to select each child (only one of which is displayed at a time).
  11677. // description:
  11678. // A TabContainer is a container that has multiple panes, but shows only
  11679. // one pane at a time. There are a set of tabs corresponding to each pane,
  11680. // where each tab has the name (aka title) of the pane, and optionally a close button.
  11681. // useMenu: [const] Boolean
  11682. // True if a menu should be used to select tabs when they are too
  11683. // wide to fit the TabContainer, false otherwise.
  11684. useMenu: true,
  11685. // useSlider: [const] Boolean
  11686. // True if a slider should be used to select tabs when they are too
  11687. // wide to fit the TabContainer, false otherwise.
  11688. useSlider: true,
  11689. // controllerWidget: String
  11690. // An optional parameter to override the widget used to display the tab labels
  11691. controllerWidget: "",
  11692. _makeController: function(/*DomNode*/ srcNode){
  11693. // summary:
  11694. // Instantiate tablist controller widget and return reference to it.
  11695. // Callback from _TabContainerBase.postCreate().
  11696. // tags:
  11697. // protected extension
  11698. var cls = this.baseClass + "-tabs" + (this.doLayout ? "" : " dijitTabNoLayout"),
  11699. TabController = lang.getObject(this.controllerWidget);
  11700. return new TabController({
  11701. id: this.id + "_tablist",
  11702. dir: this.dir,
  11703. lang: this.lang,
  11704. textDir: this.textDir,
  11705. tabPosition: this.tabPosition,
  11706. doLayout: this.doLayout,
  11707. containerId: this.id,
  11708. "class": cls,
  11709. nested: this.nested,
  11710. useMenu: this.useMenu,
  11711. useSlider: this.useSlider,
  11712. tabStripClass: this.tabStrip ? this.baseClass + (this.tabStrip ? "":"No") + "Strip": null
  11713. }, srcNode);
  11714. },
  11715. postMixInProperties: function(){
  11716. this.inherited(arguments);
  11717. // Scrolling controller only works for horizontal non-nested tabs
  11718. if(!this.controllerWidget){
  11719. this.controllerWidget = (this.tabPosition == "top" || this.tabPosition == "bottom") && !this.nested ?
  11720. "dijit.layout.ScrollingTabController" : "dijit.layout.TabController";
  11721. }
  11722. }
  11723. });
  11724. });
  11725. },
  11726. 'dijit/BackgroundIframe':function(){
  11727. define("dijit/BackgroundIframe", [
  11728. "require", // require.toUrl
  11729. ".", // to export dijit.BackgroundIframe
  11730. "dojo/_base/config",
  11731. "dojo/dom-construct", // domConstruct.create
  11732. "dojo/dom-style", // domStyle.set
  11733. "dojo/_base/lang", // lang.extend lang.hitch
  11734. "dojo/on",
  11735. "dojo/_base/sniff", // has("ie"), has("mozilla"), has("quirks")
  11736. "dojo/_base/window" // win.doc.createElement
  11737. ], function(require, dijit, config, domConstruct, domStyle, lang, on, has, win){
  11738. // module:
  11739. // dijit/BackgroundIFrame
  11740. // Flag for whether to create background iframe behind popups like Menus and Dialog.
  11741. // A background iframe is useful to prevent problems with popups appearing behind applets/pdf files,
  11742. // and is also useful on older versions of IE (IE6 and IE7) to prevent the "bleed through select" problem.
  11743. // TODO: For 2.0, make this false by default. Also, possibly move definition to has.js so that this module can be
  11744. // conditionally required via dojo/has!bgIfame?dijit/BackgroundIframe
  11745. has.add("bgIframe", has("ie") || has("mozilla"));
  11746. // summary:
  11747. // new dijit.BackgroundIframe(node)
  11748. // Makes a background iframe as a child of node, that fills
  11749. // area (and position) of node
  11750. // TODO: remove _frames, it isn't being used much, since popups never release their
  11751. // iframes (see [22236])
  11752. var _frames = new function(){
  11753. // summary:
  11754. // cache of iframes
  11755. var queue = [];
  11756. this.pop = function(){
  11757. var iframe;
  11758. if(queue.length){
  11759. iframe = queue.pop();
  11760. iframe.style.display="";
  11761. }else{
  11762. if(has("ie") < 9){
  11763. var burl = config["dojoBlankHtmlUrl"] || require.toUrl("dojo/resources/blank.html") || "javascript:\"\"";
  11764. var html="<iframe src='" + burl + "' role='presentation'"
  11765. + " style='position: absolute; left: 0px; top: 0px;"
  11766. + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
  11767. iframe = win.doc.createElement(html);
  11768. }else{
  11769. iframe = domConstruct.create("iframe");
  11770. iframe.src = 'javascript:""';
  11771. iframe.className = "dijitBackgroundIframe";
  11772. iframe.setAttribute("role", "presentation");
  11773. domStyle.set(iframe, "opacity", 0.1);
  11774. }
  11775. iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didn't work.
  11776. }
  11777. return iframe;
  11778. };
  11779. this.push = function(iframe){
  11780. iframe.style.display="none";
  11781. queue.push(iframe);
  11782. }
  11783. }();
  11784. dijit.BackgroundIframe = function(/*DomNode*/ node){
  11785. // summary:
  11786. // For IE/FF z-index schenanigans. id attribute is required.
  11787. //
  11788. // description:
  11789. // new dijit.BackgroundIframe(node)
  11790. // Makes a background iframe as a child of node, that fills
  11791. // area (and position) of node
  11792. if(!node.id){ throw new Error("no id"); }
  11793. if(has("bgIframe")){
  11794. var iframe = (this.iframe = _frames.pop());
  11795. node.appendChild(iframe);
  11796. if(has("ie")<7 || has("quirks")){
  11797. this.resize(node);
  11798. this._conn = on(node, 'resize', lang.hitch(this, function(){
  11799. this.resize(node);
  11800. }));
  11801. }else{
  11802. domStyle.set(iframe, {
  11803. width: '100%',
  11804. height: '100%'
  11805. });
  11806. }
  11807. }
  11808. };
  11809. lang.extend(dijit.BackgroundIframe, {
  11810. resize: function(node){
  11811. // summary:
  11812. // Resize the iframe so it's the same size as node.
  11813. // Needed on IE6 and IE/quirks because height:100% doesn't work right.
  11814. if(this.iframe){
  11815. domStyle.set(this.iframe, {
  11816. width: node.offsetWidth + 'px',
  11817. height: node.offsetHeight + 'px'
  11818. });
  11819. }
  11820. },
  11821. destroy: function(){
  11822. // summary:
  11823. // destroy the iframe
  11824. if(this._conn){
  11825. this._conn.remove();
  11826. this._conn = null;
  11827. }
  11828. if(this.iframe){
  11829. _frames.push(this.iframe);
  11830. delete this.iframe;
  11831. }
  11832. }
  11833. });
  11834. return dijit.BackgroundIframe;
  11835. });
  11836. },
  11837. 'url:dijit/templates/Menu.html':"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" role=\"menu\" tabIndex=\"${tabIndex}\" data-dojo-attach-event=\"onkeypress:_onKeyPress\" cellspacing=\"0\">\n\t<tbody class=\"dijitReset\" data-dojo-attach-point=\"containerNode\"></tbody>\n</table>\n",
  11838. 'dojo/dnd/Avatar':function(){
  11839. define("dojo/dnd/Avatar", ["../main", "./common"], function(dojo) {
  11840. // module:
  11841. // dojo/dnd/Avatar
  11842. // summary:
  11843. // TODOC
  11844. dojo.declare("dojo.dnd.Avatar", null, {
  11845. // summary:
  11846. // Object that represents transferred DnD items visually
  11847. // manager: Object
  11848. // a DnD manager object
  11849. constructor: function(manager){
  11850. this.manager = manager;
  11851. this.construct();
  11852. },
  11853. // methods
  11854. construct: function(){
  11855. // summary:
  11856. // constructor function;
  11857. // it is separate so it can be (dynamically) overwritten in case of need
  11858. this.isA11y = dojo.hasClass(dojo.body(),"dijit_a11y");
  11859. var a = dojo.create("table", {
  11860. "class": "dojoDndAvatar",
  11861. style: {
  11862. position: "absolute",
  11863. zIndex: "1999",
  11864. margin: "0px"
  11865. }
  11866. }),
  11867. source = this.manager.source, node,
  11868. b = dojo.create("tbody", null, a),
  11869. tr = dojo.create("tr", null, b),
  11870. td = dojo.create("td", null, tr),
  11871. icon = this.isA11y ? dojo.create("span", {
  11872. id : "a11yIcon",
  11873. innerHTML : this.manager.copy ? '+' : "<"
  11874. }, td) : null,
  11875. span = dojo.create("span", {
  11876. innerHTML: source.generateText ? this._generateText() : ""
  11877. }, td),
  11878. k = Math.min(5, this.manager.nodes.length), i = 0;
  11879. // we have to set the opacity on IE only after the node is live
  11880. dojo.attr(tr, {
  11881. "class": "dojoDndAvatarHeader",
  11882. style: {opacity: 0.9}
  11883. });
  11884. for(; i < k; ++i){
  11885. if(source.creator){
  11886. // create an avatar representation of the node
  11887. node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node;
  11888. }else{
  11889. // or just clone the node and hope it works
  11890. node = this.manager.nodes[i].cloneNode(true);
  11891. if(node.tagName.toLowerCase() == "tr"){
  11892. // insert extra table nodes
  11893. var table = dojo.create("table"),
  11894. tbody = dojo.create("tbody", null, table);
  11895. tbody.appendChild(node);
  11896. node = table;
  11897. }
  11898. }
  11899. node.id = "";
  11900. tr = dojo.create("tr", null, b);
  11901. td = dojo.create("td", null, tr);
  11902. td.appendChild(node);
  11903. dojo.attr(tr, {
  11904. "class": "dojoDndAvatarItem",
  11905. style: {opacity: (9 - i) / 10}
  11906. });
  11907. }
  11908. this.node = a;
  11909. },
  11910. destroy: function(){
  11911. // summary:
  11912. // destructor for the avatar; called to remove all references so it can be garbage-collected
  11913. dojo.destroy(this.node);
  11914. this.node = false;
  11915. },
  11916. update: function(){
  11917. // summary:
  11918. // updates the avatar to reflect the current DnD state
  11919. dojo[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop");
  11920. if (this.isA11y){
  11921. var icon = dojo.byId("a11yIcon");
  11922. var text = '+'; // assume canDrop && copy
  11923. if (this.manager.canDropFlag && !this.manager.copy) {
  11924. text = '< '; // canDrop && move
  11925. }else if (!this.manager.canDropFlag && !this.manager.copy) {
  11926. text = "o"; //!canDrop && move
  11927. }else if(!this.manager.canDropFlag){
  11928. text = 'x'; // !canDrop && copy
  11929. }
  11930. icon.innerHTML=text;
  11931. }
  11932. // replace text
  11933. dojo.query(("tr.dojoDndAvatarHeader td span" +(this.isA11y ? " span" : "")), this.node).forEach(
  11934. function(node){
  11935. node.innerHTML = this._generateText();
  11936. }, this);
  11937. },
  11938. _generateText: function(){
  11939. // summary: generates a proper text to reflect copying or moving of items
  11940. return this.manager.nodes.length.toString();
  11941. }
  11942. });
  11943. return dojo.dnd.Avatar;
  11944. });
  11945. },
  11946. 'dojox/dtl/filter/strings':function(){
  11947. define("dojox/dtl/filter/strings", [
  11948. "dojo/_base/lang",
  11949. "dojo/_base/array",
  11950. "dojox/string/tokenize",
  11951. "dojox/string/sprintf",
  11952. "../filter/htmlstrings",
  11953. "../_base"
  11954. ], function(lang,array,Tokenize,Sprintf,htmlstrings,dd){
  11955. /*=====
  11956. dd = dojox.dtl;
  11957. Tokenize = dojox.string.tokenize;
  11958. Sprintf = dojox.string.sprintf;
  11959. =====*/
  11960. lang.getObject("dojox.dtl.filter.strings", true);
  11961. lang.mixin(dd.filter.strings, {
  11962. _urlquote: function(/*String*/ url, /*String?*/ safe){
  11963. if(!safe){
  11964. safe = "/";
  11965. }
  11966. return Tokenize(url, /([^\w-_.])/g, function(token){
  11967. if(safe.indexOf(token) == -1){
  11968. if(token == " "){
  11969. return "+";
  11970. }else{
  11971. return "%" + token.charCodeAt(0).toString(16).toUpperCase();
  11972. }
  11973. }
  11974. return token;
  11975. }).join("");
  11976. },
  11977. addslashes: function(value){
  11978. // summary: Adds slashes - useful for passing strings to JavaScript, for example.
  11979. return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'");
  11980. },
  11981. capfirst: function(value){
  11982. // summary: Capitalizes the first character of the value
  11983. value = "" + value;
  11984. return value.charAt(0).toUpperCase() + value.substring(1);
  11985. },
  11986. center: function(value, arg){
  11987. // summary: Centers the value in a field of a given width
  11988. arg = arg || value.length;
  11989. value = value + "";
  11990. var diff = arg - value.length;
  11991. if(diff % 2){
  11992. value = value + " ";
  11993. diff -= 1;
  11994. }
  11995. for(var i = 0; i < diff; i += 2){
  11996. value = " " + value + " ";
  11997. }
  11998. return value;
  11999. },
  12000. cut: function(value, arg){
  12001. // summary: Removes all values of arg from the given string
  12002. arg = arg + "" || "";
  12003. value = value + "";
  12004. return value.replace(new RegExp(arg, "g"), "");
  12005. },
  12006. _fix_ampersands: /&(?!(\w+|#\d+);)/g,
  12007. fix_ampersands: function(value){
  12008. // summary: Replaces ampersands with ``&amp;`` entities
  12009. return value.replace(dojox.dtl.filter.strings._fix_ampersands, "&amp;");
  12010. },
  12011. floatformat: function(value, arg){
  12012. // summary: Format a number according to arg
  12013. // description:
  12014. // If called without an argument, displays a floating point
  12015. // number as 34.2 -- but only if there's a point to be displayed.
  12016. // With a positive numeric argument, it displays that many decimal places
  12017. // always.
  12018. // With a negative numeric argument, it will display that many decimal
  12019. // places -- but only if there's places to be displayed.
  12020. arg = parseInt(arg || -1, 10);
  12021. value = parseFloat(value);
  12022. var m = value - value.toFixed(0);
  12023. if(!m && arg < 0){
  12024. return value.toFixed();
  12025. }
  12026. value = value.toFixed(Math.abs(arg));
  12027. return (arg < 0) ? parseFloat(value) + "" : value;
  12028. },
  12029. iriencode: function(value){
  12030. return dojox.dtl.filter.strings._urlquote(value, "/#%[]=:;$&()+,!");
  12031. },
  12032. linenumbers: function(value){
  12033. // summary: Displays text with line numbers
  12034. var df = dojox.dtl.filter;
  12035. var lines = value.split("\n");
  12036. var output = [];
  12037. var width = (lines.length + "").length;
  12038. for(var i = 0, line; i < lines.length; i++){
  12039. line = lines[i];
  12040. output.push(df.strings.ljust(i + 1, width) + ". " + dojox.dtl._base.escape(line));
  12041. }
  12042. return output.join("\n");
  12043. },
  12044. ljust: function(value, arg){
  12045. value = value + "";
  12046. arg = parseInt(arg, 10);
  12047. while(value.length < arg){
  12048. value = value + " ";
  12049. }
  12050. return value;
  12051. },
  12052. lower: function(value){
  12053. // summary: Converts a string into all lowercase
  12054. return (value + "").toLowerCase();
  12055. },
  12056. make_list: function(value){
  12057. // summary:
  12058. // Returns the value turned into a list. For an integer, it's a list of
  12059. // digits. For a string, it's a list of characters.
  12060. var output = [];
  12061. if(typeof value == "number"){
  12062. value = value + "";
  12063. }
  12064. if(value.charAt){
  12065. for(var i = 0; i < value.length; i++){
  12066. output.push(value.charAt(i));
  12067. }
  12068. return output;
  12069. }
  12070. if(typeof value == "object"){
  12071. for(var key in value){
  12072. output.push(value[key]);
  12073. }
  12074. return output;
  12075. }
  12076. return [];
  12077. },
  12078. rjust: function(value, arg){
  12079. value = value + "";
  12080. arg = parseInt(arg, 10);
  12081. while(value.length < arg){
  12082. value = " " + value;
  12083. }
  12084. return value;
  12085. },
  12086. slugify: function(value){
  12087. // summary: Converts to lowercase, removes
  12088. // non-alpha chars and converts spaces to hyphens
  12089. value = value.replace(/[^\w\s-]/g, "").toLowerCase();
  12090. return value.replace(/[\-\s]+/g, "-");
  12091. },
  12092. _strings: {},
  12093. stringformat: function(value, arg){
  12094. // summary:
  12095. // Formats the variable according to the argument, a string formatting specifier.
  12096. // This specifier uses Python string formating syntax, with the exception that
  12097. // the leading "%" is dropped.
  12098. arg = "" + arg;
  12099. var strings = dojox.dtl.filter.strings._strings;
  12100. if(!strings[arg]){
  12101. strings[arg] = new Sprintf.Formatter("%" + arg);
  12102. }
  12103. return strings[arg].format(value);
  12104. },
  12105. title: function(value){
  12106. // summary: Converts a string into titlecase
  12107. var last, title = "";
  12108. for(var i = 0, current; i < value.length; i++){
  12109. current = value.charAt(i);
  12110. if(last == " " || last == "\n" || last == "\t" || !last){
  12111. title += current.toUpperCase();
  12112. }else{
  12113. title += current.toLowerCase();
  12114. }
  12115. last = current;
  12116. }
  12117. return title;
  12118. },
  12119. _truncatewords: /[ \n\r\t]/,
  12120. truncatewords: function(value, arg){
  12121. // summary: Truncates a string after a certain number of words
  12122. // arg: Integer
  12123. // Number of words to truncate after
  12124. arg = parseInt(arg, 10);
  12125. if(!arg){
  12126. return value;
  12127. }
  12128. for(var i = 0, j = value.length, count = 0, current, last; i < value.length; i++){
  12129. current = value.charAt(i);
  12130. if(dojox.dtl.filter.strings._truncatewords.test(last)){
  12131. if(!dojox.dtl.filter.strings._truncatewords.test(current)){
  12132. ++count;
  12133. if(count == arg){
  12134. return value.substring(0, j + 1);
  12135. }
  12136. }
  12137. }else if(!dojox.dtl.filter.strings._truncatewords.test(current)){
  12138. j = i;
  12139. }
  12140. last = current;
  12141. }
  12142. return value;
  12143. },
  12144. _truncate_words: /(&.*?;|<.*?>|(\w[\w\-]*))/g,
  12145. _truncate_tag: /<(\/)?([^ ]+?)(?: (\/)| .*?)?>/,
  12146. _truncate_singlets: { br: true, col: true, link: true, base: true, img: true, param: true, area: true, hr: true, input: true },
  12147. truncatewords_html: function(value, arg){
  12148. arg = parseInt(arg, 10);
  12149. if(arg <= 0){
  12150. return "";
  12151. }
  12152. var strings = dojox.dtl.filter.strings;
  12153. var words = 0;
  12154. var open = [];
  12155. var output = Tokenize(value, strings._truncate_words, function(all, word){
  12156. if(word){
  12157. // It's an actual non-HTML word
  12158. ++words;
  12159. if(words < arg){
  12160. return word;
  12161. }else if(words == arg){
  12162. return word + " ...";
  12163. }
  12164. }
  12165. // Check for tag
  12166. var tag = all.match(strings._truncate_tag);
  12167. if(!tag || words >= arg){
  12168. // Don't worry about non tags or tags after our truncate point
  12169. return;
  12170. }
  12171. var closing = tag[1];
  12172. var tagname = tag[2].toLowerCase();
  12173. var selfclosing = tag[3];
  12174. if(closing || strings._truncate_singlets[tagname]){
  12175. }else if(closing){
  12176. var i = array.indexOf(open, tagname);
  12177. if(i != -1){
  12178. open = open.slice(i + 1);
  12179. }
  12180. }else{
  12181. open.unshift(tagname);
  12182. }
  12183. return all;
  12184. }).join("");
  12185. output = output.replace(/\s+$/g, "");
  12186. for(var i = 0, tag; tag = open[i]; i++){
  12187. output += "</" + tag + ">";
  12188. }
  12189. return output;
  12190. },
  12191. upper: function(value){
  12192. return value.toUpperCase();
  12193. },
  12194. urlencode: function(value){
  12195. return dojox.dtl.filter.strings._urlquote(value);
  12196. },
  12197. _urlize: /^((?:[(>]|&lt;)*)(.*?)((?:[.,)>\n]|&gt;)*)$/,
  12198. _urlize2: /^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$/,
  12199. urlize: function(value){
  12200. return dojox.dtl.filter.strings.urlizetrunc(value);
  12201. },
  12202. urlizetrunc: function(value, arg){
  12203. arg = parseInt(arg);
  12204. return Tokenize(value, /(\S+)/g, function(word){
  12205. var matches = dojox.dtl.filter.strings._urlize.exec(word);
  12206. if(!matches){
  12207. return word;
  12208. }
  12209. var lead = matches[1];
  12210. var middle = matches[2];
  12211. var trail = matches[3];
  12212. var startsWww = middle.indexOf("www.") == 0;
  12213. var hasAt = middle.indexOf("@") != -1;
  12214. var hasColon = middle.indexOf(":") != -1;
  12215. var startsHttp = middle.indexOf("http://") == 0;
  12216. var startsHttps = middle.indexOf("https://") == 0;
  12217. var firstAlpha = /[a-zA-Z0-9]/.test(middle.charAt(0));
  12218. var last4 = middle.substring(middle.length - 4);
  12219. var trimmed = middle;
  12220. if(arg > 3){
  12221. trimmed = trimmed.substring(0, arg - 3) + "...";
  12222. }
  12223. if(startsWww || (!hasAt && !startsHttp && middle.length && firstAlpha && (last4 == ".org" || last4 == ".net" || last4 == ".com"))){
  12224. return '<a href="http://' + middle + '" rel="nofollow">' + trimmed + '</a>';
  12225. }else if(startsHttp || startsHttps){
  12226. return '<a href="' + middle + '" rel="nofollow">' + trimmed + '</a>';
  12227. }else if(hasAt && !startsWww && !hasColon && dojox.dtl.filter.strings._urlize2.test(middle)){
  12228. return '<a href="mailto:' + middle + '">' + middle + '</a>';
  12229. }
  12230. return word;
  12231. }).join("");
  12232. },
  12233. wordcount: function(value){
  12234. value = lang.trim(value);
  12235. if(!value){ return 0; }
  12236. return value.split(/\s+/g).length;
  12237. },
  12238. wordwrap: function(value, arg){
  12239. arg = parseInt(arg);
  12240. // summary: Wraps words at specified line length
  12241. var output = [];
  12242. var parts = value.split(/\s+/g);
  12243. if(parts.length){
  12244. var word = parts.shift();
  12245. output.push(word);
  12246. var pos = word.length - word.lastIndexOf("\n") - 1;
  12247. for(var i = 0; i < parts.length; i++){
  12248. word = parts[i];
  12249. if(word.indexOf("\n") != -1){
  12250. var lines = word.split(/\n/g);
  12251. }else{
  12252. var lines = [word];
  12253. }
  12254. pos += lines[0].length + 1;
  12255. if(arg && pos > arg){
  12256. output.push("\n");
  12257. pos = lines[lines.length - 1].length;
  12258. }else{
  12259. output.push(" ");
  12260. if(lines.length > 1){
  12261. pos = lines[lines.length - 1].length;
  12262. }
  12263. }
  12264. output.push(word);
  12265. }
  12266. }
  12267. return output.join("");
  12268. }
  12269. });
  12270. return dojox.dtl.filter.strings;
  12271. });
  12272. },
  12273. 'dijit/form/Button':function(){
  12274. require({cache:{
  12275. 'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#x25CF;</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\n/></span>\n"}});
  12276. define("dijit/form/Button", [
  12277. "require",
  12278. "dojo/_base/declare", // declare
  12279. "dojo/dom-class", // domClass.toggle
  12280. "dojo/_base/kernel", // kernel.deprecated
  12281. "dojo/_base/lang", // lang.trim
  12282. "dojo/ready",
  12283. "./_FormWidget",
  12284. "./_ButtonMixin",
  12285. "dojo/text!./templates/Button.html"
  12286. ], function(require, declare, domClass, kernel, lang, ready, _FormWidget, _ButtonMixin, template){
  12287. /*=====
  12288. var _FormWidget = dijit.form._FormWidget;
  12289. var _ButtonMixin = dijit.form._ButtonMixin;
  12290. =====*/
  12291. // module:
  12292. // dijit/form/Button
  12293. // summary:
  12294. // Button widget
  12295. // Back compat w/1.6, remove for 2.0
  12296. if(!kernel.isAsync){
  12297. ready(0, function(){
  12298. var requires = ["dijit/form/DropDownButton", "dijit/form/ComboButton", "dijit/form/ToggleButton"];
  12299. require(requires); // use indirection so modules not rolled into a build
  12300. });
  12301. }
  12302. return declare("dijit.form.Button", [_FormWidget, _ButtonMixin], {
  12303. // summary:
  12304. // Basically the same thing as a normal HTML button, but with special styling.
  12305. // description:
  12306. // Buttons can display a label, an icon, or both.
  12307. // A label should always be specified (through innerHTML) or the label
  12308. // attribute. It can be hidden via showLabel=false.
  12309. // example:
  12310. // | <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
  12311. //
  12312. // example:
  12313. // | var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
  12314. // | dojo.body().appendChild(button1.domNode);
  12315. // showLabel: Boolean
  12316. // Set this to true to hide the label text and display only the icon.
  12317. // (If showLabel=false then iconClass must be specified.)
  12318. // Especially useful for toolbars.
  12319. // If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon.
  12320. //
  12321. // The exception case is for computers in high-contrast mode, where the label
  12322. // will still be displayed, since the icon doesn't appear.
  12323. showLabel: true,
  12324. // iconClass: String
  12325. // Class to apply to DOMNode in button to make it display an icon
  12326. iconClass: "dijitNoIcon",
  12327. _setIconClassAttr: { node: "iconNode", type: "class" },
  12328. baseClass: "dijitButton",
  12329. templateString: template,
  12330. // Map widget attributes to DOMNode attributes.
  12331. _setValueAttr: "valueNode",
  12332. _onClick: function(/*Event*/ e){
  12333. // summary:
  12334. // Internal function to handle click actions
  12335. var ok = this.inherited(arguments);
  12336. if(ok){
  12337. if(this.valueNode){
  12338. this.valueNode.click();
  12339. e.preventDefault(); // cancel BUTTON click and continue with hidden INPUT click
  12340. // leave ok = true so that subclasses can do what they need to do
  12341. }
  12342. }
  12343. return ok;
  12344. },
  12345. _fillContent: function(/*DomNode*/ source){
  12346. // Overrides _Templated._fillContent().
  12347. // If button label is specified as srcNodeRef.innerHTML rather than
  12348. // this.params.label, handle it here.
  12349. // TODO: remove the method in 2.0, parser will do it all for me
  12350. if(source && (!this.params || !("label" in this.params))){
  12351. var sourceLabel = lang.trim(source.innerHTML);
  12352. if(sourceLabel){
  12353. this.label = sourceLabel; // _applyAttributes will be called after buildRendering completes to update the DOM
  12354. }
  12355. }
  12356. },
  12357. _setShowLabelAttr: function(val){
  12358. if(this.containerNode){
  12359. domClass.toggle(this.containerNode, "dijitDisplayNone", !val);
  12360. }
  12361. this._set("showLabel", val);
  12362. },
  12363. setLabel: function(/*String*/ content){
  12364. // summary:
  12365. // Deprecated. Use set('label', ...) instead.
  12366. kernel.deprecated("dijit.form.Button.setLabel() is deprecated. Use set('label', ...) instead.", "", "2.0");
  12367. this.set("label", content);
  12368. },
  12369. _setLabelAttr: function(/*String*/ content){
  12370. // summary:
  12371. // Hook for set('label', ...) to work.
  12372. // description:
  12373. // Set the label (text) of the button; takes an HTML string.
  12374. // If the label is hidden (showLabel=false) then and no title has
  12375. // been specified, then label is also set as title attribute of icon.
  12376. this.inherited(arguments);
  12377. if(!this.showLabel && !("title" in this.params)){
  12378. this.titleNode.title = lang.trim(this.containerNode.innerText || this.containerNode.textContent || '');
  12379. }
  12380. }
  12381. });
  12382. });
  12383. },
  12384. 'url:dijit/layout/templates/TabContainer.html':"<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" data-dojo-attach-point=\"tablistNode\"></div>\n\t<div data-dojo-attach-point=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" data-dojo-attach-point=\"containerNode\"></div>\n</div>\n",
  12385. 'dojo/dnd/move':function(){
  12386. define("dojo/dnd/move", ["../main", "./Mover", "./Moveable"], function(dojo) {
  12387. // module:
  12388. // dojo/dnd/move
  12389. // summary:
  12390. // TODOC
  12391. /*=====
  12392. dojo.declare("dojo.dnd.move.__constrainedMoveableArgs", [dojo.dnd.__MoveableArgs], {
  12393. // constraints: Function
  12394. // Calculates a constraint box.
  12395. // It is called in a context of the moveable object.
  12396. constraints: function(){},
  12397. // within: Boolean
  12398. // restrict move within boundaries.
  12399. within: false
  12400. });
  12401. =====*/
  12402. dojo.declare("dojo.dnd.move.constrainedMoveable", dojo.dnd.Moveable, {
  12403. // object attributes (for markup)
  12404. constraints: function(){},
  12405. within: false,
  12406. constructor: function(node, params){
  12407. // summary:
  12408. // an object that makes a node moveable
  12409. // node: Node
  12410. // a node (or node's id) to be moved
  12411. // params: dojo.dnd.move.__constrainedMoveableArgs?
  12412. // an optional object with additional parameters;
  12413. // the rest is passed to the base class
  12414. if(!params){ params = {}; }
  12415. this.constraints = params.constraints;
  12416. this.within = params.within;
  12417. },
  12418. onFirstMove: function(/* dojo.dnd.Mover */ mover){
  12419. // summary:
  12420. // called during the very first move notification;
  12421. // can be used to initialize coordinates, can be overwritten.
  12422. var c = this.constraintBox = this.constraints.call(this, mover);
  12423. c.r = c.l + c.w;
  12424. c.b = c.t + c.h;
  12425. if(this.within){
  12426. var mb = dojo._getMarginSize(mover.node);
  12427. c.r -= mb.w;
  12428. c.b -= mb.h;
  12429. }
  12430. },
  12431. onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
  12432. // summary:
  12433. // called during every move notification;
  12434. // should actually move the node; can be overwritten.
  12435. var c = this.constraintBox, s = mover.node.style;
  12436. this.onMoving(mover, leftTop);
  12437. leftTop.l = leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l;
  12438. leftTop.t = leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t;
  12439. s.left = leftTop.l + "px";
  12440. s.top = leftTop.t + "px";
  12441. this.onMoved(mover, leftTop);
  12442. }
  12443. });
  12444. /*=====
  12445. dojo.declare("dojo.dnd.move.__boxConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
  12446. // box: Object
  12447. // a constraint box
  12448. box: {}
  12449. });
  12450. =====*/
  12451. dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
  12452. // box:
  12453. // object attributes (for markup)
  12454. box: {},
  12455. constructor: function(node, params){
  12456. // summary:
  12457. // an object, which makes a node moveable
  12458. // node: Node
  12459. // a node (or node's id) to be moved
  12460. // params: dojo.dnd.move.__boxConstrainedMoveableArgs?
  12461. // an optional object with parameters
  12462. var box = params && params.box;
  12463. this.constraints = function(){ return box; };
  12464. }
  12465. });
  12466. /*=====
  12467. dojo.declare("dojo.dnd.move.__parentConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
  12468. // area: String
  12469. // A parent's area to restrict the move.
  12470. // Can be "margin", "border", "padding", or "content".
  12471. area: ""
  12472. });
  12473. =====*/
  12474. dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
  12475. // area:
  12476. // object attributes (for markup)
  12477. area: "content",
  12478. constructor: function(node, params){
  12479. // summary:
  12480. // an object, which makes a node moveable
  12481. // node: Node
  12482. // a node (or node's id) to be moved
  12483. // params: dojo.dnd.move.__parentConstrainedMoveableArgs?
  12484. // an optional object with parameters
  12485. var area = params && params.area;
  12486. this.constraints = function(){
  12487. var n = this.node.parentNode,
  12488. s = dojo.getComputedStyle(n),
  12489. mb = dojo._getMarginBox(n, s);
  12490. if(area == "margin"){
  12491. return mb; // Object
  12492. }
  12493. var t = dojo._getMarginExtents(n, s);
  12494. mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
  12495. if(area == "border"){
  12496. return mb; // Object
  12497. }
  12498. t = dojo._getBorderExtents(n, s);
  12499. mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
  12500. if(area == "padding"){
  12501. return mb; // Object
  12502. }
  12503. t = dojo._getPadExtents(n, s);
  12504. mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
  12505. return mb; // Object
  12506. };
  12507. }
  12508. });
  12509. // patching functions one level up for compatibility
  12510. dojo.dnd.constrainedMover = dojo.dnd.move.constrainedMover;
  12511. dojo.dnd.boxConstrainedMover = dojo.dnd.move.boxConstrainedMover;
  12512. dojo.dnd.parentConstrainedMover = dojo.dnd.move.parentConstrainedMover;
  12513. return dojo.dnd.move;
  12514. });
  12515. },
  12516. 'dijit/_WidgetBase':function(){
  12517. define("dijit/_WidgetBase", [
  12518. "require", // require.toUrl
  12519. "dojo/_base/array", // array.forEach array.map
  12520. "dojo/aspect",
  12521. "dojo/_base/config", // config.blankGif
  12522. "dojo/_base/connect", // connect.connect
  12523. "dojo/_base/declare", // declare
  12524. "dojo/dom", // dom.byId
  12525. "dojo/dom-attr", // domAttr.set domAttr.remove
  12526. "dojo/dom-class", // domClass.add domClass.replace
  12527. "dojo/dom-construct", // domConstruct.create domConstruct.destroy domConstruct.place
  12528. "dojo/dom-geometry", // isBodyLtr
  12529. "dojo/dom-style", // domStyle.set, domStyle.get
  12530. "dojo/_base/kernel",
  12531. "dojo/_base/lang", // mixin(), isArray(), etc.
  12532. "dojo/on",
  12533. "dojo/ready",
  12534. "dojo/Stateful", // Stateful
  12535. "dojo/topic",
  12536. "dojo/_base/window", // win.doc.createTextNode
  12537. "./registry" // registry.getUniqueId(), registry.findWidgets()
  12538. ], function(require, array, aspect, config, connect, declare,
  12539. dom, domAttr, domClass, domConstruct, domGeometry, domStyle, kernel,
  12540. lang, on, ready, Stateful, topic, win, registry){
  12541. /*=====
  12542. var Stateful = dojo.Stateful;
  12543. =====*/
  12544. // module:
  12545. // dijit/_WidgetBase
  12546. // summary:
  12547. // Future base class for all Dijit widgets.
  12548. // For back-compat, remove in 2.0.
  12549. if(!kernel.isAsync){
  12550. ready(0, function(){
  12551. var requires = ["dijit/_base/manager"];
  12552. require(requires); // use indirection so modules not rolled into a build
  12553. });
  12554. }
  12555. // Nested hash listing attributes for each tag, all strings in lowercase.
  12556. // ex: {"div": {"style": true, "tabindex" true}, "form": { ...
  12557. var tagAttrs = {};
  12558. function getAttrs(obj){
  12559. var ret = {};
  12560. for(var attr in obj){
  12561. ret[attr.toLowerCase()] = true;
  12562. }
  12563. return ret;
  12564. }
  12565. function nonEmptyAttrToDom(attr){
  12566. // summary:
  12567. // Returns a setter function that copies the attribute to this.domNode,
  12568. // or removes the attribute from this.domNode, depending on whether the
  12569. // value is defined or not.
  12570. return function(val){
  12571. domAttr[val ? "set" : "remove"](this.domNode, attr, val);
  12572. this._set(attr, val);
  12573. };
  12574. }
  12575. function isEqual(a, b){
  12576. // summary:
  12577. // Function that determines whether two values are identical,
  12578. // taking into account that NaN is not normally equal to itself
  12579. // in JS.
  12580. return a === b || (/* a is NaN */ a !== a && /* b is NaN */ b !== b);
  12581. }
  12582. return declare("dijit._WidgetBase", Stateful, {
  12583. // summary:
  12584. // Future base class for all Dijit widgets.
  12585. // description:
  12586. // Future base class for all Dijit widgets.
  12587. // _Widget extends this class adding support for various features needed by desktop.
  12588. //
  12589. // Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(),
  12590. // postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch().
  12591. //
  12592. // Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value).
  12593. // For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr().
  12594. //
  12595. // _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes:
  12596. //
  12597. // - DOM node attribute
  12598. // | _setFocusAttr: {node: "focusNode", type: "attribute"}
  12599. // | _setFocusAttr: "focusNode" (shorthand)
  12600. // | _setFocusAttr: "" (shorthand, maps to this.domNode)
  12601. // Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus
  12602. //
  12603. // - DOM node innerHTML
  12604. // | _setTitleAttr: { node: "titleNode", type: "innerHTML" }
  12605. // Maps this.title to this.titleNode.innerHTML
  12606. //
  12607. // - DOM node innerText
  12608. // | _setTitleAttr: { node: "titleNode", type: "innerText" }
  12609. // Maps this.title to this.titleNode.innerText
  12610. //
  12611. // - DOM node CSS class
  12612. // | _setMyClassAttr: { node: "domNode", type: "class" }
  12613. // Maps this.myClass to this.domNode.className
  12614. //
  12615. // If the value of _setXXXAttr is an array, then each element in the array matches one of the
  12616. // formats of the above list.
  12617. //
  12618. // If the custom setter is null, no action is performed other than saving the new value
  12619. // in the widget (in this).
  12620. //
  12621. // If no custom setter is defined for an attribute, then it will be copied
  12622. // to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise.
  12623. // That's only done though for attributes that match DOMNode attributes (title,
  12624. // alt, aria-labelledby, etc.)
  12625. // id: [const] String
  12626. // A unique, opaque ID string that can be assigned by users or by the
  12627. // system. If the developer passes an ID which is known not to be
  12628. // unique, the specified ID is ignored and the system-generated ID is
  12629. // used instead.
  12630. id: "",
  12631. _setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's
  12632. // lang: [const] String
  12633. // Rarely used. Overrides the default Dojo locale used to render this widget,
  12634. // as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
  12635. // Value must be among the list of locales specified during by the Dojo bootstrap,
  12636. // formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
  12637. lang: "",
  12638. // set on domNode even when there's a focus node. but don't set lang="", since that's invalid.
  12639. _setLangAttr: nonEmptyAttrToDom("lang"),
  12640. // dir: [const] String
  12641. // Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
  12642. // attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's
  12643. // default direction.
  12644. dir: "",
  12645. // set on domNode even when there's a focus node. but don't set dir="", since that's invalid.
  12646. _setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node
  12647. // textDir: String
  12648. // Bi-directional support, the main variable which is responsible for the direction of the text.
  12649. // The text direction can be different than the GUI direction by using this parameter in creation
  12650. // of a widget.
  12651. // Allowed values:
  12652. // 1. "ltr"
  12653. // 2. "rtl"
  12654. // 3. "auto" - contextual the direction of a text defined by first strong letter.
  12655. // By default is as the page direction.
  12656. textDir: "",
  12657. // class: String
  12658. // HTML class attribute
  12659. "class": "",
  12660. _setClassAttr: { node: "domNode", type: "class" },
  12661. // style: String||Object
  12662. // HTML style attributes as cssText string or name/value hash
  12663. style: "",
  12664. // title: String
  12665. // HTML title attribute.
  12666. //
  12667. // For form widgets this specifies a tooltip to display when hovering over
  12668. // the widget (just like the native HTML title attribute).
  12669. //
  12670. // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
  12671. // etc., it's used to specify the tab label, accordion pane title, etc.
  12672. title: "",
  12673. // tooltip: String
  12674. // When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
  12675. // this specifies the tooltip to appear when the mouse is hovered over that text.
  12676. tooltip: "",
  12677. // baseClass: [protected] String
  12678. // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
  12679. // widget state.
  12680. baseClass: "",
  12681. // srcNodeRef: [readonly] DomNode
  12682. // pointer to original DOM node
  12683. srcNodeRef: null,
  12684. // domNode: [readonly] DomNode
  12685. // This is our visible representation of the widget! Other DOM
  12686. // Nodes may by assigned to other properties, usually through the
  12687. // template system's data-dojo-attach-point syntax, but the domNode
  12688. // property is the canonical "top level" node in widget UI.
  12689. domNode: null,
  12690. // containerNode: [readonly] DomNode
  12691. // Designates where children of the source DOM node will be placed.
  12692. // "Children" in this case refers to both DOM nodes and widgets.
  12693. // For example, for myWidget:
  12694. //
  12695. // | <div data-dojo-type=myWidget>
  12696. // | <b> here's a plain DOM node
  12697. // | <span data-dojo-type=subWidget>and a widget</span>
  12698. // | <i> and another plain DOM node </i>
  12699. // | </div>
  12700. //
  12701. // containerNode would point to:
  12702. //
  12703. // | <b> here's a plain DOM node
  12704. // | <span data-dojo-type=subWidget>and a widget</span>
  12705. // | <i> and another plain DOM node </i>
  12706. //
  12707. // In templated widgets, "containerNode" is set via a
  12708. // data-dojo-attach-point assignment.
  12709. //
  12710. // containerNode must be defined for any widget that accepts innerHTML
  12711. // (like ContentPane or BorderContainer or even Button), and conversely
  12712. // is null for widgets that don't, like TextBox.
  12713. containerNode: null,
  12714. /*=====
  12715. // _started: Boolean
  12716. // startup() has completed.
  12717. _started: false,
  12718. =====*/
  12719. // attributeMap: [protected] Object
  12720. // Deprecated. Instead of attributeMap, widget should have a _setXXXAttr attribute
  12721. // for each XXX attribute to be mapped to the DOM.
  12722. //
  12723. // attributeMap sets up a "binding" between attributes (aka properties)
  12724. // of the widget and the widget's DOM.
  12725. // Changes to widget attributes listed in attributeMap will be
  12726. // reflected into the DOM.
  12727. //
  12728. // For example, calling set('title', 'hello')
  12729. // on a TitlePane will automatically cause the TitlePane's DOM to update
  12730. // with the new title.
  12731. //
  12732. // attributeMap is a hash where the key is an attribute of the widget,
  12733. // and the value reflects a binding to a:
  12734. //
  12735. // - DOM node attribute
  12736. // | focus: {node: "focusNode", type: "attribute"}
  12737. // Maps this.focus to this.focusNode.focus
  12738. //
  12739. // - DOM node innerHTML
  12740. // | title: { node: "titleNode", type: "innerHTML" }
  12741. // Maps this.title to this.titleNode.innerHTML
  12742. //
  12743. // - DOM node innerText
  12744. // | title: { node: "titleNode", type: "innerText" }
  12745. // Maps this.title to this.titleNode.innerText
  12746. //
  12747. // - DOM node CSS class
  12748. // | myClass: { node: "domNode", type: "class" }
  12749. // Maps this.myClass to this.domNode.className
  12750. //
  12751. // If the value is an array, then each element in the array matches one of the
  12752. // formats of the above list.
  12753. //
  12754. // There are also some shorthands for backwards compatibility:
  12755. // - string --> { node: string, type: "attribute" }, for example:
  12756. // | "focusNode" ---> { node: "focusNode", type: "attribute" }
  12757. // - "" --> { node: "domNode", type: "attribute" }
  12758. attributeMap: {},
  12759. // _blankGif: [protected] String
  12760. // Path to a blank 1x1 image.
  12761. // Used by <img> nodes in templates that really get their image via CSS background-image.
  12762. _blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
  12763. //////////// INITIALIZATION METHODS ///////////////////////////////////////
  12764. postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
  12765. // summary:
  12766. // Kicks off widget instantiation. See create() for details.
  12767. // tags:
  12768. // private
  12769. this.create(params, srcNodeRef);
  12770. },
  12771. create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
  12772. // summary:
  12773. // Kick off the life-cycle of a widget
  12774. // params:
  12775. // Hash of initialization parameters for widget, including
  12776. // scalar values (like title, duration etc.) and functions,
  12777. // typically callbacks like onClick.
  12778. // srcNodeRef:
  12779. // If a srcNodeRef (DOM node) is specified:
  12780. // - use srcNodeRef.innerHTML as my contents
  12781. // - if this is a behavioral widget then apply behavior
  12782. // to that srcNodeRef
  12783. // - otherwise, replace srcNodeRef with my generated DOM
  12784. // tree
  12785. // description:
  12786. // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
  12787. // etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html
  12788. // for a discussion of the widget creation lifecycle.
  12789. //
  12790. // Of course, adventurous developers could override create entirely, but this should
  12791. // only be done as a last resort.
  12792. // tags:
  12793. // private
  12794. // store pointer to original DOM tree
  12795. this.srcNodeRef = dom.byId(srcNodeRef);
  12796. // For garbage collection. An array of listener handles returned by this.connect() / this.subscribe()
  12797. this._connects = [];
  12798. // For widgets internal to this widget, invisible to calling code
  12799. this._supportingWidgets = [];
  12800. // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
  12801. if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
  12802. // mix in our passed parameters
  12803. if(params){
  12804. this.params = params;
  12805. lang.mixin(this, params);
  12806. }
  12807. this.postMixInProperties();
  12808. // generate an id for the widget if one wasn't specified
  12809. // (be sure to do this before buildRendering() because that function might
  12810. // expect the id to be there.)
  12811. if(!this.id){
  12812. this.id = registry.getUniqueId(this.declaredClass.replace(/\./g,"_"));
  12813. }
  12814. registry.add(this);
  12815. this.buildRendering();
  12816. if(this.domNode){
  12817. // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
  12818. // Also calls custom setters for all attributes with custom setters.
  12819. this._applyAttributes();
  12820. // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
  12821. // For 2.0, move this after postCreate(). postCreate() shouldn't depend on the
  12822. // widget being attached to the DOM since it isn't when a widget is created programmatically like
  12823. // new MyWidget({}). See #11635.
  12824. var source = this.srcNodeRef;
  12825. if(source && source.parentNode && this.domNode !== source){
  12826. source.parentNode.replaceChild(this.domNode, source);
  12827. }
  12828. }
  12829. if(this.domNode){
  12830. // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
  12831. // assuming that dojo._scopeName even exists in 2.0
  12832. this.domNode.setAttribute("widgetId", this.id);
  12833. }
  12834. this.postCreate();
  12835. // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
  12836. if(this.srcNodeRef && !this.srcNodeRef.parentNode){
  12837. delete this.srcNodeRef;
  12838. }
  12839. this._created = true;
  12840. },
  12841. _applyAttributes: function(){
  12842. // summary:
  12843. // Step during widget creation to copy widget attributes to the
  12844. // DOM according to attributeMap and _setXXXAttr objects, and also to call
  12845. // custom _setXXXAttr() methods.
  12846. //
  12847. // Skips over blank/false attribute values, unless they were explicitly specified
  12848. // as parameters to the widget, since those are the default anyway,
  12849. // and setting tabIndex="" is different than not setting tabIndex at all.
  12850. //
  12851. // For backwards-compatibility reasons attributeMap overrides _setXXXAttr when
  12852. // _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap.
  12853. // tags:
  12854. // private
  12855. // Get list of attributes where this.set(name, value) will do something beyond
  12856. // setting this[name] = value. Specifically, attributes that have:
  12857. // - associated _setXXXAttr() method/hash/string/array
  12858. // - entries in attributeMap.
  12859. var ctor = this.constructor,
  12860. list = ctor._setterAttrs;
  12861. if(!list){
  12862. list = (ctor._setterAttrs = []);
  12863. for(var attr in this.attributeMap){
  12864. list.push(attr);
  12865. }
  12866. var proto = ctor.prototype;
  12867. for(var fxName in proto){
  12868. if(fxName in this.attributeMap){ continue; }
  12869. var setterName = "_set" + fxName.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }) + "Attr";
  12870. if(setterName in proto){
  12871. list.push(fxName);
  12872. }
  12873. }
  12874. }
  12875. // Call this.set() for each attribute that was either specified as parameter to constructor,
  12876. // or was found above and has a default non-null value. For correlated attributes like value and displayedValue, the one
  12877. // specified as a parameter should take precedence, so apply attributes in this.params last.
  12878. // Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
  12879. // NaN and thus is not ignored like a default value of "".
  12880. array.forEach(list, function(attr){
  12881. if(this.params && attr in this.params){
  12882. // skip this one, do it below
  12883. }else if(this[attr]){
  12884. this.set(attr, this[attr]);
  12885. }
  12886. }, this);
  12887. for(var param in this.params){
  12888. this.set(param, this[param]);
  12889. }
  12890. },
  12891. postMixInProperties: function(){
  12892. // summary:
  12893. // Called after the parameters to the widget have been read-in,
  12894. // but before the widget template is instantiated. Especially
  12895. // useful to set properties that are referenced in the widget
  12896. // template.
  12897. // tags:
  12898. // protected
  12899. },
  12900. buildRendering: function(){
  12901. // summary:
  12902. // Construct the UI for this widget, setting this.domNode.
  12903. // Most widgets will mixin `dijit._TemplatedMixin`, which implements this method.
  12904. // tags:
  12905. // protected
  12906. if(!this.domNode){
  12907. // Create root node if it wasn't created by _Templated
  12908. this.domNode = this.srcNodeRef || domConstruct.create('div');
  12909. }
  12910. // baseClass is a single class name or occasionally a space-separated list of names.
  12911. // Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix.
  12912. // TODO: make baseClass custom setter
  12913. if(this.baseClass){
  12914. var classes = this.baseClass.split(" ");
  12915. if(!this.isLeftToRight()){
  12916. classes = classes.concat( array.map(classes, function(name){ return name+"Rtl"; }));
  12917. }
  12918. domClass.add(this.domNode, classes);
  12919. }
  12920. },
  12921. postCreate: function(){
  12922. // summary:
  12923. // Processing after the DOM fragment is created
  12924. // description:
  12925. // Called after the DOM fragment has been created, but not necessarily
  12926. // added to the document. Do not include any operations which rely on
  12927. // node dimensions or placement.
  12928. // tags:
  12929. // protected
  12930. },
  12931. startup: function(){
  12932. // summary:
  12933. // Processing after the DOM fragment is added to the document
  12934. // description:
  12935. // Called after a widget and its children have been created and added to the page,
  12936. // and all related widgets have finished their create() cycle, up through postCreate().
  12937. // This is useful for composite widgets that need to control or layout sub-widgets.
  12938. // Many layout widgets can use this as a wiring phase.
  12939. if(this._started){ return; }
  12940. this._started = true;
  12941. array.forEach(this.getChildren(), function(obj){
  12942. if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
  12943. obj.startup();
  12944. obj._started = true;
  12945. }
  12946. });
  12947. },
  12948. //////////// DESTROY FUNCTIONS ////////////////////////////////
  12949. destroyRecursive: function(/*Boolean?*/ preserveDom){
  12950. // summary:
  12951. // Destroy this widget and its descendants
  12952. // description:
  12953. // This is the generic "destructor" function that all widget users
  12954. // should call to cleanly discard with a widget. Once a widget is
  12955. // destroyed, it is removed from the manager object.
  12956. // preserveDom:
  12957. // If true, this method will leave the original DOM structure
  12958. // alone of descendant Widgets. Note: This will NOT work with
  12959. // dijit._Templated widgets.
  12960. this._beingDestroyed = true;
  12961. this.destroyDescendants(preserveDom);
  12962. this.destroy(preserveDom);
  12963. },
  12964. destroy: function(/*Boolean*/ preserveDom){
  12965. // summary:
  12966. // Destroy this widget, but not its descendants.
  12967. // This method will, however, destroy internal widgets such as those used within a template.
  12968. // preserveDom: Boolean
  12969. // If true, this method will leave the original DOM structure alone.
  12970. // Note: This will not yet work with _Templated widgets
  12971. this._beingDestroyed = true;
  12972. this.uninitialize();
  12973. // remove this.connect() and this.subscribe() listeners
  12974. var c;
  12975. while((c = this._connects.pop())){
  12976. c.remove();
  12977. }
  12978. // destroy widgets created as part of template, etc.
  12979. var w;
  12980. while((w = this._supportingWidgets.pop())){
  12981. if(w.destroyRecursive){
  12982. w.destroyRecursive();
  12983. }else if(w.destroy){
  12984. w.destroy();
  12985. }
  12986. }
  12987. this.destroyRendering(preserveDom);
  12988. registry.remove(this.id);
  12989. this._destroyed = true;
  12990. },
  12991. destroyRendering: function(/*Boolean?*/ preserveDom){
  12992. // summary:
  12993. // Destroys the DOM nodes associated with this widget
  12994. // preserveDom:
  12995. // If true, this method will leave the original DOM structure alone
  12996. // during tear-down. Note: this will not work with _Templated
  12997. // widgets yet.
  12998. // tags:
  12999. // protected
  13000. if(this.bgIframe){
  13001. this.bgIframe.destroy(preserveDom);
  13002. delete this.bgIframe;
  13003. }
  13004. if(this.domNode){
  13005. if(preserveDom){
  13006. domAttr.remove(this.domNode, "widgetId");
  13007. }else{
  13008. domConstruct.destroy(this.domNode);
  13009. }
  13010. delete this.domNode;
  13011. }
  13012. if(this.srcNodeRef){
  13013. if(!preserveDom){
  13014. domConstruct.destroy(this.srcNodeRef);
  13015. }
  13016. delete this.srcNodeRef;
  13017. }
  13018. },
  13019. destroyDescendants: function(/*Boolean?*/ preserveDom){
  13020. // summary:
  13021. // Recursively destroy the children of this widget and their
  13022. // descendants.
  13023. // preserveDom:
  13024. // If true, the preserveDom attribute is passed to all descendant
  13025. // widget's .destroy() method. Not for use with _Templated
  13026. // widgets.
  13027. // get all direct descendants and destroy them recursively
  13028. array.forEach(this.getChildren(), function(widget){
  13029. if(widget.destroyRecursive){
  13030. widget.destroyRecursive(preserveDom);
  13031. }
  13032. });
  13033. },
  13034. uninitialize: function(){
  13035. // summary:
  13036. // Stub function. Override to implement custom widget tear-down
  13037. // behavior.
  13038. // tags:
  13039. // protected
  13040. return false;
  13041. },
  13042. ////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
  13043. _setStyleAttr: function(/*String||Object*/ value){
  13044. // summary:
  13045. // Sets the style attribute of the widget according to value,
  13046. // which is either a hash like {height: "5px", width: "3px"}
  13047. // or a plain string
  13048. // description:
  13049. // Determines which node to set the style on based on style setting
  13050. // in attributeMap.
  13051. // tags:
  13052. // protected
  13053. var mapNode = this.domNode;
  13054. // Note: technically we should revert any style setting made in a previous call
  13055. // to his method, but that's difficult to keep track of.
  13056. if(lang.isObject(value)){
  13057. domStyle.set(mapNode, value);
  13058. }else{
  13059. if(mapNode.style.cssText){
  13060. mapNode.style.cssText += "; " + value;
  13061. }else{
  13062. mapNode.style.cssText = value;
  13063. }
  13064. }
  13065. this._set("style", value);
  13066. },
  13067. _attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
  13068. // summary:
  13069. // Reflect a widget attribute (title, tabIndex, duration etc.) to
  13070. // the widget DOM, as specified by commands parameter.
  13071. // If commands isn't specified then it's looked up from attributeMap.
  13072. // Note some attributes like "type"
  13073. // cannot be processed this way as they are not mutable.
  13074. //
  13075. // tags:
  13076. // private
  13077. commands = arguments.length >= 3 ? commands : this.attributeMap[attr];
  13078. array.forEach(lang.isArray(commands) ? commands : [commands], function(command){
  13079. // Get target node and what we are doing to that node
  13080. var mapNode = this[command.node || command || "domNode"]; // DOM node
  13081. var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
  13082. switch(type){
  13083. case "attribute":
  13084. if(lang.isFunction(value)){ // functions execute in the context of the widget
  13085. value = lang.hitch(this, value);
  13086. }
  13087. // Get the name of the DOM node attribute; usually it's the same
  13088. // as the name of the attribute in the widget (attr), but can be overridden.
  13089. // Also maps handler names to lowercase, like onSubmit --> onsubmit
  13090. var attrName = command.attribute ? command.attribute :
  13091. (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
  13092. domAttr.set(mapNode, attrName, value);
  13093. break;
  13094. case "innerText":
  13095. mapNode.innerHTML = "";
  13096. mapNode.appendChild(win.doc.createTextNode(value));
  13097. break;
  13098. case "innerHTML":
  13099. mapNode.innerHTML = value;
  13100. break;
  13101. case "class":
  13102. domClass.replace(mapNode, value, this[attr]);
  13103. break;
  13104. }
  13105. }, this);
  13106. },
  13107. get: function(name){
  13108. // summary:
  13109. // Get a property from a widget.
  13110. // name:
  13111. // The property to get.
  13112. // description:
  13113. // Get a named property from a widget. The property may
  13114. // potentially be retrieved via a getter method. If no getter is defined, this
  13115. // just retrieves the object's property.
  13116. //
  13117. // For example, if the widget has properties `foo` and `bar`
  13118. // and a method named `_getFooAttr()`, calling:
  13119. // `myWidget.get("foo")` would be equivalent to calling
  13120. // `widget._getFooAttr()` and `myWidget.get("bar")`
  13121. // would be equivalent to the expression
  13122. // `widget.bar2`
  13123. var names = this._getAttrNames(name);
  13124. return this[names.g] ? this[names.g]() : this[name];
  13125. },
  13126. set: function(name, value){
  13127. // summary:
  13128. // Set a property on a widget
  13129. // name:
  13130. // The property to set.
  13131. // value:
  13132. // The value to set in the property.
  13133. // description:
  13134. // Sets named properties on a widget which may potentially be handled by a
  13135. // setter in the widget.
  13136. //
  13137. // For example, if the widget has properties `foo` and `bar`
  13138. // and a method named `_setFooAttr()`, calling
  13139. // `myWidget.set("foo", "Howdy!")` would be equivalent to calling
  13140. // `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)`
  13141. // would be equivalent to the statement `widget.bar = 3;`
  13142. //
  13143. // set() may also be called with a hash of name/value pairs, ex:
  13144. //
  13145. // | myWidget.set({
  13146. // | foo: "Howdy",
  13147. // | bar: 3
  13148. // | });
  13149. //
  13150. // This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)`
  13151. if(typeof name === "object"){
  13152. for(var x in name){
  13153. this.set(x, name[x]);
  13154. }
  13155. return this;
  13156. }
  13157. var names = this._getAttrNames(name),
  13158. setter = this[names.s];
  13159. if(lang.isFunction(setter)){
  13160. // use the explicit setter
  13161. var result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
  13162. }else{
  13163. // Mapping from widget attribute to DOMNode attribute/value/etc.
  13164. // Map according to:
  13165. // 1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0)
  13166. // 2. _setFooAttr: {...} type attribute in the widget (if one exists)
  13167. // 3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick.
  13168. // Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar
  13169. // attribute name (ex: accept-charset attribute matches jsObject.acceptCharset).
  13170. // Note also that Tree.focusNode() is a function not a DOMNode, so test for that.
  13171. var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode",
  13172. tag = this[defaultNode].tagName,
  13173. attrsForTag = tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode])),
  13174. map = name in this.attributeMap ? this.attributeMap[name] :
  13175. names.s in this ? this[names.s] :
  13176. ((names.l in attrsForTag && typeof value != "function") ||
  13177. /^aria-|^data-|^role$/.test(name)) ? defaultNode : null;
  13178. if(map != null){
  13179. this._attrToDom(name, value, map);
  13180. }
  13181. this._set(name, value);
  13182. }
  13183. return result || this;
  13184. },
  13185. _attrPairNames: {}, // shared between all widgets
  13186. _getAttrNames: function(name){
  13187. // summary:
  13188. // Helper function for get() and set().
  13189. // Caches attribute name values so we don't do the string ops every time.
  13190. // tags:
  13191. // private
  13192. var apn = this._attrPairNames;
  13193. if(apn[name]){ return apn[name]; }
  13194. var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); });
  13195. return (apn[name] = {
  13196. n: name+"Node",
  13197. s: "_set"+uc+"Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr
  13198. g: "_get"+uc+"Attr",
  13199. l: uc.toLowerCase() // lowercase name w/out dashes, ex: acceptcharset
  13200. });
  13201. },
  13202. _set: function(/*String*/ name, /*anything*/ value){
  13203. // summary:
  13204. // Helper function to set new value for specified attribute, and call handlers
  13205. // registered with watch() if the value has changed.
  13206. var oldValue = this[name];
  13207. this[name] = value;
  13208. if(this._watchCallbacks && this._created && !isEqual(value, oldValue)){
  13209. this._watchCallbacks(name, oldValue, value);
  13210. }
  13211. },
  13212. on: function(/*String*/ type, /*Function*/ func){
  13213. // summary:
  13214. // Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
  13215. // description:
  13216. // Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`.
  13217. // Note that the function is not run in any particular scope, so if (for example) you want it to run in the
  13218. // widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`.
  13219. return aspect.after(this, this._onMap(type), func, true);
  13220. },
  13221. _onMap: function(/*String*/ type){
  13222. // summary:
  13223. // Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove")
  13224. var ctor = this.constructor, map = ctor._onMap;
  13225. if(!map){
  13226. map = (ctor._onMap = {});
  13227. for(var attr in ctor.prototype){
  13228. if(/^on/.test(attr)){
  13229. map[attr.replace(/^on/, "").toLowerCase()] = attr;
  13230. }
  13231. }
  13232. }
  13233. return map[type.toLowerCase()]; // String
  13234. },
  13235. toString: function(){
  13236. // summary:
  13237. // Returns a string that represents the widget
  13238. // description:
  13239. // When a widget is cast to a string, this method will be used to generate the
  13240. // output. Currently, it does not implement any sort of reversible
  13241. // serialization.
  13242. return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
  13243. },
  13244. getChildren: function(){
  13245. // summary:
  13246. // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
  13247. // Does not return nested widgets, nor widgets that are part of this widget's template.
  13248. return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit._Widget[]
  13249. },
  13250. getParent: function(){
  13251. // summary:
  13252. // Returns the parent widget of this widget
  13253. return registry.getEnclosingWidget(this.domNode.parentNode);
  13254. },
  13255. connect: function(
  13256. /*Object|null*/ obj,
  13257. /*String|Function*/ event,
  13258. /*String|Function*/ method){
  13259. // summary:
  13260. // Connects specified obj/event to specified method of this object
  13261. // and registers for disconnect() on widget destroy.
  13262. // description:
  13263. // Provide widget-specific analog to dojo.connect, except with the
  13264. // implicit use of this widget as the target object.
  13265. // Events connected with `this.connect` are disconnected upon
  13266. // destruction.
  13267. // returns:
  13268. // A handle that can be passed to `disconnect` in order to disconnect before
  13269. // the widget is destroyed.
  13270. // example:
  13271. // | var btn = new dijit.form.Button();
  13272. // | // when foo.bar() is called, call the listener we're going to
  13273. // | // provide in the scope of btn
  13274. // | btn.connect(foo, "bar", function(){
  13275. // | console.debug(this.toString());
  13276. // | });
  13277. // tags:
  13278. // protected
  13279. var handle = connect.connect(obj, event, this, method);
  13280. this._connects.push(handle);
  13281. return handle; // _Widget.Handle
  13282. },
  13283. disconnect: function(handle){
  13284. // summary:
  13285. // Disconnects handle created by `connect`.
  13286. // Also removes handle from this widget's list of connects.
  13287. // tags:
  13288. // protected
  13289. var i = array.indexOf(this._connects, handle);
  13290. if(i != -1){
  13291. handle.remove();
  13292. this._connects.splice(i, 1);
  13293. }
  13294. },
  13295. subscribe: function(t, method){
  13296. // summary:
  13297. // Subscribes to the specified topic and calls the specified method
  13298. // of this object and registers for unsubscribe() on widget destroy.
  13299. // description:
  13300. // Provide widget-specific analog to dojo.subscribe, except with the
  13301. // implicit use of this widget as the target object.
  13302. // t: String
  13303. // The topic
  13304. // method: Function
  13305. // The callback
  13306. // example:
  13307. // | var btn = new dijit.form.Button();
  13308. // | // when /my/topic is published, this button changes its label to
  13309. // | // be the parameter of the topic.
  13310. // | btn.subscribe("/my/topic", function(v){
  13311. // | this.set("label", v);
  13312. // | });
  13313. // tags:
  13314. // protected
  13315. var handle = topic.subscribe(t, lang.hitch(this, method));
  13316. this._connects.push(handle);
  13317. return handle; // _Widget.Handle
  13318. },
  13319. unsubscribe: function(/*Object*/ handle){
  13320. // summary:
  13321. // Unsubscribes handle created by this.subscribe.
  13322. // Also removes handle from this widget's list of subscriptions
  13323. // tags:
  13324. // protected
  13325. this.disconnect(handle);
  13326. },
  13327. isLeftToRight: function(){
  13328. // summary:
  13329. // Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
  13330. // tags:
  13331. // protected
  13332. return this.dir ? (this.dir == "ltr") : domGeometry.isBodyLtr(); //Boolean
  13333. },
  13334. isFocusable: function(){
  13335. // summary:
  13336. // Return true if this widget can currently be focused
  13337. // and false if not
  13338. return this.focus && (domStyle.get(this.domNode, "display") != "none");
  13339. },
  13340. placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
  13341. // summary:
  13342. // Place this widget's domNode reference somewhere in the DOM based
  13343. // on standard domConstruct.place conventions, or passing a Widget reference that
  13344. // contains and addChild member.
  13345. //
  13346. // description:
  13347. // A convenience function provided in all _Widgets, providing a simple
  13348. // shorthand mechanism to put an existing (or newly created) Widget
  13349. // somewhere in the dom, and allow chaining.
  13350. //
  13351. // reference:
  13352. // The String id of a domNode, a domNode reference, or a reference to a Widget possessing
  13353. // an addChild method.
  13354. //
  13355. // position:
  13356. // If passed a string or domNode reference, the position argument
  13357. // accepts a string just as domConstruct.place does, one of: "first", "last",
  13358. // "before", or "after".
  13359. //
  13360. // If passed a _Widget reference, and that widget reference has an ".addChild" method,
  13361. // it will be called passing this widget instance into that method, supplying the optional
  13362. // position index passed.
  13363. //
  13364. // returns:
  13365. // dijit._Widget
  13366. // Provides a useful return of the newly created dijit._Widget instance so you
  13367. // can "chain" this function by instantiating, placing, then saving the return value
  13368. // to a variable.
  13369. //
  13370. // example:
  13371. // | // create a Button with no srcNodeRef, and place it in the body:
  13372. // | var button = new dijit.form.Button({ label:"click" }).placeAt(win.body());
  13373. // | // now, 'button' is still the widget reference to the newly created button
  13374. // | button.on("click", function(e){ console.log('click'); }));
  13375. //
  13376. // example:
  13377. // | // create a button out of a node with id="src" and append it to id="wrapper":
  13378. // | var button = new dijit.form.Button({},"src").placeAt("wrapper");
  13379. //
  13380. // example:
  13381. // | // place a new button as the first element of some div
  13382. // | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
  13383. //
  13384. // example:
  13385. // | // create a contentpane and add it to a TabContainer
  13386. // | var tc = dijit.byId("myTabs");
  13387. // | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
  13388. if(reference.declaredClass && reference.addChild){
  13389. reference.addChild(this, position);
  13390. }else{
  13391. domConstruct.place(this.domNode, reference, position);
  13392. }
  13393. return this;
  13394. },
  13395. getTextDir: function(/*String*/ text,/*String*/ originalDir){
  13396. // summary:
  13397. // Return direction of the text.
  13398. // The function overridden in the _BidiSupport module,
  13399. // its main purpose is to calculate the direction of the
  13400. // text, if was defined by the programmer through textDir.
  13401. // tags:
  13402. // protected.
  13403. return originalDir;
  13404. },
  13405. applyTextDir: function(/*===== element, text =====*/){
  13406. // summary:
  13407. // The function overridden in the _BidiSupport module,
  13408. // originally used for setting element.dir according to this.textDir.
  13409. // In this case does nothing.
  13410. // element: DOMNode
  13411. // text: String
  13412. // tags:
  13413. // protected.
  13414. },
  13415. defer: function(fcn, delay){
  13416. // summary:
  13417. // Wrapper to setTimeout to avoid deferred functions executing
  13418. // after the originating widget has been destroyed.
  13419. // Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
  13420. // fcn: function reference
  13421. // delay: Optional number (defaults to 0)
  13422. // tags:
  13423. // protected.
  13424. var timer = setTimeout(lang.hitch(this,
  13425. function(){
  13426. if(!timer){ return; }
  13427. timer = null;
  13428. if(!this._destroyed){
  13429. lang.hitch(this, fcn)();
  13430. }
  13431. }),
  13432. delay || 0
  13433. );
  13434. return {
  13435. remove: function(){
  13436. if(timer){
  13437. clearTimeout(timer);
  13438. timer = null;
  13439. }
  13440. return null; // so this works well: handle = handle.remove();
  13441. }
  13442. };
  13443. }
  13444. });
  13445. });
  13446. },
  13447. 'dijit/layout/_TabContainerBase':function(){
  13448. require({cache:{
  13449. 'url:dijit/layout/templates/TabContainer.html':"<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" data-dojo-attach-point=\"tablistNode\"></div>\n\t<div data-dojo-attach-point=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" data-dojo-attach-point=\"containerNode\"></div>\n</div>\n"}});
  13450. define("dijit/layout/_TabContainerBase", [
  13451. "dojo/text!./templates/TabContainer.html",
  13452. "./StackContainer",
  13453. "./utils", // marginBox2contextBox, layoutChildren
  13454. "../_TemplatedMixin",
  13455. "dojo/_base/declare", // declare
  13456. "dojo/dom-class", // domClass.add
  13457. "dojo/dom-geometry", // domGeometry.contentBox
  13458. "dojo/dom-style" // domStyle.style
  13459. ], function(template, StackContainer, layoutUtils, _TemplatedMixin, declare, domClass, domGeometry, domStyle){
  13460. /*=====
  13461. var StackContainer = dijit.layout.StackContainer;
  13462. var _TemplatedMixin = dijit._TemplatedMixin;
  13463. =====*/
  13464. // module:
  13465. // dijit/layout/_TabContainerBase
  13466. // summary:
  13467. // Abstract base class for TabContainer. Must define _makeController() to instantiate
  13468. // and return the widget that displays the tab labels
  13469. return declare("dijit.layout._TabContainerBase", [StackContainer, _TemplatedMixin], {
  13470. // summary:
  13471. // Abstract base class for TabContainer. Must define _makeController() to instantiate
  13472. // and return the widget that displays the tab labels
  13473. // description:
  13474. // A TabContainer is a container that has multiple panes, but shows only
  13475. // one pane at a time. There are a set of tabs corresponding to each pane,
  13476. // where each tab has the name (aka title) of the pane, and optionally a close button.
  13477. // tabPosition: String
  13478. // Defines where tabs go relative to tab content.
  13479. // "top", "bottom", "left-h", "right-h"
  13480. tabPosition: "top",
  13481. baseClass: "dijitTabContainer",
  13482. // tabStrip: [const] Boolean
  13483. // Defines whether the tablist gets an extra class for layouting, putting a border/shading
  13484. // around the set of tabs. Not supported by claro theme.
  13485. tabStrip: false,
  13486. // nested: [const] Boolean
  13487. // If true, use styling for a TabContainer nested inside another TabContainer.
  13488. // For tundra etc., makes tabs look like links, and hides the outer
  13489. // border since the outer TabContainer already has a border.
  13490. nested: false,
  13491. templateString: template,
  13492. postMixInProperties: function(){
  13493. // set class name according to tab position, ex: dijitTabContainerTop
  13494. this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, "");
  13495. this.srcNodeRef && domStyle.set(this.srcNodeRef, "visibility", "hidden");
  13496. this.inherited(arguments);
  13497. },
  13498. buildRendering: function(){
  13499. this.inherited(arguments);
  13500. // Create the tab list that will have a tab (a.k.a. tab button) for each tab panel
  13501. this.tablist = this._makeController(this.tablistNode);
  13502. if(!this.doLayout){ domClass.add(this.domNode, "dijitTabContainerNoLayout"); }
  13503. if(this.nested){
  13504. /* workaround IE's lack of support for "a > b" selectors by
  13505. * tagging each node in the template.
  13506. */
  13507. domClass.add(this.domNode, "dijitTabContainerNested");
  13508. domClass.add(this.tablist.containerNode, "dijitTabContainerTabListNested");
  13509. domClass.add(this.tablistSpacer, "dijitTabContainerSpacerNested");
  13510. domClass.add(this.containerNode, "dijitTabPaneWrapperNested");
  13511. }else{
  13512. domClass.add(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled"));
  13513. }
  13514. },
  13515. _setupChild: function(/*dijit._Widget*/ tab){
  13516. // Overrides StackContainer._setupChild().
  13517. domClass.add(tab.domNode, "dijitTabPane");
  13518. this.inherited(arguments);
  13519. },
  13520. startup: function(){
  13521. if(this._started){ return; }
  13522. // wire up the tablist and its tabs
  13523. this.tablist.startup();
  13524. this.inherited(arguments);
  13525. },
  13526. layout: function(){
  13527. // Overrides StackContainer.layout().
  13528. // Configure the content pane to take up all the space except for where the tabs are
  13529. if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){return;}
  13530. var sc = this.selectedChildWidget;
  13531. if(this.doLayout){
  13532. // position and size the titles and the container node
  13533. var titleAlign = this.tabPosition.replace(/-h/, "");
  13534. this.tablist.layoutAlign = titleAlign;
  13535. var children = [this.tablist, {
  13536. domNode: this.tablistSpacer,
  13537. layoutAlign: titleAlign
  13538. }, {
  13539. domNode: this.containerNode,
  13540. layoutAlign: "client"
  13541. }];
  13542. layoutUtils.layoutChildren(this.domNode, this._contentBox, children);
  13543. // Compute size to make each of my children.
  13544. // children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above
  13545. this._containerContentBox = layoutUtils.marginBox2contentBox(this.containerNode, children[2]);
  13546. if(sc && sc.resize){
  13547. sc.resize(this._containerContentBox);
  13548. }
  13549. }else{
  13550. // just layout the tab controller, so it can position left/right buttons etc.
  13551. if(this.tablist.resize){
  13552. //make the tabs zero width so that they don't interfere with width calc, then reset
  13553. var s = this.tablist.domNode.style;
  13554. s.width="0";
  13555. var width = domGeometry.getContentBox(this.domNode).w;
  13556. s.width="";
  13557. this.tablist.resize({w: width});
  13558. }
  13559. // and call resize() on the selected pane just to tell it that it's been made visible
  13560. if(sc && sc.resize){
  13561. sc.resize();
  13562. }
  13563. }
  13564. },
  13565. destroy: function(){
  13566. if(this.tablist){
  13567. this.tablist.destroy();
  13568. }
  13569. this.inherited(arguments);
  13570. }
  13571. });
  13572. });
  13573. },
  13574. 'dojox/fx/_core':function(){
  13575. define("dojox/fx/_core", ["dojo/_base/lang", "dojo/_base/array","./_base"],
  13576. function(lang, arrayUtil, dojoxFx){
  13577. /*===== var dojox.fx._Line = line =====*/
  13578. var line = function(start, end){
  13579. // summary: a custom _Line to accomodate multi-dimensional values
  13580. //
  13581. // description:
  13582. // a normal dojo._Line is the curve, and does Line(start,end)
  13583. // for propertyAnimation. as we make more complicatied animations, we realize
  13584. // some properties can have 2, or 4 values relevant (x,y) or (t,l,r,b) for example
  13585. //
  13586. // this function provides support for those Lines, and is ported directly from 0.4
  13587. // this is a lot of extra code for something so seldom used, so we'll put it here as
  13588. // and optional core addition. you can create a new line, and use it during onAnimate
  13589. // as you see fit.
  13590. //
  13591. // start: Integer|Array
  13592. // An Integer (or an Array of integers) to use as a starting point
  13593. // end: Integer|Array
  13594. // An Integer (or an Array of integers) to use as an ending point
  13595. //
  13596. // example: see dojox.fx.smoothScroll
  13597. //
  13598. // example:
  13599. // | // this is 10 .. 100 and 50 .. 500
  13600. // | var curve = new dojox.fx._Line([10,50],[100,500]);
  13601. // | // dojo.Animation.onAnimate is called at every step of the animation
  13602. // | // to define current values. this _Line returns an array
  13603. // | // at each step. arguments[0] and [1] in this example.
  13604. //
  13605. this.start = start;
  13606. this.end = end;
  13607. var isArray = lang.isArray(start),
  13608. d = (isArray ? [] : end - start);
  13609. if(isArray){
  13610. // multi-dimensional branch
  13611. arrayUtil.forEach(this.start, function(s, i){
  13612. d[i] = this.end[i] - s;
  13613. }, this);
  13614. this.getValue = function(/*float*/ n){
  13615. var res = [];
  13616. arrayUtil.forEach(this.start, function(s, i){
  13617. res[i] = (d[i] * n) + s;
  13618. }, this);
  13619. return res; // Array
  13620. }
  13621. }else{
  13622. // single value branch, document here for both branches:
  13623. this.getValue = function(/*float*/ n){
  13624. // summary: Returns the point on the line, or an array of points
  13625. // n: a floating point number greater than 0 and less than 1
  13626. // returns: Mixed
  13627. return (d * n) + this.start; // Decimal
  13628. }
  13629. }
  13630. };
  13631. dojoxFx._Line = line; // COMPAT
  13632. return line;
  13633. });
  13634. },
  13635. 'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\n></div>\n",
  13636. 'dijit/_base/sniff':function(){
  13637. define("dijit/_base/sniff", [ "dojo/uacss" ], function(){
  13638. // module:
  13639. // dijit/_base/sniff
  13640. // summary:
  13641. // Back compatibility module, new code should require dojo/uacss directly instead of this module.
  13642. });
  13643. },
  13644. 'dojox/uuid/generateRandomUuid':function(){
  13645. define("dojox/uuid/generateRandomUuid", ['./_base'], function(){
  13646. dojox.uuid.generateRandomUuid = function(){
  13647. // summary:
  13648. // This function generates random UUIDs, meaning "version 4" UUIDs.
  13649. // description:
  13650. // A typical generated value would be something like this:
  13651. // "3b12f1df-5232-4804-897e-917bf397618a"
  13652. //
  13653. // For more information about random UUIDs, see sections 4.4 and
  13654. // 4.5 of RFC 4122: http://tools.ietf.org/html/rfc4122#section-4.4
  13655. //
  13656. // This generator function is designed to be small and fast,
  13657. // but not necessarily good.
  13658. //
  13659. // Small: This generator has a small footprint. Once comments are
  13660. // stripped, it's only about 25 lines of code, and it doesn't
  13661. // dojo.require() any other modules.
  13662. //
  13663. // Fast: This generator can generate lots of new UUIDs fairly quickly
  13664. // (at least, more quickly than the other dojo UUID generators).
  13665. //
  13666. // Not necessarily good: We use Math.random() as our source
  13667. // of randomness, which may or may not provide much randomness.
  13668. // examples:
  13669. // var string = dojox.uuid.generateRandomUuid();
  13670. var HEX_RADIX = 16;
  13671. function _generateRandomEightCharacterHexString(){
  13672. // Make random32bitNumber be a randomly generated floating point number
  13673. // between 0 and (4,294,967,296 - 1), inclusive.
  13674. var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
  13675. var eightCharacterHexString = random32bitNumber.toString(HEX_RADIX);
  13676. while(eightCharacterHexString.length < 8){
  13677. eightCharacterHexString = "0" + eightCharacterHexString;
  13678. }
  13679. return eightCharacterHexString; // for example: "3B12F1DF"
  13680. }
  13681. var hyphen = "-";
  13682. var versionCodeForRandomlyGeneratedUuids = "4"; // 8 == binary2hex("0100")
  13683. var variantCodeForDCEUuids = "8"; // 8 == binary2hex("1000")
  13684. var a = _generateRandomEightCharacterHexString();
  13685. var b = _generateRandomEightCharacterHexString();
  13686. b = b.substring(0, 4) + hyphen + versionCodeForRandomlyGeneratedUuids + b.substring(5, 8);
  13687. var c = _generateRandomEightCharacterHexString();
  13688. c = variantCodeForDCEUuids + c.substring(1, 4) + hyphen + c.substring(4, 8);
  13689. var d = _generateRandomEightCharacterHexString();
  13690. var returnValue = a + hyphen + b + hyphen + c + d;
  13691. returnValue = returnValue.toLowerCase();
  13692. return returnValue; // String
  13693. };
  13694. return dojox.uuid.generateRandomUuid;
  13695. });
  13696. },
  13697. 'dijit/Toolbar':function(){
  13698. define("dijit/Toolbar", [
  13699. "require",
  13700. "dojo/_base/declare", // declare
  13701. "dojo/_base/kernel",
  13702. "dojo/keys", // keys.LEFT_ARROW keys.RIGHT_ARROW
  13703. "dojo/ready",
  13704. "./_Widget",
  13705. "./_KeyNavContainer",
  13706. "./_TemplatedMixin"
  13707. ], function(require, declare, kernel, keys, ready, _Widget, _KeyNavContainer, _TemplatedMixin){
  13708. /*=====
  13709. var _Widget = dijit._Widget;
  13710. var _KeyNavContainer = dijit._KeyNavContainer;
  13711. var _TemplatedMixin = dijit._TemplatedMixin;
  13712. =====*/
  13713. // module:
  13714. // dijit/Toolbar
  13715. // summary:
  13716. // A Toolbar widget, used to hold things like `dijit.Editor` buttons
  13717. // Back compat w/1.6, remove for 2.0
  13718. if(!kernel.isAsync){
  13719. ready(0, function(){
  13720. var requires = ["dijit/ToolbarSeparator"];
  13721. require(requires); // use indirection so modules not rolled into a build
  13722. });
  13723. }
  13724. return declare("dijit.Toolbar", [_Widget, _TemplatedMixin, _KeyNavContainer], {
  13725. // summary:
  13726. // A Toolbar widget, used to hold things like `dijit.Editor` buttons
  13727. templateString:
  13728. '<div class="dijit" role="toolbar" tabIndex="${tabIndex}" data-dojo-attach-point="containerNode">' +
  13729. '</div>',
  13730. baseClass: "dijitToolbar",
  13731. postCreate: function(){
  13732. this.inherited(arguments);
  13733. this.connectKeyNavHandlers(
  13734. this.isLeftToRight() ? [keys.LEFT_ARROW] : [keys.RIGHT_ARROW],
  13735. this.isLeftToRight() ? [keys.RIGHT_ARROW] : [keys.LEFT_ARROW]
  13736. );
  13737. }
  13738. });
  13739. });
  13740. },
  13741. 'dojo/fx/easing':function(){
  13742. define("dojo/fx/easing", ["../_base/lang"], function(lang) {
  13743. // module:
  13744. // dojo/fx/easing
  13745. // summary:
  13746. // This module defines standard easing functions that are useful for animations.
  13747. var easingFuncs = /*===== dojo.fx.easing= =====*/ {
  13748. // summary:
  13749. // Collection of easing functions to use beyond the default
  13750. // `dojo._defaultEasing` function.
  13751. //
  13752. // description:
  13753. //
  13754. // Easing functions are used to manipulate the iteration through
  13755. // an `dojo.Animation`s _Line. _Line being the properties of an Animation,
  13756. // and the easing function progresses through that Line determing
  13757. // how quickly (or slowly) it should go. Or more accurately: modify
  13758. // the value of the _Line based on the percentage of animation completed.
  13759. //
  13760. // All functions follow a simple naming convention of "ease type" + "when".
  13761. // If the name of the function ends in Out, the easing described appears
  13762. // towards the end of the animation. "In" means during the beginning,
  13763. // and InOut means both ranges of the Animation will applied, both
  13764. // beginning and end.
  13765. //
  13766. // One does not call the easing function directly, it must be passed to
  13767. // the `easing` property of an animation.
  13768. //
  13769. // example:
  13770. // | dojo.require("dojo.fx.easing");
  13771. // | var anim = dojo.fadeOut({
  13772. // | node: 'node',
  13773. // | duration: 2000,
  13774. // | // note there is no ()
  13775. // | easing: dojo.fx.easing.quadIn
  13776. // | }).play();
  13777. //
  13778. linear: function(/* Decimal? */n){
  13779. // summary: A linear easing function
  13780. return n;
  13781. },
  13782. quadIn: function(/* Decimal? */n){
  13783. return Math.pow(n, 2);
  13784. },
  13785. quadOut: function(/* Decimal? */n){
  13786. return n * (n - 2) * -1;
  13787. },
  13788. quadInOut: function(/* Decimal? */n){
  13789. n = n * 2;
  13790. if(n < 1){ return Math.pow(n, 2) / 2; }
  13791. return -1 * ((--n) * (n - 2) - 1) / 2;
  13792. },
  13793. cubicIn: function(/* Decimal? */n){
  13794. return Math.pow(n, 3);
  13795. },
  13796. cubicOut: function(/* Decimal? */n){
  13797. return Math.pow(n - 1, 3) + 1;
  13798. },
  13799. cubicInOut: function(/* Decimal? */n){
  13800. n = n * 2;
  13801. if(n < 1){ return Math.pow(n, 3) / 2; }
  13802. n -= 2;
  13803. return (Math.pow(n, 3) + 2) / 2;
  13804. },
  13805. quartIn: function(/* Decimal? */n){
  13806. return Math.pow(n, 4);
  13807. },
  13808. quartOut: function(/* Decimal? */n){
  13809. return -1 * (Math.pow(n - 1, 4) - 1);
  13810. },
  13811. quartInOut: function(/* Decimal? */n){
  13812. n = n * 2;
  13813. if(n < 1){ return Math.pow(n, 4) / 2; }
  13814. n -= 2;
  13815. return -1 / 2 * (Math.pow(n, 4) - 2);
  13816. },
  13817. quintIn: function(/* Decimal? */n){
  13818. return Math.pow(n, 5);
  13819. },
  13820. quintOut: function(/* Decimal? */n){
  13821. return Math.pow(n - 1, 5) + 1;
  13822. },
  13823. quintInOut: function(/* Decimal? */n){
  13824. n = n * 2;
  13825. if(n < 1){ return Math.pow(n, 5) / 2; }
  13826. n -= 2;
  13827. return (Math.pow(n, 5) + 2) / 2;
  13828. },
  13829. sineIn: function(/* Decimal? */n){
  13830. return -1 * Math.cos(n * (Math.PI / 2)) + 1;
  13831. },
  13832. sineOut: function(/* Decimal? */n){
  13833. return Math.sin(n * (Math.PI / 2));
  13834. },
  13835. sineInOut: function(/* Decimal? */n){
  13836. return -1 * (Math.cos(Math.PI * n) - 1) / 2;
  13837. },
  13838. expoIn: function(/* Decimal? */n){
  13839. return (n == 0) ? 0 : Math.pow(2, 10 * (n - 1));
  13840. },
  13841. expoOut: function(/* Decimal? */n){
  13842. return (n == 1) ? 1 : (-1 * Math.pow(2, -10 * n) + 1);
  13843. },
  13844. expoInOut: function(/* Decimal? */n){
  13845. if(n == 0){ return 0; }
  13846. if(n == 1){ return 1; }
  13847. n = n * 2;
  13848. if(n < 1){ return Math.pow(2, 10 * (n - 1)) / 2; }
  13849. --n;
  13850. return (-1 * Math.pow(2, -10 * n) + 2) / 2;
  13851. },
  13852. circIn: function(/* Decimal? */n){
  13853. return -1 * (Math.sqrt(1 - Math.pow(n, 2)) - 1);
  13854. },
  13855. circOut: function(/* Decimal? */n){
  13856. n = n - 1;
  13857. return Math.sqrt(1 - Math.pow(n, 2));
  13858. },
  13859. circInOut: function(/* Decimal? */n){
  13860. n = n * 2;
  13861. if(n < 1){ return -1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) - 1); }
  13862. n -= 2;
  13863. return 1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) + 1);
  13864. },
  13865. backIn: function(/* Decimal? */n){
  13866. // summary:
  13867. // An easing function that starts away from the target,
  13868. // and quickly accelerates towards the end value.
  13869. //
  13870. // Use caution when the easing will cause values to become
  13871. // negative as some properties cannot be set to negative values.
  13872. var s = 1.70158;
  13873. return Math.pow(n, 2) * ((s + 1) * n - s);
  13874. },
  13875. backOut: function(/* Decimal? */n){
  13876. // summary:
  13877. // An easing function that pops past the range briefly, and slowly comes back.
  13878. //
  13879. // description:
  13880. // An easing function that pops past the range briefly, and slowly comes back.
  13881. //
  13882. // Use caution when the easing will cause values to become negative as some
  13883. // properties cannot be set to negative values.
  13884. n = n - 1;
  13885. var s = 1.70158;
  13886. return Math.pow(n, 2) * ((s + 1) * n + s) + 1;
  13887. },
  13888. backInOut: function(/* Decimal? */n){
  13889. // summary:
  13890. // An easing function combining the effects of `backIn` and `backOut`
  13891. //
  13892. // description:
  13893. // An easing function combining the effects of `backIn` and `backOut`.
  13894. // Use caution when the easing will cause values to become negative
  13895. // as some properties cannot be set to negative values.
  13896. var s = 1.70158 * 1.525;
  13897. n = n * 2;
  13898. if(n < 1){ return (Math.pow(n, 2) * ((s + 1) * n - s)) / 2; }
  13899. n-=2;
  13900. return (Math.pow(n, 2) * ((s + 1) * n + s) + 2) / 2;
  13901. },
  13902. elasticIn: function(/* Decimal? */n){
  13903. // summary:
  13904. // An easing function the elastically snaps from the start value
  13905. //
  13906. // description:
  13907. // An easing function the elastically snaps from the start value
  13908. //
  13909. // Use caution when the elasticity will cause values to become negative
  13910. // as some properties cannot be set to negative values.
  13911. if(n == 0 || n == 1){ return n; }
  13912. var p = .3;
  13913. var s = p / 4;
  13914. n = n - 1;
  13915. return -1 * Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p);
  13916. },
  13917. elasticOut: function(/* Decimal? */n){
  13918. // summary:
  13919. // An easing function that elasticly snaps around the target value,
  13920. // near the end of the Animation
  13921. //
  13922. // description:
  13923. // An easing function that elasticly snaps around the target value,
  13924. // near the end of the Animation
  13925. //
  13926. // Use caution when the elasticity will cause values to become
  13927. // negative as some properties cannot be set to negative values.
  13928. if(n==0 || n == 1){ return n; }
  13929. var p = .3;
  13930. var s = p / 4;
  13931. return Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p) + 1;
  13932. },
  13933. elasticInOut: function(/* Decimal? */n){
  13934. // summary:
  13935. // An easing function that elasticly snaps around the value, near
  13936. // the beginning and end of the Animation.
  13937. //
  13938. // description:
  13939. // An easing function that elasticly snaps around the value, near
  13940. // the beginning and end of the Animation.
  13941. //
  13942. // Use caution when the elasticity will cause values to become
  13943. // negative as some properties cannot be set to negative values.
  13944. if(n == 0) return 0;
  13945. n = n * 2;
  13946. if(n == 2) return 1;
  13947. var p = .3 * 1.5;
  13948. var s = p / 4;
  13949. if(n < 1){
  13950. n -= 1;
  13951. return -.5 * (Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p));
  13952. }
  13953. n -= 1;
  13954. return .5 * (Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p)) + 1;
  13955. },
  13956. bounceIn: function(/* Decimal? */n){
  13957. // summary:
  13958. // An easing function that 'bounces' near the beginning of an Animation
  13959. return (1 - easingFuncs.bounceOut(1 - n)); // Decimal
  13960. },
  13961. bounceOut: function(/* Decimal? */n){
  13962. // summary:
  13963. // An easing function that 'bounces' near the end of an Animation
  13964. var s = 7.5625;
  13965. var p = 2.75;
  13966. var l;
  13967. if(n < (1 / p)){
  13968. l = s * Math.pow(n, 2);
  13969. }else if(n < (2 / p)){
  13970. n -= (1.5 / p);
  13971. l = s * Math.pow(n, 2) + .75;
  13972. }else if(n < (2.5 / p)){
  13973. n -= (2.25 / p);
  13974. l = s * Math.pow(n, 2) + .9375;
  13975. }else{
  13976. n -= (2.625 / p);
  13977. l = s * Math.pow(n, 2) + .984375;
  13978. }
  13979. return l;
  13980. },
  13981. bounceInOut: function(/* Decimal? */n){
  13982. // summary:
  13983. // An easing function that 'bounces' at the beginning and end of the Animation
  13984. if(n < 0.5){ return easingFuncs.bounceIn(n * 2) / 2; }
  13985. return (easingFuncs.bounceOut(n * 2 - 1) / 2) + 0.5; // Decimal
  13986. }
  13987. };
  13988. lang.setObject("dojo.fx.easing", easingFuncs);
  13989. return easingFuncs;
  13990. });
  13991. },
  13992. 'dijit/layout/StackContainer':function(){
  13993. define("dijit/layout/StackContainer", [
  13994. "dojo/_base/array", // array.forEach array.indexOf array.some
  13995. "dojo/cookie", // cookie
  13996. "dojo/_base/declare", // declare
  13997. "dojo/dom-class", // domClass.add domClass.replace
  13998. "dojo/_base/kernel", // kernel.isAsync
  13999. "dojo/_base/lang", // lang.extend
  14000. "dojo/ready",
  14001. "dojo/topic", // publish
  14002. "../registry", // registry.byId
  14003. "../_WidgetBase",
  14004. "./_LayoutWidget",
  14005. "dojo/i18n!../nls/common"
  14006. ], function(array, cookie, declare, domClass, kernel, lang, ready, topic,
  14007. registry, _WidgetBase, _LayoutWidget){
  14008. /*=====
  14009. var _WidgetBase = dijit._WidgetBase;
  14010. var _LayoutWidget = dijit.layout._LayoutWidget;
  14011. var StackController = dijit.layout.StackController;
  14012. =====*/
  14013. // module:
  14014. // dijit/layout/StackContainer
  14015. // summary:
  14016. // A container that has multiple children, but shows only one child at a time.
  14017. // Back compat w/1.6, remove for 2.0
  14018. if(!kernel.isAsync){
  14019. ready(0, function(){
  14020. var requires = ["dijit/layout/StackController"];
  14021. require(requires); // use indirection so modules not rolled into a build
  14022. });
  14023. }
  14024. // These arguments can be specified for the children of a StackContainer.
  14025. // Since any widget can be specified as a StackContainer child, mix them
  14026. // into the base widget class. (This is a hack, but it's effective.)
  14027. lang.extend(_WidgetBase, {
  14028. // selected: Boolean
  14029. // Parameter for children of `dijit.layout.StackContainer` or subclasses.
  14030. // Specifies that this widget should be the initially displayed pane.
  14031. // Note: to change the selected child use `dijit.layout.StackContainer.selectChild`
  14032. selected: false,
  14033. // closable: Boolean
  14034. // Parameter for children of `dijit.layout.StackContainer` or subclasses.
  14035. // True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
  14036. closable: false,
  14037. // iconClass: String
  14038. // Parameter for children of `dijit.layout.StackContainer` or subclasses.
  14039. // CSS Class specifying icon to use in label associated with this pane.
  14040. iconClass: "dijitNoIcon",
  14041. // showTitle: Boolean
  14042. // Parameter for children of `dijit.layout.StackContainer` or subclasses.
  14043. // When true, display title of this widget as tab label etc., rather than just using
  14044. // icon specified in iconClass
  14045. showTitle: true
  14046. });
  14047. return declare("dijit.layout.StackContainer", _LayoutWidget, {
  14048. // summary:
  14049. // A container that has multiple children, but shows only
  14050. // one child at a time
  14051. //
  14052. // description:
  14053. // A container for widgets (ContentPanes, for example) That displays
  14054. // only one Widget at a time.
  14055. //
  14056. // Publishes topics [widgetId]-addChild, [widgetId]-removeChild, and [widgetId]-selectChild
  14057. //
  14058. // Can be base class for container, Wizard, Show, etc.
  14059. // doLayout: Boolean
  14060. // If true, change the size of my currently displayed child to match my size
  14061. doLayout: true,
  14062. // persist: Boolean
  14063. // Remembers the selected child across sessions
  14064. persist: false,
  14065. baseClass: "dijitStackContainer",
  14066. /*=====
  14067. // selectedChildWidget: [readonly] dijit._Widget
  14068. // References the currently selected child widget, if any.
  14069. // Adjust selected child with selectChild() method.
  14070. selectedChildWidget: null,
  14071. =====*/
  14072. buildRendering: function(){
  14073. this.inherited(arguments);
  14074. domClass.add(this.domNode, "dijitLayoutContainer");
  14075. this.containerNode.setAttribute("role", "tabpanel");
  14076. },
  14077. postCreate: function(){
  14078. this.inherited(arguments);
  14079. this.connect(this.domNode, "onkeypress", this._onKeyPress);
  14080. },
  14081. startup: function(){
  14082. if(this._started){ return; }
  14083. var children = this.getChildren();
  14084. // Setup each page panel to be initially hidden
  14085. array.forEach(children, this._setupChild, this);
  14086. // Figure out which child to initially display, defaulting to first one
  14087. if(this.persist){
  14088. this.selectedChildWidget = registry.byId(cookie(this.id + "_selectedChild"));
  14089. }else{
  14090. array.some(children, function(child){
  14091. if(child.selected){
  14092. this.selectedChildWidget = child;
  14093. }
  14094. return child.selected;
  14095. }, this);
  14096. }
  14097. var selected = this.selectedChildWidget;
  14098. if(!selected && children[0]){
  14099. selected = this.selectedChildWidget = children[0];
  14100. selected.selected = true;
  14101. }
  14102. // Publish information about myself so any StackControllers can initialize.
  14103. // This needs to happen before this.inherited(arguments) so that for
  14104. // TabContainer, this._contentBox doesn't include the space for the tab labels.
  14105. topic.publish(this.id+"-startup", {children: children, selected: selected});
  14106. // Startup each child widget, and do initial layout like setting this._contentBox,
  14107. // then calls this.resize() which does the initial sizing on the selected child.
  14108. this.inherited(arguments);
  14109. },
  14110. resize: function(){
  14111. // Resize is called when we are first made visible (it's called from startup()
  14112. // if we are initially visible). If this is the first time we've been made
  14113. // visible then show our first child.
  14114. if(!this._hasBeenShown){
  14115. this._hasBeenShown = true;
  14116. var selected = this.selectedChildWidget;
  14117. if(selected){
  14118. this._showChild(selected);
  14119. }
  14120. }
  14121. this.inherited(arguments);
  14122. },
  14123. _setupChild: function(/*dijit._Widget*/ child){
  14124. // Overrides _LayoutWidget._setupChild()
  14125. this.inherited(arguments);
  14126. domClass.replace(child.domNode, "dijitHidden", "dijitVisible");
  14127. // remove the title attribute so it doesn't show up when i hover
  14128. // over a node
  14129. child.domNode.title = "";
  14130. },
  14131. addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
  14132. // Overrides _Container.addChild() to do layout and publish events
  14133. this.inherited(arguments);
  14134. if(this._started){
  14135. topic.publish(this.id+"-addChild", child, insertIndex); // publish
  14136. // in case the tab titles have overflowed from one line to two lines
  14137. // (or, if this if first child, from zero lines to one line)
  14138. // TODO: w/ScrollingTabController this is no longer necessary, although
  14139. // ScrollTabController.resize() does need to get called to show/hide
  14140. // the navigation buttons as appropriate, but that's handled in ScrollingTabController.onAddChild().
  14141. // If this is updated to not layout [except for initial child added / last child removed], update
  14142. // "childless startup" test in StackContainer.html to check for no resize event after second addChild()
  14143. this.layout();
  14144. // if this is the first child, then select it
  14145. if(!this.selectedChildWidget){
  14146. this.selectChild(child);
  14147. }
  14148. }
  14149. },
  14150. removeChild: function(/*dijit._Widget*/ page){
  14151. // Overrides _Container.removeChild() to do layout and publish events
  14152. this.inherited(arguments);
  14153. if(this._started){
  14154. // this will notify any tablists to remove a button; do this first because it may affect sizing
  14155. topic.publish(this.id + "-removeChild", page); // publish
  14156. }
  14157. // If all our children are being destroyed than don't run the code below (to select another page),
  14158. // because we are deleting every page one by one
  14159. if(this._descendantsBeingDestroyed){ return; }
  14160. // Select new page to display, also updating TabController to show the respective tab.
  14161. // Do this before layout call because it can affect the height of the TabController.
  14162. if(this.selectedChildWidget === page){
  14163. this.selectedChildWidget = undefined;
  14164. if(this._started){
  14165. var children = this.getChildren();
  14166. if(children.length){
  14167. this.selectChild(children[0]);
  14168. }
  14169. }
  14170. }
  14171. if(this._started){
  14172. // In case the tab titles now take up one line instead of two lines
  14173. // (note though that ScrollingTabController never overflows to multiple lines),
  14174. // or the height has changed slightly because of addition/removal of tab which close icon
  14175. this.layout();
  14176. }
  14177. },
  14178. selectChild: function(/*dijit._Widget|String*/ page, /*Boolean*/ animate){
  14179. // summary:
  14180. // Show the given widget (which must be one of my children)
  14181. // page:
  14182. // Reference to child widget or id of child widget
  14183. page = registry.byId(page);
  14184. if(this.selectedChildWidget != page){
  14185. // Deselect old page and select new one
  14186. var d = this._transition(page, this.selectedChildWidget, animate);
  14187. this._set("selectedChildWidget", page);
  14188. topic.publish(this.id+"-selectChild", page); // publish
  14189. if(this.persist){
  14190. cookie(this.id + "_selectedChild", this.selectedChildWidget.id);
  14191. }
  14192. }
  14193. return d; // If child has an href, promise that fires when the child's href finishes loading
  14194. },
  14195. _transition: function(newWidget, oldWidget /*===== , animate =====*/){
  14196. // summary:
  14197. // Hide the old widget and display the new widget.
  14198. // Subclasses should override this.
  14199. // newWidget: dijit._Widget
  14200. // The newly selected widget.
  14201. // oldWidget: dijit._Widget
  14202. // The previously selected widget.
  14203. // animate: Boolean
  14204. // Used by AccordionContainer to turn on/off slide effect.
  14205. // tags:
  14206. // protected extension
  14207. if(oldWidget){
  14208. this._hideChild(oldWidget);
  14209. }
  14210. var d = this._showChild(newWidget);
  14211. // Size the new widget, in case this is the first time it's being shown,
  14212. // or I have been resized since the last time it was shown.
  14213. // Note that page must be visible for resizing to work.
  14214. if(newWidget.resize){
  14215. if(this.doLayout){
  14216. newWidget.resize(this._containerContentBox || this._contentBox);
  14217. }else{
  14218. // the child should pick it's own size but we still need to call resize()
  14219. // (with no arguments) to let the widget lay itself out
  14220. newWidget.resize();
  14221. }
  14222. }
  14223. return d; // If child has an href, promise that fires when the child's href finishes loading
  14224. },
  14225. _adjacent: function(/*Boolean*/ forward){
  14226. // summary:
  14227. // Gets the next/previous child widget in this container from the current selection.
  14228. var children = this.getChildren();
  14229. var index = array.indexOf(children, this.selectedChildWidget);
  14230. index += forward ? 1 : children.length - 1;
  14231. return children[ index % children.length ]; // dijit._Widget
  14232. },
  14233. forward: function(){
  14234. // summary:
  14235. // Advance to next page.
  14236. return this.selectChild(this._adjacent(true), true);
  14237. },
  14238. back: function(){
  14239. // summary:
  14240. // Go back to previous page.
  14241. return this.selectChild(this._adjacent(false), true);
  14242. },
  14243. _onKeyPress: function(e){
  14244. topic.publish(this.id+"-containerKeyPress", { e: e, page: this}); // publish
  14245. },
  14246. layout: function(){
  14247. // Implement _LayoutWidget.layout() virtual method.
  14248. var child = this.selectedChildWidget;
  14249. if(child && child.resize){
  14250. if(this.doLayout){
  14251. child.resize(this._containerContentBox || this._contentBox);
  14252. }else{
  14253. child.resize();
  14254. }
  14255. }
  14256. },
  14257. _showChild: function(/*dijit._Widget*/ page){
  14258. // summary:
  14259. // Show the specified child by changing it's CSS, and call _onShow()/onShow() so
  14260. // it can do any updates it needs regarding loading href's etc.
  14261. // returns:
  14262. // Promise that fires when page has finished showing, or true if there's no href
  14263. var children = this.getChildren();
  14264. page.isFirstChild = (page == children[0]);
  14265. page.isLastChild = (page == children[children.length-1]);
  14266. page._set("selected", true);
  14267. domClass.replace(page.domNode, "dijitVisible", "dijitHidden");
  14268. return (page._onShow && page._onShow()) || true;
  14269. },
  14270. _hideChild: function(/*dijit._Widget*/ page){
  14271. // summary:
  14272. // Hide the specified child by changing it's CSS, and call _onHide() so
  14273. // it's notified.
  14274. page._set("selected", false);
  14275. domClass.replace(page.domNode, "dijitHidden", "dijitVisible");
  14276. page.onHide && page.onHide();
  14277. },
  14278. closeChild: function(/*dijit._Widget*/ page){
  14279. // summary:
  14280. // Callback when user clicks the [X] to remove a page.
  14281. // If onClose() returns true then remove and destroy the child.
  14282. // tags:
  14283. // private
  14284. var remove = page.onClose(this, page);
  14285. if(remove){
  14286. this.removeChild(page);
  14287. // makes sure we can clean up executeScripts in ContentPane onUnLoad
  14288. page.destroyRecursive();
  14289. }
  14290. },
  14291. destroyDescendants: function(/*Boolean*/ preserveDom){
  14292. this._descendantsBeingDestroyed = true;
  14293. this.selectedChildWidget = undefined;
  14294. array.forEach(this.getChildren(), function(child){
  14295. if(!preserveDom){
  14296. this.removeChild(child);
  14297. }
  14298. child.destroyRecursive(preserveDom);
  14299. }, this);
  14300. this._descendantsBeingDestroyed = false;
  14301. }
  14302. });
  14303. });
  14304. },
  14305. 'dojo/regexp':function(){
  14306. define("dojo/regexp", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
  14307. // module:
  14308. // dojo/regexp
  14309. // summary:
  14310. // TODOC
  14311. lang.getObject("regexp", true, dojo);
  14312. /*=====
  14313. dojo.regexp = {
  14314. // summary: Regular expressions and Builder resources
  14315. };
  14316. =====*/
  14317. dojo.regexp.escapeString = function(/*String*/str, /*String?*/except){
  14318. // summary:
  14319. // Adds escape sequences for special characters in regular expressions
  14320. // except:
  14321. // a String with special characters to be left unescaped
  14322. return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(ch){
  14323. if(except && except.indexOf(ch) != -1){
  14324. return ch;
  14325. }
  14326. return "\\" + ch;
  14327. }); // String
  14328. };
  14329. dojo.regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){
  14330. // summary:
  14331. // Builds a regular expression that groups subexpressions
  14332. // description:
  14333. // A utility function used by some of the RE generators. The
  14334. // subexpressions are constructed by the function, re, in the second
  14335. // parameter. re builds one subexpression for each elem in the array
  14336. // a, in the first parameter. Returns a string for a regular
  14337. // expression that groups all the subexpressions.
  14338. // arr:
  14339. // A single value or an array of values.
  14340. // re:
  14341. // A function. Takes one parameter and converts it to a regular
  14342. // expression.
  14343. // nonCapture:
  14344. // If true, uses non-capturing match, otherwise matches are retained
  14345. // by regular expression. Defaults to false
  14346. // case 1: a is a single value.
  14347. if(!(arr instanceof Array)){
  14348. return re(arr); // String
  14349. }
  14350. // case 2: a is an array
  14351. var b = [];
  14352. for(var i = 0; i < arr.length; i++){
  14353. // convert each elem to a RE
  14354. b.push(re(arr[i]));
  14355. }
  14356. // join the REs as alternatives in a RE group.
  14357. return dojo.regexp.group(b.join("|"), nonCapture); // String
  14358. };
  14359. dojo.regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){
  14360. // summary:
  14361. // adds group match to expression
  14362. // nonCapture:
  14363. // If true, uses non-capturing match, otherwise matches are retained
  14364. // by regular expression.
  14365. return "(" + (nonCapture ? "?:":"") + expression + ")"; // String
  14366. };
  14367. return dojo.regexp;
  14368. });
  14369. },
  14370. 'dijit/DropDownMenu':function(){
  14371. require({cache:{
  14372. 'url:dijit/templates/Menu.html':"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" role=\"menu\" tabIndex=\"${tabIndex}\" data-dojo-attach-event=\"onkeypress:_onKeyPress\" cellspacing=\"0\">\n\t<tbody class=\"dijitReset\" data-dojo-attach-point=\"containerNode\"></tbody>\n</table>\n"}});
  14373. define("dijit/DropDownMenu", [
  14374. "dojo/_base/declare", // declare
  14375. "dojo/_base/event", // event.stop
  14376. "dojo/keys", // keys
  14377. "dojo/text!./templates/Menu.html",
  14378. "./_OnDijitClickMixin",
  14379. "./_MenuBase"
  14380. ], function(declare, event, keys, template, _OnDijitClickMixin, _MenuBase){
  14381. /*=====
  14382. var _MenuBase = dijit._MenuBase;
  14383. var _OnDijitClickMixin = dijit._OnDijitClickMixin;
  14384. =====*/
  14385. // module:
  14386. // dijit/DropDownMenu
  14387. // summary:
  14388. // dijit.DropDownMenu widget
  14389. return declare("dijit.DropDownMenu", [_MenuBase, _OnDijitClickMixin], {
  14390. // summary:
  14391. // A menu, without features for context menu (Meaning, drop down menu)
  14392. templateString: template,
  14393. baseClass: "dijitMenu",
  14394. postCreate: function(){
  14395. var l = this.isLeftToRight();
  14396. this._openSubMenuKey = l ? keys.RIGHT_ARROW : keys.LEFT_ARROW;
  14397. this._closeSubMenuKey = l ? keys.LEFT_ARROW : keys.RIGHT_ARROW;
  14398. this.connectKeyNavHandlers([keys.UP_ARROW], [keys.DOWN_ARROW]);
  14399. },
  14400. _onKeyPress: function(/*Event*/ evt){
  14401. // summary:
  14402. // Handle keyboard based menu navigation.
  14403. // tags:
  14404. // protected
  14405. if(evt.ctrlKey || evt.altKey){ return; }
  14406. switch(evt.charOrCode){
  14407. case this._openSubMenuKey:
  14408. this._moveToPopup(evt);
  14409. event.stop(evt);
  14410. break;
  14411. case this._closeSubMenuKey:
  14412. if(this.parentMenu){
  14413. if(this.parentMenu._isMenuBar){
  14414. this.parentMenu.focusPrev();
  14415. }else{
  14416. this.onCancel(false);
  14417. }
  14418. }else{
  14419. event.stop(evt);
  14420. }
  14421. break;
  14422. }
  14423. }
  14424. });
  14425. });
  14426. },
  14427. 'dijit/form/_FormMixin':function(){
  14428. define("dijit/form/_FormMixin", [
  14429. "dojo/_base/array", // array.every array.filter array.forEach array.indexOf array.map
  14430. "dojo/_base/declare", // declare
  14431. "dojo/_base/kernel", // kernel.deprecated
  14432. "dojo/_base/lang", // lang.hitch lang.isArray
  14433. "dojo/window" // winUtils.scrollIntoView
  14434. ], function(array, declare, kernel, lang, winUtils){
  14435. // module:
  14436. // dijit/form/_FormMixin
  14437. // summary:
  14438. // Mixin for containers of form widgets (i.e. widgets that represent a single value
  14439. // and can be children of a <form> node or dijit.form.Form widget)
  14440. return declare("dijit.form._FormMixin", null, {
  14441. // summary:
  14442. // Mixin for containers of form widgets (i.e. widgets that represent a single value
  14443. // and can be children of a <form> node or dijit.form.Form widget)
  14444. // description:
  14445. // Can extract all the form widgets
  14446. // values and combine them into a single javascript object, or alternately
  14447. // take such an object and set the values for all the contained
  14448. // form widgets
  14449. /*=====
  14450. // value: Object
  14451. // Name/value hash for each child widget with a name and value.
  14452. // Child widgets without names are not part of the hash.
  14453. //
  14454. // If there are multiple child widgets w/the same name, value is an array,
  14455. // unless they are radio buttons in which case value is a scalar (since only
  14456. // one radio button can be checked at a time).
  14457. //
  14458. // If a child widget's name is a dot separated list (like a.b.c.d), it's a nested structure.
  14459. //
  14460. // Example:
  14461. // | { name: "John Smith", interests: ["sports", "movies"] }
  14462. =====*/
  14463. // state: [readonly] String
  14464. // Will be "Error" if one or more of the child widgets has an invalid value,
  14465. // "Incomplete" if not all of the required child widgets are filled in. Otherwise, "",
  14466. // which indicates that the form is ready to be submitted.
  14467. state: "",
  14468. // TODO:
  14469. // * Repeater
  14470. // * better handling for arrays. Often form elements have names with [] like
  14471. // * people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
  14472. //
  14473. //
  14474. _getDescendantFormWidgets: function(/*dijit._WidgetBase[]?*/ children){
  14475. // summary:
  14476. // Returns all form widget descendants, searching through non-form child widgets like BorderContainer
  14477. var res = [];
  14478. array.forEach(children || this.getChildren(), function(child){
  14479. if("value" in child){
  14480. res.push(child);
  14481. }else{
  14482. res = res.concat(this._getDescendantFormWidgets(child.getChildren()));
  14483. }
  14484. }, this);
  14485. return res;
  14486. },
  14487. reset: function(){
  14488. array.forEach(this._getDescendantFormWidgets(), function(widget){
  14489. if(widget.reset){
  14490. widget.reset();
  14491. }
  14492. });
  14493. },
  14494. validate: function(){
  14495. // summary:
  14496. // returns if the form is valid - same as isValid - but
  14497. // provides a few additional (ui-specific) features.
  14498. // 1 - it will highlight any sub-widgets that are not
  14499. // valid
  14500. // 2 - it will call focus() on the first invalid
  14501. // sub-widget
  14502. var didFocus = false;
  14503. return array.every(array.map(this._getDescendantFormWidgets(), function(widget){
  14504. // Need to set this so that "required" widgets get their
  14505. // state set.
  14506. widget._hasBeenBlurred = true;
  14507. var valid = widget.disabled || !widget.validate || widget.validate();
  14508. if(!valid && !didFocus){
  14509. // Set focus of the first non-valid widget
  14510. winUtils.scrollIntoView(widget.containerNode || widget.domNode);
  14511. widget.focus();
  14512. didFocus = true;
  14513. }
  14514. return valid;
  14515. }), function(item){ return item; });
  14516. },
  14517. setValues: function(val){
  14518. kernel.deprecated(this.declaredClass+"::setValues() is deprecated. Use set('value', val) instead.", "", "2.0");
  14519. return this.set('value', val);
  14520. },
  14521. _setValueAttr: function(/*Object*/ obj){
  14522. // summary:
  14523. // Fill in form values from according to an Object (in the format returned by get('value'))
  14524. // generate map from name --> [list of widgets with that name]
  14525. var map = { };
  14526. array.forEach(this._getDescendantFormWidgets(), function(widget){
  14527. if(!widget.name){ return; }
  14528. var entry = map[widget.name] || (map[widget.name] = [] );
  14529. entry.push(widget);
  14530. });
  14531. for(var name in map){
  14532. if(!map.hasOwnProperty(name)){
  14533. continue;
  14534. }
  14535. var widgets = map[name], // array of widgets w/this name
  14536. values = lang.getObject(name, false, obj); // list of values for those widgets
  14537. if(values === undefined){
  14538. continue;
  14539. }
  14540. if(!lang.isArray(values)){
  14541. values = [ values ];
  14542. }
  14543. if(typeof widgets[0].checked == 'boolean'){
  14544. // for checkbox/radio, values is a list of which widgets should be checked
  14545. array.forEach(widgets, function(w){
  14546. w.set('value', array.indexOf(values, w.value) != -1);
  14547. });
  14548. }else if(widgets[0].multiple){
  14549. // it takes an array (e.g. multi-select)
  14550. widgets[0].set('value', values);
  14551. }else{
  14552. // otherwise, values is a list of values to be assigned sequentially to each widget
  14553. array.forEach(widgets, function(w, i){
  14554. w.set('value', values[i]);
  14555. });
  14556. }
  14557. }
  14558. /***
  14559. * TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets)
  14560. array.forEach(this.containerNode.elements, function(element){
  14561. if(element.name == ''){return}; // like "continue"
  14562. var namePath = element.name.split(".");
  14563. var myObj=obj;
  14564. var name=namePath[namePath.length-1];
  14565. for(var j=1,len2=namePath.length;j<len2;++j){
  14566. var p=namePath[j - 1];
  14567. // repeater support block
  14568. var nameA=p.split("[");
  14569. if(nameA.length > 1){
  14570. if(typeof(myObj[nameA[0]]) == "undefined"){
  14571. myObj[nameA[0]]=[ ];
  14572. } // if
  14573. nameIndex=parseInt(nameA[1]);
  14574. if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
  14575. myObj[nameA[0]][nameIndex] = { };
  14576. }
  14577. myObj=myObj[nameA[0]][nameIndex];
  14578. continue;
  14579. } // repeater support ends
  14580. if(typeof(myObj[p]) == "undefined"){
  14581. myObj=undefined;
  14582. break;
  14583. };
  14584. myObj=myObj[p];
  14585. }
  14586. if(typeof(myObj) == "undefined"){
  14587. return; // like "continue"
  14588. }
  14589. if(typeof(myObj[name]) == "undefined" && this.ignoreNullValues){
  14590. return; // like "continue"
  14591. }
  14592. // TODO: widget values (just call set('value', ...) on the widget)
  14593. // TODO: maybe should call dojo.getNodeProp() instead
  14594. switch(element.type){
  14595. case "checkbox":
  14596. element.checked = (name in myObj) &&
  14597. array.some(myObj[name], function(val){ return val == element.value; });
  14598. break;
  14599. case "radio":
  14600. element.checked = (name in myObj) && myObj[name] == element.value;
  14601. break;
  14602. case "select-multiple":
  14603. element.selectedIndex=-1;
  14604. array.forEach(element.options, function(option){
  14605. option.selected = array.some(myObj[name], function(val){ return option.value == val; });
  14606. });
  14607. break;
  14608. case "select-one":
  14609. element.selectedIndex="0";
  14610. array.forEach(element.options, function(option){
  14611. option.selected = option.value == myObj[name];
  14612. });
  14613. break;
  14614. case "hidden":
  14615. case "text":
  14616. case "textarea":
  14617. case "password":
  14618. element.value = myObj[name] || "";
  14619. break;
  14620. }
  14621. });
  14622. */
  14623. // Note: no need to call this._set("value", ...) as the child updates will trigger onChange events
  14624. // which I am monitoring.
  14625. },
  14626. getValues: function(){
  14627. kernel.deprecated(this.declaredClass+"::getValues() is deprecated. Use get('value') instead.", "", "2.0");
  14628. return this.get('value');
  14629. },
  14630. _getValueAttr: function(){
  14631. // summary:
  14632. // Returns Object representing form values. See description of `value` for details.
  14633. // description:
  14634. // The value is updated into this.value every time a child has an onChange event,
  14635. // so in the common case this function could just return this.value. However,
  14636. // that wouldn't work when:
  14637. //
  14638. // 1. User presses return key to submit a form. That doesn't fire an onchange event,
  14639. // and even if it did it would come too late due to the setTimeout(..., 0) in _handleOnChange()
  14640. //
  14641. // 2. app for some reason calls this.get("value") while the user is typing into a
  14642. // form field. Not sure if that case needs to be supported or not.
  14643. // get widget values
  14644. var obj = { };
  14645. array.forEach(this._getDescendantFormWidgets(), function(widget){
  14646. var name = widget.name;
  14647. if(!name || widget.disabled){ return; }
  14648. // Single value widget (checkbox, radio, or plain <input> type widget)
  14649. var value = widget.get('value');
  14650. // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
  14651. if(typeof widget.checked == 'boolean'){
  14652. if(/Radio/.test(widget.declaredClass)){
  14653. // radio button
  14654. if(value !== false){
  14655. lang.setObject(name, value, obj);
  14656. }else{
  14657. // give radio widgets a default of null
  14658. value = lang.getObject(name, false, obj);
  14659. if(value === undefined){
  14660. lang.setObject(name, null, obj);
  14661. }
  14662. }
  14663. }else{
  14664. // checkbox/toggle button
  14665. var ary=lang.getObject(name, false, obj);
  14666. if(!ary){
  14667. ary=[];
  14668. lang.setObject(name, ary, obj);
  14669. }
  14670. if(value !== false){
  14671. ary.push(value);
  14672. }
  14673. }
  14674. }else{
  14675. var prev=lang.getObject(name, false, obj);
  14676. if(typeof prev != "undefined"){
  14677. if(lang.isArray(prev)){
  14678. prev.push(value);
  14679. }else{
  14680. lang.setObject(name, [prev, value], obj);
  14681. }
  14682. }else{
  14683. // unique name
  14684. lang.setObject(name, value, obj);
  14685. }
  14686. }
  14687. });
  14688. /***
  14689. * code for plain input boxes (see also domForm.formToObject, can we use that instead of this code?
  14690. * but it doesn't understand [] notation, presumably)
  14691. var obj = { };
  14692. array.forEach(this.containerNode.elements, function(elm){
  14693. if(!elm.name) {
  14694. return; // like "continue"
  14695. }
  14696. var namePath = elm.name.split(".");
  14697. var myObj=obj;
  14698. var name=namePath[namePath.length-1];
  14699. for(var j=1,len2=namePath.length;j<len2;++j){
  14700. var nameIndex = null;
  14701. var p=namePath[j - 1];
  14702. var nameA=p.split("[");
  14703. if(nameA.length > 1){
  14704. if(typeof(myObj[nameA[0]]) == "undefined"){
  14705. myObj[nameA[0]]=[ ];
  14706. } // if
  14707. nameIndex=parseInt(nameA[1]);
  14708. if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
  14709. myObj[nameA[0]][nameIndex] = { };
  14710. }
  14711. }else if(typeof(myObj[nameA[0]]) == "undefined"){
  14712. myObj[nameA[0]] = { }
  14713. } // if
  14714. if(nameA.length == 1){
  14715. myObj=myObj[nameA[0]];
  14716. }else{
  14717. myObj=myObj[nameA[0]][nameIndex];
  14718. } // if
  14719. } // for
  14720. if((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type == "radio" && elm.checked)){
  14721. if(name == name.split("[")[0]){
  14722. myObj[name]=elm.value;
  14723. }else{
  14724. // can not set value when there is no name
  14725. }
  14726. }else if(elm.type == "checkbox" && elm.checked){
  14727. if(typeof(myObj[name]) == 'undefined'){
  14728. myObj[name]=[ ];
  14729. }
  14730. myObj[name].push(elm.value);
  14731. }else if(elm.type == "select-multiple"){
  14732. if(typeof(myObj[name]) == 'undefined'){
  14733. myObj[name]=[ ];
  14734. }
  14735. for(var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){
  14736. if(elm.options[jdx].selected){
  14737. myObj[name].push(elm.options[jdx].value);
  14738. }
  14739. }
  14740. } // if
  14741. name=undefined;
  14742. }); // forEach
  14743. ***/
  14744. return obj;
  14745. },
  14746. isValid: function(){
  14747. // summary:
  14748. // Returns true if all of the widgets are valid.
  14749. // Deprecated, will be removed in 2.0. Use get("state") instead.
  14750. return this.state == "";
  14751. },
  14752. onValidStateChange: function(/*Boolean*/ /*===== isValid =====*/){
  14753. // summary:
  14754. // Stub function to connect to if you want to do something
  14755. // (like disable/enable a submit button) when the valid
  14756. // state changes on the form as a whole.
  14757. //
  14758. // Deprecated. Will be removed in 2.0. Use watch("state", ...) instead.
  14759. },
  14760. _getState: function(){
  14761. // summary:
  14762. // Compute what this.state should be based on state of children
  14763. var states = array.map(this._descendants, function(w){
  14764. return w.get("state") || "";
  14765. });
  14766. return array.indexOf(states, "Error") >= 0 ? "Error" :
  14767. array.indexOf(states, "Incomplete") >= 0 ? "Incomplete" : "";
  14768. },
  14769. disconnectChildren: function(){
  14770. // summary:
  14771. // Remove connections to monitor changes to children's value, error state, and disabled state,
  14772. // in order to update Form.value and Form.state.
  14773. array.forEach(this._childConnections || [], lang.hitch(this, "disconnect"));
  14774. array.forEach(this._childWatches || [], function(w){ w.unwatch(); });
  14775. },
  14776. connectChildren: function(/*Boolean*/ inStartup){
  14777. // summary:
  14778. // Setup connections to monitor changes to children's value, error state, and disabled state,
  14779. // in order to update Form.value and Form.state.
  14780. //
  14781. // You can call this function directly, ex. in the event that you
  14782. // programmatically add a widget to the form *after* the form has been
  14783. // initialized.
  14784. var _this = this;
  14785. // Remove old connections, if any
  14786. this.disconnectChildren();
  14787. this._descendants = this._getDescendantFormWidgets();
  14788. // (Re)set this.value and this.state. Send watch() notifications but not on startup.
  14789. var set = inStartup ? function(name, val){ _this[name] = val; } : lang.hitch(this, "_set");
  14790. set("value", this.get("value"));
  14791. set("state", this._getState());
  14792. // Monitor changes to error state and disabled state in order to update
  14793. // Form.state
  14794. var conns = (this._childConnections = []),
  14795. watches = (this._childWatches = []);
  14796. array.forEach(array.filter(this._descendants,
  14797. function(item){ return item.validate; }
  14798. ),
  14799. function(widget){
  14800. // We are interested in whenever the widget changes validity state - or
  14801. // whenever the disabled attribute on that widget is changed.
  14802. array.forEach(["state", "disabled"], function(attr){
  14803. watches.push(widget.watch(attr, function(){
  14804. _this.set("state", _this._getState());
  14805. }));
  14806. });
  14807. });
  14808. // And monitor calls to child.onChange so we can update this.value
  14809. var onChange = function(){
  14810. // summary:
  14811. // Called when child's value or disabled state changes
  14812. // Use setTimeout() to collapse value changes in multiple children into a single
  14813. // update to my value. Multiple updates will occur on:
  14814. // 1. Form.set()
  14815. // 2. Form.reset()
  14816. // 3. user selecting a radio button (which will de-select another radio button,
  14817. // causing two onChange events)
  14818. if(_this._onChangeDelayTimer){
  14819. clearTimeout(_this._onChangeDelayTimer);
  14820. }
  14821. _this._onChangeDelayTimer = setTimeout(function(){
  14822. delete _this._onChangeDelayTimer;
  14823. _this._set("value", _this.get("value"));
  14824. }, 10);
  14825. };
  14826. array.forEach(
  14827. array.filter(this._descendants, function(item){ return item.onChange; } ),
  14828. function(widget){
  14829. // When a child widget's value changes,
  14830. // the efficient thing to do is to just update that one attribute in this.value,
  14831. // but that gets a little complicated when a checkbox is checked/unchecked
  14832. // since this.value["checkboxName"] contains an array of all the checkboxes w/the same name.
  14833. // Doing simple thing for now.
  14834. conns.push(_this.connect(widget, "onChange", onChange));
  14835. // Disabling/enabling a child widget should remove it's value from this.value.
  14836. // Again, this code could be more efficient, doing simple thing for now.
  14837. watches.push(widget.watch("disabled", onChange));
  14838. }
  14839. );
  14840. },
  14841. startup: function(){
  14842. this.inherited(arguments);
  14843. // Initialize value and valid/invalid state tracking. Needs to be done in startup()
  14844. // so that children are initialized.
  14845. this.connectChildren(true);
  14846. // Make state change call onValidStateChange(), will be removed in 2.0
  14847. this.watch("state", function(attr, oldVal, newVal){ this.onValidStateChange(newVal == ""); });
  14848. },
  14849. destroy: function(){
  14850. this.disconnectChildren();
  14851. this.inherited(arguments);
  14852. }
  14853. });
  14854. });
  14855. },
  14856. 'dijit/Menu':function(){
  14857. define("dijit/Menu", [
  14858. "require",
  14859. "dojo/_base/array", // array.forEach
  14860. "dojo/_base/declare", // declare
  14861. "dojo/_base/event", // event.stop
  14862. "dojo/dom", // dom.byId dom.isDescendant
  14863. "dojo/dom-attr", // domAttr.get domAttr.set domAttr.has domAttr.remove
  14864. "dojo/dom-geometry", // domStyle.getComputedStyle domGeometry.position
  14865. "dojo/dom-style", // domStyle.getComputedStyle
  14866. "dojo/_base/kernel",
  14867. "dojo/keys", // keys.F10
  14868. "dojo/_base/lang", // lang.hitch
  14869. "dojo/on",
  14870. "dojo/_base/sniff", // has("ie"), has("quirks")
  14871. "dojo/_base/window", // win.body win.doc.documentElement win.doc.frames win.withGlobal
  14872. "dojo/window", // winUtils.get
  14873. "./popup",
  14874. "./DropDownMenu",
  14875. "dojo/ready"
  14876. ], function(require, array, declare, event, dom, domAttr, domGeometry, domStyle, kernel, keys, lang, on,
  14877. has, win, winUtils, pm, DropDownMenu, ready){
  14878. /*=====
  14879. var DropDownMenu = dijit.DropDownMenu;
  14880. =====*/
  14881. // module:
  14882. // dijit/Menu
  14883. // summary:
  14884. // Includes dijit.Menu widget and base class dijit._MenuBase
  14885. // Back compat w/1.6, remove for 2.0
  14886. if(!kernel.isAsync){
  14887. ready(0, function(){
  14888. var requires = ["dijit/MenuItem", "dijit/PopupMenuItem", "dijit/CheckedMenuItem", "dijit/MenuSeparator"];
  14889. require(requires); // use indirection so modules not rolled into a build
  14890. });
  14891. }
  14892. return declare("dijit.Menu", DropDownMenu, {
  14893. // summary:
  14894. // A context menu you can assign to multiple elements
  14895. constructor: function(){
  14896. this._bindings = [];
  14897. },
  14898. // targetNodeIds: [const] String[]
  14899. // Array of dom node ids of nodes to attach to.
  14900. // Fill this with nodeIds upon widget creation and it becomes context menu for those nodes.
  14901. targetNodeIds: [],
  14902. // contextMenuForWindow: [const] Boolean
  14903. // If true, right clicking anywhere on the window will cause this context menu to open.
  14904. // If false, must specify targetNodeIds.
  14905. contextMenuForWindow: false,
  14906. // leftClickToOpen: [const] Boolean
  14907. // If true, menu will open on left click instead of right click, similar to a file menu.
  14908. leftClickToOpen: false,
  14909. // refocus: Boolean
  14910. // When this menu closes, re-focus the element which had focus before it was opened.
  14911. refocus: true,
  14912. postCreate: function(){
  14913. if(this.contextMenuForWindow){
  14914. this.bindDomNode(win.body());
  14915. }else{
  14916. // TODO: should have _setTargetNodeIds() method to handle initialization and a possible
  14917. // later set('targetNodeIds', ...) call. There's also a problem that targetNodeIds[]
  14918. // gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610)
  14919. array.forEach(this.targetNodeIds, this.bindDomNode, this);
  14920. }
  14921. this.inherited(arguments);
  14922. },
  14923. // thanks burstlib!
  14924. _iframeContentWindow: function(/* HTMLIFrameElement */iframe_el){
  14925. // summary:
  14926. // Returns the window reference of the passed iframe
  14927. // tags:
  14928. // private
  14929. return winUtils.get(this._iframeContentDocument(iframe_el)) ||
  14930. // Moz. TODO: is this available when defaultView isn't?
  14931. this._iframeContentDocument(iframe_el)['__parent__'] ||
  14932. (iframe_el.name && win.doc.frames[iframe_el.name]) || null; // Window
  14933. },
  14934. _iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){
  14935. // summary:
  14936. // Returns a reference to the document object inside iframe_el
  14937. // tags:
  14938. // protected
  14939. return iframe_el.contentDocument // W3
  14940. || (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE
  14941. || (iframe_el.name && win.doc.frames[iframe_el.name] && win.doc.frames[iframe_el.name].document)
  14942. || null; // HTMLDocument
  14943. },
  14944. bindDomNode: function(/*String|DomNode*/ node){
  14945. // summary:
  14946. // Attach menu to given node
  14947. node = dom.byId(node);
  14948. var cn; // Connect node
  14949. // Support context menus on iframes. Rather than binding to the iframe itself we need
  14950. // to bind to the <body> node inside the iframe.
  14951. if(node.tagName.toLowerCase() == "iframe"){
  14952. var iframe = node,
  14953. window = this._iframeContentWindow(iframe);
  14954. cn = win.withGlobal(window, win.body);
  14955. }else{
  14956. // To capture these events at the top level, attach to <html>, not <body>.
  14957. // Otherwise right-click context menu just doesn't work.
  14958. cn = (node == win.body() ? win.doc.documentElement : node);
  14959. }
  14960. // "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode())
  14961. var binding = {
  14962. node: node,
  14963. iframe: iframe
  14964. };
  14965. // Save info about binding in _bindings[], and make node itself record index(+1) into
  14966. // _bindings[] array. Prefix w/_dijitMenu to avoid setting an attribute that may
  14967. // start with a number, which fails on FF/safari.
  14968. domAttr.set(node, "_dijitMenu" + this.id, this._bindings.push(binding));
  14969. // Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished
  14970. // loading yet, in which case we need to wait for the onload event first, and then connect
  14971. // On linux Shift-F10 produces the oncontextmenu event, but on Windows it doesn't, so
  14972. // we need to monitor keyboard events in addition to the oncontextmenu event.
  14973. var doConnects = lang.hitch(this, function(cn){
  14974. return [
  14975. // TODO: when leftClickToOpen is true then shouldn't space/enter key trigger the menu,
  14976. // rather than shift-F10?
  14977. on(cn, this.leftClickToOpen ? "click" : "contextmenu", lang.hitch(this, function(evt){
  14978. // Schedule context menu to be opened unless it's already been scheduled from onkeydown handler
  14979. event.stop(evt);
  14980. this._scheduleOpen(evt.target, iframe, {x: evt.pageX, y: evt.pageY});
  14981. })),
  14982. on(cn, "keydown", lang.hitch(this, function(evt){
  14983. if(evt.shiftKey && evt.keyCode == keys.F10){
  14984. event.stop(evt);
  14985. this._scheduleOpen(evt.target, iframe); // no coords - open near target node
  14986. }
  14987. }))
  14988. ];
  14989. });
  14990. binding.connects = cn ? doConnects(cn) : [];
  14991. if(iframe){
  14992. // Setup handler to [re]bind to the iframe when the contents are initially loaded,
  14993. // and every time the contents change.
  14994. // Need to do this b/c we are actually binding to the iframe's <body> node.
  14995. // Note: can't use connect.connect(), see #9609.
  14996. binding.onloadHandler = lang.hitch(this, function(){
  14997. // want to remove old connections, but IE throws exceptions when trying to
  14998. // access the <body> node because it's already gone, or at least in a state of limbo
  14999. var window = this._iframeContentWindow(iframe);
  15000. cn = win.withGlobal(window, win.body);
  15001. binding.connects = doConnects(cn);
  15002. });
  15003. if(iframe.addEventListener){
  15004. iframe.addEventListener("load", binding.onloadHandler, false);
  15005. }else{
  15006. iframe.attachEvent("onload", binding.onloadHandler);
  15007. }
  15008. }
  15009. },
  15010. unBindDomNode: function(/*String|DomNode*/ nodeName){
  15011. // summary:
  15012. // Detach menu from given node
  15013. var node;
  15014. try{
  15015. node = dom.byId(nodeName);
  15016. }catch(e){
  15017. // On IE the dom.byId() call will get an exception if the attach point was
  15018. // the <body> node of an <iframe> that has since been reloaded (and thus the
  15019. // <body> node is in a limbo state of destruction.
  15020. return;
  15021. }
  15022. // node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array
  15023. var attrName = "_dijitMenu" + this.id;
  15024. if(node && domAttr.has(node, attrName)){
  15025. var bid = domAttr.get(node, attrName)-1, b = this._bindings[bid], h;
  15026. while(h = b.connects.pop()){
  15027. h.remove();
  15028. }
  15029. // Remove listener for iframe onload events
  15030. var iframe = b.iframe;
  15031. if(iframe){
  15032. if(iframe.removeEventListener){
  15033. iframe.removeEventListener("load", b.onloadHandler, false);
  15034. }else{
  15035. iframe.detachEvent("onload", b.onloadHandler);
  15036. }
  15037. }
  15038. domAttr.remove(node, attrName);
  15039. delete this._bindings[bid];
  15040. }
  15041. },
  15042. _scheduleOpen: function(/*DomNode?*/ target, /*DomNode?*/ iframe, /*Object?*/ coords){
  15043. // summary:
  15044. // Set timer to display myself. Using a timer rather than displaying immediately solves
  15045. // two problems:
  15046. //
  15047. // 1. IE: without the delay, focus work in "open" causes the system
  15048. // context menu to appear in spite of stopEvent.
  15049. //
  15050. // 2. Avoid double-shows on linux, where shift-F10 generates an oncontextmenu event
  15051. // even after a event.stop(e). (Shift-F10 on windows doesn't generate the
  15052. // oncontextmenu event.)
  15053. if(!this._openTimer){
  15054. this._openTimer = setTimeout(lang.hitch(this, function(){
  15055. delete this._openTimer;
  15056. this._openMyself({
  15057. target: target,
  15058. iframe: iframe,
  15059. coords: coords
  15060. });
  15061. }), 1);
  15062. }
  15063. },
  15064. _openMyself: function(args){
  15065. // summary:
  15066. // Internal function for opening myself when the user does a right-click or something similar.
  15067. // args:
  15068. // This is an Object containing:
  15069. // * target:
  15070. // The node that is being clicked
  15071. // * iframe:
  15072. // If an <iframe> is being clicked, iframe points to that iframe
  15073. // * coords:
  15074. // Put menu at specified x/y position in viewport, or if iframe is
  15075. // specified, then relative to iframe.
  15076. //
  15077. // _openMyself() formerly took the event object, and since various code references
  15078. // evt.target (after connecting to _openMyself()), using an Object for parameters
  15079. // (so that old code still works).
  15080. var target = args.target,
  15081. iframe = args.iframe,
  15082. coords = args.coords;
  15083. // Get coordinates to open menu, either at specified (mouse) position or (if triggered via keyboard)
  15084. // then near the node the menu is assigned to.
  15085. if(coords){
  15086. if(iframe){
  15087. // Specified coordinates are on <body> node of an <iframe>, convert to match main document
  15088. var ifc = domGeometry.position(iframe, true),
  15089. window = this._iframeContentWindow(iframe),
  15090. scroll = win.withGlobal(window, "_docScroll", dojo);
  15091. var cs = domStyle.getComputedStyle(iframe),
  15092. tp = domStyle.toPixelValue,
  15093. left = (has("ie") && has("quirks") ? 0 : tp(iframe, cs.paddingLeft)) + (has("ie") && has("quirks") ? tp(iframe, cs.borderLeftWidth) : 0),
  15094. top = (has("ie") && has("quirks") ? 0 : tp(iframe, cs.paddingTop)) + (has("ie") && has("quirks") ? tp(iframe, cs.borderTopWidth) : 0);
  15095. coords.x += ifc.x + left - scroll.x;
  15096. coords.y += ifc.y + top - scroll.y;
  15097. }
  15098. }else{
  15099. coords = domGeometry.position(target, true);
  15100. coords.x += 10;
  15101. coords.y += 10;
  15102. }
  15103. var self=this;
  15104. var prevFocusNode = this._focusManager.get("prevNode");
  15105. var curFocusNode = this._focusManager.get("curNode");
  15106. var savedFocusNode = !curFocusNode || (dom.isDescendant(curFocusNode, this.domNode)) ? prevFocusNode : curFocusNode;
  15107. function closeAndRestoreFocus(){
  15108. // user has clicked on a menu or popup
  15109. if(self.refocus && savedFocusNode){
  15110. savedFocusNode.focus();
  15111. }
  15112. pm.close(self);
  15113. }
  15114. pm.open({
  15115. popup: this,
  15116. x: coords.x,
  15117. y: coords.y,
  15118. onExecute: closeAndRestoreFocus,
  15119. onCancel: closeAndRestoreFocus,
  15120. orient: this.isLeftToRight() ? 'L' : 'R'
  15121. });
  15122. this.focus();
  15123. this._onBlur = function(){
  15124. this.inherited('_onBlur', arguments);
  15125. // Usually the parent closes the child widget but if this is a context
  15126. // menu then there is no parent
  15127. pm.close(this);
  15128. // don't try to restore focus; user has clicked another part of the screen
  15129. // and set focus there
  15130. };
  15131. },
  15132. uninitialize: function(){
  15133. array.forEach(this._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this);
  15134. this.inherited(arguments);
  15135. }
  15136. });
  15137. });
  15138. },
  15139. 'dijit/layout/ContentPane':function(){
  15140. define("dijit/layout/ContentPane", [
  15141. "dojo/_base/kernel", // kernel.deprecated
  15142. "dojo/_base/lang", // lang.mixin lang.delegate lang.hitch lang.isFunction lang.isObject
  15143. "../_Widget",
  15144. "./_ContentPaneResizeMixin",
  15145. "dojo/string", // string.substitute
  15146. "dojo/html", // html._ContentSetter html._emptyNode
  15147. "dojo/i18n!../nls/loading",
  15148. "dojo/_base/array", // array.forEach
  15149. "dojo/_base/declare", // declare
  15150. "dojo/_base/Deferred", // Deferred
  15151. "dojo/dom", // dom.byId
  15152. "dojo/dom-attr", // domAttr.attr
  15153. "dojo/_base/window", // win.body win.doc.createDocumentFragment
  15154. "dojo/_base/xhr", // xhr.get
  15155. "dojo/i18n" // i18n.getLocalization
  15156. ], function(kernel, lang, _Widget, _ContentPaneResizeMixin, string, html, nlsLoading,
  15157. array, declare, Deferred, dom, domAttr, win, xhr, i18n){
  15158. /*=====
  15159. var _Widget = dijit._Widget;
  15160. var _ContentPaneResizeMixin = dijit.layout._ContentPaneResizeMixin;
  15161. =====*/
  15162. // module:
  15163. // dijit/layout/ContentPane
  15164. // summary:
  15165. // A widget containing an HTML fragment, specified inline
  15166. // or by uri. Fragment may include widgets.
  15167. return declare("dijit.layout.ContentPane", [_Widget, _ContentPaneResizeMixin], {
  15168. // summary:
  15169. // A widget containing an HTML fragment, specified inline
  15170. // or by uri. Fragment may include widgets.
  15171. //
  15172. // description:
  15173. // This widget embeds a document fragment in the page, specified
  15174. // either by uri, javascript generated markup or DOM reference.
  15175. // Any widgets within this content are instantiated and managed,
  15176. // but laid out according to the HTML structure. Unlike IFRAME,
  15177. // ContentPane embeds a document fragment as would be found
  15178. // inside the BODY tag of a full HTML document. It should not
  15179. // contain the HTML, HEAD, or BODY tags.
  15180. // For more advanced functionality with scripts and
  15181. // stylesheets, see dojox.layout.ContentPane. This widget may be
  15182. // used stand alone or as a base class for other widgets.
  15183. // ContentPane is useful as a child of other layout containers
  15184. // such as BorderContainer or TabContainer, but note that those
  15185. // widgets can contain any widget as a child.
  15186. //
  15187. // example:
  15188. // Some quick samples:
  15189. // To change the innerHTML: cp.set('content', '<b>new content</b>')
  15190. //
  15191. // Or you can send it a NodeList: cp.set('content', dojo.query('div [class=selected]', userSelection))
  15192. //
  15193. // To do an ajax update: cp.set('href', url)
  15194. // href: String
  15195. // The href of the content that displays now.
  15196. // Set this at construction if you want to load data externally when the
  15197. // pane is shown. (Set preload=true to load it immediately.)
  15198. // Changing href after creation doesn't have any effect; Use set('href', ...);
  15199. href: "",
  15200. // content: String || DomNode || NodeList || dijit._Widget
  15201. // The innerHTML of the ContentPane.
  15202. // Note that the initialization parameter / argument to set("content", ...)
  15203. // can be a String, DomNode, Nodelist, or _Widget.
  15204. content: "",
  15205. // extractContent: Boolean
  15206. // Extract visible content from inside of <body> .... </body>.
  15207. // I.e., strip <html> and <head> (and it's contents) from the href
  15208. extractContent: false,
  15209. // parseOnLoad: Boolean
  15210. // Parse content and create the widgets, if any.
  15211. parseOnLoad: true,
  15212. // parserScope: String
  15213. // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo,
  15214. // will search for data-dojo-type (or dojoType). For backwards compatibility
  15215. // reasons defaults to dojo._scopeName (which is "dojo" except when
  15216. // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
  15217. parserScope: kernel._scopeName,
  15218. // preventCache: Boolean
  15219. // Prevent caching of data from href's by appending a timestamp to the href.
  15220. preventCache: false,
  15221. // preload: Boolean
  15222. // Force load of data on initialization even if pane is hidden.
  15223. preload: false,
  15224. // refreshOnShow: Boolean
  15225. // Refresh (re-download) content when pane goes from hidden to shown
  15226. refreshOnShow: false,
  15227. // loadingMessage: String
  15228. // Message that shows while downloading
  15229. loadingMessage: "<span class='dijitContentPaneLoading'><span class='dijitInline dijitIconLoading'></span>${loadingState}</span>",
  15230. // errorMessage: String
  15231. // Message that shows if an error occurs
  15232. errorMessage: "<span class='dijitContentPaneError'><span class='dijitInline dijitIconError'></span>${errorState}</span>",
  15233. // isLoaded: [readonly] Boolean
  15234. // True if the ContentPane has data in it, either specified
  15235. // during initialization (via href or inline content), or set
  15236. // via set('content', ...) / set('href', ...)
  15237. //
  15238. // False if it doesn't have any content, or if ContentPane is
  15239. // still in the process of downloading href.
  15240. isLoaded: false,
  15241. baseClass: "dijitContentPane",
  15242. /*======
  15243. // ioMethod: dojo.xhrGet|dojo.xhrPost
  15244. // Function that should grab the content specified via href.
  15245. ioMethod: dojo.xhrGet,
  15246. ======*/
  15247. // ioArgs: Object
  15248. // Parameters to pass to xhrGet() request, for example:
  15249. // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="href: './bar', ioArgs: {timeout: 500}">
  15250. ioArgs: {},
  15251. // onLoadDeferred: [readonly] dojo.Deferred
  15252. // This is the `dojo.Deferred` returned by set('href', ...) and refresh().
  15253. // Calling onLoadDeferred.addCallback() or addErrback() registers your
  15254. // callback to be called only once, when the prior set('href', ...) call or
  15255. // the initial href parameter to the constructor finishes loading.
  15256. //
  15257. // This is different than an onLoad() handler which gets called any time any href
  15258. // or content is loaded.
  15259. onLoadDeferred: null,
  15260. // Cancel _WidgetBase's _setTitleAttr because we don't want the title attribute (used to specify
  15261. // tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the
  15262. // entire pane.
  15263. _setTitleAttr: null,
  15264. // Flag to parser that I'll parse my contents, so it shouldn't.
  15265. stopParser: true,
  15266. // template: [private] Boolean
  15267. // Flag from the parser that this ContentPane is inside a template
  15268. // so the contents are pre-parsed.
  15269. // (TODO: this declaration can be commented out in 2.0)
  15270. template: false,
  15271. create: function(params, srcNodeRef){
  15272. // Convert a srcNodeRef argument into a content parameter, so that the original contents are
  15273. // processed in the same way as contents set via set("content", ...), calling the parser etc.
  15274. // Avoid modifying original params object since that breaks NodeList instantiation, see #11906.
  15275. if((!params || !params.template) && srcNodeRef && !("href" in params) && !("content" in params)){
  15276. var df = win.doc.createDocumentFragment();
  15277. srcNodeRef = dom.byId(srcNodeRef);
  15278. while(srcNodeRef.firstChild){
  15279. df.appendChild(srcNodeRef.firstChild);
  15280. }
  15281. params = lang.delegate(params, {content: df});
  15282. }
  15283. this.inherited(arguments, [params, srcNodeRef]);
  15284. },
  15285. postMixInProperties: function(){
  15286. this.inherited(arguments);
  15287. var messages = i18n.getLocalization("dijit", "loading", this.lang);
  15288. this.loadingMessage = string.substitute(this.loadingMessage, messages);
  15289. this.errorMessage = string.substitute(this.errorMessage, messages);
  15290. },
  15291. buildRendering: function(){
  15292. this.inherited(arguments);
  15293. // Since we have no template we need to set this.containerNode ourselves, to make getChildren() work.
  15294. // For subclasses of ContentPane that do have a template, does nothing.
  15295. if(!this.containerNode){
  15296. this.containerNode = this.domNode;
  15297. }
  15298. // remove the title attribute so it doesn't show up when hovering
  15299. // over a node (TODO: remove in 2.0, no longer needed after #11490)
  15300. this.domNode.removeAttribute("title");
  15301. if(!domAttr.get(this.domNode,"role")){
  15302. this.domNode.setAttribute("role", "group");
  15303. }
  15304. },
  15305. startup: function(){
  15306. // summary:
  15307. // Call startup() on all children including non _Widget ones like dojo.dnd.Source objects
  15308. // This starts all the widgets
  15309. this.inherited(arguments);
  15310. // And this catches stuff like dojo.dnd.Source
  15311. if(this._contentSetter){
  15312. array.forEach(this._contentSetter.parseResults, function(obj){
  15313. if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
  15314. obj.startup();
  15315. obj._started = true;
  15316. }
  15317. }, this);
  15318. }
  15319. },
  15320. setHref: function(/*String|Uri*/ href){
  15321. // summary:
  15322. // Deprecated. Use set('href', ...) instead.
  15323. kernel.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0");
  15324. return this.set("href", href);
  15325. },
  15326. _setHrefAttr: function(/*String|Uri*/ href){
  15327. // summary:
  15328. // Hook so set("href", ...) works.
  15329. // description:
  15330. // Reset the (external defined) content of this pane and replace with new url
  15331. // Note: It delays the download until widget is shown if preload is false.
  15332. // href:
  15333. // url to the page you want to get, must be within the same domain as your mainpage
  15334. // Cancel any in-flight requests (a set('href', ...) will cancel any in-flight set('href', ...))
  15335. this.cancel();
  15336. this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
  15337. this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
  15338. this._set("href", href);
  15339. // _setHrefAttr() is called during creation and by the user, after creation.
  15340. // Assuming preload == false, only in the second case do we actually load the URL;
  15341. // otherwise it's done in startup(), and only if this widget is shown.
  15342. if(this.preload || (this._created && this._isShown())){
  15343. this._load();
  15344. }else{
  15345. // Set flag to indicate that href needs to be loaded the next time the
  15346. // ContentPane is made visible
  15347. this._hrefChanged = true;
  15348. }
  15349. return this.onLoadDeferred; // Deferred
  15350. },
  15351. setContent: function(/*String|DomNode|Nodelist*/data){
  15352. // summary:
  15353. // Deprecated. Use set('content', ...) instead.
  15354. kernel.deprecated("dijit.layout.ContentPane.setContent() is deprecated. Use set('content', ...) instead.", "", "2.0");
  15355. this.set("content", data);
  15356. },
  15357. _setContentAttr: function(/*String|DomNode|Nodelist*/data){
  15358. // summary:
  15359. // Hook to make set("content", ...) work.
  15360. // Replaces old content with data content, include style classes from old content
  15361. // data:
  15362. // the new Content may be String, DomNode or NodeList
  15363. //
  15364. // if data is a NodeList (or an array of nodes) nodes are copied
  15365. // so you can import nodes from another document implicitly
  15366. // clear href so we can't run refresh and clear content
  15367. // refresh should only work if we downloaded the content
  15368. this._set("href", "");
  15369. // Cancel any in-flight requests (a set('content', ...) will cancel any in-flight set('href', ...))
  15370. this.cancel();
  15371. // Even though user is just setting content directly, still need to define an onLoadDeferred
  15372. // because the _onLoadHandler() handler is still getting called from setContent()
  15373. this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
  15374. if(this._created){
  15375. // For back-compat reasons, call onLoad() for set('content', ...)
  15376. // calls but not for content specified in srcNodeRef (ie: <div data-dojo-type=ContentPane>...</div>)
  15377. // or as initialization parameter (ie: new ContentPane({content: ...})
  15378. this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
  15379. }
  15380. this._setContent(data || "");
  15381. this._isDownloaded = false; // mark that content is from a set('content') not a set('href')
  15382. return this.onLoadDeferred; // Deferred
  15383. },
  15384. _getContentAttr: function(){
  15385. // summary:
  15386. // Hook to make get("content") work
  15387. return this.containerNode.innerHTML;
  15388. },
  15389. cancel: function(){
  15390. // summary:
  15391. // Cancels an in-flight download of content
  15392. if(this._xhrDfd && (this._xhrDfd.fired == -1)){
  15393. this._xhrDfd.cancel();
  15394. }
  15395. delete this._xhrDfd; // garbage collect
  15396. this.onLoadDeferred = null;
  15397. },
  15398. uninitialize: function(){
  15399. if(this._beingDestroyed){
  15400. this.cancel();
  15401. }
  15402. this.inherited(arguments);
  15403. },
  15404. destroyRecursive: function(/*Boolean*/ preserveDom){
  15405. // summary:
  15406. // Destroy the ContentPane and its contents
  15407. // if we have multiple controllers destroying us, bail after the first
  15408. if(this._beingDestroyed){
  15409. return;
  15410. }
  15411. this.inherited(arguments);
  15412. },
  15413. _onShow: function(){
  15414. // summary:
  15415. // Called when the ContentPane is made visible
  15416. // description:
  15417. // For a plain ContentPane, this is called on initialization, from startup().
  15418. // If the ContentPane is a hidden pane of a TabContainer etc., then it's
  15419. // called whenever the pane is made visible.
  15420. //
  15421. // Does necessary processing, including href download and layout/resize of
  15422. // child widget(s)
  15423. this.inherited(arguments);
  15424. if(this.href){
  15425. if(!this._xhrDfd && // if there's an href that isn't already being loaded
  15426. (!this.isLoaded || this._hrefChanged || this.refreshOnShow)
  15427. ){
  15428. return this.refresh(); // If child has an href, promise that fires when the load is complete
  15429. }
  15430. }
  15431. },
  15432. refresh: function(){
  15433. // summary:
  15434. // [Re]download contents of href and display
  15435. // description:
  15436. // 1. cancels any currently in-flight requests
  15437. // 2. posts "loading..." message
  15438. // 3. sends XHR to download new data
  15439. // Cancel possible prior in-flight request
  15440. this.cancel();
  15441. this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
  15442. this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
  15443. this._load();
  15444. return this.onLoadDeferred; // If child has an href, promise that fires when refresh is complete
  15445. },
  15446. _load: function(){
  15447. // summary:
  15448. // Load/reload the href specified in this.href
  15449. // display loading message
  15450. this._setContent(this.onDownloadStart(), true);
  15451. var self = this;
  15452. var getArgs = {
  15453. preventCache: (this.preventCache || this.refreshOnShow),
  15454. url: this.href,
  15455. handleAs: "text"
  15456. };
  15457. if(lang.isObject(this.ioArgs)){
  15458. lang.mixin(getArgs, this.ioArgs);
  15459. }
  15460. var hand = (this._xhrDfd = (this.ioMethod || xhr.get)(getArgs));
  15461. hand.addCallback(function(html){
  15462. try{
  15463. self._isDownloaded = true;
  15464. self._setContent(html, false);
  15465. self.onDownloadEnd();
  15466. }catch(err){
  15467. self._onError('Content', err); // onContentError
  15468. }
  15469. delete self._xhrDfd;
  15470. return html;
  15471. });
  15472. hand.addErrback(function(err){
  15473. if(!hand.canceled){
  15474. // show error message in the pane
  15475. self._onError('Download', err); // onDownloadError
  15476. }
  15477. delete self._xhrDfd;
  15478. return err;
  15479. });
  15480. // Remove flag saying that a load is needed
  15481. delete this._hrefChanged;
  15482. },
  15483. _onLoadHandler: function(data){
  15484. // summary:
  15485. // This is called whenever new content is being loaded
  15486. this._set("isLoaded", true);
  15487. try{
  15488. this.onLoadDeferred.callback(data);
  15489. }catch(e){
  15490. console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message);
  15491. }
  15492. },
  15493. _onUnloadHandler: function(){
  15494. // summary:
  15495. // This is called whenever the content is being unloaded
  15496. this._set("isLoaded", false);
  15497. try{
  15498. this.onUnload();
  15499. }catch(e){
  15500. console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message);
  15501. }
  15502. },
  15503. destroyDescendants: function(/*Boolean*/ preserveDom){
  15504. // summary:
  15505. // Destroy all the widgets inside the ContentPane and empty containerNode
  15506. // Make sure we call onUnload (but only when the ContentPane has real content)
  15507. if(this.isLoaded){
  15508. this._onUnloadHandler();
  15509. }
  15510. // Even if this.isLoaded == false there might still be a "Loading..." message
  15511. // to erase, so continue...
  15512. // For historical reasons we need to delete all widgets under this.containerNode,
  15513. // even ones that the user has created manually.
  15514. var setter = this._contentSetter;
  15515. array.forEach(this.getChildren(), function(widget){
  15516. if(widget.destroyRecursive){
  15517. widget.destroyRecursive(preserveDom);
  15518. }
  15519. });
  15520. if(setter){
  15521. // Most of the widgets in setter.parseResults have already been destroyed, but
  15522. // things like Menu that have been moved to <body> haven't yet
  15523. array.forEach(setter.parseResults, function(widget){
  15524. if(widget.destroyRecursive && widget.domNode && widget.domNode.parentNode == win.body()){
  15525. widget.destroyRecursive(preserveDom);
  15526. }
  15527. });
  15528. delete setter.parseResults;
  15529. }
  15530. // And then clear away all the DOM nodes
  15531. if(!preserveDom){
  15532. html._emptyNode(this.containerNode);
  15533. }
  15534. // Delete any state information we have about current contents
  15535. delete this._singleChild;
  15536. },
  15537. _setContent: function(/*String|DocumentFragment*/ cont, /*Boolean*/ isFakeContent){
  15538. // summary:
  15539. // Insert the content into the container node
  15540. // first get rid of child widgets
  15541. this.destroyDescendants();
  15542. // html.set will take care of the rest of the details
  15543. // we provide an override for the error handling to ensure the widget gets the errors
  15544. // configure the setter instance with only the relevant widget instance properties
  15545. // NOTE: unless we hook into attr, or provide property setters for each property,
  15546. // we need to re-configure the ContentSetter with each use
  15547. var setter = this._contentSetter;
  15548. if(! (setter && setter instanceof html._ContentSetter)){
  15549. setter = this._contentSetter = new html._ContentSetter({
  15550. node: this.containerNode,
  15551. _onError: lang.hitch(this, this._onError),
  15552. onContentError: lang.hitch(this, function(e){
  15553. // fires if a domfault occurs when we are appending this.errorMessage
  15554. // like for instance if domNode is a UL and we try append a DIV
  15555. var errMess = this.onContentError(e);
  15556. try{
  15557. this.containerNode.innerHTML = errMess;
  15558. }catch(e){
  15559. console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
  15560. }
  15561. })/*,
  15562. _onError */
  15563. });
  15564. }
  15565. var setterParams = lang.mixin({
  15566. cleanContent: this.cleanContent,
  15567. extractContent: this.extractContent,
  15568. parseContent: !cont.domNode && this.parseOnLoad,
  15569. parserScope: this.parserScope,
  15570. startup: false,
  15571. dir: this.dir,
  15572. lang: this.lang,
  15573. textDir: this.textDir
  15574. }, this._contentSetterParams || {});
  15575. setter.set( (lang.isObject(cont) && cont.domNode) ? cont.domNode : cont, setterParams );
  15576. // setter params must be pulled afresh from the ContentPane each time
  15577. delete this._contentSetterParams;
  15578. if(this.doLayout){
  15579. this._checkIfSingleChild();
  15580. }
  15581. if(!isFakeContent){
  15582. if(this._started){
  15583. // Startup each top level child widget (and they will start their children, recursively)
  15584. delete this._started;
  15585. this.startup();
  15586. // Call resize() on each of my child layout widgets,
  15587. // or resize() on my single child layout widget...
  15588. // either now (if I'm currently visible) or when I become visible
  15589. this._scheduleLayout();
  15590. }
  15591. this._onLoadHandler(cont);
  15592. }
  15593. },
  15594. _onError: function(type, err, consoleText){
  15595. this.onLoadDeferred.errback(err);
  15596. // shows user the string that is returned by on[type]Error
  15597. // override on[type]Error and return your own string to customize
  15598. var errText = this['on' + type + 'Error'].call(this, err);
  15599. if(consoleText){
  15600. console.error(consoleText, err);
  15601. }else if(errText){// a empty string won't change current content
  15602. this._setContent(errText, true);
  15603. }
  15604. },
  15605. // EVENT's, should be overide-able
  15606. onLoad: function(/*===== data =====*/){
  15607. // summary:
  15608. // Event hook, is called after everything is loaded and widgetified
  15609. // tags:
  15610. // callback
  15611. },
  15612. onUnload: function(){
  15613. // summary:
  15614. // Event hook, is called before old content is cleared
  15615. // tags:
  15616. // callback
  15617. },
  15618. onDownloadStart: function(){
  15619. // summary:
  15620. // Called before download starts.
  15621. // description:
  15622. // The string returned by this function will be the html
  15623. // that tells the user we are loading something.
  15624. // Override with your own function if you want to change text.
  15625. // tags:
  15626. // extension
  15627. return this.loadingMessage;
  15628. },
  15629. onContentError: function(/*Error*/ /*===== error =====*/){
  15630. // summary:
  15631. // Called on DOM faults, require faults etc. in content.
  15632. //
  15633. // In order to display an error message in the pane, return
  15634. // the error message from this method, as an HTML string.
  15635. //
  15636. // By default (if this method is not overriden), it returns
  15637. // nothing, so the error message is just printed to the console.
  15638. // tags:
  15639. // extension
  15640. },
  15641. onDownloadError: function(/*Error*/ /*===== error =====*/){
  15642. // summary:
  15643. // Called when download error occurs.
  15644. //
  15645. // In order to display an error message in the pane, return
  15646. // the error message from this method, as an HTML string.
  15647. //
  15648. // Default behavior (if this method is not overriden) is to display
  15649. // the error message inside the pane.
  15650. // tags:
  15651. // extension
  15652. return this.errorMessage;
  15653. },
  15654. onDownloadEnd: function(){
  15655. // summary:
  15656. // Called when download is finished.
  15657. // tags:
  15658. // callback
  15659. }
  15660. });
  15661. });
  15662. },
  15663. 'dojox/dtl/filter/htmlstrings':function(){
  15664. define("dojox/dtl/filter/htmlstrings", [
  15665. "dojo/_base/lang",
  15666. "../_base"
  15667. ], function(lang,dd){
  15668. /*=====
  15669. dd = dojox.dtl;
  15670. =====*/
  15671. lang.getObject("dojox.dtl.filter.htmlstrings", true);
  15672. lang.mixin(dd.filter.htmlstrings, {
  15673. _linebreaksrn: /(\r\n|\n\r)/g,
  15674. _linebreaksn: /\n{2,}/g,
  15675. _linebreakss: /(^\s+|\s+$)/g,
  15676. _linebreaksbr: /\n/g,
  15677. _removetagsfind: /[a-z0-9]+/g,
  15678. _striptags: /<[^>]*?>/g,
  15679. linebreaks: function(value){
  15680. // summary: Converts newlines into <p> and <br />s
  15681. var output = [];
  15682. var dh = dd.filter.htmlstrings;
  15683. value = value.replace(dh._linebreaksrn, "\n");
  15684. var parts = value.split(dh._linebreaksn);
  15685. for(var i = 0; i < parts.length; i++){
  15686. var part = parts[i].replace(dh._linebreakss, "").replace(dh._linebreaksbr, "<br />");
  15687. output.push("<p>" + part + "</p>");
  15688. }
  15689. return output.join("\n\n");
  15690. },
  15691. linebreaksbr: function(value){
  15692. // summary: Converts newlines into <br />s
  15693. var dh = dd.filter.htmlstrings;
  15694. return value.replace(dh._linebreaksrn, "\n").replace(dh._linebreaksbr, "<br />");
  15695. },
  15696. removetags: function(value, arg){
  15697. // summary: Removes a space separated list of [X]HTML tags from the output"
  15698. var dh = dd.filter.htmlstrings;
  15699. var tags = [];
  15700. var group;
  15701. while(group = dh._removetagsfind.exec(arg)){
  15702. tags.push(group[0]);
  15703. }
  15704. tags = "(" + tags.join("|") + ")";
  15705. return value.replace(new RegExp("</?\s*" + tags + "\s*[^>]*>", "gi"), "");
  15706. },
  15707. striptags: function(value){
  15708. // summary: Strips all [X]HTML tags
  15709. return value.replace(dojox.dtl.filter.htmlstrings._striptags, "");
  15710. }
  15711. });
  15712. return dojox.dtl.filter.htmlstrings;
  15713. });
  15714. },
  15715. 'dojox/dtl/_base':function(){
  15716. define("dojox/dtl/_base", [
  15717. "dojo/_base/kernel",
  15718. "dojo/_base/lang",
  15719. "dojox/string/tokenize",
  15720. "dojo/_base/json",
  15721. "dojo/dom",
  15722. "dojo/_base/xhr",
  15723. "dojox/string/Builder",
  15724. "dojo/_base/Deferred"],
  15725. function(kernel, lang, Tokenize, json, dom, xhr, StringBuilder, deferred){
  15726. /*=====
  15727. Tokenize = dojox.string.tokenize;
  15728. StringBuilder = dojox.string.Builder;
  15729. =====*/
  15730. kernel.experimental("dojox.dtl");
  15731. var dd = lang.getObject("dojox.dtl", true);
  15732. dd._base = {};
  15733. /*=====
  15734. dd = dojox.dtl;
  15735. =====*/
  15736. dd.TOKEN_BLOCK = -1;
  15737. dd.TOKEN_VAR = -2;
  15738. dd.TOKEN_COMMENT = -3;
  15739. dd.TOKEN_TEXT = 3;
  15740. /*=====
  15741. dd._Context = function(dict){
  15742. // summary: Pass one of these when rendering a template to tell the template what values to use.
  15743. }
  15744. =====*/
  15745. dd._Context = lang.extend(function(dict){
  15746. // summary: Pass one of these when rendering a template to tell the template what values to use.
  15747. if(dict){
  15748. lang._mixin(this, dict);
  15749. if(dict.get){
  15750. // Preserve passed getter and restore prototype get
  15751. this._getter = dict.get;
  15752. delete this.get;
  15753. }
  15754. }
  15755. },
  15756. {
  15757. push: function(){
  15758. var last = this;
  15759. var context = lang.delegate(this);
  15760. context.pop = function(){ return last; }
  15761. return context;
  15762. },
  15763. pop: function(){
  15764. throw new Error("pop() called on empty Context");
  15765. },
  15766. get: function(key, otherwise){
  15767. var n = this._normalize;
  15768. if(this._getter){
  15769. var got = this._getter(key);
  15770. if(got !== undefined){
  15771. return n(got);
  15772. }
  15773. }
  15774. if(this[key] !== undefined){
  15775. return n(this[key]);
  15776. }
  15777. return otherwise;
  15778. },
  15779. _normalize: function(value){
  15780. if(value instanceof Date){
  15781. value.year = value.getFullYear();
  15782. value.month = value.getMonth() + 1;
  15783. value.day = value.getDate();
  15784. value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2);
  15785. value.hour = value.getHours();
  15786. value.minute = value.getMinutes();
  15787. value.second = value.getSeconds();
  15788. value.microsecond = value.getMilliseconds();
  15789. }
  15790. return value;
  15791. },
  15792. update: function(dict){
  15793. var context = this.push();
  15794. if(dict){
  15795. lang._mixin(this, dict);
  15796. }
  15797. return context;
  15798. }
  15799. });
  15800. var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;
  15801. var split_re = /\s+/g;
  15802. var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){
  15803. splitter = splitter || split_re;
  15804. if(!(splitter instanceof RegExp)){
  15805. splitter = new RegExp(splitter, "g");
  15806. }
  15807. if(!splitter.global){
  15808. throw new Error("You must use a globally flagged RegExp with split " + splitter);
  15809. }
  15810. splitter.exec(""); // Reset the global
  15811. var part, parts = [], lastIndex = 0, i = 0;
  15812. while((part = splitter.exec(this))){
  15813. parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length));
  15814. lastIndex = splitter.lastIndex;
  15815. if(limit && (++i > limit - 1)){
  15816. break;
  15817. }
  15818. }
  15819. parts.push(this.slice(lastIndex));
  15820. return parts;
  15821. }
  15822. dd.Token = function(token_type, contents){
  15823. this.token_type = token_type;
  15824. this.contents = new String(lang.trim(contents));
  15825. this.contents.split = split;
  15826. this.split = function(){
  15827. return String.prototype.split.apply(this.contents, arguments);
  15828. }
  15829. }
  15830. dd.Token.prototype.split_contents = function(/*Integer?*/ limit){
  15831. var bit, bits = [], i = 0;
  15832. limit = limit || 999;
  15833. while(i++ < limit && (bit = smart_split_re.exec(this.contents))){
  15834. bit = bit[0];
  15835. if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){
  15836. bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"');
  15837. }else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){
  15838. bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'");
  15839. }else{
  15840. bits.push(bit);
  15841. }
  15842. }
  15843. return bits;
  15844. }
  15845. var ddt = dd.text = {
  15846. _get: function(module, name, errorless){
  15847. // summary: Used to find both tags and filters
  15848. var params = dd.register.get(module, name.toLowerCase(), errorless);
  15849. if(!params){
  15850. if(!errorless){
  15851. throw new Error("No tag found for " + name);
  15852. }
  15853. return null;
  15854. }
  15855. var fn = params[1];
  15856. var deps = params[2];
  15857. var parts;
  15858. if(fn.indexOf(":") != -1){
  15859. parts = fn.split(":");
  15860. fn = parts.pop();
  15861. }
  15862. // FIXME: THIS DESIGN DOES NOT WORK WITH ASYNC LOADERS!
  15863. var mod = deps;
  15864. if (/\./.test(deps)) {
  15865. deps = deps.replace(/\./g, "/");
  15866. }
  15867. require([deps], function(){});
  15868. var parent = lang.getObject(mod);
  15869. return parent[fn || name] || parent[name + "_"] || parent[fn + "_"];
  15870. },
  15871. getTag: function(name, errorless){
  15872. return ddt._get("tag", name, errorless);
  15873. },
  15874. getFilter: function(name, errorless){
  15875. return ddt._get("filter", name, errorless);
  15876. },
  15877. getTemplate: function(file){
  15878. return new dd.Template(ddt.getTemplateString(file));
  15879. },
  15880. getTemplateString: function(file){
  15881. return xhr._getText(file.toString()) || "";
  15882. },
  15883. _resolveLazy: function(location, sync, json){
  15884. if(sync){
  15885. if(json){
  15886. return json.fromJson(xhr._getText(location)) || {};
  15887. }else{
  15888. return dd.text.getTemplateString(location);
  15889. }
  15890. }else{
  15891. return xhr.get({
  15892. handleAs: json ? "json" : "text",
  15893. url: location
  15894. });
  15895. }
  15896. },
  15897. _resolveTemplateArg: function(arg, sync){
  15898. if(ddt._isTemplate(arg)){
  15899. if(!sync){
  15900. var d = new deferred();
  15901. d.callback(arg);
  15902. return d;
  15903. }
  15904. return arg;
  15905. }
  15906. return ddt._resolveLazy(arg, sync);
  15907. },
  15908. _isTemplate: function(arg){
  15909. return (arg === undefined) || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1));
  15910. },
  15911. _resolveContextArg: function(arg, sync){
  15912. if(arg.constructor == Object){
  15913. if(!sync){
  15914. var d = new deferred;
  15915. d.callback(arg);
  15916. return d;
  15917. }
  15918. return arg;
  15919. }
  15920. return ddt._resolveLazy(arg, sync, true);
  15921. },
  15922. _re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,
  15923. tokenize: function(str){
  15924. return Tokenize(str, ddt._re, ddt._parseDelims);
  15925. },
  15926. _parseDelims: function(varr, load, tag){
  15927. if(varr){
  15928. return [dd.TOKEN_VAR, varr];
  15929. }else if(load){
  15930. var parts = lang.trim(tag).split(/\s+/g);
  15931. for(var i = 0, part; part = parts[i]; i++){
  15932. if (/\./.test(part)){
  15933. part = part.replace(/\./g,"/");
  15934. }
  15935. require([part]);
  15936. }
  15937. }else{
  15938. return [dd.TOKEN_BLOCK, tag];
  15939. }
  15940. }
  15941. }
  15942. /*=====
  15943. dd.Template = function(template, isString){
  15944. // summary:
  15945. // The base class for text-based templates.
  15946. // template: String|dojo._Url
  15947. // The string or location of the string to
  15948. // use as a template
  15949. // isString: Boolean
  15950. // Indicates whether the template is a string or a url.
  15951. };
  15952. dd.Template.prototype.update= function(node, context){
  15953. // summary:
  15954. // Updates this template according to the given context.
  15955. // node: DOMNode|String|dojo.NodeList
  15956. // A node reference or set of nodes
  15957. // context: dojo._Url|String|Object
  15958. // The context object or location
  15959. }
  15960. dd.Template.prototype.render= function(context, buffer){
  15961. // summary:
  15962. // Renders this template.
  15963. // context: Object
  15964. // The runtime context.
  15965. // buffer: StringBuilder?
  15966. // A string buffer.
  15967. }
  15968. =====*/
  15969. dd.Template = lang.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){
  15970. // template:
  15971. // The string or location of the string to
  15972. // use as a template
  15973. var str = isString ? template : ddt._resolveTemplateArg(template, true) || "";
  15974. var tokens = ddt.tokenize(str);
  15975. var parser = new dd._Parser(tokens);
  15976. this.nodelist = parser.parse();
  15977. },
  15978. {
  15979. update: function(node, context){
  15980. // summary:
  15981. // Updates this template according to the given context.
  15982. // node: DOMNode|String|dojo.NodeList
  15983. // A node reference or set of nodes
  15984. // context: dojo._Url|String|Object
  15985. // The context object or location
  15986. return ddt._resolveContextArg(context).addCallback(this, function(contextObject){
  15987. var content = this.render(new dd._Context(contextObject));
  15988. if(node.forEach){
  15989. node.forEach(function(item){
  15990. item.innerHTML = content;
  15991. });
  15992. }else{
  15993. dom.byId(node).innerHTML = content;
  15994. }
  15995. return this;
  15996. });
  15997. },
  15998. render: function(context, /*concatenatable?*/ buffer){
  15999. buffer = buffer || this.getBuffer();
  16000. context = context || new dd._Context({});
  16001. return this.nodelist.render(context, buffer) + "";
  16002. },
  16003. getBuffer: function(){
  16004. return new StringBuilder();
  16005. }
  16006. });
  16007. var qfRe = /\{\{\s*(.+?)\s*\}\}/g;
  16008. dd.quickFilter = function(str){
  16009. if(!str){
  16010. return new dd._NodeList();
  16011. }
  16012. if(str.indexOf("{%") == -1){
  16013. return new dd._QuickNodeList(Tokenize(str, qfRe, function(token){
  16014. return new dd._Filter(token);
  16015. }));
  16016. }
  16017. }
  16018. dd._QuickNodeList = lang.extend(function(contents){
  16019. this.contents = contents;
  16020. },
  16021. {
  16022. render: function(context, buffer){
  16023. for(var i = 0, l = this.contents.length; i < l; i++){
  16024. if(this.contents[i].resolve){
  16025. buffer = buffer.concat(this.contents[i].resolve(context));
  16026. }else{
  16027. buffer = buffer.concat(this.contents[i]);
  16028. }
  16029. }
  16030. return buffer;
  16031. },
  16032. dummyRender: function(context){ return this.render(context, dd.Template.prototype.getBuffer()).toString(); },
  16033. clone: function(buffer){ return this; }
  16034. });
  16035. dd._Filter = lang.extend(function(token){
  16036. // summary: Uses a string to find (and manipulate) a variable
  16037. if(!token) throw new Error("Filter must be called with variable name");
  16038. this.contents = token;
  16039. var cache = this._cache[token];
  16040. if(cache){
  16041. this.key = cache[0];
  16042. this.filters = cache[1];
  16043. }else{
  16044. this.filters = [];
  16045. Tokenize(token, this._re, this._tokenize, this);
  16046. this._cache[token] = [this.key, this.filters];
  16047. }
  16048. },
  16049. {
  16050. _cache: {},
  16051. _re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
  16052. _values: {
  16053. 0: '"', // _("text")
  16054. 1: '"', // "text"
  16055. 2: "", // variable
  16056. 8: '"' // 'text'
  16057. },
  16058. _args: {
  16059. 4: '"', // :_("text")
  16060. 5: '"', // :"text"
  16061. 6: "", // :variable
  16062. 7: "'"// :'text'
  16063. },
  16064. _tokenize: function(){
  16065. var pos, arg;
  16066. for(var i = 0, has = []; i < arguments.length; i++){
  16067. has[i] = (arguments[i] !== undefined && typeof arguments[i] == "string" && arguments[i]);
  16068. }
  16069. if(!this.key){
  16070. for(pos in this._values){
  16071. if(has[pos]){
  16072. this.key = this._values[pos] + arguments[pos] + this._values[pos];
  16073. break;
  16074. }
  16075. }
  16076. }else{
  16077. for(pos in this._args){
  16078. if(has[pos]){
  16079. var value = arguments[pos];
  16080. if(this._args[pos] == "'"){
  16081. value = value.replace(/\\'/g, "'");
  16082. }else if(this._args[pos] == '"'){
  16083. value = value.replace(/\\"/g, '"');
  16084. }
  16085. arg = [!this._args[pos], value];
  16086. break;
  16087. }
  16088. }
  16089. // Get a named filter
  16090. var fn = ddt.getFilter(arguments[3]);
  16091. if(!lang.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter");
  16092. this.filters.push([fn, arg]);
  16093. }
  16094. },
  16095. getExpression: function(){
  16096. return this.contents;
  16097. },
  16098. resolve: function(context){
  16099. if(this.key === undefined){
  16100. return "";
  16101. }
  16102. var str = this.resolvePath(this.key, context);
  16103. for(var i = 0, filter; filter = this.filters[i]; i++){
  16104. // Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string
  16105. // and [1][1] is either the variable name of the string content.
  16106. if(filter[1]){
  16107. if(filter[1][0]){
  16108. str = filter[0](str, this.resolvePath(filter[1][1], context));
  16109. }else{
  16110. str = filter[0](str, filter[1][1]);
  16111. }
  16112. }else{
  16113. str = filter[0](str);
  16114. }
  16115. }
  16116. return str;
  16117. },
  16118. resolvePath: function(path, context){
  16119. var current, parts;
  16120. var first = path.charAt(0);
  16121. var last = path.slice(-1);
  16122. if(!isNaN(parseInt(first))){
  16123. current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
  16124. }else if(first == '"' && first == last){
  16125. current = path.slice(1, -1);
  16126. }else{
  16127. if(path == "true"){ return true; }
  16128. if(path == "false"){ return false; }
  16129. if(path == "null" || path == "None"){ return null; }
  16130. parts = path.split(".");
  16131. current = context.get(parts[0]);
  16132. if(lang.isFunction(current)){
  16133. var self = context.getThis && context.getThis();
  16134. if(current.alters_data){
  16135. current = "";
  16136. }else if(self){
  16137. current = current.call(self);
  16138. }else{
  16139. current = "";
  16140. }
  16141. }
  16142. for(var i = 1; i < parts.length; i++){
  16143. var part = parts[i];
  16144. if(current){
  16145. var base = current;
  16146. if(lang.isObject(current) && part == "items" && current[part] === undefined){
  16147. var items = [];
  16148. for(var key in current){
  16149. items.push([key, current[key]]);
  16150. }
  16151. current = items;
  16152. continue;
  16153. }
  16154. if(current.get && lang.isFunction(current.get) && current.get.safe){
  16155. current = current.get(part);
  16156. }else if(current[part] === undefined){
  16157. current = current[part];
  16158. break;
  16159. }else{
  16160. current = current[part];
  16161. }
  16162. if(lang.isFunction(current)){
  16163. if(current.alters_data){
  16164. current = "";
  16165. }else{
  16166. current = current.call(base);
  16167. }
  16168. }else if(current instanceof Date){
  16169. current = dd._Context.prototype._normalize(current);
  16170. }
  16171. }else{
  16172. return "";
  16173. }
  16174. }
  16175. }
  16176. return current;
  16177. }
  16178. });
  16179. dd._TextNode = dd._Node = lang.extend(function(/*Object*/ obj){
  16180. // summary: Basic catch-all node
  16181. this.contents = obj;
  16182. },
  16183. {
  16184. set: function(data){
  16185. this.contents = data;
  16186. return this;
  16187. },
  16188. render: function(context, buffer){
  16189. // summary: Adds content onto the buffer
  16190. return buffer.concat(this.contents);
  16191. },
  16192. isEmpty: function(){
  16193. return !lang.trim(this.contents);
  16194. },
  16195. clone: function(){ return this; }
  16196. });
  16197. dd._NodeList = lang.extend(function(/*Node[]*/ nodes){
  16198. // summary: Allows us to render a group of nodes
  16199. this.contents = nodes || [];
  16200. this.last = "";
  16201. },
  16202. {
  16203. push: function(node){
  16204. // summary: Add a new node to the list
  16205. this.contents.push(node);
  16206. return this;
  16207. },
  16208. concat: function(nodes){
  16209. this.contents = this.contents.concat(nodes);
  16210. return this;
  16211. },
  16212. render: function(context, buffer){
  16213. // summary: Adds all content onto the buffer
  16214. for(var i = 0; i < this.contents.length; i++){
  16215. buffer = this.contents[i].render(context, buffer);
  16216. if(!buffer) throw new Error("Template must return buffer");
  16217. }
  16218. return buffer;
  16219. },
  16220. dummyRender: function(context){
  16221. return this.render(context, dd.Template.prototype.getBuffer()).toString();
  16222. },
  16223. unrender: function(){ return arguments[1]; },
  16224. clone: function(){ return this; },
  16225. rtrim: function(){
  16226. while(1){
  16227. i = this.contents.length - 1;
  16228. if(this.contents[i] instanceof dd._TextNode && this.contents[i].isEmpty()){
  16229. this.contents.pop();
  16230. }else{
  16231. break;
  16232. }
  16233. }
  16234. return this;
  16235. }
  16236. });
  16237. dd._VarNode = lang.extend(function(str){
  16238. // summary: A node to be processed as a variable
  16239. this.contents = new dd._Filter(str);
  16240. },
  16241. {
  16242. render: function(context, buffer){
  16243. var str = this.contents.resolve(context);
  16244. if(!str.safe){
  16245. str = dd._base.escape("" + str);
  16246. }
  16247. return buffer.concat(str);
  16248. }
  16249. });
  16250. dd._noOpNode = new function(){
  16251. // summary: Adds a no-op node. Useful in custom tags
  16252. this.render = this.unrender = function(){ return arguments[1]; }
  16253. this.clone = function(){ return this; }
  16254. }
  16255. dd._Parser = lang.extend(function(tokens){
  16256. // summary: Parser used during initialization and for tag groups.
  16257. this.contents = tokens;
  16258. },
  16259. {
  16260. i: 0,
  16261. parse: function(/*Array?*/ stop_at){
  16262. // summary: Turns tokens into nodes
  16263. // description: Steps into tags are they're found. Blocks use the parse object
  16264. // to find their closing tag (the stop_at array). stop_at is inclusive, it
  16265. // returns the node that matched.
  16266. var terminators = {}, token;
  16267. stop_at = stop_at || [];
  16268. for(var i = 0; i < stop_at.length; i++){
  16269. terminators[stop_at[i]] = true;
  16270. }
  16271. var nodelist = new dd._NodeList();
  16272. while(this.i < this.contents.length){
  16273. token = this.contents[this.i++];
  16274. if(typeof token == "string"){
  16275. nodelist.push(new dd._TextNode(token));
  16276. }else{
  16277. var type = token[0];
  16278. var text = token[1];
  16279. if(type == dd.TOKEN_VAR){
  16280. nodelist.push(new dd._VarNode(text));
  16281. }else if(type == dd.TOKEN_BLOCK){
  16282. if(terminators[text]){
  16283. --this.i;
  16284. return nodelist;
  16285. }
  16286. var cmd = text.split(/\s+/g);
  16287. if(cmd.length){
  16288. cmd = cmd[0];
  16289. var fn = ddt.getTag(cmd);
  16290. if(fn){
  16291. nodelist.push(fn(this, new dd.Token(type, text)));
  16292. }
  16293. }
  16294. }
  16295. }
  16296. }
  16297. if(stop_at.length){
  16298. throw new Error("Could not find closing tag(s): " + stop_at.toString());
  16299. }
  16300. this.contents.length = 0;
  16301. return nodelist;
  16302. },
  16303. next_token: function(){
  16304. // summary: Returns the next token in the list.
  16305. var token = this.contents[this.i++];
  16306. return new dd.Token(token[0], token[1]);
  16307. },
  16308. delete_first_token: function(){
  16309. this.i++;
  16310. },
  16311. skip_past: function(endtag){
  16312. while(this.i < this.contents.length){
  16313. var token = this.contents[this.i++];
  16314. if(token[0] == dd.TOKEN_BLOCK && token[1] == endtag){
  16315. return;
  16316. }
  16317. }
  16318. throw new Error("Unclosed tag found when looking for " + endtag);
  16319. },
  16320. create_variable_node: function(expr){
  16321. return new dd._VarNode(expr);
  16322. },
  16323. create_text_node: function(expr){
  16324. return new dd._TextNode(expr || "");
  16325. },
  16326. getTemplate: function(file){
  16327. return new dd.Template(file);
  16328. }
  16329. });
  16330. dd.register = {
  16331. _registry: {
  16332. attributes: [],
  16333. tags: [],
  16334. filters: []
  16335. },
  16336. get: function(/*String*/ module, /*String*/ name){
  16337. var registry = dd.register._registry[module + "s"];
  16338. for(var i = 0, entry; entry = registry[i]; i++){
  16339. if(typeof entry[0] == "string"){
  16340. if(entry[0] == name){
  16341. return entry;
  16342. }
  16343. }else if(name.match(entry[0])){
  16344. return entry;
  16345. }
  16346. }
  16347. },
  16348. getAttributeTags: function(){
  16349. var tags = [];
  16350. var registry = dd.register._registry.attributes;
  16351. for(var i = 0, entry; entry = registry[i]; i++){
  16352. if(entry.length == 3){
  16353. tags.push(entry);
  16354. }else{
  16355. var fn = lang.getObject(entry[1]);
  16356. if(fn && lang.isFunction(fn)){
  16357. entry.push(fn);
  16358. tags.push(entry);
  16359. }
  16360. }
  16361. }
  16362. return tags;
  16363. },
  16364. _any: function(type, base, locations){
  16365. for(var path in locations){
  16366. for(var i = 0, fn; fn = locations[path][i]; i++){
  16367. var key = fn;
  16368. if(lang.isArray(fn)){
  16369. key = fn[0];
  16370. fn = fn[1];
  16371. }
  16372. if(typeof key == "string"){
  16373. if(key.substr(0, 5) == "attr:"){
  16374. var attr = fn;
  16375. if(attr.substr(0, 5) == "attr:"){
  16376. attr = attr.slice(5);
  16377. }
  16378. dd.register._registry.attributes.push([attr.toLowerCase(), base + "." + path + "." + attr]);
  16379. }
  16380. key = key.toLowerCase()
  16381. }
  16382. dd.register._registry[type].push([
  16383. key,
  16384. fn,
  16385. base + "." + path
  16386. ]);
  16387. }
  16388. }
  16389. },
  16390. tags: function(/*String*/ base, /*Object*/ locations){
  16391. dd.register._any("tags", base, locations);
  16392. },
  16393. filters: function(/*String*/ base, /*Object*/ locations){
  16394. dd.register._any("filters", base, locations);
  16395. }
  16396. }
  16397. var escapeamp = /&/g;
  16398. var escapelt = /</g;
  16399. var escapegt = />/g;
  16400. var escapeqt = /'/g;
  16401. var escapedblqt = /"/g;
  16402. dd._base.escape = function(value){
  16403. // summary: Escapes a string's HTML
  16404. return dd.mark_safe(value.replace(escapeamp, '&amp;').replace(escapelt, '&lt;').replace(escapegt, '&gt;').replace(escapedblqt, '&quot;').replace(escapeqt, '&#39;'));
  16405. }
  16406. dd._base.safe = function(value){
  16407. if(typeof value == "string"){
  16408. value = new String(value);
  16409. }
  16410. if(typeof value == "object"){
  16411. value.safe = true;
  16412. }
  16413. return value;
  16414. }
  16415. dd.mark_safe = dd._base.safe;
  16416. dd.register.tags("dojox.dtl.tag", {
  16417. "date": ["now"],
  16418. "logic": ["if", "for", "ifequal", "ifnotequal"],
  16419. "loader": ["extends", "block", "include", "load", "ssi"],
  16420. "misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"],
  16421. "loop": ["cycle", "ifchanged", "regroup"]
  16422. });
  16423. dd.register.filters("dojox.dtl.filter", {
  16424. "dates": ["date", "time", "timesince", "timeuntil"],
  16425. "htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"],
  16426. "integers": ["add", "get_digit"],
  16427. "lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"],
  16428. "logic": ["default", "default_if_none", "divisibleby", "yesno"],
  16429. "misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"],
  16430. "strings": ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"]
  16431. });
  16432. dd.register.filters("dojox.dtl", {
  16433. "_base": ["escape", "safe"]
  16434. });
  16435. return dd;
  16436. });
  16437. },
  16438. 'dijit/_KeyNavContainer':function(){
  16439. define("dijit/_KeyNavContainer", [
  16440. "dojo/_base/kernel", // kernel.deprecated
  16441. "./_Container",
  16442. "./_FocusMixin",
  16443. "dojo/_base/array", // array.forEach
  16444. "dojo/keys", // keys.END keys.HOME
  16445. "dojo/_base/declare", // declare
  16446. "dojo/_base/event", // event.stop
  16447. "dojo/dom-attr", // domAttr.set
  16448. "dojo/_base/lang" // lang.hitch
  16449. ], function(kernel, _Container, _FocusMixin, array, keys, declare, event, domAttr, lang){
  16450. /*=====
  16451. var _FocusMixin = dijit._FocusMixin;
  16452. var _Container = dijit._Container;
  16453. =====*/
  16454. // module:
  16455. // dijit/_KeyNavContainer
  16456. // summary:
  16457. // A _Container with keyboard navigation of its children.
  16458. return declare("dijit._KeyNavContainer", [_FocusMixin, _Container], {
  16459. // summary:
  16460. // A _Container with keyboard navigation of its children.
  16461. // description:
  16462. // To use this mixin, call connectKeyNavHandlers() in
  16463. // postCreate().
  16464. // It provides normalized keyboard and focusing code for Container
  16465. // widgets.
  16466. /*=====
  16467. // focusedChild: [protected] Widget
  16468. // The currently focused child widget, or null if there isn't one
  16469. focusedChild: null,
  16470. =====*/
  16471. // tabIndex: Integer
  16472. // Tab index of the container; same as HTML tabIndex attribute.
  16473. // Note then when user tabs into the container, focus is immediately
  16474. // moved to the first item in the container.
  16475. tabIndex: "0",
  16476. connectKeyNavHandlers: function(/*keys[]*/ prevKeyCodes, /*keys[]*/ nextKeyCodes){
  16477. // summary:
  16478. // Call in postCreate() to attach the keyboard handlers
  16479. // to the container.
  16480. // preKeyCodes: keys[]
  16481. // Key codes for navigating to the previous child.
  16482. // nextKeyCodes: keys[]
  16483. // Key codes for navigating to the next child.
  16484. // tags:
  16485. // protected
  16486. // TODO: call this automatically from my own postCreate()
  16487. var keyCodes = (this._keyNavCodes = {});
  16488. var prev = lang.hitch(this, "focusPrev");
  16489. var next = lang.hitch(this, "focusNext");
  16490. array.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; });
  16491. array.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; });
  16492. keyCodes[keys.HOME] = lang.hitch(this, "focusFirstChild");
  16493. keyCodes[keys.END] = lang.hitch(this, "focusLastChild");
  16494. this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
  16495. this.connect(this.domNode, "onfocus", "_onContainerFocus");
  16496. },
  16497. startupKeyNavChildren: function(){
  16498. kernel.deprecated("startupKeyNavChildren() call no longer needed", "", "2.0");
  16499. },
  16500. startup: function(){
  16501. this.inherited(arguments);
  16502. array.forEach(this.getChildren(), lang.hitch(this, "_startupChild"));
  16503. },
  16504. addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
  16505. this.inherited(arguments);
  16506. this._startupChild(widget);
  16507. },
  16508. focus: function(){
  16509. // summary:
  16510. // Default focus() implementation: focus the first child.
  16511. this.focusFirstChild();
  16512. },
  16513. focusFirstChild: function(){
  16514. // summary:
  16515. // Focus the first focusable child in the container.
  16516. // tags:
  16517. // protected
  16518. this.focusChild(this._getFirstFocusableChild());
  16519. },
  16520. focusLastChild: function(){
  16521. // summary:
  16522. // Focus the last focusable child in the container.
  16523. // tags:
  16524. // protected
  16525. this.focusChild(this._getLastFocusableChild());
  16526. },
  16527. focusNext: function(){
  16528. // summary:
  16529. // Focus the next widget
  16530. // tags:
  16531. // protected
  16532. this.focusChild(this._getNextFocusableChild(this.focusedChild, 1));
  16533. },
  16534. focusPrev: function(){
  16535. // summary:
  16536. // Focus the last focusable node in the previous widget
  16537. // (ex: go to the ComboButton icon section rather than button section)
  16538. // tags:
  16539. // protected
  16540. this.focusChild(this._getNextFocusableChild(this.focusedChild, -1), true);
  16541. },
  16542. focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
  16543. // summary:
  16544. // Focus specified child widget.
  16545. // widget:
  16546. // Reference to container's child widget
  16547. // last:
  16548. // If true and if widget has multiple focusable nodes, focus the
  16549. // last one instead of the first one
  16550. // tags:
  16551. // protected
  16552. if(!widget){ return; }
  16553. if(this.focusedChild && widget !== this.focusedChild){
  16554. this._onChildBlur(this.focusedChild); // used by _MenuBase
  16555. }
  16556. widget.set("tabIndex", this.tabIndex); // for IE focus outline to appear, must set tabIndex before focs
  16557. widget.focus(last ? "end" : "start");
  16558. this._set("focusedChild", widget);
  16559. },
  16560. _startupChild: function(/*dijit._Widget*/ widget){
  16561. // summary:
  16562. // Setup for each child widget
  16563. // description:
  16564. // Sets tabIndex=-1 on each child, so that the tab key will
  16565. // leave the container rather than visiting each child.
  16566. // tags:
  16567. // private
  16568. widget.set("tabIndex", "-1");
  16569. this.connect(widget, "_onFocus", function(){
  16570. // Set valid tabIndex so tabbing away from widget goes to right place, see #10272
  16571. widget.set("tabIndex", this.tabIndex);
  16572. });
  16573. this.connect(widget, "_onBlur", function(){
  16574. widget.set("tabIndex", "-1");
  16575. });
  16576. },
  16577. _onContainerFocus: function(evt){
  16578. // summary:
  16579. // Handler for when the container gets focus
  16580. // description:
  16581. // Initially the container itself has a tabIndex, but when it gets
  16582. // focus, switch focus to first child...
  16583. // tags:
  16584. // private
  16585. // Note that we can't use _onFocus() because switching focus from the
  16586. // _onFocus() handler confuses the focus.js code
  16587. // (because it causes _onFocusNode() to be called recursively)
  16588. // Also, _onFocus() would fire when focus went directly to a child widget due to mouse click.
  16589. // Ignore spurious focus events:
  16590. // 1. focus on a child widget bubbles on FF
  16591. // 2. on IE, clicking the scrollbar of a select dropdown moves focus from the focused child item to me
  16592. if(evt.target !== this.domNode || this.focusedChild){ return; }
  16593. this.focusFirstChild();
  16594. // and then set the container's tabIndex to -1,
  16595. // (don't remove as that breaks Safari 4)
  16596. // so that tab or shift-tab will go to the fields after/before
  16597. // the container, rather than the container itself
  16598. domAttr.set(this.domNode, "tabIndex", "-1");
  16599. },
  16600. _onBlur: function(evt){
  16601. // When focus is moved away the container, and its descendant (popup) widgets,
  16602. // then restore the container's tabIndex so that user can tab to it again.
  16603. // Note that using _onBlur() so that this doesn't happen when focus is shifted
  16604. // to one of my child widgets (typically a popup)
  16605. if(this.tabIndex){
  16606. domAttr.set(this.domNode, "tabIndex", this.tabIndex);
  16607. }
  16608. this.focusedChild = null;
  16609. this.inherited(arguments);
  16610. },
  16611. _onContainerKeypress: function(evt){
  16612. // summary:
  16613. // When a key is pressed, if it's an arrow key etc. then
  16614. // it's handled here.
  16615. // tags:
  16616. // private
  16617. if(evt.ctrlKey || evt.altKey){ return; }
  16618. var func = this._keyNavCodes[evt.charOrCode];
  16619. if(func){
  16620. func();
  16621. event.stop(evt);
  16622. }
  16623. },
  16624. _onChildBlur: function(/*dijit._Widget*/ /*===== widget =====*/){
  16625. // summary:
  16626. // Called when focus leaves a child widget to go
  16627. // to a sibling widget.
  16628. // Used by MenuBase.js (TODO: move code there)
  16629. // tags:
  16630. // protected
  16631. },
  16632. _getFirstFocusableChild: function(){
  16633. // summary:
  16634. // Returns first child that can be focused
  16635. return this._getNextFocusableChild(null, 1); // dijit._Widget
  16636. },
  16637. _getLastFocusableChild: function(){
  16638. // summary:
  16639. // Returns last child that can be focused
  16640. return this._getNextFocusableChild(null, -1); // dijit._Widget
  16641. },
  16642. _getNextFocusableChild: function(child, dir){
  16643. // summary:
  16644. // Returns the next or previous focusable child, compared
  16645. // to "child"
  16646. // child: Widget
  16647. // The current widget
  16648. // dir: Integer
  16649. // * 1 = after
  16650. // * -1 = before
  16651. if(child){
  16652. child = this._getSiblingOfChild(child, dir);
  16653. }
  16654. var children = this.getChildren();
  16655. for(var i=0; i < children.length; i++){
  16656. if(!child){
  16657. child = children[(dir>0) ? 0 : (children.length-1)];
  16658. }
  16659. if(child.isFocusable()){
  16660. return child; // dijit._Widget
  16661. }
  16662. child = this._getSiblingOfChild(child, dir);
  16663. }
  16664. // no focusable child found
  16665. return null; // dijit._Widget
  16666. }
  16667. });
  16668. });
  16669. },
  16670. 'dijit/layout/utils':function(){
  16671. define("dijit/layout/utils", [
  16672. "dojo/_base/array", // array.filter array.forEach
  16673. "dojo/dom-class", // domClass.add domClass.remove
  16674. "dojo/dom-geometry", // domGeometry.marginBox
  16675. "dojo/dom-style", // domStyle.getComputedStyle
  16676. "dojo/_base/lang", // lang.mixin
  16677. ".." // for exporting symbols to dijit, remove in 2.0
  16678. ], function(array, domClass, domGeometry, domStyle, lang, dijit){
  16679. // module:
  16680. // dijit/layout/utils
  16681. // summary:
  16682. // marginBox2contentBox() and layoutChildren()
  16683. var layout = lang.getObject("layout", true, dijit);
  16684. /*===== layout = dijit.layout =====*/
  16685. layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
  16686. // summary:
  16687. // Given the margin-box size of a node, return its content box size.
  16688. // Functions like domGeometry.contentBox() but is more reliable since it doesn't have
  16689. // to wait for the browser to compute sizes.
  16690. var cs = domStyle.getComputedStyle(node);
  16691. var me = domGeometry.getMarginExtents(node, cs);
  16692. var pb = domGeometry.getPadBorderExtents(node, cs);
  16693. return {
  16694. l: domStyle.toPixelValue(node, cs.paddingLeft),
  16695. t: domStyle.toPixelValue(node, cs.paddingTop),
  16696. w: mb.w - (me.w + pb.w),
  16697. h: mb.h - (me.h + pb.h)
  16698. };
  16699. };
  16700. function capitalize(word){
  16701. return word.substring(0,1).toUpperCase() + word.substring(1);
  16702. }
  16703. function size(widget, dim){
  16704. // size the child
  16705. var newSize = widget.resize ? widget.resize(dim) : domGeometry.setMarginBox(widget.domNode, dim);
  16706. // record child's size
  16707. if(newSize){
  16708. // if the child returned it's new size then use that
  16709. lang.mixin(widget, newSize);
  16710. }else{
  16711. // otherwise, call getMarginBox(), but favor our own numbers when we have them.
  16712. // the browser lies sometimes
  16713. lang.mixin(widget, domGeometry.getMarginBox(widget.domNode));
  16714. lang.mixin(widget, dim);
  16715. }
  16716. }
  16717. layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children,
  16718. /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){
  16719. // summary:
  16720. // Layout a bunch of child dom nodes within a parent dom node
  16721. // container:
  16722. // parent node
  16723. // dim:
  16724. // {l, t, w, h} object specifying dimensions of container into which to place children
  16725. // children:
  16726. // an array of Widgets or at least objects containing:
  16727. // * domNode: pointer to DOM node to position
  16728. // * region or layoutAlign: position to place DOM node
  16729. // * resize(): (optional) method to set size of node
  16730. // * id: (optional) Id of widgets, referenced from resize object, below.
  16731. // changedRegionId:
  16732. // If specified, the slider for the region with the specified id has been dragged, and thus
  16733. // the region's height or width should be adjusted according to changedRegionSize
  16734. // changedRegionSize:
  16735. // See changedRegionId.
  16736. // copy dim because we are going to modify it
  16737. dim = lang.mixin({}, dim);
  16738. domClass.add(container, "dijitLayoutContainer");
  16739. // Move "client" elements to the end of the array for layout. a11y dictates that the author
  16740. // needs to be able to put them in the document in tab-order, but this algorithm requires that
  16741. // client be last. TODO: move these lines to LayoutContainer? Unneeded other places I think.
  16742. children = array.filter(children, function(item){ return item.region != "center" && item.layoutAlign != "client"; })
  16743. .concat(array.filter(children, function(item){ return item.region == "center" || item.layoutAlign == "client"; }));
  16744. // set positions/sizes
  16745. array.forEach(children, function(child){
  16746. var elm = child.domNode,
  16747. pos = (child.region || child.layoutAlign);
  16748. if(!pos){
  16749. throw new Error("No region setting for " + child.id)
  16750. }
  16751. // set elem to upper left corner of unused space; may move it later
  16752. var elmStyle = elm.style;
  16753. elmStyle.left = dim.l+"px";
  16754. elmStyle.top = dim.t+"px";
  16755. elmStyle.position = "absolute";
  16756. domClass.add(elm, "dijitAlign" + capitalize(pos));
  16757. // Size adjustments to make to this child widget
  16758. var sizeSetting = {};
  16759. // Check for optional size adjustment due to splitter drag (height adjustment for top/bottom align
  16760. // panes and width adjustment for left/right align panes.
  16761. if(changedRegionId && changedRegionId == child.id){
  16762. sizeSetting[child.region == "top" || child.region == "bottom" ? "h" : "w"] = changedRegionSize;
  16763. }
  16764. // set size && adjust record of remaining space.
  16765. // note that setting the width of a <div> may affect its height.
  16766. if(pos == "top" || pos == "bottom"){
  16767. sizeSetting.w = dim.w;
  16768. size(child, sizeSetting);
  16769. dim.h -= child.h;
  16770. if(pos == "top"){
  16771. dim.t += child.h;
  16772. }else{
  16773. elmStyle.top = dim.t + dim.h + "px";
  16774. }
  16775. }else if(pos == "left" || pos == "right"){
  16776. sizeSetting.h = dim.h;
  16777. size(child, sizeSetting);
  16778. dim.w -= child.w;
  16779. if(pos == "left"){
  16780. dim.l += child.w;
  16781. }else{
  16782. elmStyle.left = dim.l + dim.w + "px";
  16783. }
  16784. }else if(pos == "client" || pos == "center"){
  16785. size(child, dim);
  16786. }
  16787. });
  16788. };
  16789. return {
  16790. marginBox2contentBox: layout.marginBox2contentBox,
  16791. layoutChildren: layout.layoutChildren
  16792. };
  16793. });
  16794. },
  16795. 'dijit/_Contained':function(){
  16796. define("dijit/_Contained", [
  16797. "dojo/_base/declare", // declare
  16798. "./registry" // registry.getEnclosingWidget(), registry.byNode()
  16799. ], function(declare, registry){
  16800. // module:
  16801. // dijit/_Contained
  16802. // summary:
  16803. // Mixin for widgets that are children of a container widget
  16804. return declare("dijit._Contained", null, {
  16805. // summary:
  16806. // Mixin for widgets that are children of a container widget
  16807. //
  16808. // example:
  16809. // | // make a basic custom widget that knows about it's parents
  16810. // | declare("my.customClass",[dijit._Widget,dijit._Contained],{});
  16811. _getSibling: function(/*String*/ which){
  16812. // summary:
  16813. // Returns next or previous sibling
  16814. // which:
  16815. // Either "next" or "previous"
  16816. // tags:
  16817. // private
  16818. var node = this.domNode;
  16819. do{
  16820. node = node[which+"Sibling"];
  16821. }while(node && node.nodeType != 1);
  16822. return node && registry.byNode(node); // dijit._Widget
  16823. },
  16824. getPreviousSibling: function(){
  16825. // summary:
  16826. // Returns null if this is the first child of the parent,
  16827. // otherwise returns the next element sibling to the "left".
  16828. return this._getSibling("previous"); // dijit._Widget
  16829. },
  16830. getNextSibling: function(){
  16831. // summary:
  16832. // Returns null if this is the last child of the parent,
  16833. // otherwise returns the next element sibling to the "right".
  16834. return this._getSibling("next"); // dijit._Widget
  16835. },
  16836. getIndexInParent: function(){
  16837. // summary:
  16838. // Returns the index of this widget within its container parent.
  16839. // It returns -1 if the parent does not exist, or if the parent
  16840. // is not a dijit._Container
  16841. var p = this.getParent();
  16842. if(!p || !p.getIndexOfChild){
  16843. return -1; // int
  16844. }
  16845. return p.getIndexOfChild(this); // int
  16846. }
  16847. });
  16848. });
  16849. },
  16850. 'dojox/json/query':function(){
  16851. define("dojox/json/query", ["dojo/_base/kernel", "dojox", "dojo/_base/array"], function(dojo, dojox){
  16852. dojo.getObject("json", true, dojox);
  16853. dojox.json._slice = function(obj,start,end,step){
  16854. // handles slice operations: [3:6:2]
  16855. var len=obj.length,results = [];
  16856. end = end || len;
  16857. start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
  16858. end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
  16859. for(var i=start; i<end; i+=step){
  16860. results.push(obj[i]);
  16861. }
  16862. return results;
  16863. }
  16864. dojox.json._find = function e(obj,name){
  16865. // handles ..name, .*, [*], [val1,val2], [val]
  16866. // name can be a property to search for, undefined for full recursive, or an array for picking by index
  16867. var results = [];
  16868. function walk(obj){
  16869. if(name){
  16870. if(name===true && !(obj instanceof Array)){
  16871. //recursive object search
  16872. results.push(obj);
  16873. }else if(obj[name]){
  16874. // found the name, add to our results
  16875. results.push(obj[name]);
  16876. }
  16877. }
  16878. for(var i in obj){
  16879. var val = obj[i];
  16880. if(!name){
  16881. // if we don't have a name we are just getting all the properties values (.* or [*])
  16882. results.push(val);
  16883. }else if(val && typeof val == 'object'){
  16884. walk(val);
  16885. }
  16886. }
  16887. }
  16888. if(name instanceof Array){
  16889. // this is called when multiple items are in the brackets: [3,4,5]
  16890. if(name.length==1){
  16891. // this can happen as a result of the parser becoming confused about commas
  16892. // in the brackets like [@.func(4,2)]. Fixing the parser would require recursive
  16893. // analsys, very expensive, but this fixes the problem nicely.
  16894. return obj[name[0]];
  16895. }
  16896. for(var i = 0; i < name.length; i++){
  16897. results.push(obj[name[i]]);
  16898. }
  16899. }else{
  16900. // otherwise we expanding
  16901. walk(obj);
  16902. }
  16903. return results;
  16904. }
  16905. dojox.json._distinctFilter = function(array, callback){
  16906. // does the filter with removal of duplicates in O(n)
  16907. var outArr = [];
  16908. var primitives = {};
  16909. for(var i=0,l=array.length; i<l; ++i){
  16910. var value = array[i];
  16911. if(callback(value, i, array)){
  16912. if((typeof value == 'object') && value){
  16913. // with objects we prevent duplicates with a marker property
  16914. if(!value.__included){
  16915. value.__included = true;
  16916. outArr.push(value);
  16917. }
  16918. }else if(!primitives[value + typeof value]){
  16919. // with primitives we prevent duplicates by putting it in a map
  16920. primitives[value + typeof value] = true;
  16921. outArr.push(value);
  16922. }
  16923. }
  16924. }
  16925. for(i=0,l=outArr.length; i<l; ++i){
  16926. // cleanup the marker properties
  16927. if(outArr[i]){
  16928. delete outArr[i].__included;
  16929. }
  16930. }
  16931. return outArr;
  16932. }
  16933. return dojox.json.query = function(/*String*/query,/*Object?*/obj){
  16934. // summary:
  16935. // Performs a JSONQuery on the provided object and returns the results.
  16936. // If no object is provided (just a query), it returns a "compiled" function that evaluates objects
  16937. // according to the provided query.
  16938. // query:
  16939. // Query string
  16940. // obj:
  16941. // Target of the JSONQuery
  16942. //
  16943. // description:
  16944. // JSONQuery provides a comprehensive set of data querying tools including filtering,
  16945. // recursive search, sorting, mapping, range selection, and powerful expressions with
  16946. // wildcard string comparisons and various operators. JSONQuery generally supersets
  16947. // JSONPath and provides syntax that matches and behaves like JavaScript where
  16948. // possible.
  16949. //
  16950. // JSONQuery evaluations begin with the provided object, which can referenced with
  16951. // $. From
  16952. // the starting object, various operators can be successively applied, each operating
  16953. // on the result of the last operation.
  16954. //
  16955. // Supported Operators:
  16956. // --------------------
  16957. // * .property - This will return the provided property of the object, behaving exactly
  16958. // like JavaScript.
  16959. // * [expression] - This returns the property name/index defined by the evaluation of
  16960. // the provided expression, behaving exactly like JavaScript.
  16961. // * [?expression] - This will perform a filter operation on an array, returning all the
  16962. // items in an array that match the provided expression. This operator does not
  16963. // need to be in brackets, you can simply use ?expression, but since it does not
  16964. // have any containment, no operators can be used afterwards when used
  16965. // without brackets.
  16966. // * [^?expression] - This will perform a distinct filter operation on an array. This behaves
  16967. // as [?expression] except that it will remove any duplicate values/objects from the
  16968. // result set.
  16969. // * [/expression], [\expression], [/expression, /expression] - This performs a sort
  16970. // operation on an array, with sort based on the provide expression. Multiple comma delimited sort
  16971. // expressions can be provided for multiple sort orders (first being highest priority). /
  16972. // indicates ascending order and \ indicates descending order
  16973. // * [=expression] - This performs a map operation on an array, creating a new array
  16974. // with each item being the evaluation of the expression for each item in the source array.
  16975. // * [start:end:step] - This performs an array slice/range operation, returning the elements
  16976. // from the optional start index to the optional end index, stepping by the optional step number.
  16977. // * [expr,expr] - This a union operator, returning an array of all the property/index values from
  16978. // the evaluation of the comma delimited expressions.
  16979. // * .* or [*] - This returns the values of all the properties of the current object.
  16980. // * $ - This is the root object, If a JSONQuery expression does not being with a $,
  16981. // it will be auto-inserted at the beginning.
  16982. // * @ - This is the current object in filter, sort, and map expressions. This is generally
  16983. // not necessary, names are auto-converted to property references of the current object
  16984. // in expressions.
  16985. // * ..property - Performs a recursive search for the given property name, returning
  16986. // an array of all values with such a property name in the current object and any subobjects
  16987. // * expr = expr - Performs a comparison (like JS's ==). When comparing to
  16988. // a string, the comparison string may contain wildcards * (matches any number of
  16989. // characters) and ? (matches any single character).
  16990. // * expr ~ expr - Performs a string comparison with case insensitivity.
  16991. // * ..[?expression] - This will perform a deep search filter operation on all the objects and
  16992. // subobjects of the current data. Rather than only searching an array, this will search
  16993. // property values, arrays, and their children.
  16994. // * $1,$2,$3, etc. - These are references to extra parameters passed to the query
  16995. // function or the evaluator function.
  16996. // * +, -, /, *, &, |, %, (, ), <, >, <=, >=, != - These operators behave just as they do
  16997. // in JavaScript.
  16998. //
  16999. //
  17000. //
  17001. // | dojox.json.query(queryString,object)
  17002. // and
  17003. // | dojox.json.query(queryString)(object)
  17004. // always return identical results. The first one immediately evaluates, the second one returns a
  17005. // function that then evaluates the object.
  17006. //
  17007. // example:
  17008. // | dojox.json.query("foo",{foo:"bar"})
  17009. // This will return "bar".
  17010. //
  17011. // example:
  17012. // | evaluator = dojox.json.query("?foo='bar'&rating>3");
  17013. // This creates a function that finds all the objects in an array with a property
  17014. // foo that is equals to "bar" and with a rating property with a value greater
  17015. // than 3.
  17016. // | evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}])
  17017. // This returns:
  17018. // | {foo:"bar",rating:4}
  17019. //
  17020. // example:
  17021. // | evaluator = dojox.json.query("$[?price<15.00][\rating][0:10]");
  17022. // This finds objects in array with a price less than 15.00 and sorts then
  17023. // by rating, highest rated first, and returns the first ten items in from this
  17024. // filtered and sorted list.
  17025. var depth = 0;
  17026. var str = [];
  17027. query = query.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,function(t){
  17028. depth += t == '[' ? 1 : t == ']' ? -1 : 0; // keep track of bracket depth
  17029. return (t == ']' && depth > 0) ? '`]' : // we mark all the inner brackets as skippable
  17030. (t.charAt(0) == '"' || t.charAt(0) == "'") ? "`" + (str.push(t) - 1) :// and replace all the strings
  17031. t;
  17032. });
  17033. var prefix = '';
  17034. function call(name){
  17035. // creates a function call and puts the expression so far in a parameter for a call
  17036. prefix = name + "(" + prefix;
  17037. }
  17038. function makeRegex(t,a,b,c,d,e,f,g){
  17039. // creates a regular expression matcher for when wildcards and ignore case is used
  17040. return str[g].match(/[\*\?]/) || f == '~' ?
  17041. "/^" + str[g].substring(1,str[g].length-1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g,"\\$1$2").replace(/([\*\?])/g,"[\\w\\W]$1") + (f == '~' ? '$/i' : '$/') + ".test(" + a + ")" :
  17042. t;
  17043. }
  17044. query.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,function(){
  17045. throw new Error("Unsafe function call");
  17046. });
  17047. query = query.replace(/([^<>=]=)([^=])/g,"$1=$2"). // change the equals to comparisons except operators ==, <=, >=
  17048. replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,function(t){
  17049. return t.charAt(0) == '.' ? t : // leave .prop alone
  17050. t == '@' ? "$obj" :// the reference to the current object
  17051. (t.match(/:|^(\$|Math|true|false|null)$/) ? "" : "$obj.") + t; // plain names should be properties of root... unless they are a label in object initializer
  17052. }).
  17053. replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,function(t,a,b){
  17054. var oper = t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/); // [?expr] and ?expr and [=expr and =expr
  17055. if(oper){
  17056. var prefix = '';
  17057. if(t.match(/^\./)){
  17058. // recursive object search
  17059. call("dojox.json._find");
  17060. prefix = ",true)";
  17061. }
  17062. call(oper[1].match(/\=/) ? "dojo.map" : oper[1].match(/\^/) ? "dojox.json._distinctFilter" : "dojo.filter");
  17063. return prefix + ",function($obj){return " + oper[2] + "})";
  17064. }
  17065. oper = t.match(/^\[\s*([\/\\].*)\]/); // [/sortexpr,\sortexpr]
  17066. if(oper){
  17067. // make a copy of the array and then sort it using the sorting expression
  17068. return ".concat().sort(function(a,b){" + oper[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,function(t,a,b){
  17069. return "var av= " + b.replace(/\$obj/,"a") + ",bv= " + b.replace(/\$obj/,"b") + // FIXME: Should check to make sure the $obj token isn't followed by characters
  17070. ";if(av>bv||bv==null){return " + (a== "/" ? 1 : -1) +";}\n" +
  17071. "if(bv>av||av==null){return " + (a== "/" ? -1 : 1) +";}\n";
  17072. }) + "return 0;})";
  17073. }
  17074. oper = t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/); // slice [0:3]
  17075. if(oper){
  17076. call("dojox.json._slice");
  17077. return "," + (oper[1] || 0) + "," + (oper[2] || 0) + "," + (oper[3] || 1) + ")";
  17078. }
  17079. if(t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)){ // ..prop and [*]
  17080. call("dojox.json._find");
  17081. return (t.charAt(1) == '.' ?
  17082. ",'" + b + "'" : // ..prop
  17083. t.match(/,/) ?
  17084. "," + t : // [prop1,prop2]
  17085. "") + ")"; // [*]
  17086. }
  17087. return t;
  17088. }).
  17089. replace(/(\$obj\s*((\.\s*[\w_$]+\s*)|(\[\s*`([0-9]+)\s*`\]))*)(==|~)\s*`([0-9]+)/g,makeRegex). // create regex matching
  17090. replace(/`([0-9]+)\s*(==|~)\s*(\$obj\s*((\.\s*[\w_$]+)|(\[\s*`([0-9]+)\s*`\]))*)/g,function(t,a,b,c,d,e,f,g){ // and do it for reverse =
  17091. return makeRegex(t,c,d,e,f,g,b,a);
  17092. });
  17093. query = prefix + (query.charAt(0) == '$' ? "" : "$") + query.replace(/`([0-9]+|\])/g,function(t,a){
  17094. //restore the strings
  17095. return a == ']' ? ']' : str[a];
  17096. });
  17097. // create a function within this scope (so it can use expand and slice)
  17098. var executor = eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return " + query + "}");
  17099. for(var i = 0;i<arguments.length-1;i++){
  17100. arguments[i] = arguments[i+1];
  17101. }
  17102. return obj ? executor.apply(this,arguments) : executor;
  17103. };
  17104. });
  17105. },
  17106. 'dijit/tree/_dndSelector':function(){
  17107. define("dijit/tree/_dndSelector", [
  17108. "dojo/_base/array", // array.filter array.forEach array.map
  17109. "dojo/_base/connect", // connect.isCopyKey
  17110. "dojo/_base/declare", // declare
  17111. "dojo/_base/lang", // lang.hitch
  17112. "dojo/mouse", // mouse.isLeft
  17113. "dojo/on",
  17114. "dojo/touch",
  17115. "dojo/_base/window", // win.global
  17116. "./_dndContainer"
  17117. ], function(array, connect, declare, lang, mouse, on, touch, win, _dndContainer){
  17118. // module:
  17119. // dijit/tree/_dndSelector
  17120. // summary:
  17121. // This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
  17122. // It's based on `dojo.dnd.Selector`.
  17123. return declare("dijit.tree._dndSelector", _dndContainer, {
  17124. // summary:
  17125. // This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
  17126. // It's based on `dojo.dnd.Selector`.
  17127. // tags:
  17128. // protected
  17129. /*=====
  17130. // selection: Hash<String, DomNode>
  17131. // (id, DomNode) map for every TreeNode that's currently selected.
  17132. // The DOMNode is the TreeNode.rowNode.
  17133. selection: {},
  17134. =====*/
  17135. constructor: function(){
  17136. // summary:
  17137. // Initialization
  17138. // tags:
  17139. // private
  17140. this.selection={};
  17141. this.anchor = null;
  17142. this.tree.domNode.setAttribute("aria-multiselect", !this.singular);
  17143. this.events.push(
  17144. on(this.tree.domNode, touch.press, lang.hitch(this,"onMouseDown")),
  17145. on(this.tree.domNode, touch.release, lang.hitch(this,"onMouseUp")),
  17146. on(this.tree.domNode, touch.move, lang.hitch(this,"onMouseMove"))
  17147. );
  17148. },
  17149. // singular: Boolean
  17150. // Allows selection of only one element, if true.
  17151. // Tree hasn't been tested in singular=true mode, unclear if it works.
  17152. singular: false,
  17153. // methods
  17154. getSelectedTreeNodes: function(){
  17155. // summary:
  17156. // Returns a list of selected node(s).
  17157. // Used by dndSource on the start of a drag.
  17158. // tags:
  17159. // protected
  17160. var nodes=[], sel = this.selection;
  17161. for(var i in sel){
  17162. nodes.push(sel[i]);
  17163. }
  17164. return nodes;
  17165. },
  17166. selectNone: function(){
  17167. // summary:
  17168. // Unselects all items
  17169. // tags:
  17170. // private
  17171. this.setSelection([]);
  17172. return this; // self
  17173. },
  17174. destroy: function(){
  17175. // summary:
  17176. // Prepares the object to be garbage-collected
  17177. this.inherited(arguments);
  17178. this.selection = this.anchor = null;
  17179. },
  17180. addTreeNode: function(/*dijit._TreeNode*/node, /*Boolean?*/isAnchor){
  17181. // summary:
  17182. // add node to current selection
  17183. // node: Node
  17184. // node to add
  17185. // isAnchor: Boolean
  17186. // Whether the node should become anchor.
  17187. this.setSelection(this.getSelectedTreeNodes().concat( [node] ));
  17188. if(isAnchor){ this.anchor = node; }
  17189. return node;
  17190. },
  17191. removeTreeNode: function(/*dijit._TreeNode*/node){
  17192. // summary:
  17193. // remove node from current selection
  17194. // node: Node
  17195. // node to remove
  17196. this.setSelection(this._setDifference(this.getSelectedTreeNodes(), [node]));
  17197. return node;
  17198. },
  17199. isTreeNodeSelected: function(/*dijit._TreeNode*/node){
  17200. // summary:
  17201. // return true if node is currently selected
  17202. // node: Node
  17203. // the node to check whether it's in the current selection
  17204. return node.id && !!this.selection[node.id];
  17205. },
  17206. setSelection: function(/*dijit._treeNode[]*/ newSelection){
  17207. // summary:
  17208. // set the list of selected nodes to be exactly newSelection. All changes to the
  17209. // selection should be passed through this function, which ensures that derived
  17210. // attributes are kept up to date. Anchor will be deleted if it has been removed
  17211. // from the selection, but no new anchor will be added by this function.
  17212. // newSelection: Node[]
  17213. // list of tree nodes to make selected
  17214. var oldSelection = this.getSelectedTreeNodes();
  17215. array.forEach(this._setDifference(oldSelection, newSelection), lang.hitch(this, function(node){
  17216. node.setSelected(false);
  17217. if(this.anchor == node){
  17218. delete this.anchor;
  17219. }
  17220. delete this.selection[node.id];
  17221. }));
  17222. array.forEach(this._setDifference(newSelection, oldSelection), lang.hitch(this, function(node){
  17223. node.setSelected(true);
  17224. this.selection[node.id] = node;
  17225. }));
  17226. this._updateSelectionProperties();
  17227. },
  17228. _setDifference: function(xs,ys){
  17229. // summary:
  17230. // Returns a copy of xs which lacks any objects
  17231. // occurring in ys. Checks for membership by
  17232. // modifying and then reading the object, so it will
  17233. // not properly handle sets of numbers or strings.
  17234. array.forEach(ys, function(y){ y.__exclude__ = true; });
  17235. var ret = array.filter(xs, function(x){ return !x.__exclude__; });
  17236. // clean up after ourselves.
  17237. array.forEach(ys, function(y){ delete y['__exclude__'] });
  17238. return ret;
  17239. },
  17240. _updateSelectionProperties: function(){
  17241. // summary:
  17242. // Update the following tree properties from the current selection:
  17243. // path[s], selectedItem[s], selectedNode[s]
  17244. var selected = this.getSelectedTreeNodes();
  17245. var paths = [], nodes = [];
  17246. array.forEach(selected, function(node){
  17247. nodes.push(node);
  17248. paths.push(node.getTreePath());
  17249. });
  17250. var items = array.map(nodes,function(node){ return node.item; });
  17251. this.tree._set("paths", paths);
  17252. this.tree._set("path", paths[0] || []);
  17253. this.tree._set("selectedNodes", nodes);
  17254. this.tree._set("selectedNode", nodes[0] || null);
  17255. this.tree._set("selectedItems", items);
  17256. this.tree._set("selectedItem", items[0] || null);
  17257. },
  17258. // mouse events
  17259. onMouseDown: function(e){
  17260. // summary:
  17261. // Event processor for onmousedown/ontouchstart
  17262. // e: Event
  17263. // onmousedown/ontouchstart event
  17264. // tags:
  17265. // protected
  17266. // ignore click on expando node
  17267. if(!this.current || this.tree.isExpandoNode(e.target, this.current)){ return; }
  17268. if(e.type == "mousedown" && mouse.isLeft(e)){
  17269. // Prevent text selection while dragging on desktop, see #16328. But don't call preventDefault()
  17270. // for mobile because it will break things completely, see #15838. Also, don't preventDefault() on
  17271. // MSPointerDown or pointerdown events, because that stops the mousedown event from being generated,
  17272. // see #17709.
  17273. // TODO: remove this completely in 2.0. It shouldn't be needed since dojo/dnd/Manager already
  17274. // calls preventDefault() for the "selectstart" event. It can also be achieved via CSS:
  17275. // http://stackoverflow.com/questions/826782/css-rule-to-disable-text-selection-highlighting
  17276. e.preventDefault();
  17277. }else if(e.type != "touchstart"){
  17278. // Ignore right click
  17279. return;
  17280. }
  17281. var treeNode = this.current,
  17282. copy = connect.isCopyKey(e), id = treeNode.id;
  17283. // if shift key is not pressed, and the node is already in the selection,
  17284. // delay deselection until onmouseup so in the case of DND, deselection
  17285. // will be canceled by onmousemove.
  17286. if(!this.singular && !e.shiftKey && this.selection[id]){
  17287. this._doDeselect = true;
  17288. return;
  17289. }else{
  17290. this._doDeselect = false;
  17291. }
  17292. this.userSelect(treeNode, copy, e.shiftKey);
  17293. },
  17294. onMouseUp: function(e){
  17295. // summary:
  17296. // Event processor for onmouseup/ontouchend
  17297. // e: Event
  17298. // onmouseup/ontouchend event
  17299. // tags:
  17300. // protected
  17301. // _doDeselect is the flag to indicate that the user wants to either ctrl+click on
  17302. // a already selected item (to deselect the item), or click on a not-yet selected item
  17303. // (which should remove all current selection, and add the clicked item). This can not
  17304. // be done in onMouseDown, because the user may start a drag after mousedown. By moving
  17305. // the deselection logic here, the user can drags an already selected item.
  17306. if(!this._doDeselect){ return; }
  17307. this._doDeselect = false;
  17308. this.userSelect(this.current, connect.isCopyKey(e), e.shiftKey);
  17309. },
  17310. onMouseMove: function(/*===== e =====*/){
  17311. // summary:
  17312. // event processor for onmousemove/ontouchmove
  17313. // e: Event
  17314. // onmousemove/ontouchmove event
  17315. this._doDeselect = false;
  17316. },
  17317. _compareNodes: function(n1, n2){
  17318. if(n1 === n2){
  17319. return 0;
  17320. }
  17321. if('sourceIndex' in document.documentElement){ //IE
  17322. //TODO: does not yet work if n1 and/or n2 is a text node
  17323. return n1.sourceIndex - n2.sourceIndex;
  17324. }else if('compareDocumentPosition' in document.documentElement){ //FF, Opera
  17325. return n1.compareDocumentPosition(n2) & 2 ? 1: -1;
  17326. }else if(document.createRange){ //Webkit
  17327. var r1 = doc.createRange();
  17328. r1.setStartBefore(n1);
  17329. var r2 = doc.createRange();
  17330. r2.setStartBefore(n2);
  17331. return r1.compareBoundaryPoints(r1.END_TO_END, r2);
  17332. }else{
  17333. throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser");
  17334. }
  17335. },
  17336. userSelect: function(node, multi, range){
  17337. // summary:
  17338. // Add or remove the given node from selection, responding
  17339. // to a user action such as a click or keypress.
  17340. // multi: Boolean
  17341. // Indicates whether this is meant to be a multi-select action (e.g. ctrl-click)
  17342. // range: Boolean
  17343. // Indicates whether this is meant to be a ranged action (e.g. shift-click)
  17344. // tags:
  17345. // protected
  17346. if(this.singular){
  17347. if(this.anchor == node && multi){
  17348. this.selectNone();
  17349. }else{
  17350. this.setSelection([node]);
  17351. this.anchor = node;
  17352. }
  17353. }else{
  17354. if(range && this.anchor){
  17355. var cr = this._compareNodes(this.anchor.rowNode, node.rowNode),
  17356. begin, end, anchor = this.anchor;
  17357. if(cr < 0){ //current is after anchor
  17358. begin = anchor;
  17359. end = node;
  17360. }else{ //current is before anchor
  17361. begin = node;
  17362. end = anchor;
  17363. }
  17364. var nodes = [];
  17365. //add everything betweeen begin and end inclusively
  17366. while(begin != end){
  17367. nodes.push(begin);
  17368. begin = this.tree._getNextNode(begin);
  17369. }
  17370. nodes.push(end);
  17371. this.setSelection(nodes);
  17372. }else{
  17373. if( this.selection[ node.id ] && multi ){
  17374. this.removeTreeNode( node );
  17375. }else if(multi){
  17376. this.addTreeNode(node, true);
  17377. }else{
  17378. this.setSelection([node]);
  17379. this.anchor = node;
  17380. }
  17381. }
  17382. }
  17383. },
  17384. getItem: function(/*String*/ key){
  17385. // summary:
  17386. // Returns the dojo.dnd.Item (representing a dragged node) by it's key (id).
  17387. // Called by dojo.dnd.Source.checkAcceptance().
  17388. // tags:
  17389. // protected
  17390. var widget = this.selection[key];
  17391. return {
  17392. data: widget,
  17393. type: ["treeNode"]
  17394. }; // dojo.dnd.Item
  17395. },
  17396. forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
  17397. // summary:
  17398. // Iterates over selected items;
  17399. // see `dojo.dnd.Container.forInItems()` for details
  17400. o = o || win.global;
  17401. for(var id in this.selection){
  17402. // console.log("selected item id: " + id);
  17403. f.call(o, this.getItem(id), id, this);
  17404. }
  17405. }
  17406. });
  17407. });
  17408. },
  17409. 'dijit/_Container':function(){
  17410. define("dijit/_Container", [
  17411. "dojo/_base/array", // array.forEach array.indexOf
  17412. "dojo/_base/declare", // declare
  17413. "dojo/dom-construct", // domConstruct.place
  17414. "./registry" // registry.byNode()
  17415. ], function(array, declare, domConstruct, registry){
  17416. // module:
  17417. // dijit/_Container
  17418. // summary:
  17419. // Mixin for widgets that contain a set of widget children.
  17420. return declare("dijit._Container", null, {
  17421. // summary:
  17422. // Mixin for widgets that contain a set of widget children.
  17423. // description:
  17424. // Use this mixin for widgets that needs to know about and
  17425. // keep track of their widget children. Suitable for widgets like BorderContainer
  17426. // and TabContainer which contain (only) a set of child widgets.
  17427. //
  17428. // It's not suitable for widgets like ContentPane
  17429. // which contains mixed HTML (plain DOM nodes in addition to widgets),
  17430. // and where contained widgets are not necessarily directly below
  17431. // this.containerNode. In that case calls like addChild(node, position)
  17432. // wouldn't make sense.
  17433. buildRendering: function(){
  17434. this.inherited(arguments);
  17435. if(!this.containerNode){
  17436. // all widgets with descendants must set containerNode
  17437. this.containerNode = this.domNode;
  17438. }
  17439. },
  17440. addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
  17441. // summary:
  17442. // Makes the given widget a child of this widget.
  17443. // description:
  17444. // Inserts specified child widget's dom node as a child of this widget's
  17445. // container node, and possibly does other processing (such as layout).
  17446. var refNode = this.containerNode;
  17447. if(insertIndex && typeof insertIndex == "number"){
  17448. var children = this.getChildren();
  17449. if(children && children.length >= insertIndex){
  17450. refNode = children[insertIndex-1].domNode;
  17451. insertIndex = "after";
  17452. }
  17453. }
  17454. domConstruct.place(widget.domNode, refNode, insertIndex);
  17455. // If I've been started but the child widget hasn't been started,
  17456. // start it now. Make sure to do this after widget has been
  17457. // inserted into the DOM tree, so it can see that it's being controlled by me,
  17458. // so it doesn't try to size itself.
  17459. if(this._started && !widget._started){
  17460. widget.startup();
  17461. }
  17462. },
  17463. removeChild: function(/*Widget|int*/ widget){
  17464. // summary:
  17465. // Removes the passed widget instance from this widget but does
  17466. // not destroy it. You can also pass in an integer indicating
  17467. // the index within the container to remove
  17468. if(typeof widget == "number"){
  17469. widget = this.getChildren()[widget];
  17470. }
  17471. if(widget){
  17472. var node = widget.domNode;
  17473. if(node && node.parentNode){
  17474. node.parentNode.removeChild(node); // detach but don't destroy
  17475. }
  17476. }
  17477. },
  17478. hasChildren: function(){
  17479. // summary:
  17480. // Returns true if widget has children, i.e. if this.containerNode contains something.
  17481. return this.getChildren().length > 0; // Boolean
  17482. },
  17483. _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
  17484. // summary:
  17485. // Get the next or previous widget sibling of child
  17486. // dir:
  17487. // if 1, get the next sibling
  17488. // if -1, get the previous sibling
  17489. // tags:
  17490. // private
  17491. var node = child.domNode,
  17492. which = (dir>0 ? "nextSibling" : "previousSibling");
  17493. do{
  17494. node = node[which];
  17495. }while(node && (node.nodeType != 1 || !registry.byNode(node)));
  17496. return node && registry.byNode(node); // dijit._Widget
  17497. },
  17498. getIndexOfChild: function(/*dijit._Widget*/ child){
  17499. // summary:
  17500. // Gets the index of the child in this container or -1 if not found
  17501. return array.indexOf(this.getChildren(), child); // int
  17502. }
  17503. });
  17504. });
  17505. },
  17506. 'dojo/dnd/Source':function(){
  17507. define("dojo/dnd/Source", ["../main", "./Selector", "./Manager"], function(dojo, Selector, Manager) {
  17508. // module:
  17509. // dojo/dnd/Source
  17510. // summary:
  17511. // TODOC
  17512. /*=====
  17513. Selector = dojo.dnd.Selector;
  17514. =====*/
  17515. /*
  17516. Container property:
  17517. "Horizontal"- if this is the horizontal container
  17518. Source states:
  17519. "" - normal state
  17520. "Moved" - this source is being moved
  17521. "Copied" - this source is being copied
  17522. Target states:
  17523. "" - normal state
  17524. "Disabled" - the target cannot accept an avatar
  17525. Target anchor state:
  17526. "" - item is not selected
  17527. "Before" - insert point is before the anchor
  17528. "After" - insert point is after the anchor
  17529. */
  17530. /*=====
  17531. dojo.dnd.__SourceArgs = function(){
  17532. // summary:
  17533. // a dict of parameters for DnD Source configuration. Note that any
  17534. // property on Source elements may be configured, but this is the
  17535. // short-list
  17536. // isSource: Boolean?
  17537. // can be used as a DnD source. Defaults to true.
  17538. // accept: Array?
  17539. // list of accepted types (text strings) for a target; defaults to
  17540. // ["text"]
  17541. // autoSync: Boolean
  17542. // if true refreshes the node list on every operation; false by default
  17543. // copyOnly: Boolean?
  17544. // copy items, if true, use a state of Ctrl key otherwise,
  17545. // see selfCopy and selfAccept for more details
  17546. // delay: Number
  17547. // the move delay in pixels before detecting a drag; 0 by default
  17548. // horizontal: Boolean?
  17549. // a horizontal container, if true, vertical otherwise or when omitted
  17550. // selfCopy: Boolean?
  17551. // copy items by default when dropping on itself,
  17552. // false by default, works only if copyOnly is true
  17553. // selfAccept: Boolean?
  17554. // accept its own items when copyOnly is true,
  17555. // true by default, works only if copyOnly is true
  17556. // withHandles: Boolean?
  17557. // allows dragging only by handles, false by default
  17558. // generateText: Boolean?
  17559. // generate text node for drag and drop, true by default
  17560. this.isSource = isSource;
  17561. this.accept = accept;
  17562. this.autoSync = autoSync;
  17563. this.copyOnly = copyOnly;
  17564. this.delay = delay;
  17565. this.horizontal = horizontal;
  17566. this.selfCopy = selfCopy;
  17567. this.selfAccept = selfAccept;
  17568. this.withHandles = withHandles;
  17569. this.generateText = true;
  17570. }
  17571. =====*/
  17572. // For back-compat, remove in 2.0.
  17573. if(!dojo.isAsync){
  17574. dojo.ready(0, function(){
  17575. var requires = ["dojo/dnd/AutoSource", "dojo/dnd/Target"];
  17576. require(requires); // use indirection so modules not rolled into a build
  17577. })
  17578. }
  17579. return dojo.declare("dojo.dnd.Source", Selector, {
  17580. // summary:
  17581. // a Source object, which can be used as a DnD source, or a DnD target
  17582. // object attributes (for markup)
  17583. isSource: true,
  17584. horizontal: false,
  17585. copyOnly: false,
  17586. selfCopy: false,
  17587. selfAccept: true,
  17588. skipForm: false,
  17589. withHandles: false,
  17590. autoSync: false,
  17591. delay: 0, // pixels
  17592. accept: ["text"],
  17593. generateText: true,
  17594. constructor: function(/*DOMNode|String*/node, /*dojo.dnd.__SourceArgs?*/params){
  17595. // summary:
  17596. // a constructor of the Source
  17597. // node:
  17598. // node or node's id to build the source on
  17599. // params:
  17600. // any property of this class may be configured via the params
  17601. // object which is mixed-in to the `dojo.dnd.Source` instance
  17602. dojo.mixin(this, dojo.mixin({}, params));
  17603. var type = this.accept;
  17604. if(type.length){
  17605. this.accept = {};
  17606. for(var i = 0; i < type.length; ++i){
  17607. this.accept[type[i]] = 1;
  17608. }
  17609. }
  17610. // class-specific variables
  17611. this.isDragging = false;
  17612. this.mouseDown = false;
  17613. this.targetAnchor = null;
  17614. this.targetBox = null;
  17615. this.before = true;
  17616. this._lastX = 0;
  17617. this._lastY = 0;
  17618. // states
  17619. this.sourceState = "";
  17620. if(this.isSource){
  17621. dojo.addClass(this.node, "dojoDndSource");
  17622. }
  17623. this.targetState = "";
  17624. if(this.accept){
  17625. dojo.addClass(this.node, "dojoDndTarget");
  17626. }
  17627. if(this.horizontal){
  17628. dojo.addClass(this.node, "dojoDndHorizontal");
  17629. }
  17630. // set up events
  17631. this.topics = [
  17632. dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
  17633. dojo.subscribe("/dnd/start", this, "onDndStart"),
  17634. dojo.subscribe("/dnd/drop", this, "onDndDrop"),
  17635. dojo.subscribe("/dnd/cancel", this, "onDndCancel")
  17636. ];
  17637. },
  17638. // methods
  17639. checkAcceptance: function(source, nodes){
  17640. // summary:
  17641. // checks if the target can accept nodes from this source
  17642. // source: Object
  17643. // the source which provides items
  17644. // nodes: Array
  17645. // the list of transferred items
  17646. if(this == source){
  17647. return !this.copyOnly || this.selfAccept;
  17648. }
  17649. for(var i = 0; i < nodes.length; ++i){
  17650. var type = source.getItem(nodes[i].id).type;
  17651. // type instanceof Array
  17652. var flag = false;
  17653. for(var j = 0; j < type.length; ++j){
  17654. if(type[j] in this.accept){
  17655. flag = true;
  17656. break;
  17657. }
  17658. }
  17659. if(!flag){
  17660. return false; // Boolean
  17661. }
  17662. }
  17663. return true; // Boolean
  17664. },
  17665. copyState: function(keyPressed, self){
  17666. // summary:
  17667. // Returns true if we need to copy items, false to move.
  17668. // It is separated to be overwritten dynamically, if needed.
  17669. // keyPressed: Boolean
  17670. // the "copy" key was pressed
  17671. // self: Boolean?
  17672. // optional flag that means that we are about to drop on itself
  17673. if(keyPressed){ return true; }
  17674. if(arguments.length < 2){
  17675. self = this == Manager.manager().target;
  17676. }
  17677. if(self){
  17678. if(this.copyOnly){
  17679. return this.selfCopy;
  17680. }
  17681. }else{
  17682. return this.copyOnly;
  17683. }
  17684. return false; // Boolean
  17685. },
  17686. destroy: function(){
  17687. // summary:
  17688. // prepares the object to be garbage-collected
  17689. dojo.dnd.Source.superclass.destroy.call(this);
  17690. dojo.forEach(this.topics, dojo.unsubscribe);
  17691. this.targetAnchor = null;
  17692. },
  17693. // mouse event processors
  17694. onMouseMove: function(e){
  17695. // summary:
  17696. // event processor for onmousemove
  17697. // e: Event
  17698. // mouse event
  17699. if(this.isDragging && this.targetState == "Disabled"){ return; }
  17700. dojo.dnd.Source.superclass.onMouseMove.call(this, e);
  17701. var m = Manager.manager();
  17702. if(!this.isDragging){
  17703. if(this.mouseDown && this.isSource &&
  17704. (Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay)){
  17705. var nodes = this.getSelectedNodes();
  17706. if(nodes.length){
  17707. m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e), true));
  17708. }
  17709. }
  17710. }
  17711. if(this.isDragging){
  17712. // calculate before/after
  17713. var before = false;
  17714. if(this.current){
  17715. if(!this.targetBox || this.targetAnchor != this.current){
  17716. this.targetBox = dojo.position(this.current, true);
  17717. }
  17718. if(this.horizontal){
  17719. before = (e.pageX - this.targetBox.x) < (this.targetBox.w / 2);
  17720. }else{
  17721. before = (e.pageY - this.targetBox.y) < (this.targetBox.h / 2);
  17722. }
  17723. }
  17724. if(this.current != this.targetAnchor || before != this.before){
  17725. this._markTargetAnchor(before);
  17726. m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
  17727. }
  17728. }
  17729. },
  17730. onMouseDown: function(e){
  17731. // summary:
  17732. // event processor for onmousedown
  17733. // e: Event
  17734. // mouse event
  17735. if(!this.mouseDown && this._legalMouseDown(e) && (!this.skipForm || !dojo.dnd.isFormElement(e))){
  17736. this.mouseDown = true;
  17737. this._lastX = e.pageX;
  17738. this._lastY = e.pageY;
  17739. dojo.dnd.Source.superclass.onMouseDown.call(this, e);
  17740. }
  17741. },
  17742. onMouseUp: function(e){
  17743. // summary:
  17744. // event processor for onmouseup
  17745. // e: Event
  17746. // mouse event
  17747. if(this.mouseDown){
  17748. this.mouseDown = false;
  17749. dojo.dnd.Source.superclass.onMouseUp.call(this, e);
  17750. }
  17751. },
  17752. // topic event processors
  17753. onDndSourceOver: function(source){
  17754. // summary:
  17755. // topic event processor for /dnd/source/over, called when detected a current source
  17756. // source: Object
  17757. // the source which has the mouse over it
  17758. if(this != source){
  17759. this.mouseDown = false;
  17760. if(this.targetAnchor){
  17761. this._unmarkTargetAnchor();
  17762. }
  17763. }else if(this.isDragging){
  17764. var m = Manager.manager();
  17765. m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
  17766. }
  17767. },
  17768. onDndStart: function(source, nodes, copy){
  17769. // summary:
  17770. // topic event processor for /dnd/start, called to initiate the DnD operation
  17771. // source: Object
  17772. // the source which provides items
  17773. // nodes: Array
  17774. // the list of transferred items
  17775. // copy: Boolean
  17776. // copy items, if true, move items otherwise
  17777. if(this.autoSync){ this.sync(); }
  17778. if(this.isSource){
  17779. this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
  17780. }
  17781. var accepted = this.accept && this.checkAcceptance(source, nodes);
  17782. this._changeState("Target", accepted ? "" : "Disabled");
  17783. if(this == source){
  17784. Manager.manager().overSource(this);
  17785. }
  17786. this.isDragging = true;
  17787. },
  17788. onDndDrop: function(source, nodes, copy, target){
  17789. // summary:
  17790. // topic event processor for /dnd/drop, called to finish the DnD operation
  17791. // source: Object
  17792. // the source which provides items
  17793. // nodes: Array
  17794. // the list of transferred items
  17795. // copy: Boolean
  17796. // copy items, if true, move items otherwise
  17797. // target: Object
  17798. // the target which accepts items
  17799. if(this == target){
  17800. // this one is for us => move nodes!
  17801. this.onDrop(source, nodes, copy);
  17802. }
  17803. this.onDndCancel();
  17804. },
  17805. onDndCancel: function(){
  17806. // summary:
  17807. // topic event processor for /dnd/cancel, called to cancel the DnD operation
  17808. if(this.targetAnchor){
  17809. this._unmarkTargetAnchor();
  17810. this.targetAnchor = null;
  17811. }
  17812. this.before = true;
  17813. this.isDragging = false;
  17814. this.mouseDown = false;
  17815. this._changeState("Source", "");
  17816. this._changeState("Target", "");
  17817. },
  17818. // local events
  17819. onDrop: function(source, nodes, copy){
  17820. // summary:
  17821. // called only on the current target, when drop is performed
  17822. // source: Object
  17823. // the source which provides items
  17824. // nodes: Array
  17825. // the list of transferred items
  17826. // copy: Boolean
  17827. // copy items, if true, move items otherwise
  17828. if(this != source){
  17829. this.onDropExternal(source, nodes, copy);
  17830. }else{
  17831. this.onDropInternal(nodes, copy);
  17832. }
  17833. },
  17834. onDropExternal: function(source, nodes, copy){
  17835. // summary:
  17836. // called only on the current target, when drop is performed
  17837. // from an external source
  17838. // source: Object
  17839. // the source which provides items
  17840. // nodes: Array
  17841. // the list of transferred items
  17842. // copy: Boolean
  17843. // copy items, if true, move items otherwise
  17844. var oldCreator = this._normalizedCreator;
  17845. // transferring nodes from the source to the target
  17846. if(this.creator){
  17847. // use defined creator
  17848. this._normalizedCreator = function(node, hint){
  17849. return oldCreator.call(this, source.getItem(node.id).data, hint);
  17850. };
  17851. }else{
  17852. // we have no creator defined => move/clone nodes
  17853. if(copy){
  17854. // clone nodes
  17855. this._normalizedCreator = function(node, hint){
  17856. var t = source.getItem(node.id);
  17857. var n = node.cloneNode(true);
  17858. n.id = dojo.dnd.getUniqueId();
  17859. return {node: n, data: t.data, type: t.type};
  17860. };
  17861. }else{
  17862. // move nodes
  17863. this._normalizedCreator = function(node, hint){
  17864. var t = source.getItem(node.id);
  17865. source.delItem(node.id);
  17866. return {node: node, data: t.data, type: t.type};
  17867. };
  17868. }
  17869. }
  17870. this.selectNone();
  17871. if(!copy && !this.creator){
  17872. source.selectNone();
  17873. }
  17874. this.insertNodes(true, nodes, this.before, this.current);
  17875. if(!copy && this.creator){
  17876. source.deleteSelectedNodes();
  17877. }
  17878. this._normalizedCreator = oldCreator;
  17879. },
  17880. onDropInternal: function(nodes, copy){
  17881. // summary:
  17882. // called only on the current target, when drop is performed
  17883. // from the same target/source
  17884. // nodes: Array
  17885. // the list of transferred items
  17886. // copy: Boolean
  17887. // copy items, if true, move items otherwise
  17888. var oldCreator = this._normalizedCreator;
  17889. // transferring nodes within the single source
  17890. if(this.current && this.current.id in this.selection){
  17891. // do nothing
  17892. return;
  17893. }
  17894. if(copy){
  17895. if(this.creator){
  17896. // create new copies of data items
  17897. this._normalizedCreator = function(node, hint){
  17898. return oldCreator.call(this, this.getItem(node.id).data, hint);
  17899. };
  17900. }else{
  17901. // clone nodes
  17902. this._normalizedCreator = function(node, hint){
  17903. var t = this.getItem(node.id);
  17904. var n = node.cloneNode(true);
  17905. n.id = dojo.dnd.getUniqueId();
  17906. return {node: n, data: t.data, type: t.type};
  17907. };
  17908. }
  17909. }else{
  17910. // move nodes
  17911. if(!this.current){
  17912. // do nothing
  17913. return;
  17914. }
  17915. this._normalizedCreator = function(node, hint){
  17916. var t = this.getItem(node.id);
  17917. return {node: node, data: t.data, type: t.type};
  17918. };
  17919. }
  17920. this._removeSelection();
  17921. this.insertNodes(true, nodes, this.before, this.current);
  17922. this._normalizedCreator = oldCreator;
  17923. },
  17924. onDraggingOver: function(){
  17925. // summary:
  17926. // called during the active DnD operation, when items
  17927. // are dragged over this target, and it is not disabled
  17928. },
  17929. onDraggingOut: function(){
  17930. // summary:
  17931. // called during the active DnD operation, when items
  17932. // are dragged away from this target, and it is not disabled
  17933. },
  17934. // utilities
  17935. onOverEvent: function(){
  17936. // summary:
  17937. // this function is called once, when mouse is over our container
  17938. dojo.dnd.Source.superclass.onOverEvent.call(this);
  17939. Manager.manager().overSource(this);
  17940. if(this.isDragging && this.targetState != "Disabled"){
  17941. this.onDraggingOver();
  17942. }
  17943. },
  17944. onOutEvent: function(){
  17945. // summary:
  17946. // this function is called once, when mouse is out of our container
  17947. dojo.dnd.Source.superclass.onOutEvent.call(this);
  17948. Manager.manager().outSource(this);
  17949. if(this.isDragging && this.targetState != "Disabled"){
  17950. this.onDraggingOut();
  17951. }
  17952. },
  17953. _markTargetAnchor: function(before){
  17954. // summary:
  17955. // assigns a class to the current target anchor based on "before" status
  17956. // before: Boolean
  17957. // insert before, if true, after otherwise
  17958. if(this.current == this.targetAnchor && this.before == before){ return; }
  17959. if(this.targetAnchor){
  17960. this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
  17961. }
  17962. this.targetAnchor = this.current;
  17963. this.targetBox = null;
  17964. this.before = before;
  17965. if(this.targetAnchor){
  17966. this._addItemClass(this.targetAnchor, this.before ? "Before" : "After");
  17967. }
  17968. },
  17969. _unmarkTargetAnchor: function(){
  17970. // summary:
  17971. // removes a class of the current target anchor based on "before" status
  17972. if(!this.targetAnchor){ return; }
  17973. this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
  17974. this.targetAnchor = null;
  17975. this.targetBox = null;
  17976. this.before = true;
  17977. },
  17978. _markDndStatus: function(copy){
  17979. // summary:
  17980. // changes source's state based on "copy" status
  17981. this._changeState("Source", copy ? "Copied" : "Moved");
  17982. },
  17983. _legalMouseDown: function(e){
  17984. // summary:
  17985. // checks if user clicked on "approved" items
  17986. // e: Event
  17987. // mouse event
  17988. // accept only the left mouse button
  17989. if(!dojo.mouseButtons.isLeft(e)){ return false; }
  17990. if(!this.withHandles){ return true; }
  17991. // check for handles
  17992. for(var node = e.target; node && node !== this.node; node = node.parentNode){
  17993. if(dojo.hasClass(node, "dojoDndHandle")){ return true; }
  17994. if(dojo.hasClass(node, "dojoDndItem") || dojo.hasClass(node, "dojoDndIgnore")){ break; }
  17995. }
  17996. return false; // Boolean
  17997. }
  17998. });
  17999. });
  18000. },
  18001. 'dojo/html':function(){
  18002. define("dojo/html", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/declare", "./dom", "./dom-construct", "./parser"], function(dojo, lang, darray, declare, dom, domConstruct, parser) {
  18003. // module:
  18004. // dojo/html
  18005. // summary:
  18006. // TODOC
  18007. lang.getObject("html", true, dojo);
  18008. // the parser might be needed..
  18009. // idCounter is incremented with each instantiation to allow asignment of a unique id for tracking, logging purposes
  18010. var idCounter = 0;
  18011. dojo.html._secureForInnerHtml = function(/*String*/ cont){
  18012. // summary:
  18013. // removes !DOCTYPE and title elements from the html string.
  18014. //
  18015. // khtml is picky about dom faults, you can't attach a style or <title> node as child of body
  18016. // must go into head, so we need to cut out those tags
  18017. // cont:
  18018. // An html string for insertion into the dom
  18019. //
  18020. return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
  18021. };
  18022. /*====
  18023. dojo.html._emptyNode = function(node){
  18024. // summary:
  18025. // removes all child nodes from the given node
  18026. // node: DOMNode
  18027. // the parent element
  18028. };
  18029. =====*/
  18030. dojo.html._emptyNode = domConstruct.empty;
  18031. dojo.html._setNodeContent = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont){
  18032. // summary:
  18033. // inserts the given content into the given node
  18034. // node:
  18035. // the parent element
  18036. // content:
  18037. // the content to be set on the parent element.
  18038. // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
  18039. // always empty
  18040. domConstruct.empty(node);
  18041. if(cont) {
  18042. if(typeof cont == "string") {
  18043. cont = domConstruct.toDom(cont, node.ownerDocument);
  18044. }
  18045. if(!cont.nodeType && lang.isArrayLike(cont)) {
  18046. // handle as enumerable, but it may shrink as we enumerate it
  18047. for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0) {
  18048. domConstruct.place( cont[i], node, "last");
  18049. }
  18050. } else {
  18051. // pass nodes, documentFragments and unknowns through to dojo.place
  18052. domConstruct.place(cont, node, "last");
  18053. }
  18054. }
  18055. // return DomNode
  18056. return node;
  18057. };
  18058. // we wrap up the content-setting operation in a object
  18059. declare("dojo.html._ContentSetter", null,
  18060. {
  18061. // node: DomNode|String
  18062. // An node which will be the parent element that we set content into
  18063. node: "",
  18064. // content: String|DomNode|DomNode[]
  18065. // The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
  18066. content: "",
  18067. // id: String?
  18068. // Usually only used internally, and auto-generated with each instance
  18069. id: "",
  18070. // cleanContent: Boolean
  18071. // Should the content be treated as a full html document,
  18072. // and the real content stripped of <html>, <body> wrapper before injection
  18073. cleanContent: false,
  18074. // extractContent: Boolean
  18075. // Should the content be treated as a full html document, and the real content stripped of <html>, <body> wrapper before injection
  18076. extractContent: false,
  18077. // parseContent: Boolean
  18078. // Should the node by passed to the parser after the new content is set
  18079. parseContent: false,
  18080. // parserScope: String
  18081. // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo,
  18082. // will search for data-dojo-type (or dojoType). For backwards compatibility
  18083. // reasons defaults to dojo._scopeName (which is "dojo" except when
  18084. // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
  18085. parserScope: dojo._scopeName,
  18086. // startup: Boolean
  18087. // Start the child widgets after parsing them. Only obeyed if parseContent is true.
  18088. startup: true,
  18089. // lifecyle methods
  18090. constructor: function(/* Object */params, /* String|DomNode */node){
  18091. // summary:
  18092. // Provides a configurable, extensible object to wrap the setting on content on a node
  18093. // call the set() method to actually set the content..
  18094. // the original params are mixed directly into the instance "this"
  18095. lang.mixin(this, params || {});
  18096. // give precedence to params.node vs. the node argument
  18097. // and ensure its a node, not an id string
  18098. node = this.node = dom.byId( this.node || node );
  18099. if(!this.id){
  18100. this.id = [
  18101. "Setter",
  18102. (node) ? node.id || node.tagName : "",
  18103. idCounter++
  18104. ].join("_");
  18105. }
  18106. },
  18107. set: function(/* String|DomNode|NodeList? */ cont, /* Object? */ params){
  18108. // summary:
  18109. // front-end to the set-content sequence
  18110. // cont:
  18111. // An html string, node or enumerable list of nodes for insertion into the dom
  18112. // If not provided, the object's content property will be used
  18113. if(undefined !== cont){
  18114. this.content = cont;
  18115. }
  18116. // in the re-use scenario, set needs to be able to mixin new configuration
  18117. if(params){
  18118. this._mixin(params);
  18119. }
  18120. this.onBegin();
  18121. this.setContent();
  18122. this.onEnd();
  18123. return this.node;
  18124. },
  18125. setContent: function(){
  18126. // summary:
  18127. // sets the content on the node
  18128. var node = this.node;
  18129. if(!node) {
  18130. // can't proceed
  18131. throw new Error(this.declaredClass + ": setContent given no node");
  18132. }
  18133. try{
  18134. node = dojo.html._setNodeContent(node, this.content);
  18135. }catch(e){
  18136. // check if a domfault occurs when we are appending this.errorMessage
  18137. // like for instance if domNode is a UL and we try append a DIV
  18138. // FIXME: need to allow the user to provide a content error message string
  18139. var errMess = this.onContentError(e);
  18140. try{
  18141. node.innerHTML = errMess;
  18142. }catch(e){
  18143. console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e);
  18144. }
  18145. }
  18146. // always put back the node for the next method
  18147. this.node = node; // DomNode
  18148. },
  18149. empty: function() {
  18150. // summary
  18151. // cleanly empty out existing content
  18152. // destroy any widgets from a previous run
  18153. // NOTE: if you dont want this you'll need to empty
  18154. // the parseResults array property yourself to avoid bad things happenning
  18155. if(this.parseResults && this.parseResults.length) {
  18156. darray.forEach(this.parseResults, function(w) {
  18157. if(w.destroy){
  18158. w.destroy();
  18159. }
  18160. });
  18161. delete this.parseResults;
  18162. }
  18163. // this is fast, but if you know its already empty or safe, you could
  18164. // override empty to skip this step
  18165. dojo.html._emptyNode(this.node);
  18166. },
  18167. onBegin: function(){
  18168. // summary
  18169. // Called after instantiation, but before set();
  18170. // It allows modification of any of the object properties
  18171. // - including the node and content provided - before the set operation actually takes place
  18172. // This default implementation checks for cleanContent and extractContent flags to
  18173. // optionally pre-process html string content
  18174. var cont = this.content;
  18175. if(lang.isString(cont)){
  18176. if(this.cleanContent){
  18177. cont = dojo.html._secureForInnerHtml(cont);
  18178. }
  18179. if(this.extractContent){
  18180. var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
  18181. if(match){ cont = match[1]; }
  18182. }
  18183. }
  18184. // clean out the node and any cruft associated with it - like widgets
  18185. this.empty();
  18186. this.content = cont;
  18187. return this.node; /* DomNode */
  18188. },
  18189. onEnd: function(){
  18190. // summary
  18191. // Called after set(), when the new content has been pushed into the node
  18192. // It provides an opportunity for post-processing before handing back the node to the caller
  18193. // This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
  18194. if(this.parseContent){
  18195. // populates this.parseResults if you need those..
  18196. this._parse();
  18197. }
  18198. return this.node; /* DomNode */
  18199. },
  18200. tearDown: function(){
  18201. // summary
  18202. // manually reset the Setter instance if its being re-used for example for another set()
  18203. // description
  18204. // tearDown() is not called automatically.
  18205. // In normal use, the Setter instance properties are simply allowed to fall out of scope
  18206. // but the tearDown method can be called to explicitly reset this instance.
  18207. delete this.parseResults;
  18208. delete this.node;
  18209. delete this.content;
  18210. },
  18211. onContentError: function(err){
  18212. return "Error occured setting content: " + err;
  18213. },
  18214. _mixin: function(params){
  18215. // mix properties/methods into the instance
  18216. // TODO: the intention with tearDown is to put the Setter's state
  18217. // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
  18218. // so we could do something here to move the original properties aside for later restoration
  18219. var empty = {}, key;
  18220. for(key in params){
  18221. if(key in empty){ continue; }
  18222. // TODO: here's our opportunity to mask the properties we dont consider configurable/overridable
  18223. // .. but history shows we'll almost always guess wrong
  18224. this[key] = params[key];
  18225. }
  18226. },
  18227. _parse: function(){
  18228. // summary:
  18229. // runs the dojo parser over the node contents, storing any results in this.parseResults
  18230. // Any errors resulting from parsing are passed to _onError for handling
  18231. var rootNode = this.node;
  18232. try{
  18233. // store the results (widgets, whatever) for potential retrieval
  18234. var inherited = {};
  18235. darray.forEach(["dir", "lang", "textDir"], function(name){
  18236. if(this[name]){
  18237. inherited[name] = this[name];
  18238. }
  18239. }, this);
  18240. this.parseResults = parser.parse({
  18241. rootNode: rootNode,
  18242. noStart: !this.startup,
  18243. inherited: inherited,
  18244. scope: this.parserScope
  18245. });
  18246. }catch(e){
  18247. this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id);
  18248. }
  18249. },
  18250. _onError: function(type, err, consoleText){
  18251. // summary:
  18252. // shows user the string that is returned by on[type]Error
  18253. // overide/implement on[type]Error and return your own string to customize
  18254. var errText = this['on' + type + 'Error'].call(this, err);
  18255. if(consoleText){
  18256. console.error(consoleText, err);
  18257. }else if(errText){ // a empty string won't change current content
  18258. dojo.html._setNodeContent(this.node, errText, true);
  18259. }
  18260. }
  18261. }); // end dojo.declare()
  18262. dojo.html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
  18263. // summary:
  18264. // inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
  18265. // may be a better choice for simple HTML insertion.
  18266. // description:
  18267. // Unless you need to use the params capabilities of this method, you should use
  18268. // dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
  18269. // an HTML string into the DOM, but it only handles inserting an HTML string as DOM
  18270. // elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
  18271. // or the other capabilities as defined by the params object for this method.
  18272. // node:
  18273. // the parent element that will receive the content
  18274. // cont:
  18275. // the content to be set on the parent element.
  18276. // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
  18277. // params:
  18278. // Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
  18279. // example:
  18280. // A safe string/node/nodelist content replacement/injection with hooks for extension
  18281. // Example Usage:
  18282. // dojo.html.set(node, "some string");
  18283. // dojo.html.set(node, contentNode, {options});
  18284. // dojo.html.set(node, myNode.childNodes, {options});
  18285. if(undefined == cont){
  18286. console.warn("dojo.html.set: no cont argument provided, using empty string");
  18287. cont = "";
  18288. }
  18289. if(!params){
  18290. // simple and fast
  18291. return dojo.html._setNodeContent(node, cont, true);
  18292. }else{
  18293. // more options but slower
  18294. // note the arguments are reversed in order, to match the convention for instantiation via the parser
  18295. var op = new dojo.html._ContentSetter(lang.mixin(
  18296. params,
  18297. { content: cont, node: node }
  18298. ));
  18299. return op.set();
  18300. }
  18301. };
  18302. return dojo.html;
  18303. });
  18304. },
  18305. 'dijit/_base/typematic':function(){
  18306. define("dijit/_base/typematic", ["../typematic"], function(){
  18307. // for back-compat, just loads top level module
  18308. });
  18309. },
  18310. 'dijit/_base':function(){
  18311. define("dijit/_base", [
  18312. ".",
  18313. "./a11y", // used to be in dijit/_base/manager
  18314. "./WidgetSet", // used to be in dijit/_base/manager
  18315. "./_base/focus",
  18316. "./_base/manager",
  18317. "./_base/place",
  18318. "./_base/popup",
  18319. "./_base/scroll",
  18320. "./_base/sniff",
  18321. "./_base/typematic",
  18322. "./_base/wai",
  18323. "./_base/window"
  18324. ], function(dijit){
  18325. // module:
  18326. // dijit/_base
  18327. // summary:
  18328. // Includes all the modules in dijit/_base
  18329. return dijit._base;
  18330. });
  18331. },
  18332. 'dijit/layout/BorderContainer':function(){
  18333. define("dijit/layout/BorderContainer", [
  18334. "dojo/_base/array", // array.filter array.forEach array.map
  18335. "dojo/cookie", // cookie
  18336. "dojo/_base/declare", // declare
  18337. "dojo/dom-class", // domClass.add domClass.remove domClass.toggle
  18338. "dojo/dom-construct", // domConstruct.destroy domConstruct.place
  18339. "dojo/dom-geometry", // domGeometry.marginBox
  18340. "dojo/dom-style", // domStyle.style
  18341. "dojo/_base/event", // event.stop
  18342. "dojo/keys",
  18343. "dojo/_base/lang", // lang.getObject lang.hitch
  18344. "dojo/on",
  18345. "dojo/touch",
  18346. "dojo/_base/window", // win.body win.doc win.doc.createElement
  18347. "../_WidgetBase",
  18348. "../_Widget",
  18349. "../_TemplatedMixin",
  18350. "./_LayoutWidget",
  18351. "./utils" // layoutUtils.layoutChildren
  18352. ], function(array, cookie, declare, domClass, domConstruct, domGeometry, domStyle, event, keys, lang, on, touch, win,
  18353. _WidgetBase, _Widget, _TemplatedMixin, _LayoutWidget, layoutUtils){
  18354. /*=====
  18355. var _WidgetBase = dijit._WidgetBase;
  18356. var _Widget = dijit._Widget;
  18357. var _TemplatedMixin = dijit._TemplatedMixin;
  18358. var _LayoutWidget = dijit.layout._LayoutWidget;
  18359. =====*/
  18360. // module:
  18361. // dijit/layout/BorderContainer
  18362. // summary:
  18363. // Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
  18364. var _Splitter = declare("dijit.layout._Splitter", [_Widget, _TemplatedMixin ],
  18365. {
  18366. // summary:
  18367. // A draggable spacer between two items in a `dijit.layout.BorderContainer`.
  18368. // description:
  18369. // This is instantiated by `dijit.layout.BorderContainer`. Users should not
  18370. // create it directly.
  18371. // tags:
  18372. // private
  18373. /*=====
  18374. // container: [const] dijit.layout.BorderContainer
  18375. // Pointer to the parent BorderContainer
  18376. container: null,
  18377. // child: [const] dijit.layout._LayoutWidget
  18378. // Pointer to the pane associated with this splitter
  18379. child: null,
  18380. // region: [const] String
  18381. // Region of pane associated with this splitter.
  18382. // "top", "bottom", "left", "right".
  18383. region: null,
  18384. =====*/
  18385. // live: [const] Boolean
  18386. // If true, the child's size changes and the child widget is redrawn as you drag the splitter;
  18387. // otherwise, the size doesn't change until you drop the splitter (by mouse-up)
  18388. live: true,
  18389. templateString: '<div class="dijitSplitter" data-dojo-attach-event="onkeypress:_onKeyPress,press:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse" tabIndex="0" role="separator"><div class="dijitSplitterThumb"></div></div>',
  18390. constructor: function(){
  18391. this._handlers = [];
  18392. },
  18393. postMixInProperties: function(){
  18394. this.inherited(arguments);
  18395. this.horizontal = /top|bottom/.test(this.region);
  18396. this._factor = /top|left/.test(this.region) ? 1 : -1;
  18397. this._cookieName = this.container.id + "_" + this.region;
  18398. },
  18399. buildRendering: function(){
  18400. this.inherited(arguments);
  18401. domClass.add(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V"));
  18402. if(this.container.persist){
  18403. // restore old size
  18404. var persistSize = cookie(this._cookieName);
  18405. if(persistSize){
  18406. this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize;
  18407. }
  18408. }
  18409. },
  18410. _computeMaxSize: function(){
  18411. // summary:
  18412. // Return the maximum size that my corresponding pane can be set to
  18413. var dim = this.horizontal ? 'h' : 'w',
  18414. childSize = domGeometry.getMarginBox(this.child.domNode)[dim],
  18415. center = array.filter(this.container.getChildren(), function(child){ return child.region == "center";})[0],
  18416. spaceAvailable = domGeometry.getMarginBox(center.domNode)[dim]; // can expand until center is crushed to 0
  18417. return Math.min(this.child.maxSize, childSize + spaceAvailable);
  18418. },
  18419. _startDrag: function(e){
  18420. if(!this.cover){
  18421. this.cover = win.doc.createElement('div');
  18422. domClass.add(this.cover, "dijitSplitterCover");
  18423. domConstruct.place(this.cover, this.child.domNode, "after");
  18424. }
  18425. domClass.add(this.cover, "dijitSplitterCoverActive");
  18426. // Safeguard in case the stop event was missed. Shouldn't be necessary if we always get the mouse up.
  18427. if(this.fake){ domConstruct.destroy(this.fake); }
  18428. if(!(this._resize = this.live)){ //TODO: disable live for IE6?
  18429. // create fake splitter to display at old position while we drag
  18430. (this.fake = this.domNode.cloneNode(true)).removeAttribute("id");
  18431. domClass.add(this.domNode, "dijitSplitterShadow");
  18432. domConstruct.place(this.fake, this.domNode, "after");
  18433. }
  18434. domClass.add(this.domNode, "dijitSplitterActive dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
  18435. if(this.fake){
  18436. domClass.remove(this.fake, "dijitSplitterHover dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover");
  18437. }
  18438. //Performance: load data info local vars for onmousevent function closure
  18439. var factor = this._factor,
  18440. isHorizontal = this.horizontal,
  18441. axis = isHorizontal ? "pageY" : "pageX",
  18442. pageStart = e[axis],
  18443. splitterStyle = this.domNode.style,
  18444. dim = isHorizontal ? 'h' : 'w',
  18445. childStart = domGeometry.getMarginBox(this.child.domNode)[dim],
  18446. max = this._computeMaxSize(),
  18447. min = this.child.minSize || 20,
  18448. region = this.region,
  18449. splitterAttr = region == "top" || region == "bottom" ? "top" : "left", // style attribute of splitter to adjust
  18450. splitterStart = parseInt(splitterStyle[splitterAttr], 10),
  18451. resize = this._resize,
  18452. layoutFunc = lang.hitch(this.container, "_layoutChildren", this.child.id),
  18453. de = win.doc;
  18454. this._handlers = this._handlers.concat([
  18455. on(de, touch.move, this._drag = function(e, forceResize){
  18456. var delta = e[axis] - pageStart,
  18457. childSize = factor * delta + childStart,
  18458. boundChildSize = Math.max(Math.min(childSize, max), min);
  18459. if(resize || forceResize){
  18460. layoutFunc(boundChildSize);
  18461. }
  18462. // TODO: setting style directly (usually) sets content box size, need to set margin box size
  18463. splitterStyle[splitterAttr] = delta + splitterStart + factor*(boundChildSize - childSize) + "px";
  18464. }),
  18465. on(de, "dragstart", event.stop),
  18466. on(win.body(), "selectstart", event.stop),
  18467. on(de, touch.release, lang.hitch(this, "_stopDrag"))
  18468. ]);
  18469. event.stop(e);
  18470. },
  18471. _onMouse: function(e){
  18472. // summary:
  18473. // Handler for onmouseenter / onmouseleave events
  18474. var o = (e.type == "mouseover" || e.type == "mouseenter");
  18475. domClass.toggle(this.domNode, "dijitSplitterHover", o);
  18476. domClass.toggle(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o);
  18477. },
  18478. _stopDrag: function(e){
  18479. try{
  18480. if(this.cover){
  18481. domClass.remove(this.cover, "dijitSplitterCoverActive");
  18482. }
  18483. if(this.fake){ domConstruct.destroy(this.fake); }
  18484. domClass.remove(this.domNode, "dijitSplitterActive dijitSplitter"
  18485. + (this.horizontal ? "H" : "V") + "Active dijitSplitterShadow");
  18486. this._drag(e); //TODO: redundant with onmousemove?
  18487. this._drag(e, true);
  18488. }finally{
  18489. this._cleanupHandlers();
  18490. delete this._drag;
  18491. }
  18492. if(this.container.persist){
  18493. cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365});
  18494. }
  18495. },
  18496. _cleanupHandlers: function(){
  18497. var h;
  18498. while(h = this._handlers.pop()){ h.remove(); }
  18499. },
  18500. _onKeyPress: function(/*Event*/ e){
  18501. // should we apply typematic to this?
  18502. this._resize = true;
  18503. var horizontal = this.horizontal;
  18504. var tick = 1;
  18505. switch(e.charOrCode){
  18506. case horizontal ? keys.UP_ARROW : keys.LEFT_ARROW:
  18507. tick *= -1;
  18508. // break;
  18509. case horizontal ? keys.DOWN_ARROW : keys.RIGHT_ARROW:
  18510. break;
  18511. default:
  18512. // this.inherited(arguments);
  18513. return;
  18514. }
  18515. var childSize = domGeometry.getMarginSize(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick;
  18516. this.container._layoutChildren(this.child.id, Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize));
  18517. event.stop(e);
  18518. },
  18519. destroy: function(){
  18520. this._cleanupHandlers();
  18521. delete this.child;
  18522. delete this.container;
  18523. delete this.cover;
  18524. delete this.fake;
  18525. this.inherited(arguments);
  18526. }
  18527. });
  18528. var _Gutter = declare("dijit.layout._Gutter", [_Widget, _TemplatedMixin],
  18529. {
  18530. // summary:
  18531. // Just a spacer div to separate side pane from center pane.
  18532. // Basically a trick to lookup the gutter/splitter width from the theme.
  18533. // description:
  18534. // Instantiated by `dijit.layout.BorderContainer`. Users should not
  18535. // create directly.
  18536. // tags:
  18537. // private
  18538. templateString: '<div class="dijitGutter" role="presentation"></div>',
  18539. postMixInProperties: function(){
  18540. this.inherited(arguments);
  18541. this.horizontal = /top|bottom/.test(this.region);
  18542. },
  18543. buildRendering: function(){
  18544. this.inherited(arguments);
  18545. domClass.add(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V"));
  18546. }
  18547. });
  18548. var BorderContainer = declare("dijit.layout.BorderContainer", _LayoutWidget, {
  18549. // summary:
  18550. // Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
  18551. //
  18552. // description:
  18553. // A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;",
  18554. // that contains a child widget marked region="center" and optionally children widgets marked
  18555. // region equal to "top", "bottom", "leading", "trailing", "left" or "right".
  18556. // Children along the edges will be laid out according to width or height dimensions and may
  18557. // include optional splitters (splitter="true") to make them resizable by the user. The remaining
  18558. // space is designated for the center region.
  18559. //
  18560. // The outer size must be specified on the BorderContainer node. Width must be specified for the sides
  18561. // and height for the top and bottom, respectively. No dimensions should be specified on the center;
  18562. // it will fill the remaining space. Regions named "leading" and "trailing" may be used just like
  18563. // "left" and "right" except that they will be reversed in right-to-left environments.
  18564. //
  18565. // For complex layouts, multiple children can be specified for a single region. In this case, the
  18566. // layoutPriority flag on the children determines which child is closer to the edge (low layoutPriority)
  18567. // and which child is closer to the center (high layoutPriority). layoutPriority can also be used
  18568. // instead of the design attribute to control layout precedence of horizontal vs. vertical panes.
  18569. // example:
  18570. // | <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'sidebar', gutters: false"
  18571. // | style="width: 400px; height: 300px;">
  18572. // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'top'">header text</div>
  18573. // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'right', splitter: true" style="width: 200px;">table of contents</div>
  18574. // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'center'">client area</div>
  18575. // | </div>
  18576. // design: String
  18577. // Which design is used for the layout:
  18578. // - "headline" (default) where the top and bottom extend
  18579. // the full width of the container
  18580. // - "sidebar" where the left and right sides extend from top to bottom.
  18581. design: "headline",
  18582. // gutters: [const] Boolean
  18583. // Give each pane a border and margin.
  18584. // Margin determined by domNode.paddingLeft.
  18585. // When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing.
  18586. gutters: true,
  18587. // liveSplitters: [const] Boolean
  18588. // Specifies whether splitters resize as you drag (true) or only upon mouseup (false)
  18589. liveSplitters: true,
  18590. // persist: Boolean
  18591. // Save splitter positions in a cookie.
  18592. persist: false,
  18593. baseClass: "dijitBorderContainer",
  18594. // _splitterClass: Function||String
  18595. // Optional hook to override the default Splitter widget used by BorderContainer
  18596. _splitterClass: _Splitter,
  18597. postMixInProperties: function(){
  18598. // change class name to indicate that BorderContainer is being used purely for
  18599. // layout (like LayoutContainer) rather than for pretty formatting.
  18600. if(!this.gutters){
  18601. this.baseClass += "NoGutter";
  18602. }
  18603. this.inherited(arguments);
  18604. },
  18605. startup: function(){
  18606. if(this._started){ return; }
  18607. array.forEach(this.getChildren(), this._setupChild, this);
  18608. this.inherited(arguments);
  18609. },
  18610. _setupChild: function(/*dijit._Widget*/ child){
  18611. // Override _LayoutWidget._setupChild().
  18612. var region = child.region;
  18613. if(region){
  18614. this.inherited(arguments);
  18615. domClass.add(child.domNode, this.baseClass+"Pane");
  18616. var ltr = this.isLeftToRight();
  18617. if(region == "leading"){ region = ltr ? "left" : "right"; }
  18618. if(region == "trailing"){ region = ltr ? "right" : "left"; }
  18619. // Create draggable splitter for resizing pane,
  18620. // or alternately if splitter=false but BorderContainer.gutters=true then
  18621. // insert dummy div just for spacing
  18622. if(region != "center" && (child.splitter || this.gutters) && !child._splitterWidget){
  18623. var _Splitter = child.splitter ? this._splitterClass : _Gutter;
  18624. if(lang.isString(_Splitter)){
  18625. _Splitter = lang.getObject(_Splitter); // for back-compat, remove in 2.0
  18626. }
  18627. var splitter = new _Splitter({
  18628. id: child.id + "_splitter",
  18629. container: this,
  18630. child: child,
  18631. region: region,
  18632. live: this.liveSplitters
  18633. });
  18634. splitter.isSplitter = true;
  18635. child._splitterWidget = splitter;
  18636. domConstruct.place(splitter.domNode, child.domNode, "after");
  18637. // Splitters aren't added as Contained children, so we need to call startup explicitly
  18638. splitter.startup();
  18639. }
  18640. child.region = region; // TODO: technically wrong since it overwrites "trailing" with "left" etc.
  18641. }
  18642. },
  18643. layout: function(){
  18644. // Implement _LayoutWidget.layout() virtual method.
  18645. this._layoutChildren();
  18646. },
  18647. addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
  18648. // Override _LayoutWidget.addChild().
  18649. this.inherited(arguments);
  18650. if(this._started){
  18651. this.layout(); //OPT
  18652. }
  18653. },
  18654. removeChild: function(/*dijit._Widget*/ child){
  18655. // Override _LayoutWidget.removeChild().
  18656. var region = child.region;
  18657. var splitter = child._splitterWidget;
  18658. if(splitter){
  18659. splitter.destroy();
  18660. delete child._splitterWidget;
  18661. }
  18662. this.inherited(arguments);
  18663. if(this._started){
  18664. this._layoutChildren();
  18665. }
  18666. // Clean up whatever style changes we made to the child pane.
  18667. // Unclear how height and width should be handled.
  18668. domClass.remove(child.domNode, this.baseClass+"Pane");
  18669. domStyle.set(child.domNode, {
  18670. top: "auto",
  18671. bottom: "auto",
  18672. left: "auto",
  18673. right: "auto",
  18674. position: "static"
  18675. });
  18676. domStyle.set(child.domNode, region == "top" || region == "bottom" ? "width" : "height", "auto");
  18677. },
  18678. getChildren: function(){
  18679. // Override _LayoutWidget.getChildren() to only return real children, not the splitters.
  18680. return array.filter(this.inherited(arguments), function(widget){
  18681. return !widget.isSplitter;
  18682. });
  18683. },
  18684. // TODO: remove in 2.0
  18685. getSplitter: function(/*String*/region){
  18686. // summary:
  18687. // Returns the widget responsible for rendering the splitter associated with region
  18688. // tags:
  18689. // deprecated
  18690. return array.filter(this.getChildren(), function(child){
  18691. return child.region == region;
  18692. })[0]._splitterWidget;
  18693. },
  18694. resize: function(newSize, currentSize){
  18695. // Overrides _LayoutWidget.resize().
  18696. // resetting potential padding to 0px to provide support for 100% width/height + padding
  18697. // TODO: this hack doesn't respect the box model and is a temporary fix
  18698. if(!this.cs || !this.pe){
  18699. var node = this.domNode;
  18700. this.cs = domStyle.getComputedStyle(node);
  18701. this.pe = domGeometry.getPadExtents(node, this.cs);
  18702. this.pe.r = domStyle.toPixelValue(node, this.cs.paddingRight);
  18703. this.pe.b = domStyle.toPixelValue(node, this.cs.paddingBottom);
  18704. domStyle.set(node, "padding", "0px");
  18705. }
  18706. this.inherited(arguments);
  18707. },
  18708. _layoutChildren: function(/*String?*/ changedChildId, /*Number?*/ changedChildSize){
  18709. // summary:
  18710. // This is the main routine for setting size/position of each child.
  18711. // description:
  18712. // With no arguments, measures the height of top/bottom panes, the width
  18713. // of left/right panes, and then sizes all panes accordingly.
  18714. //
  18715. // With changedRegion specified (as "left", "top", "bottom", or "right"),
  18716. // it changes that region's width/height to changedRegionSize and
  18717. // then resizes other regions that were affected.
  18718. // changedChildId:
  18719. // Id of the child which should be resized because splitter was dragged.
  18720. // changedChildSize:
  18721. // The new width/height (in pixels) to make specified child
  18722. if(!this._borderBox || !this._borderBox.h){
  18723. // We are currently hidden, or we haven't been sized by our parent yet.
  18724. // Abort. Someone will resize us later.
  18725. return;
  18726. }
  18727. // Generate list of wrappers of my children in the order that I want layoutChildren()
  18728. // to process them (i.e. from the outside to the inside)
  18729. var wrappers = array.map(this.getChildren(), function(child, idx){
  18730. return {
  18731. pane: child,
  18732. weight: [
  18733. child.region == "center" ? Infinity : 0,
  18734. child.layoutPriority,
  18735. (this.design == "sidebar" ? 1 : -1) * (/top|bottom/.test(child.region) ? 1 : -1),
  18736. idx
  18737. ]
  18738. };
  18739. }, this);
  18740. wrappers.sort(function(a, b){
  18741. var aw = a.weight, bw = b.weight;
  18742. for(var i=0; i<aw.length; i++){
  18743. if(aw[i] != bw[i]){
  18744. return aw[i] - bw[i];
  18745. }
  18746. }
  18747. return 0;
  18748. });
  18749. // Make new list, combining the externally specified children with splitters and gutters
  18750. var childrenAndSplitters = [];
  18751. array.forEach(wrappers, function(wrapper){
  18752. var pane = wrapper.pane;
  18753. childrenAndSplitters.push(pane);
  18754. if(pane._splitterWidget){
  18755. childrenAndSplitters.push(pane._splitterWidget);
  18756. }
  18757. });
  18758. // Compute the box in which to lay out my children
  18759. var dim = {
  18760. l: this.pe.l,
  18761. t: this.pe.t,
  18762. w: this._borderBox.w - this.pe.w,
  18763. h: this._borderBox.h - this.pe.h
  18764. };
  18765. // Layout the children, possibly changing size due to a splitter drag
  18766. layoutUtils.layoutChildren(this.domNode, dim, childrenAndSplitters,
  18767. changedChildId, changedChildSize);
  18768. },
  18769. destroyRecursive: function(){
  18770. // Destroy splitters first, while getChildren() still works
  18771. array.forEach(this.getChildren(), function(child){
  18772. var splitter = child._splitterWidget;
  18773. if(splitter){
  18774. splitter.destroy();
  18775. }
  18776. delete child._splitterWidget;
  18777. });
  18778. // Then destroy the real children, and myself
  18779. this.inherited(arguments);
  18780. }
  18781. });
  18782. // This argument can be specified for the children of a BorderContainer.
  18783. // Since any widget can be specified as a LayoutContainer child, mix it
  18784. // into the base widget class. (This is a hack, but it's effective.)
  18785. lang.extend(_WidgetBase, {
  18786. // region: [const] String
  18787. // Parameter for children of `dijit.layout.BorderContainer`.
  18788. // Values: "top", "bottom", "leading", "trailing", "left", "right", "center".
  18789. // See the `dijit.layout.BorderContainer` description for details.
  18790. region: '',
  18791. // layoutPriority: [const] Number
  18792. // Parameter for children of `dijit.layout.BorderContainer`.
  18793. // Children with a higher layoutPriority will be placed closer to the BorderContainer center,
  18794. // between children with a lower layoutPriority.
  18795. layoutPriority: 0,
  18796. // splitter: [const] Boolean
  18797. // Parameter for child of `dijit.layout.BorderContainer` where region != "center".
  18798. // If true, enables user to resize the widget by putting a draggable splitter between
  18799. // this widget and the region=center widget.
  18800. splitter: false,
  18801. // minSize: [const] Number
  18802. // Parameter for children of `dijit.layout.BorderContainer`.
  18803. // Specifies a minimum size (in pixels) for this widget when resized by a splitter.
  18804. minSize: 0,
  18805. // maxSize: [const] Number
  18806. // Parameter for children of `dijit.layout.BorderContainer`.
  18807. // Specifies a maximum size (in pixels) for this widget when resized by a splitter.
  18808. maxSize: Infinity
  18809. });
  18810. // For monkey patching
  18811. BorderContainer._Splitter = _Splitter;
  18812. BorderContainer._Gutter = _Gutter;
  18813. return BorderContainer;
  18814. });
  18815. },
  18816. 'dojo/window':function(){
  18817. define("dojo/window", ["./_base/lang", "./_base/sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style", "./dom-construct"],
  18818. function(lang, has, baseWindow, dom, geom, style, domConstruct) {
  18819. // feature detection
  18820. /* not needed but included here for future reference
  18821. has.add("rtl-innerVerticalScrollBar-on-left", function(win, doc){
  18822. var body = baseWindow.body(doc),
  18823. scrollable = domConstruct.create('div', {
  18824. style: {overflow:'scroll', overflowX:'hidden', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', width:'64px', height:'64px'}
  18825. }, body, "last"),
  18826. center = domConstruct.create('center', {
  18827. style: {overflow:'hidden', direction:'ltr'}
  18828. }, scrollable, "last"),
  18829. inner = domConstruct.create('div', {
  18830. style: {overflow:'visible', display:'inline' }
  18831. }, center, "last");
  18832. inner.innerHTML="&nbsp;";
  18833. var midPoint = Math.max(inner.offsetLeft, geom.position(inner).x);
  18834. var ret = midPoint >= 32;
  18835. center.removeChild(inner);
  18836. scrollable.removeChild(center);
  18837. body.removeChild(scrollable);
  18838. return ret;
  18839. });
  18840. */
  18841. has.add("rtl-adjust-position-for-verticalScrollBar", function(win, doc){
  18842. var body = baseWindow.body(doc),
  18843. scrollable = domConstruct.create('div', {
  18844. style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'}
  18845. }, body, "last"),
  18846. div = domConstruct.create('div', {
  18847. style: {overflow:'hidden', direction:'ltr'}
  18848. }, scrollable, "last"),
  18849. ret = geom.position(div).x != 0;
  18850. scrollable.removeChild(div);
  18851. body.removeChild(scrollable);
  18852. return ret;
  18853. });
  18854. has.add("position-fixed-support", function(win, doc){
  18855. // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed
  18856. var body = baseWindow.body(doc),
  18857. outer = domConstruct.create('span', {
  18858. style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'}
  18859. }, body, "last"),
  18860. inner = domConstruct.create('span', {
  18861. style: {position:'fixed', left:'0', top:'0'}
  18862. }, outer, "last"),
  18863. ret = geom.position(inner).x != geom.position(outer).x;
  18864. outer.removeChild(inner);
  18865. body.removeChild(outer);
  18866. return ret;
  18867. });
  18868. // module:
  18869. // dojo/window
  18870. // summary:
  18871. // TODOC
  18872. var window = lang.getObject("dojo.window", true);
  18873. /*=====
  18874. dojo.window = {
  18875. // summary:
  18876. // TODO
  18877. };
  18878. window = dojo.window;
  18879. =====*/
  18880. window.getBox = function(){
  18881. // summary:
  18882. // Returns the dimensions and scroll position of the viewable area of a browser window
  18883. var
  18884. scrollRoot = (baseWindow.doc.compatMode == 'BackCompat') ? baseWindow.body() : baseWindow.doc.documentElement,
  18885. // get scroll position
  18886. scroll = geom.docScroll(), // scrollRoot.scrollTop/Left should work
  18887. w, h;
  18888. if(has("touch")){ // if(scrollbars not supported)
  18889. var uiWindow = baseWindow.doc.parentWindow || baseWindow.doc.defaultView; // use UI window, not dojo.global window. baseWindow.doc.parentWindow probably not needed since it's not defined for webkit
  18890. // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight
  18891. w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated
  18892. h = uiWindow.innerHeight || scrollRoot.clientHeight;
  18893. }else{
  18894. // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight
  18895. // uiWindow.innerWidth/Height includes the scrollbar and cannot be used
  18896. w = scrollRoot.clientWidth;
  18897. h = scrollRoot.clientHeight;
  18898. }
  18899. return {
  18900. l: scroll.x,
  18901. t: scroll.y,
  18902. w: w,
  18903. h: h
  18904. };
  18905. };
  18906. window.get = function(doc){
  18907. // summary:
  18908. // Get window object associated with document doc
  18909. // In some IE versions (at least 6.0), document.parentWindow does not return a
  18910. // reference to the real window object (maybe a copy), so we must fix it as well
  18911. // We use IE specific execScript to attach the real window reference to
  18912. // document._parentWindow for later use
  18913. if(has("ie") < 9 && window !== document.parentWindow){
  18914. /*
  18915. In IE 6, only the variable "window" can be used to connect events (others
  18916. may be only copies).
  18917. */
  18918. doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
  18919. //to prevent memory leak, unset it after use
  18920. //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
  18921. var win = doc._parentWindow;
  18922. doc._parentWindow = null;
  18923. return win; // Window
  18924. }
  18925. return doc.parentWindow || doc.defaultView; // Window
  18926. };
  18927. window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  18928. // summary:
  18929. // Scroll the passed node into view using minimal movement, if it is not already.
  18930. // Don't rely on node.scrollIntoView working just because the function is there since
  18931. // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement.
  18932. // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode
  18933. // and when there's a fixed position scrollable element
  18934. try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
  18935. node = dom.byId(node);
  18936. var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined?
  18937. body = baseWindow.body(doc),
  18938. html = doc.documentElement || body.parentNode,
  18939. isIE = has("ie"),
  18940. isWK = has("webkit");
  18941. // if an untested browser, then use the native method
  18942. if(node == body || node == html){ return; }
  18943. if(!(has("mozilla") || isIE || isWK || has("opera") || has("trident")) && ("scrollIntoView" in node)){
  18944. node.scrollIntoView(false); // short-circuit to native if possible
  18945. return;
  18946. }
  18947. var backCompat = doc.compatMode == 'BackCompat',
  18948. rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth),
  18949. rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight),
  18950. scrollRoot = (isWK || backCompat) ? body : html,
  18951. nodePos = pos || geom.position(node),
  18952. el = node.parentNode,
  18953. isFixed = function(el){
  18954. return (isIE <= 6 || (isIE == 7 && backCompat))
  18955. ? false
  18956. : (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed"));
  18957. },
  18958. self = this,
  18959. scrollElementBy = function(el, x, y){
  18960. if(el.tagName == "BODY" || el.tagName == "HTML"){
  18961. self.get(el.ownerDocument).scrollBy(x, y);
  18962. }else{
  18963. x && (el.scrollLeft += x);
  18964. y && (el.scrollTop += y);
  18965. }
  18966. };
  18967. if(isFixed(node)){ return; } // nothing to do
  18968. while(el){
  18969. if(el == body){ el = scrollRoot; }
  18970. var elPos = geom.position(el),
  18971. fixedPos = isFixed(el),
  18972. rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl";
  18973. if(el == scrollRoot){
  18974. elPos.w = rootWidth; elPos.h = rootHeight;
  18975. if(scrollRoot == html && (isIE || has("trident")) && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
  18976. if(elPos.x < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.x = 0; } // older IE can have values > 0
  18977. if(elPos.y < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.y = 0; }
  18978. }else{
  18979. var pb = geom.getPadBorderExtents(el);
  18980. elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
  18981. var clientSize = el.clientWidth,
  18982. scrollBarSize = elPos.w - clientSize;
  18983. if(clientSize > 0 && scrollBarSize > 0){
  18984. if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){
  18985. elPos.x += scrollBarSize;
  18986. }
  18987. elPos.w = clientSize;
  18988. }
  18989. clientSize = el.clientHeight;
  18990. scrollBarSize = elPos.h - clientSize;
  18991. if(clientSize > 0 && scrollBarSize > 0){
  18992. elPos.h = clientSize;
  18993. }
  18994. }
  18995. if(fixedPos){ // bounded by viewport, not parents
  18996. if(elPos.y < 0){
  18997. elPos.h += elPos.y; elPos.y = 0;
  18998. }
  18999. if(elPos.x < 0){
  19000. elPos.w += elPos.x; elPos.x = 0;
  19001. }
  19002. if(elPos.y + elPos.h > rootHeight){
  19003. elPos.h = rootHeight - elPos.y;
  19004. }
  19005. if(elPos.x + elPos.w > rootWidth){
  19006. elPos.w = rootWidth - elPos.x;
  19007. }
  19008. }
  19009. // calculate overflow in all 4 directions
  19010. var l = nodePos.x - elPos.x, // beyond left: < 0
  19011. // t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
  19012. t = nodePos.y - elPos.y, // beyond top: < 0
  19013. r = l + nodePos.w - elPos.w, // beyond right: > 0
  19014. bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
  19015. var s, old;
  19016. if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
  19017. s = Math[l < 0? "max" : "min"](l, r);
  19018. if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9 || has("trident"))){ s = -s; }
  19019. old = el.scrollLeft;
  19020. scrollElementBy(el, s, 0);
  19021. s = el.scrollLeft - old;
  19022. nodePos.x -= s;
  19023. }
  19024. if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
  19025. s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
  19026. old = el.scrollTop;
  19027. scrollElementBy(el, 0, s);
  19028. s = el.scrollTop - old;
  19029. nodePos.y -= s;
  19030. }
  19031. el = (el != scrollRoot) && !fixedPos && el.parentNode;
  19032. }
  19033. }catch(error){
  19034. console.error('scrollIntoView: ' + error);
  19035. node.scrollIntoView(false);
  19036. }
  19037. };
  19038. return window;
  19039. });
  19040. },
  19041. 'dojo/number':function(){
  19042. define("dojo/number", ["./_base/kernel", "./_base/lang", "./i18n", "./i18n!./cldr/nls/number", "./string", "./regexp"],
  19043. function(dojo, lang, i18n, nlsNumber, dstring, dregexp) {
  19044. // module:
  19045. // dojo/number
  19046. // summary:
  19047. // TODOC
  19048. lang.getObject("number", true, dojo);
  19049. /*=====
  19050. dojo.number = {
  19051. // summary: localized formatting and parsing routines for Number
  19052. }
  19053. dojo.number.__FormatOptions = function(){
  19054. // pattern: String?
  19055. // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
  19056. // with this string. Default value is based on locale. Overriding this property will defeat
  19057. // localization. Literal characters in patterns are not supported.
  19058. // type: String?
  19059. // choose a format type based on the locale from the following:
  19060. // decimal, scientific (not yet supported), percent, currency. decimal by default.
  19061. // places: Number?
  19062. // fixed number of decimal places to show. This overrides any
  19063. // information in the provided pattern.
  19064. // round: Number?
  19065. // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
  19066. // means do not round.
  19067. // locale: String?
  19068. // override the locale used to determine formatting rules
  19069. // fractional: Boolean?
  19070. // If false, show no decimal places, overriding places and pattern settings.
  19071. this.pattern = pattern;
  19072. this.type = type;
  19073. this.places = places;
  19074. this.round = round;
  19075. this.locale = locale;
  19076. this.fractional = fractional;
  19077. }
  19078. =====*/
  19079. dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){
  19080. // summary:
  19081. // Format a Number as a String, using locale-specific settings
  19082. // description:
  19083. // Create a string from a Number using a known localized pattern.
  19084. // Formatting patterns appropriate to the locale are chosen from the
  19085. // [Common Locale Data Repository](http://unicode.org/cldr) as well as the appropriate symbols and
  19086. // delimiters.
  19087. // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null.
  19088. // value:
  19089. // the number to be formatted
  19090. options = lang.mixin({}, options || {});
  19091. var locale = i18n.normalizeLocale(options.locale),
  19092. bundle = i18n.getLocalization("dojo.cldr", "number", locale);
  19093. options.customs = bundle;
  19094. var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];
  19095. if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null
  19096. return dojo.number._applyPattern(value, pattern, options); // String
  19097. };
  19098. //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough
  19099. dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough
  19100. dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){
  19101. // summary:
  19102. // Apply pattern to format value as a string using options. Gives no
  19103. // consideration to local customs.
  19104. // value:
  19105. // the number to be formatted.
  19106. // pattern:
  19107. // a pattern string as described by
  19108. // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
  19109. // options: dojo.number.__FormatOptions?
  19110. // _applyPattern is usually called via `dojo.number.format()` which
  19111. // populates an extra property in the options parameter, "customs".
  19112. // The customs object specifies group and decimal parameters if set.
  19113. //TODO: support escapes
  19114. options = options || {};
  19115. var group = options.customs.group,
  19116. decimal = options.customs.decimal,
  19117. patternList = pattern.split(';'),
  19118. positivePattern = patternList[0];
  19119. pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern);
  19120. //TODO: only test against unescaped
  19121. if(pattern.indexOf('%') != -1){
  19122. value *= 100;
  19123. }else if(pattern.indexOf('\u2030') != -1){
  19124. value *= 1000; // per mille
  19125. }else if(pattern.indexOf('\u00a4') != -1){
  19126. group = options.customs.currencyGroup || group;//mixins instead?
  19127. decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead?
  19128. pattern = pattern.replace(/\u00a4{1,3}/, function(match){
  19129. var prop = ["symbol", "currency", "displayName"][match.length-1];
  19130. return options[prop] || options.currency || "";
  19131. });
  19132. }else if(pattern.indexOf('E') != -1){
  19133. throw new Error("exponential notation not supported");
  19134. }
  19135. //TODO: support @ sig figs?
  19136. var numberPatternRE = dojo.number._numberPatternRE;
  19137. var numberPattern = positivePattern.match(numberPatternRE);
  19138. if(!numberPattern){
  19139. throw new Error("unable to find a number expression in pattern: "+pattern);
  19140. }
  19141. if(options.fractional === false){ options.places = 0; }
  19142. return pattern.replace(numberPatternRE,
  19143. dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round}));
  19144. };
  19145. dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){
  19146. // summary:
  19147. // Rounds to the nearest value with the given number of decimal places, away from zero
  19148. // description:
  19149. // Rounds to the nearest value with the given number of decimal places, away from zero if equal.
  19150. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by
  19151. // fractional increments also, such as the nearest quarter.
  19152. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround.
  19153. // value:
  19154. // The number to round
  19155. // places:
  19156. // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding.
  19157. // Must be non-negative.
  19158. // increment:
  19159. // Rounds next place to nearest value of increment/10. 10 by default.
  19160. // example:
  19161. // >>> dojo.number.round(-0.5)
  19162. // -1
  19163. // >>> dojo.number.round(162.295, 2)
  19164. // 162.29 // note floating point error. Should be 162.3
  19165. // >>> dojo.number.round(10.71, 0, 2.5)
  19166. // 10.75
  19167. var factor = 10 / (increment || 10);
  19168. return (factor * +value).toFixed(places) / factor; // Number
  19169. };
  19170. if((0.9).toFixed() == 0){
  19171. // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit
  19172. // is just after the rounding place and is >=5
  19173. var round = dojo.number.round;
  19174. dojo.number.round = function(v, p, m){
  19175. var d = Math.pow(10, -p || 0), a = Math.abs(v);
  19176. if(!v || a >= d){
  19177. d = 0;
  19178. }else{
  19179. a /= d;
  19180. if(a < 0.5 || a >= 0.95){
  19181. d = 0;
  19182. }
  19183. }
  19184. return round(v, p, m) + (v > 0 ? d : -d);
  19185. };
  19186. }
  19187. /*=====
  19188. dojo.number.__FormatAbsoluteOptions = function(){
  19189. // decimal: String?
  19190. // the decimal separator
  19191. // group: String?
  19192. // the group separator
  19193. // places: Number?|String?
  19194. // number of decimal places. the range "n,m" will format to m places.
  19195. // round: Number?
  19196. // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
  19197. // means don't round.
  19198. this.decimal = decimal;
  19199. this.group = group;
  19200. this.places = places;
  19201. this.round = round;
  19202. }
  19203. =====*/
  19204. dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){
  19205. // summary:
  19206. // Apply numeric pattern to absolute value using options. Gives no
  19207. // consideration to local customs.
  19208. // value:
  19209. // the number to be formatted, ignores sign
  19210. // pattern:
  19211. // the number portion of a pattern (e.g. `#,##0.00`)
  19212. options = options || {};
  19213. if(options.places === true){options.places=0;}
  19214. if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit
  19215. var patternParts = pattern.split("."),
  19216. comma = typeof options.places == "string" && options.places.indexOf(","),
  19217. maxPlaces = options.places;
  19218. if(comma){
  19219. maxPlaces = options.places.substring(comma + 1);
  19220. }else if(!(maxPlaces >= 0)){
  19221. maxPlaces = (patternParts[1] || []).length;
  19222. }
  19223. if(!(options.round < 0)){
  19224. value = dojo.number.round(value, maxPlaces, options.round);
  19225. }
  19226. var valueParts = String(Math.abs(value)).split("."),
  19227. fractional = valueParts[1] || "";
  19228. if(patternParts[1] || options.places){
  19229. if(comma){
  19230. options.places = options.places.substring(0, comma);
  19231. }
  19232. // Pad fractional with trailing zeros
  19233. var pad = options.places !== undefined ? options.places : (patternParts[1] && patternParts[1].lastIndexOf("0") + 1);
  19234. if(pad > fractional.length){
  19235. valueParts[1] = dstring.pad(fractional, pad, '0', true);
  19236. }
  19237. // Truncate fractional
  19238. if(maxPlaces < fractional.length){
  19239. valueParts[1] = fractional.substr(0, maxPlaces);
  19240. }
  19241. }else{
  19242. if(valueParts[1]){ valueParts.pop(); }
  19243. }
  19244. // Pad whole with leading zeros
  19245. var patternDigits = patternParts[0].replace(',', '');
  19246. pad = patternDigits.indexOf("0");
  19247. if(pad != -1){
  19248. pad = patternDigits.length - pad;
  19249. if(pad > valueParts[0].length){
  19250. valueParts[0] = dstring.pad(valueParts[0], pad);
  19251. }
  19252. // Truncate whole
  19253. if(patternDigits.indexOf("#") == -1){
  19254. valueParts[0] = valueParts[0].substr(valueParts[0].length - pad);
  19255. }
  19256. }
  19257. // Add group separators
  19258. var index = patternParts[0].lastIndexOf(','),
  19259. groupSize, groupSize2;
  19260. if(index != -1){
  19261. groupSize = patternParts[0].length - index - 1;
  19262. var remainder = patternParts[0].substr(0, index);
  19263. index = remainder.lastIndexOf(',');
  19264. if(index != -1){
  19265. groupSize2 = remainder.length - index - 1;
  19266. }
  19267. }
  19268. var pieces = [];
  19269. for(var whole = valueParts[0]; whole;){
  19270. var off = whole.length - groupSize;
  19271. pieces.push((off > 0) ? whole.substr(off) : whole);
  19272. whole = (off > 0) ? whole.slice(0, off) : "";
  19273. if(groupSize2){
  19274. groupSize = groupSize2;
  19275. delete groupSize2;
  19276. }
  19277. }
  19278. valueParts[0] = pieces.reverse().join(options.group || ",");
  19279. return valueParts.join(options.decimal || ".");
  19280. };
  19281. /*=====
  19282. dojo.number.__RegexpOptions = function(){
  19283. // pattern: String?
  19284. // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
  19285. // with this string. Default value is based on locale. Overriding this property will defeat
  19286. // localization.
  19287. // type: String?
  19288. // choose a format type based on the locale from the following:
  19289. // decimal, scientific (not yet supported), percent, currency. decimal by default.
  19290. // locale: String?
  19291. // override the locale used to determine formatting rules
  19292. // strict: Boolean?
  19293. // strict parsing, false by default. Strict parsing requires input as produced by the format() method.
  19294. // Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
  19295. // places: Number|String?
  19296. // number of decimal places to accept: Infinity, a positive number, or
  19297. // a range "n,m". Defined by pattern or Infinity if pattern not provided.
  19298. this.pattern = pattern;
  19299. this.type = type;
  19300. this.locale = locale;
  19301. this.strict = strict;
  19302. this.places = places;
  19303. }
  19304. =====*/
  19305. dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){
  19306. // summary:
  19307. // Builds the regular needed to parse a number
  19308. // description:
  19309. // Returns regular expression with positive and negative match, group
  19310. // and decimal separators
  19311. return dojo.number._parseInfo(options).regexp; // String
  19312. };
  19313. dojo.number._parseInfo = function(/*Object?*/options){
  19314. options = options || {};
  19315. var locale = i18n.normalizeLocale(options.locale),
  19316. bundle = i18n.getLocalization("dojo.cldr", "number", locale),
  19317. pattern = options.pattern || bundle[(options.type || "decimal") + "Format"],
  19318. //TODO: memoize?
  19319. group = bundle.group,
  19320. decimal = bundle.decimal,
  19321. factor = 1;
  19322. if(pattern.indexOf('%') != -1){
  19323. factor /= 100;
  19324. }else if(pattern.indexOf('\u2030') != -1){
  19325. factor /= 1000; // per mille
  19326. }else{
  19327. var isCurrency = pattern.indexOf('\u00a4') != -1;
  19328. if(isCurrency){
  19329. group = bundle.currencyGroup || group;
  19330. decimal = bundle.currencyDecimal || decimal;
  19331. }
  19332. }
  19333. //TODO: handle quoted escapes
  19334. var patternList = pattern.split(';');
  19335. if(patternList.length == 1){
  19336. patternList.push("-" + patternList[0]);
  19337. }
  19338. var re = dregexp.buildGroupRE(patternList, function(pattern){
  19339. pattern = "(?:"+dregexp.escapeString(pattern, '.')+")";
  19340. return pattern.replace(dojo.number._numberPatternRE, function(format){
  19341. var flags = {
  19342. signed: false,
  19343. separator: options.strict ? group : [group,""],
  19344. fractional: options.fractional,
  19345. decimal: decimal,
  19346. exponent: false
  19347. },
  19348. parts = format.split('.'),
  19349. places = options.places;
  19350. // special condition for percent (factor != 1)
  19351. // allow decimal places even if not specified in pattern
  19352. if(parts.length == 1 && factor != 1){
  19353. parts[1] = "###";
  19354. }
  19355. if(parts.length == 1 || places === 0){
  19356. flags.fractional = false;
  19357. }else{
  19358. if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0') + 1 : Infinity; }
  19359. if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified
  19360. if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; }
  19361. flags.places = places;
  19362. }
  19363. var groups = parts[0].split(',');
  19364. if(groups.length > 1){
  19365. flags.groupSize = groups.pop().length;
  19366. if(groups.length > 1){
  19367. flags.groupSize2 = groups.pop().length;
  19368. }
  19369. }
  19370. return "("+dojo.number._realNumberRegexp(flags)+")";
  19371. });
  19372. }, true);
  19373. if(isCurrency){
  19374. // substitute the currency symbol for the placeholder in the pattern
  19375. re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){
  19376. var prop = ["symbol", "currency", "displayName"][target.length-1],
  19377. symbol = dregexp.escapeString(options[prop] || options.currency || "");
  19378. before = before ? "[\\s\\xa0]" : "";
  19379. after = after ? "[\\s\\xa0]" : "";
  19380. if(!options.strict){
  19381. if(before){before += "*";}
  19382. if(after){after += "*";}
  19383. return "(?:"+before+symbol+after+")?";
  19384. }
  19385. return before+symbol+after;
  19386. });
  19387. }
  19388. //TODO: substitute localized sign/percent/permille/etc.?
  19389. // normalize whitespace and return
  19390. return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object
  19391. };
  19392. /*=====
  19393. dojo.number.__ParseOptions = function(){
  19394. // pattern: String?
  19395. // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
  19396. // with this string. Default value is based on locale. Overriding this property will defeat
  19397. // localization. Literal characters in patterns are not supported.
  19398. // type: String?
  19399. // choose a format type based on the locale from the following:
  19400. // decimal, scientific (not yet supported), percent, currency. decimal by default.
  19401. // locale: String?
  19402. // override the locale used to determine formatting rules
  19403. // strict: Boolean?
  19404. // strict parsing, false by default. Strict parsing requires input as produced by the format() method.
  19405. // Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
  19406. // fractional: Boolean?|Array?
  19407. // Whether to include the fractional portion, where the number of decimal places are implied by pattern
  19408. // or explicit 'places' parameter. The value [true,false] makes the fractional portion optional.
  19409. this.pattern = pattern;
  19410. this.type = type;
  19411. this.locale = locale;
  19412. this.strict = strict;
  19413. this.fractional = fractional;
  19414. }
  19415. =====*/
  19416. dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){
  19417. // summary:
  19418. // Convert a properly formatted string to a primitive Number, using
  19419. // locale-specific settings.
  19420. // description:
  19421. // Create a Number from a string using a known localized pattern.
  19422. // Formatting patterns are chosen appropriate to the locale
  19423. // and follow the syntax described by
  19424. // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
  19425. // Note that literal characters in patterns are not supported.
  19426. // expression:
  19427. // A string representation of a Number
  19428. var info = dojo.number._parseInfo(options),
  19429. results = (new RegExp("^"+info.regexp+"$")).exec(expression);
  19430. if(!results){
  19431. return NaN; //NaN
  19432. }
  19433. var absoluteMatch = results[1]; // match for the positive expression
  19434. if(!results[1]){
  19435. if(!results[2]){
  19436. return NaN; //NaN
  19437. }
  19438. // matched the negative pattern
  19439. absoluteMatch =results[2];
  19440. info.factor *= -1;
  19441. }
  19442. // Transform it to something Javascript can parse as a number. Normalize
  19443. // decimal point and strip out group separators or alternate forms of whitespace
  19444. absoluteMatch = absoluteMatch.
  19445. replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), "").
  19446. replace(info.decimal, ".");
  19447. // Adjust for negative sign, percent, etc. as necessary
  19448. return absoluteMatch * info.factor; //Number
  19449. };
  19450. /*=====
  19451. dojo.number.__RealNumberRegexpFlags = function(){
  19452. // places: Number?
  19453. // The integer number of decimal places or a range given as "n,m". If
  19454. // not given, the decimal part is optional and the number of places is
  19455. // unlimited.
  19456. // decimal: String?
  19457. // A string for the character used as the decimal point. Default
  19458. // is ".".
  19459. // fractional: Boolean?|Array?
  19460. // Whether decimal places are used. Can be true, false, or [true,
  19461. // false]. Default is [true, false] which means optional.
  19462. // exponent: Boolean?|Array?
  19463. // Express in exponential notation. Can be true, false, or [true,
  19464. // false]. Default is [true, false], (i.e. will match if the
  19465. // exponential part is present are not).
  19466. // eSigned: Boolean?|Array?
  19467. // The leading plus-or-minus sign on the exponent. Can be true,
  19468. // false, or [true, false]. Default is [true, false], (i.e. will
  19469. // match if it is signed or unsigned). flags in regexp.integer can be
  19470. // applied.
  19471. this.places = places;
  19472. this.decimal = decimal;
  19473. this.fractional = fractional;
  19474. this.exponent = exponent;
  19475. this.eSigned = eSigned;
  19476. }
  19477. =====*/
  19478. dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){
  19479. // summary:
  19480. // Builds a regular expression to match a real number in exponential
  19481. // notation
  19482. // assign default values to missing parameters
  19483. flags = flags || {};
  19484. //TODO: use mixin instead?
  19485. if(!("places" in flags)){ flags.places = Infinity; }
  19486. if(typeof flags.decimal != "string"){ flags.decimal = "."; }
  19487. if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; }
  19488. if(!("exponent" in flags)){ flags.exponent = [true, false]; }
  19489. if(!("eSigned" in flags)){ flags.eSigned = [true, false]; }
  19490. var integerRE = dojo.number._integerRegexp(flags),
  19491. decimalRE = dregexp.buildGroupRE(flags.fractional,
  19492. function(q){
  19493. var re = "";
  19494. if(q && (flags.places!==0)){
  19495. re = "\\" + flags.decimal;
  19496. if(flags.places == Infinity){
  19497. re = "(?:" + re + "\\d+)?";
  19498. }else{
  19499. re += "\\d{" + flags.places + "}";
  19500. }
  19501. }
  19502. return re;
  19503. },
  19504. true
  19505. );
  19506. var exponentRE = dregexp.buildGroupRE(flags.exponent,
  19507. function(q){
  19508. if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }
  19509. return "";
  19510. }
  19511. );
  19512. var realRE = integerRE + decimalRE;
  19513. // allow for decimals without integers, e.g. .25
  19514. if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";}
  19515. return realRE + exponentRE; // String
  19516. };
  19517. /*=====
  19518. dojo.number.__IntegerRegexpFlags = function(){
  19519. // signed: Boolean?
  19520. // The leading plus-or-minus sign. Can be true, false, or `[true,false]`.
  19521. // Default is `[true, false]`, (i.e. will match if it is signed
  19522. // or unsigned).
  19523. // separator: String?
  19524. // The character used as the thousands separator. Default is no
  19525. // separator. For more than one symbol use an array, e.g. `[",", ""]`,
  19526. // makes ',' optional.
  19527. // groupSize: Number?
  19528. // group size between separators
  19529. // groupSize2: Number?
  19530. // second grouping, where separators 2..n have a different interval than the first separator (for India)
  19531. this.signed = signed;
  19532. this.separator = separator;
  19533. this.groupSize = groupSize;
  19534. this.groupSize2 = groupSize2;
  19535. }
  19536. =====*/
  19537. dojo.number._integerRegexp = function(/*dojo.number.__IntegerRegexpFlags?*/flags){
  19538. // summary:
  19539. // Builds a regular expression that matches an integer
  19540. // assign default values to missing parameters
  19541. flags = flags || {};
  19542. if(!("signed" in flags)){ flags.signed = [true, false]; }
  19543. if(!("separator" in flags)){
  19544. flags.separator = "";
  19545. }else if(!("groupSize" in flags)){
  19546. flags.groupSize = 3;
  19547. }
  19548. var signRE = dregexp.buildGroupRE(flags.signed,
  19549. function(q){ return q ? "[-+]" : ""; },
  19550. true
  19551. );
  19552. var numberRE = dregexp.buildGroupRE(flags.separator,
  19553. function(sep){
  19554. if(!sep){
  19555. return "(?:\\d+)";
  19556. }
  19557. sep = dregexp.escapeString(sep);
  19558. if(sep == " "){ sep = "\\s"; }
  19559. else if(sep == "\xa0"){ sep = "\\s\\xa0"; }
  19560. var grp = flags.groupSize, grp2 = flags.groupSize2;
  19561. //TODO: should we continue to enforce that numbers with separators begin with 1-9? See #6933
  19562. if(grp2){
  19563. var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";
  19564. return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;
  19565. }
  19566. return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)";
  19567. },
  19568. true
  19569. );
  19570. return signRE + numberRE; // String
  19571. };
  19572. return dojo.number;
  19573. });
  19574. },
  19575. 'dijit/_FocusMixin':function(){
  19576. define("dijit/_FocusMixin", [
  19577. "./focus",
  19578. "./_WidgetBase",
  19579. "dojo/_base/declare", // declare
  19580. "dojo/_base/lang" // lang.extend
  19581. ], function(focus, _WidgetBase, declare, lang){
  19582. /*=====
  19583. var _WidgetBase = dijit._WidgetBase;
  19584. =====*/
  19585. // module:
  19586. // dijit/_FocusMixin
  19587. // summary:
  19588. // Mixin to widget to provide _onFocus() and _onBlur() methods that
  19589. // fire when a widget or it's descendants get/lose focus
  19590. // We don't know where _FocusMixin will occur in the inheritance chain, but we need the _onFocus()/_onBlur() below
  19591. // to be last in the inheritance chain, so mixin to _WidgetBase.
  19592. lang.extend(_WidgetBase, {
  19593. // focused: [readonly] Boolean
  19594. // This widget or a widget it contains has focus, or is "active" because
  19595. // it was recently clicked.
  19596. focused: false,
  19597. onFocus: function(){
  19598. // summary:
  19599. // Called when the widget becomes "active" because
  19600. // it or a widget inside of it either has focus, or has recently
  19601. // been clicked.
  19602. // tags:
  19603. // callback
  19604. },
  19605. onBlur: function(){
  19606. // summary:
  19607. // Called when the widget stops being "active" because
  19608. // focus moved to something outside of it, or the user
  19609. // clicked somewhere outside of it, or the widget was
  19610. // hidden.
  19611. // tags:
  19612. // callback
  19613. },
  19614. _onFocus: function(){
  19615. // summary:
  19616. // This is where widgets do processing for when they are active,
  19617. // such as changing CSS classes. See onFocus() for more details.
  19618. // tags:
  19619. // protected
  19620. this.onFocus();
  19621. },
  19622. _onBlur: function(){
  19623. // summary:
  19624. // This is where widgets do processing for when they stop being active,
  19625. // such as changing CSS classes. See onBlur() for more details.
  19626. // tags:
  19627. // protected
  19628. this.onBlur();
  19629. }
  19630. });
  19631. return declare("dijit._FocusMixin", null, {
  19632. // summary:
  19633. // Mixin to widget to provide _onFocus() and _onBlur() methods that
  19634. // fire when a widget or it's descendants get/lose focus
  19635. // flag that I want _onFocus()/_onBlur() notifications from focus manager
  19636. _focusManager: focus
  19637. });
  19638. });
  19639. },
  19640. 'dijit/_WidgetsInTemplateMixin':function(){
  19641. define("dijit/_WidgetsInTemplateMixin", [
  19642. "dojo/_base/array", // array.forEach
  19643. "dojo/_base/declare", // declare
  19644. "dojo/parser", // parser.parse
  19645. "dijit/registry" // registry.findWidgets
  19646. ], function(array, declare, parser, registry){
  19647. // module:
  19648. // dijit/_WidgetsInTemplateMixin
  19649. // summary:
  19650. // Mixin to supplement _TemplatedMixin when template contains widgets
  19651. return declare("dijit._WidgetsInTemplateMixin", null, {
  19652. // summary:
  19653. // Mixin to supplement _TemplatedMixin when template contains widgets
  19654. // _earlyTemplatedStartup: Boolean
  19655. // A fallback to preserve the 1.0 - 1.3 behavior of children in
  19656. // templates having their startup called before the parent widget
  19657. // fires postCreate. Defaults to 'false', causing child widgets to
  19658. // have their .startup() called immediately before a parent widget
  19659. // .startup(), but always after the parent .postCreate(). Set to
  19660. // 'true' to re-enable to previous, arguably broken, behavior.
  19661. _earlyTemplatedStartup: false,
  19662. // widgetsInTemplate: [protected] Boolean
  19663. // Should we parse the template to find widgets that might be
  19664. // declared in markup inside it? (Remove for 2.0 and assume true)
  19665. widgetsInTemplate: true,
  19666. _beforeFillContent: function(){
  19667. if(this.widgetsInTemplate){
  19668. // Before copying over content, instantiate widgets in template
  19669. var node = this.domNode;
  19670. var cw = (this._startupWidgets = parser.parse(node, {
  19671. noStart: !this._earlyTemplatedStartup,
  19672. template: true,
  19673. inherited: {dir: this.dir, lang: this.lang, textDir: this.textDir},
  19674. propsThis: this, // so data-dojo-props of widgets in the template can reference "this" to refer to me
  19675. scope: "dojo" // even in multi-version mode templates use dojoType/data-dojo-type
  19676. }));
  19677. this._supportingWidgets = registry.findWidgets(node);
  19678. this._attachTemplateNodes(cw, function(n,p){
  19679. return n[p];
  19680. });
  19681. }
  19682. },
  19683. startup: function(){
  19684. array.forEach(this._startupWidgets, function(w){
  19685. if(w && !w._started && w.startup){
  19686. w.startup();
  19687. }
  19688. });
  19689. this.inherited(arguments);
  19690. }
  19691. });
  19692. });
  19693. },
  19694. 'dojo/fx/Toggler':function(){
  19695. define("dojo/fx/Toggler", ["../_base/lang","../_base/declare","../_base/fx", "../_base/connect"],
  19696. function(lang, declare, baseFx, connectUtil) {
  19697. // module:
  19698. // dojo/fx/Toggler
  19699. // summary:
  19700. // TODOC
  19701. return declare("dojo.fx.Toggler", null, {
  19702. // summary:
  19703. // A simple `dojo.Animation` toggler API.
  19704. //
  19705. // description:
  19706. // class constructor for an animation toggler. It accepts a packed
  19707. // set of arguments about what type of animation to use in each
  19708. // direction, duration, etc. All available members are mixed into
  19709. // these animations from the constructor (for example, `node`,
  19710. // `showDuration`, `hideDuration`).
  19711. //
  19712. // example:
  19713. // | var t = new dojo.fx.Toggler({
  19714. // | node: "nodeId",
  19715. // | showDuration: 500,
  19716. // | // hideDuration will default to "200"
  19717. // | showFunc: dojo.fx.wipeIn,
  19718. // | // hideFunc will default to "fadeOut"
  19719. // | });
  19720. // | t.show(100); // delay showing for 100ms
  19721. // | // ...time passes...
  19722. // | t.hide();
  19723. // node: DomNode
  19724. // the node to target for the showing and hiding animations
  19725. node: null,
  19726. // showFunc: Function
  19727. // The function that returns the `dojo.Animation` to show the node
  19728. showFunc: baseFx.fadeIn,
  19729. // hideFunc: Function
  19730. // The function that returns the `dojo.Animation` to hide the node
  19731. hideFunc: baseFx.fadeOut,
  19732. // showDuration:
  19733. // Time in milliseconds to run the show Animation
  19734. showDuration: 200,
  19735. // hideDuration:
  19736. // Time in milliseconds to run the hide Animation
  19737. hideDuration: 200,
  19738. // FIXME: need a policy for where the toggler should "be" the next
  19739. // time show/hide are called if we're stopped somewhere in the
  19740. // middle.
  19741. // FIXME: also would be nice to specify individual showArgs/hideArgs mixed into
  19742. // each animation individually.
  19743. // FIXME: also would be nice to have events from the animations exposed/bridged
  19744. /*=====
  19745. _showArgs: null,
  19746. _showAnim: null,
  19747. _hideArgs: null,
  19748. _hideAnim: null,
  19749. _isShowing: false,
  19750. _isHiding: false,
  19751. =====*/
  19752. constructor: function(args){
  19753. var _t = this;
  19754. lang.mixin(_t, args);
  19755. _t.node = args.node;
  19756. _t._showArgs = lang.mixin({}, args);
  19757. _t._showArgs.node = _t.node;
  19758. _t._showArgs.duration = _t.showDuration;
  19759. _t.showAnim = _t.showFunc(_t._showArgs);
  19760. _t._hideArgs = lang.mixin({}, args);
  19761. _t._hideArgs.node = _t.node;
  19762. _t._hideArgs.duration = _t.hideDuration;
  19763. _t.hideAnim = _t.hideFunc(_t._hideArgs);
  19764. connectUtil.connect(_t.showAnim, "beforeBegin", lang.hitch(_t.hideAnim, "stop", true));
  19765. connectUtil.connect(_t.hideAnim, "beforeBegin", lang.hitch(_t.showAnim, "stop", true));
  19766. },
  19767. show: function(delay){
  19768. // summary: Toggle the node to showing
  19769. // delay: Integer?
  19770. // Ammount of time to stall playing the show animation
  19771. return this.showAnim.play(delay || 0);
  19772. },
  19773. hide: function(delay){
  19774. // summary: Toggle the node to hidden
  19775. // delay: Integer?
  19776. // Ammount of time to stall playing the hide animation
  19777. return this.hideAnim.play(delay || 0);
  19778. }
  19779. });
  19780. });
  19781. },
  19782. 'url:dojox/layout/resources/ExpandoPane.html':"<div class=\"dojoxExpandoPane\">\n\t<div dojoAttachPoint=\"titleWrapper\" class=\"dojoxExpandoTitle\">\n\t\t<div class=\"dojoxExpandoIcon\" dojoAttachPoint=\"iconNode\" dojoAttachEvent=\"onclick:toggle\"><span class=\"a11yNode\">X</span></div>\t\t\t\n\t\t<span class=\"dojoxExpandoTitleNode\" dojoAttachPoint=\"titleNode\">${title}</span>\n\t</div>\n\t<div class=\"dojoxExpandoWrapper\" dojoAttachPoint=\"cwrapper\" dojoAttachEvent=\"ondblclick:_trap\">\n\t\t<div class=\"dojoxExpandoContent\" dojoAttachPoint=\"containerNode\"></div>\n\t</div>\n</div>\n",
  19783. 'dojox/fx/_base':function(){
  19784. define("dojox/fx/_base", ["dojo/_base/array","dojo/_base/lang", "dojo/_base/fx", "dojo/fx", "dojo/dom", "dojo/dom-style",
  19785. "dojo/dom-geometry", "dojo/_base/connect", "dojo/_base/html"],
  19786. function(arrayUtil, lang, baseFx, coreFx, dom, domStyle, domGeom, connectUtil, htmlUtil){
  19787. // summary: Experimental and extended Animations beyond Dojo Core / Base functionality.
  19788. // Provides advanced Lines, Animations, and convenience aliases.
  19789. var dojoxFx = lang.getObject("dojox.fx", true);
  19790. /*
  19791. lang.mixin(dojox.fx, {
  19792. // anim: Function
  19793. // Alias of `dojo.anim` - the shorthand `dojo.animateProperty` with auto-play
  19794. anim: dojo.fx.anim,
  19795. // animateProperty: Function
  19796. // Alias of `dojo.animateProperty` - animate any CSS property
  19797. animateProperty: dojox.fx.animateProperty,
  19798. // fadeTo: Function
  19799. // Fade an element from an opacity to an opacity.
  19800. // Omit `start:` property to detect. `end:` property is required.
  19801. // Ultimately an alias to `dojo._fade`
  19802. fadeTo: dojo._fade,
  19803. // fadeIn: Function
  19804. // Alias of `dojo.fadeIn` - Fade a node in.
  19805. fadeIn: dojo.fadeIn,
  19806. // fadeOut: Function
  19807. // Alias of `dojo.fadeOut` - Fades a node out.
  19808. fadeOut: dojo.fadeOut,
  19809. // combine: Function
  19810. // Alias of `dojo.fx.combine` - Run an array of animations in parallel
  19811. combine: dojo.fx.combine,
  19812. // chain: Function
  19813. // Alias of `dojo.fx.chain` - Run an array of animations in sequence
  19814. chain: dojo.fx.chain,
  19815. // slideTo: Function
  19816. // Alias of `dojo.fx.slideTo` - Slide a node to a defined top/left coordinate
  19817. slideTo: dojo.fx.slideTo,
  19818. // wipeIn: Function
  19819. // Alias of `dojo.fx.wipeIn` - Wipe a node to visible
  19820. wipeIn: dojo.fx.wipeIn,
  19821. // wipeOut: Function
  19822. // Alias of `dojo.fx.wipeOut` - Wipe a node to non-visible
  19823. wipeOut: dojo.fx.wipeOut
  19824. });
  19825. */
  19826. dojoxFx.sizeTo = function(/* Object */args){
  19827. // summary:
  19828. // Creates an animation that will size a node
  19829. //
  19830. // description:
  19831. // Returns an animation that will size the target node
  19832. // defined in args Object about it's center to
  19833. // a width and height defined by (args.width, args.height),
  19834. // supporting an optional method: chain||combine mixin
  19835. // (defaults to chain).
  19836. //
  19837. // - works best on absolutely or relatively positioned elements
  19838. //
  19839. // example:
  19840. // | // size #myNode to 400px x 200px over 1 second
  19841. // | dojo.fx.sizeTo({
  19842. // | node:'myNode',
  19843. // | duration: 1000,
  19844. // | width: 400,
  19845. // | height: 200,
  19846. // | method: "combine"
  19847. // | }).play();
  19848. //
  19849. var node = args.node = dom.byId(args.node),
  19850. abs = "absolute";
  19851. var method = args.method || "chain";
  19852. if(!args.duration){ args.duration = 500; } // default duration needed
  19853. if(method == "chain"){ args.duration = Math.floor(args.duration / 2); }
  19854. var top, newTop, left, newLeft, width, height = null;
  19855. var init = (function(n){
  19856. return function(){
  19857. var cs = domStyle.getComputedStyle(n),
  19858. pos = cs.position,
  19859. w = cs.width,
  19860. h = cs.height
  19861. ;
  19862. top = (pos == abs ? n.offsetTop : parseInt(cs.top) || 0);
  19863. left = (pos == abs ? n.offsetLeft : parseInt(cs.left) || 0);
  19864. width = (w == "auto" ? 0 : parseInt(w));
  19865. height = (h == "auto" ? 0 : parseInt(h));
  19866. newLeft = left - Math.floor((args.width - width) / 2);
  19867. newTop = top - Math.floor((args.height - height) / 2);
  19868. if(pos != abs && pos != 'relative'){
  19869. var ret = domStyle.coords(n, true);
  19870. top = ret.y;
  19871. left = ret.x;
  19872. n.style.position = abs;
  19873. n.style.top = top + "px";
  19874. n.style.left = left + "px";
  19875. }
  19876. }
  19877. })(node);
  19878. var anim1 = baseFx.animateProperty(lang.mixin({
  19879. properties: {
  19880. height: function(){
  19881. init();
  19882. return { end: args.height || 0, start: height };
  19883. },
  19884. top: function(){
  19885. return { start: top, end: newTop };
  19886. }
  19887. }
  19888. }, args));
  19889. var anim2 = baseFx.animateProperty(lang.mixin({
  19890. properties: {
  19891. width: function(){
  19892. return { start: width, end: args.width || 0 }
  19893. },
  19894. left: function(){
  19895. return { start: left, end: newLeft }
  19896. }
  19897. }
  19898. }, args));
  19899. var anim = coreFx[(args.method == "combine" ? "combine" : "chain")]([anim1, anim2]);
  19900. return anim; // dojo.Animation
  19901. };
  19902. dojoxFx.slideBy = function(/* Object */args){
  19903. // summary:
  19904. // Returns an animation to slide a node by a defined offset.
  19905. //
  19906. // description:
  19907. // Returns an animation that will slide a node (args.node) from it's
  19908. // current position to it's current posision plus the numbers defined
  19909. // in args.top and args.left. standard dojo.fx mixin's apply.
  19910. //
  19911. // example:
  19912. // | // slide domNode 50px down, and 22px left
  19913. // | dojox.fx.slideBy({
  19914. // | node: domNode, duration:400,
  19915. // | top: 50, left: -22
  19916. // | }).play();
  19917. var node = args.node = dom.byId(args.node),
  19918. top, left;
  19919. var init = (function(n){
  19920. return function(){
  19921. var cs = domStyle.getComputedStyle(n);
  19922. var pos = cs.position;
  19923. top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
  19924. left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
  19925. if(pos != 'absolute' && pos != 'relative'){
  19926. var ret = domGeom.coords(n, true);
  19927. top = ret.y;
  19928. left = ret.x;
  19929. n.style.position = "absolute";
  19930. n.style.top = top + "px";
  19931. n.style.left = left + "px";
  19932. }
  19933. }
  19934. })(node);
  19935. init();
  19936. var _anim = baseFx.animateProperty(lang.mixin({
  19937. properties: {
  19938. // FIXME: is there a way to update the _Line after creation?
  19939. // null start values allow chaining to work, animateProperty will
  19940. // determine them for us (except in ie6? -- ugh)
  19941. top: top + (args.top || 0),
  19942. left: left + (args.left || 0)
  19943. }
  19944. }, args));
  19945. connectUtil.connect(_anim, "beforeBegin", _anim, init);
  19946. return _anim; // dojo.Animation
  19947. };
  19948. dojoxFx.crossFade = function(/* Object */args){
  19949. // summary:
  19950. // Returns an animation cross fading two element simultaneously
  19951. //
  19952. // args:
  19953. // args.nodes: Array - two element array of domNodes, or id's
  19954. //
  19955. // all other standard animation args mixins apply. args.node ignored.
  19956. //
  19957. // simple check for which node is visible, maybe too simple?
  19958. var node1 = args.nodes[0] = dom.byId(args.nodes[0]),
  19959. op1 = htmlUtil.style(node1,"opacity"),
  19960. node2 = args.nodes[1] = dom.byId(args.nodes[1]),
  19961. op2 = htmlUtil.style(node2, "opacity")
  19962. ;
  19963. var _anim = coreFx.combine([
  19964. baseFx[(op1 == 0 ? "fadeIn" : "fadeOut")](lang.mixin({
  19965. node: node1
  19966. },args)),
  19967. baseFx[(op1 == 0 ? "fadeOut" : "fadeIn")](lang.mixin({
  19968. node: node2
  19969. },args))
  19970. ]);
  19971. return _anim; // dojo.Animation
  19972. };
  19973. dojoxFx.highlight = function(/*Object*/ args){
  19974. // summary:
  19975. // Highlight a node
  19976. //
  19977. // description:
  19978. // Returns an animation that sets the node background to args.color
  19979. // then gradually fades back the original node background color
  19980. //
  19981. // example:
  19982. // | dojox.fx.highlight({ node:"foo" }).play();
  19983. var node = args.node = dom.byId(args.node);
  19984. args.duration = args.duration || 400;
  19985. // Assign default color light yellow
  19986. var startColor = args.color || '#ffff99',
  19987. endColor = htmlUtil.style(node, "backgroundColor")
  19988. ;
  19989. // safari "fix"
  19990. // safari reports rgba(0, 0, 0, 0) (black) as transparent color, while
  19991. // other browsers return "transparent", rendered as white by default by
  19992. // dojo.Color; now dojo.Color maps "transparent" to
  19993. // djConfig.transparentColor ([r, g, b]), if present; so we can use
  19994. // the color behind the effect node
  19995. if(endColor == "rgba(0, 0, 0, 0)"){
  19996. endColor = "transparent";
  19997. }
  19998. var anim = baseFx.animateProperty(lang.mixin({
  19999. properties: {
  20000. backgroundColor: { start: startColor, end: endColor }
  20001. }
  20002. }, args));
  20003. if(endColor == "transparent"){
  20004. connectUtil.connect(anim, "onEnd", anim, function(){
  20005. node.style.backgroundColor = endColor;
  20006. });
  20007. }
  20008. return anim; // dojo.Animation
  20009. };
  20010. dojoxFx.wipeTo = function(/*Object*/ args){
  20011. // summary:
  20012. // Animate a node wiping to a specific width or height
  20013. //
  20014. // description:
  20015. // Returns an animation that will expand the
  20016. // node defined in 'args' object from it's current to
  20017. // the height or width value given by the args object.
  20018. //
  20019. // default to height:, so leave height null and specify width:
  20020. // to wipeTo a width. note: this may be deprecated by a
  20021. //
  20022. // Note that the final value should not include
  20023. // units and should be an integer. Thus a valid args object
  20024. // would look something like this:
  20025. //
  20026. // | dojox.fx.wipeTo({ node: "nodeId", height: 200 }).play();
  20027. //
  20028. // Node must have no margin/border/padding, so put another
  20029. // node inside your target node for additional styling.
  20030. args.node = dom.byId(args.node);
  20031. var node = args.node, s = node.style;
  20032. var dir = (args.width ? "width" : "height"),
  20033. endVal = args[dir],
  20034. props = {}
  20035. ;
  20036. props[dir] = {
  20037. // wrapped in functions so we wait till the last second to query (in case value has changed)
  20038. start: function(){
  20039. // start at current [computed] height, but use 1px rather than 0
  20040. // because 0 causes IE to display the whole panel
  20041. s.overflow = "hidden";
  20042. if(s.visibility == "hidden" || s.display == "none"){
  20043. s[dir] = "1px";
  20044. s.display = "";
  20045. s.visibility = "";
  20046. return 1;
  20047. }else{
  20048. var now = htmlUtil.style(node,dir);
  20049. return Math.max(now, 1);
  20050. }
  20051. },
  20052. end: endVal
  20053. };
  20054. var anim = baseFx.animateProperty(lang.mixin({ properties: props }, args));
  20055. return anim; // dojo.Animation
  20056. };
  20057. return dojoxFx;
  20058. });
  20059. },
  20060. 'dojo/dnd/Target':function(){
  20061. define("dojo/dnd/Target", [ "./Source" ], function(Source){
  20062. /*===== Source = dojo.dnd.Source =====*/
  20063. return dojo.declare("dojo.dnd.Target", Source, {
  20064. // summary: a Target object, which can be used as a DnD target
  20065. constructor: function(node, params){
  20066. // summary:
  20067. // a constructor of the Target --- see the `dojo.dnd.Source.constructor` for details
  20068. this.isSource = false;
  20069. dojo.removeClass(this.node, "dojoDndSource");
  20070. }
  20071. });
  20072. });
  20073. },
  20074. 'dojo/data/util/sorter':function(){
  20075. define("dojo/data/util/sorter", ["../../_base/lang"], function(lang) {
  20076. // module:
  20077. // dojo/data/util/sorter
  20078. // summary:
  20079. // TODOC
  20080. var sorter = lang.getObject("dojo.data.util.sorter", true);
  20081. sorter.basicComparator = function( /*anything*/ a,
  20082. /*anything*/ b){
  20083. // summary:
  20084. // Basic comparision function that compares if an item is greater or less than another item
  20085. // description:
  20086. // returns 1 if a > b, -1 if a < b, 0 if equal.
  20087. // 'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list.
  20088. // And compared to each other, null is equivalent to undefined.
  20089. //null is a problematic compare, so if null, we set to undefined.
  20090. //Makes the check logic simple, compact, and consistent
  20091. //And (null == undefined) === true, so the check later against null
  20092. //works for undefined and is less bytes.
  20093. var r = -1;
  20094. if(a === null){
  20095. a = undefined;
  20096. }
  20097. if(b === null){
  20098. b = undefined;
  20099. }
  20100. if(a == b){
  20101. r = 0;
  20102. }else if(a > b || a == null){
  20103. r = 1;
  20104. }
  20105. return r; //int {-1,0,1}
  20106. };
  20107. sorter.createSortFunction = function( /* attributes array */sortSpec, /*dojo.data.core.Read*/ store){
  20108. // summary:
  20109. // Helper function to generate the sorting function based off the list of sort attributes.
  20110. // description:
  20111. // The sort function creation will look for a property on the store called 'comparatorMap'. If it exists
  20112. // it will look in the mapping for comparisons function for the attributes. If one is found, it will
  20113. // use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates.
  20114. // Returns the sorting function for this particular list of attributes and sorting directions.
  20115. //
  20116. // sortSpec: array
  20117. // A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending.
  20118. // The objects should be formatted as follows:
  20119. // {
  20120. // attribute: "attributeName-string" || attribute,
  20121. // descending: true|false; // Default is false.
  20122. // }
  20123. // store: object
  20124. // The datastore object to look up item values from.
  20125. //
  20126. var sortFunctions=[];
  20127. function createSortFunction(attr, dir, comp, s){
  20128. //Passing in comp and s (comparator and store), makes this
  20129. //function much faster.
  20130. return function(itemA, itemB){
  20131. var a = s.getValue(itemA, attr);
  20132. var b = s.getValue(itemB, attr);
  20133. return dir * comp(a,b); //int
  20134. };
  20135. }
  20136. var sortAttribute;
  20137. var map = store.comparatorMap;
  20138. var bc = sorter.basicComparator;
  20139. for(var i = 0; i < sortSpec.length; i++){
  20140. sortAttribute = sortSpec[i];
  20141. var attr = sortAttribute.attribute;
  20142. if(attr){
  20143. var dir = (sortAttribute.descending) ? -1 : 1;
  20144. var comp = bc;
  20145. if(map){
  20146. if(typeof attr !== "string" && ("toString" in attr)){
  20147. attr = attr.toString();
  20148. }
  20149. comp = map[attr] || bc;
  20150. }
  20151. sortFunctions.push(createSortFunction(attr,
  20152. dir, comp, store));
  20153. }
  20154. }
  20155. return function(rowA, rowB){
  20156. var i=0;
  20157. while(i < sortFunctions.length){
  20158. var ret = sortFunctions[i++](rowA, rowB);
  20159. if(ret !== 0){
  20160. return ret;//int
  20161. }
  20162. }
  20163. return 0; //int
  20164. }; // Function
  20165. };
  20166. return sorter;
  20167. });
  20168. },
  20169. 'dijit/form/_ButtonMixin':function(){
  20170. define("dijit/form/_ButtonMixin", [
  20171. "dojo/_base/declare", // declare
  20172. "dojo/dom", // dom.setSelectable
  20173. "dojo/_base/event", // event.stop
  20174. "../registry" // registry.byNode
  20175. ], function(declare, dom, event, registry){
  20176. // module:
  20177. // dijit/form/_ButtonMixin
  20178. // summary:
  20179. // A mixin to add a thin standard API wrapper to a normal HTML button
  20180. return declare("dijit.form._ButtonMixin", null, {
  20181. // summary:
  20182. // A mixin to add a thin standard API wrapper to a normal HTML button
  20183. // description:
  20184. // A label should always be specified (through innerHTML) or the label attribute.
  20185. // Attach points:
  20186. // focusNode (required): this node receives focus
  20187. // valueNode (optional): this node's value gets submitted with FORM elements
  20188. // containerNode (optional): this node gets the innerHTML assignment for label
  20189. // example:
  20190. // | <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
  20191. //
  20192. // example:
  20193. // | var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
  20194. // | dojo.body().appendChild(button1.domNode);
  20195. // label: HTML String
  20196. // Content to display in button.
  20197. label: "",
  20198. // type: [const] String
  20199. // Type of button (submit, reset, button, checkbox, radio)
  20200. type: "button",
  20201. _onClick: function(/*Event*/ e){
  20202. // summary:
  20203. // Internal function to handle click actions
  20204. if(this.disabled){
  20205. event.stop(e);
  20206. return false;
  20207. }
  20208. var preventDefault = this.onClick(e) === false; // user click actions
  20209. if(!preventDefault && this.type == "submit" && !(this.valueNode||this.focusNode).form){ // see if a non-form widget needs to be signalled
  20210. for(var node=this.domNode; node.parentNode; node=node.parentNode){
  20211. var widget=registry.byNode(node);
  20212. if(widget && typeof widget._onSubmit == "function"){
  20213. widget._onSubmit(e);
  20214. preventDefault = true;
  20215. break;
  20216. }
  20217. }
  20218. }
  20219. if(preventDefault){
  20220. e.preventDefault();
  20221. }
  20222. return !preventDefault;
  20223. },
  20224. postCreate: function(){
  20225. this.inherited(arguments);
  20226. dom.setSelectable(this.focusNode, false);
  20227. },
  20228. onClick: function(/*Event*/ /*===== e =====*/){
  20229. // summary:
  20230. // Callback for when button is clicked.
  20231. // If type="submit", return true to perform submit, or false to cancel it.
  20232. // type:
  20233. // callback
  20234. return true; // Boolean
  20235. },
  20236. _setLabelAttr: function(/*String*/ content){
  20237. // summary:
  20238. // Hook for set('label', ...) to work.
  20239. // description:
  20240. // Set the label (text) of the button; takes an HTML string.
  20241. this._set("label", content);
  20242. (this.containerNode||this.focusNode).innerHTML = content;
  20243. }
  20244. });
  20245. });
  20246. },
  20247. 'dijit/registry':function(){
  20248. define("dijit/registry", [
  20249. "dojo/_base/array", // array.forEach array.map
  20250. "dojo/_base/sniff", // has("ie")
  20251. "dojo/_base/unload", // unload.addOnWindowUnload
  20252. "dojo/_base/window", // win.body
  20253. "." // dijit._scopeName
  20254. ], function(array, has, unload, win, dijit){
  20255. // module:
  20256. // dijit/registry
  20257. // summary:
  20258. // Registry of existing widget on page, plus some utility methods.
  20259. // Must be accessed through AMD api, ex:
  20260. // require(["dijit/registry"], function(registry){ registry.byId("foo"); })
  20261. var _widgetTypeCtr = {}, hash = {};
  20262. var registry = {
  20263. // summary:
  20264. // A set of widgets indexed by id
  20265. length: 0,
  20266. add: function(/*dijit._Widget*/ widget){
  20267. // summary:
  20268. // Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
  20269. //
  20270. // widget: dijit._Widget
  20271. // Any dijit._Widget subclass.
  20272. if(hash[widget.id]){
  20273. throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
  20274. }
  20275. hash[widget.id] = widget;
  20276. this.length++;
  20277. },
  20278. remove: function(/*String*/ id){
  20279. // summary:
  20280. // Remove a widget from the registry. Does not destroy the widget; simply
  20281. // removes the reference.
  20282. if(hash[id]){
  20283. delete hash[id];
  20284. this.length--;
  20285. }
  20286. },
  20287. byId: function(/*String|Widget*/ id){
  20288. // summary:
  20289. // Find a widget by it's id.
  20290. // If passed a widget then just returns the widget.
  20291. return typeof id == "string" ? hash[id] : id; // dijit._Widget
  20292. },
  20293. byNode: function(/*DOMNode*/ node){
  20294. // summary:
  20295. // Returns the widget corresponding to the given DOMNode
  20296. return hash[node.getAttribute("widgetId")]; // dijit._Widget
  20297. },
  20298. toArray: function(){
  20299. // summary:
  20300. // Convert registry into a true Array
  20301. //
  20302. // example:
  20303. // Work with the widget .domNodes in a real Array
  20304. // | array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
  20305. var ar = [];
  20306. for(var id in hash){
  20307. ar.push(hash[id]);
  20308. }
  20309. return ar; // dijit._Widget[]
  20310. },
  20311. getUniqueId: function(/*String*/widgetType){
  20312. // summary:
  20313. // Generates a unique id for a given widgetType
  20314. var id;
  20315. do{
  20316. id = widgetType + "_" +
  20317. (widgetType in _widgetTypeCtr ?
  20318. ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
  20319. }while(hash[id]);
  20320. return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
  20321. },
  20322. findWidgets: function(/*DomNode*/ root){
  20323. // summary:
  20324. // Search subtree under root returning widgets found.
  20325. // Doesn't search for nested widgets (ie, widgets inside other widgets).
  20326. var outAry = [];
  20327. function getChildrenHelper(root){
  20328. for(var node = root.firstChild; node; node = node.nextSibling){
  20329. if(node.nodeType == 1){
  20330. var widgetId = node.getAttribute("widgetId");
  20331. if(widgetId){
  20332. var widget = hash[widgetId];
  20333. if(widget){ // may be null on page w/multiple dojo's loaded
  20334. outAry.push(widget);
  20335. }
  20336. }else{
  20337. getChildrenHelper(node);
  20338. }
  20339. }
  20340. }
  20341. }
  20342. getChildrenHelper(root);
  20343. return outAry;
  20344. },
  20345. _destroyAll: function(){
  20346. // summary:
  20347. // Code to destroy all widgets and do other cleanup on page unload
  20348. // Clean up focus manager lingering references to widgets and nodes
  20349. dijit._curFocus = null;
  20350. dijit._prevFocus = null;
  20351. dijit._activeStack = [];
  20352. // Destroy all the widgets, top down
  20353. array.forEach(registry.findWidgets(win.body()), function(widget){
  20354. // Avoid double destroy of widgets like Menu that are attached to <body>
  20355. // even though they are logically children of other widgets.
  20356. if(!widget._destroyed){
  20357. if(widget.destroyRecursive){
  20358. widget.destroyRecursive();
  20359. }else if(widget.destroy){
  20360. widget.destroy();
  20361. }
  20362. }
  20363. });
  20364. },
  20365. getEnclosingWidget: function(/*DOMNode*/ node){
  20366. // summary:
  20367. // Returns the widget whose DOM tree contains the specified DOMNode, or null if
  20368. // the node is not contained within the DOM tree of any widget
  20369. while(node){
  20370. var id = node.getAttribute && node.getAttribute("widgetId");
  20371. if(id){
  20372. return hash[id];
  20373. }
  20374. node = node.parentNode;
  20375. }
  20376. return null;
  20377. },
  20378. // In case someone needs to access hash.
  20379. // Actually, this is accessed from WidgetSet back-compatibility code
  20380. _hash: hash
  20381. };
  20382. /*=====
  20383. dijit.registry = {
  20384. // summary:
  20385. // A list of widgets on a page.
  20386. };
  20387. =====*/
  20388. dijit.registry = registry;
  20389. return registry;
  20390. });
  20391. },
  20392. 'dojo/date/locale':function(){
  20393. define("dojo/date/locale", [
  20394. "../_base/kernel",
  20395. "../_base/lang",
  20396. "../_base/array",
  20397. "../date",
  20398. "../cldr/supplemental",
  20399. "../regexp",
  20400. "../string",
  20401. "../i18n!../cldr/nls/gregorian"
  20402. ], function(dojo, lang, array, date, cldr, regexp, string, gregorian) {
  20403. // module:
  20404. // dojo/date/locale
  20405. // summary:
  20406. // This modules defines dojo.date.locale, localization methods for Date.
  20407. lang.getObject("date.locale", true, dojo);
  20408. // Localization methods for Date. Honor local customs using locale-dependent dojo.cldr data.
  20409. // Load the bundles containing localization information for
  20410. // names and formats
  20411. //NOTE: Everything in this module assumes Gregorian calendars.
  20412. // Other calendars will be implemented in separate modules.
  20413. // Format a pattern without literals
  20414. function formatPattern(dateObject, bundle, options, pattern){
  20415. return pattern.replace(/([a-z])\1*/ig, function(match){
  20416. var s, pad,
  20417. c = match.charAt(0),
  20418. l = match.length,
  20419. widthList = ["abbr", "wide", "narrow"];
  20420. switch(c){
  20421. case 'G':
  20422. s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1];
  20423. break;
  20424. case 'y':
  20425. s = dateObject.getFullYear();
  20426. switch(l){
  20427. case 1:
  20428. break;
  20429. case 2:
  20430. if(!options.fullYear){
  20431. s = String(s); s = s.substr(s.length - 2);
  20432. break;
  20433. }
  20434. // fallthrough
  20435. default:
  20436. pad = true;
  20437. }
  20438. break;
  20439. case 'Q':
  20440. case 'q':
  20441. s = Math.ceil((dateObject.getMonth()+1)/3);
  20442. // switch(l){
  20443. // case 1: case 2:
  20444. pad = true;
  20445. // break;
  20446. // case 3: case 4: // unimplemented
  20447. // }
  20448. break;
  20449. case 'M':
  20450. var m = dateObject.getMonth();
  20451. if(l<3){
  20452. s = m+1; pad = true;
  20453. }else{
  20454. var propM = ["months", "format", widthList[l-3]].join("-");
  20455. s = bundle[propM][m];
  20456. }
  20457. break;
  20458. case 'w':
  20459. var firstDay = 0;
  20460. s = dojo.date.locale._getWeekOfYear(dateObject, firstDay); pad = true;
  20461. break;
  20462. case 'd':
  20463. s = dateObject.getDate(); pad = true;
  20464. break;
  20465. case 'D':
  20466. s = dojo.date.locale._getDayOfYear(dateObject); pad = true;
  20467. break;
  20468. case 'E':
  20469. var d = dateObject.getDay();
  20470. if(l<3){
  20471. s = d+1; pad = true;
  20472. }else{
  20473. var propD = ["days", "format", widthList[l-3]].join("-");
  20474. s = bundle[propD][d];
  20475. }
  20476. break;
  20477. case 'a':
  20478. var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm';
  20479. s = options[timePeriod] || bundle['dayPeriods-format-wide-' + timePeriod];
  20480. break;
  20481. case 'h':
  20482. case 'H':
  20483. case 'K':
  20484. case 'k':
  20485. var h = dateObject.getHours();
  20486. // strange choices in the date format make it impossible to write this succinctly
  20487. switch (c){
  20488. case 'h': // 1-12
  20489. s = (h % 12) || 12;
  20490. break;
  20491. case 'H': // 0-23
  20492. s = h;
  20493. break;
  20494. case 'K': // 0-11
  20495. s = (h % 12);
  20496. break;
  20497. case 'k': // 1-24
  20498. s = h || 24;
  20499. break;
  20500. }
  20501. pad = true;
  20502. break;
  20503. case 'm':
  20504. s = dateObject.getMinutes(); pad = true;
  20505. break;
  20506. case 's':
  20507. s = dateObject.getSeconds(); pad = true;
  20508. break;
  20509. case 'S':
  20510. s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true;
  20511. break;
  20512. case 'v': // FIXME: don't know what this is. seems to be same as z?
  20513. case 'z':
  20514. // We only have one timezone to offer; the one from the browser
  20515. s = dojo.date.locale._getZone(dateObject, true, options);
  20516. if(s){break;}
  20517. l=4;
  20518. // fallthrough... use GMT if tz not available
  20519. case 'Z':
  20520. var offset = dojo.date.locale._getZone(dateObject, false, options);
  20521. var tz = [
  20522. (offset<=0 ? "+" : "-"),
  20523. string.pad(Math.floor(Math.abs(offset)/60), 2),
  20524. string.pad(Math.abs(offset)% 60, 2)
  20525. ];
  20526. if(l==4){
  20527. tz.splice(0, 0, "GMT");
  20528. tz.splice(3, 0, ":");
  20529. }
  20530. s = tz.join("");
  20531. break;
  20532. // case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A': case 'e':
  20533. // console.log(match+" modifier unimplemented");
  20534. default:
  20535. throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern);
  20536. }
  20537. if(pad){ s = string.pad(s, l); }
  20538. return s;
  20539. });
  20540. }
  20541. /*=====
  20542. dojo.date.locale.__FormatOptions = function(){
  20543. // selector: String
  20544. // choice of 'time','date' (default: date and time)
  20545. // formatLength: String
  20546. // choice of long, short, medium or full (plus any custom additions). Defaults to 'short'
  20547. // datePattern:String
  20548. // override pattern with this string
  20549. // timePattern:String
  20550. // override pattern with this string
  20551. // am: String
  20552. // override strings for am in times
  20553. // pm: String
  20554. // override strings for pm in times
  20555. // locale: String
  20556. // override the locale used to determine formatting rules
  20557. // fullYear: Boolean
  20558. // (format only) use 4 digit years whenever 2 digit years are called for
  20559. // strict: Boolean
  20560. // (parse only) strict parsing, off by default
  20561. this.selector = selector;
  20562. this.formatLength = formatLength;
  20563. this.datePattern = datePattern;
  20564. this.timePattern = timePattern;
  20565. this.am = am;
  20566. this.pm = pm;
  20567. this.locale = locale;
  20568. this.fullYear = fullYear;
  20569. this.strict = strict;
  20570. }
  20571. =====*/
  20572. dojo.date.locale._getZone = function(/*Date*/dateObject, /*boolean*/getName, /*dojo.date.locale.__FormatOptions?*/options){
  20573. // summary:
  20574. // Returns the zone (or offset) for the given date and options. This
  20575. // is broken out into a separate function so that it can be overridden
  20576. // by timezone-aware code.
  20577. //
  20578. // dateObject:
  20579. // the date and/or time being formatted.
  20580. //
  20581. // getName:
  20582. // Whether to return the timezone string (if true), or the offset (if false)
  20583. //
  20584. // options:
  20585. // The options being used for formatting
  20586. if(getName){
  20587. return date.getTimezoneName(dateObject);
  20588. }else{
  20589. return dateObject.getTimezoneOffset();
  20590. }
  20591. };
  20592. dojo.date.locale.format = function(/*Date*/dateObject, /*dojo.date.locale.__FormatOptions?*/options){
  20593. // summary:
  20594. // Format a Date object as a String, using locale-specific settings.
  20595. //
  20596. // description:
  20597. // Create a string from a Date object using a known localized pattern.
  20598. // By default, this method formats both date and time from dateObject.
  20599. // Formatting patterns are chosen appropriate to the locale. Different
  20600. // formatting lengths may be chosen, with "full" used by default.
  20601. // Custom patterns may be used or registered with translations using
  20602. // the dojo.date.locale.addCustomFormats method.
  20603. // Formatting patterns are implemented using [the syntax described at
  20604. // unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
  20605. //
  20606. // dateObject:
  20607. // the date and/or time to be formatted. If a time only is formatted,
  20608. // the values in the year, month, and day fields are irrelevant. The
  20609. // opposite is true when formatting only dates.
  20610. options = options || {};
  20611. var locale = dojo.i18n.normalizeLocale(options.locale),
  20612. formatLength = options.formatLength || 'short',
  20613. bundle = dojo.date.locale._getGregorianBundle(locale),
  20614. str = [],
  20615. sauce = lang.hitch(this, formatPattern, dateObject, bundle, options);
  20616. if(options.selector == "year"){
  20617. return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce);
  20618. }
  20619. var pattern;
  20620. if(options.selector != "date"){
  20621. pattern = options.timePattern || bundle["timeFormat-"+formatLength];
  20622. if(pattern){str.push(_processPattern(pattern, sauce));}
  20623. }
  20624. if(options.selector != "time"){
  20625. pattern = options.datePattern || bundle["dateFormat-"+formatLength];
  20626. if(pattern){str.push(_processPattern(pattern, sauce));}
  20627. }
  20628. return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
  20629. function(match, key){ return str[key]; }); // String
  20630. };
  20631. dojo.date.locale.regexp = function(/*dojo.date.locale.__FormatOptions?*/options){
  20632. // summary:
  20633. // Builds the regular needed to parse a localized date
  20634. return dojo.date.locale._parseInfo(options).regexp; // String
  20635. };
  20636. dojo.date.locale._parseInfo = function(/*dojo.date.locale.__FormatOptions?*/options){
  20637. options = options || {};
  20638. var locale = dojo.i18n.normalizeLocale(options.locale),
  20639. bundle = dojo.date.locale._getGregorianBundle(locale),
  20640. formatLength = options.formatLength || 'short',
  20641. datePattern = options.datePattern || bundle["dateFormat-" + formatLength],
  20642. timePattern = options.timePattern || bundle["timeFormat-" + formatLength],
  20643. pattern;
  20644. if(options.selector == 'date'){
  20645. pattern = datePattern;
  20646. }else if(options.selector == 'time'){
  20647. pattern = timePattern;
  20648. }else{
  20649. pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
  20650. function(match, key){ return [timePattern, datePattern][key]; });
  20651. }
  20652. var tokens = [],
  20653. re = _processPattern(pattern, lang.hitch(this, _buildDateTimeRE, tokens, bundle, options));
  20654. return {regexp: re, tokens: tokens, bundle: bundle};
  20655. };
  20656. dojo.date.locale.parse = function(/*String*/value, /*dojo.date.locale.__FormatOptions?*/options){
  20657. // summary:
  20658. // Convert a properly formatted string to a primitive Date object,
  20659. // using locale-specific settings.
  20660. //
  20661. // description:
  20662. // Create a Date object from a string using a known localized pattern.
  20663. // By default, this method parses looking for both date and time in the string.
  20664. // Formatting patterns are chosen appropriate to the locale. Different
  20665. // formatting lengths may be chosen, with "full" used by default.
  20666. // Custom patterns may be used or registered with translations using
  20667. // the dojo.date.locale.addCustomFormats method.
  20668. //
  20669. // Formatting patterns are implemented using [the syntax described at
  20670. // unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
  20671. // When two digit years are used, a century is chosen according to a sliding
  20672. // window of 80 years before and 20 years after present year, for both `yy` and `yyyy` patterns.
  20673. // year < 100CE requires strict mode.
  20674. //
  20675. // value:
  20676. // A string representation of a date
  20677. // remove non-printing bidi control chars from input and pattern
  20678. var controlChars = /[\u200E\u200F\u202A\u202E]/g,
  20679. info = dojo.date.locale._parseInfo(options),
  20680. tokens = info.tokens, bundle = info.bundle,
  20681. re = new RegExp("^" + info.regexp.replace(controlChars, "") + "$",
  20682. info.strict ? "" : "i"),
  20683. match = re.exec(value && value.replace(controlChars, ""));
  20684. if(!match){ return null; } // null
  20685. var widthList = ['abbr', 'wide', 'narrow'],
  20686. result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end
  20687. amPm = "",
  20688. valid = dojo.every(match, function(v, i){
  20689. if(!i){return true;}
  20690. var token=tokens[i-1];
  20691. var l=token.length;
  20692. switch(token.charAt(0)){
  20693. case 'y':
  20694. if(l != 2 && options.strict){
  20695. //interpret year literally, so '5' would be 5 A.D.
  20696. result[0] = v;
  20697. }else{
  20698. if(v<100){
  20699. v = Number(v);
  20700. //choose century to apply, according to a sliding window
  20701. //of 80 years before and 20 years after present year
  20702. var year = '' + new Date().getFullYear(),
  20703. century = year.substring(0, 2) * 100,
  20704. cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99);
  20705. result[0] = (v < cutoff) ? century + v : century - 100 + v;
  20706. }else{
  20707. //we expected 2 digits and got more...
  20708. if(options.strict){
  20709. return false;
  20710. }
  20711. //interpret literally, so '150' would be 150 A.D.
  20712. //also tolerate '1950', if 'yyyy' input passed to 'yy' format
  20713. result[0] = v;
  20714. }
  20715. }
  20716. break;
  20717. case 'M':
  20718. if(l>2){
  20719. var months = bundle['months-format-' + widthList[l-3]].concat();
  20720. if(!options.strict){
  20721. //Tolerate abbreviating period in month part
  20722. //Case-insensitive comparison
  20723. v = v.replace(".","").toLowerCase();
  20724. months = dojo.map(months, function(s){ return s.replace(".","").toLowerCase(); } );
  20725. }
  20726. v = dojo.indexOf(months, v);
  20727. if(v == -1){
  20728. // console.log("dojo.date.locale.parse: Could not parse month name: '" + v + "'.");
  20729. return false;
  20730. }
  20731. }else{
  20732. v--;
  20733. }
  20734. result[1] = v;
  20735. break;
  20736. case 'E':
  20737. case 'e':
  20738. var days = bundle['days-format-' + widthList[l-3]].concat();
  20739. if(!options.strict){
  20740. //Case-insensitive comparison
  20741. v = v.toLowerCase();
  20742. days = dojo.map(days, function(d){return d.toLowerCase();});
  20743. }
  20744. v = dojo.indexOf(days, v);
  20745. if(v == -1){
  20746. // console.log("dojo.date.locale.parse: Could not parse weekday name: '" + v + "'.");
  20747. return false;
  20748. }
  20749. //TODO: not sure what to actually do with this input,
  20750. //in terms of setting something on the Date obj...?
  20751. //without more context, can't affect the actual date
  20752. //TODO: just validate?
  20753. break;
  20754. case 'D':
  20755. result[1] = 0;
  20756. // fallthrough...
  20757. case 'd':
  20758. result[2] = v;
  20759. break;
  20760. case 'a': //am/pm
  20761. var am = options.am || bundle['dayPeriods-format-wide-am'],
  20762. pm = options.pm || bundle['dayPeriods-format-wide-pm'];
  20763. if(!options.strict){
  20764. var period = /\./g;
  20765. v = v.replace(period,'').toLowerCase();
  20766. am = am.replace(period,'').toLowerCase();
  20767. pm = pm.replace(period,'').toLowerCase();
  20768. }
  20769. if(options.strict && v != am && v != pm){
  20770. // console.log("dojo.date.locale.parse: Could not parse am/pm part.");
  20771. return false;
  20772. }
  20773. // we might not have seen the hours field yet, so store the state and apply hour change later
  20774. amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';
  20775. break;
  20776. case 'K': //hour (1-24)
  20777. if(v == 24){ v = 0; }
  20778. // fallthrough...
  20779. case 'h': //hour (1-12)
  20780. case 'H': //hour (0-23)
  20781. case 'k': //hour (0-11)
  20782. //TODO: strict bounds checking, padding
  20783. if(v > 23){
  20784. // console.log("dojo.date.locale.parse: Illegal hours value");
  20785. return false;
  20786. }
  20787. //in the 12-hour case, adjusting for am/pm requires the 'a' part
  20788. //which could come before or after the hour, so we will adjust later
  20789. result[3] = v;
  20790. break;
  20791. case 'm': //minutes
  20792. result[4] = v;
  20793. break;
  20794. case 's': //seconds
  20795. result[5] = v;
  20796. break;
  20797. case 'S': //milliseconds
  20798. result[6] = v;
  20799. // break;
  20800. // case 'w':
  20801. //TODO var firstDay = 0;
  20802. // default:
  20803. //TODO: throw?
  20804. // console.log("dojo.date.locale.parse: unsupported pattern char=" + token.charAt(0));
  20805. }
  20806. return true;
  20807. });
  20808. var hours = +result[3];
  20809. if(amPm === 'p' && hours < 12){
  20810. result[3] = hours + 12; //e.g., 3pm -> 15
  20811. }else if(amPm === 'a' && hours == 12){
  20812. result[3] = 0; //12am -> 0
  20813. }
  20814. //TODO: implement a getWeekday() method in order to test
  20815. //validity of input strings containing 'EEE' or 'EEEE'...
  20816. var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date
  20817. if(options.strict){
  20818. dateObject.setFullYear(result[0]);
  20819. }
  20820. // Check for overflow. The Date() constructor normalizes things like April 32nd...
  20821. //TODO: why isn't this done for times as well?
  20822. var allTokens = tokens.join(""),
  20823. dateToken = allTokens.indexOf('d') != -1,
  20824. monthToken = allTokens.indexOf('M') != -1;
  20825. if(!valid ||
  20826. (monthToken && dateObject.getMonth() > result[1]) ||
  20827. (dateToken && dateObject.getDate() > result[2])){
  20828. return null;
  20829. }
  20830. // Check for underflow, due to DST shifts. See #9366
  20831. // This assumes a 1 hour dst shift correction at midnight
  20832. // We could compare the timezone offset after the shift and add the difference instead.
  20833. if((monthToken && dateObject.getMonth() < result[1]) ||
  20834. (dateToken && dateObject.getDate() < result[2])){
  20835. dateObject = date.add(dateObject, "hour", 1);
  20836. }
  20837. return dateObject; // Date
  20838. };
  20839. function _processPattern(pattern, applyPattern, applyLiteral, applyAll){
  20840. //summary: Process a pattern with literals in it
  20841. // Break up on single quotes, treat every other one as a literal, except '' which becomes '
  20842. var identity = function(x){return x;};
  20843. applyPattern = applyPattern || identity;
  20844. applyLiteral = applyLiteral || identity;
  20845. applyAll = applyAll || identity;
  20846. //split on single quotes (which escape literals in date format strings)
  20847. //but preserve escaped single quotes (e.g., o''clock)
  20848. var chunks = pattern.match(/(''|[^'])+/g),
  20849. literal = pattern.charAt(0) == "'";
  20850. dojo.forEach(chunks, function(chunk, i){
  20851. if(!chunk){
  20852. chunks[i]='';
  20853. }else{
  20854. chunks[i]=(literal ? applyLiteral : applyPattern)(chunk.replace(/''/g, "'"));
  20855. literal = !literal;
  20856. }
  20857. });
  20858. return applyAll(chunks.join(''));
  20859. }
  20860. function _buildDateTimeRE(tokens, bundle, options, pattern){
  20861. pattern = regexp.escapeString(pattern);
  20862. if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pm
  20863. return pattern.replace(/([a-z])\1*/ig, function(match){
  20864. // Build a simple regexp. Avoid captures, which would ruin the tokens list
  20865. var s,
  20866. c = match.charAt(0),
  20867. l = match.length,
  20868. p2 = '', p3 = '';
  20869. if(options.strict){
  20870. if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }
  20871. if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }
  20872. }else{
  20873. p2 = '0?'; p3 = '0{0,2}';
  20874. }
  20875. switch(c){
  20876. case 'y':
  20877. s = '\\d{2,4}';
  20878. break;
  20879. case 'M':
  20880. s = (l>2) ? '\\S+?' : '1[0-2]|'+p2+'[1-9]';
  20881. break;
  20882. case 'D':
  20883. s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|'+p2+'[1-9][0-9]|'+p3+'[1-9]';
  20884. break;
  20885. case 'd':
  20886. s = '3[01]|[12]\\d|'+p2+'[1-9]';
  20887. break;
  20888. case 'w':
  20889. s = '[1-4][0-9]|5[0-3]|'+p2+'[1-9]';
  20890. break;
  20891. case 'E':
  20892. s = '\\S+';
  20893. break;
  20894. case 'h': //hour (1-12)
  20895. s = '1[0-2]|'+p2+'[1-9]';
  20896. break;
  20897. case 'k': //hour (0-11)
  20898. s = '1[01]|'+p2+'\\d';
  20899. break;
  20900. case 'H': //hour (0-23)
  20901. s = '1\\d|2[0-3]|'+p2+'\\d';
  20902. break;
  20903. case 'K': //hour (1-24)
  20904. s = '1\\d|2[0-4]|'+p2+'[1-9]';
  20905. break;
  20906. case 'm':
  20907. case 's':
  20908. s = '[0-5]\\d';
  20909. break;
  20910. case 'S':
  20911. s = '\\d{'+l+'}';
  20912. break;
  20913. case 'a':
  20914. var am = options.am || bundle['dayPeriods-format-wide-am'],
  20915. pm = options.pm || bundle['dayPeriods-format-wide-pm'];
  20916. s = am + '|' + pm;
  20917. if(!options.strict){
  20918. if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }
  20919. if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }
  20920. if(s.indexOf('.') != -1){ s += '|' + s.replace(/\./g, ""); }
  20921. }
  20922. s = s.replace(/\./g, "\\.");
  20923. break;
  20924. default:
  20925. // case 'v':
  20926. // case 'z':
  20927. // case 'Z':
  20928. s = ".*";
  20929. // console.log("parse of date format, pattern=" + pattern);
  20930. }
  20931. if(tokens){ tokens.push(match); }
  20932. return "(" + s + ")"; // add capture
  20933. }).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace. Need explicit handling of \xa0 for IE.
  20934. }
  20935. var _customFormats = [];
  20936. dojo.date.locale.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){
  20937. // summary:
  20938. // Add a reference to a bundle containing localized custom formats to be
  20939. // used by date/time formatting and parsing routines.
  20940. //
  20941. // description:
  20942. // The user may add custom localized formats where the bundle has properties following the
  20943. // same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx`
  20944. // The pattern string should match the format used by the CLDR.
  20945. // See dojo.date.locale.format() for details.
  20946. // The resources must be loaded by dojo.requireLocalization() prior to use
  20947. _customFormats.push({pkg:packageName,name:bundleName});
  20948. };
  20949. dojo.date.locale._getGregorianBundle = function(/*String*/locale){
  20950. var gregorian = {};
  20951. dojo.forEach(_customFormats, function(desc){
  20952. var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
  20953. gregorian = lang.mixin(gregorian, bundle);
  20954. }, this);
  20955. return gregorian; /*Object*/
  20956. };
  20957. dojo.date.locale.addCustomFormats("dojo.cldr","gregorian");
  20958. dojo.date.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale){
  20959. // summary:
  20960. // Used to get localized strings from dojo.cldr for day or month names.
  20961. //
  20962. // item:
  20963. // 'months' || 'days'
  20964. // type:
  20965. // 'wide' || 'abbr' || 'narrow' (e.g. "Monday", "Mon", or "M" respectively, in English)
  20966. // context:
  20967. // 'standAlone' || 'format' (default)
  20968. // locale:
  20969. // override locale used to find the names
  20970. var label,
  20971. lookup = dojo.date.locale._getGregorianBundle(locale),
  20972. props = [item, context, type];
  20973. if(context == 'standAlone'){
  20974. var key = props.join('-');
  20975. label = lookup[key];
  20976. // Fall back to 'format' flavor of name
  20977. if(label[0] == 1){ label = undefined; } // kludge, in the absence of real aliasing support in dojo.cldr
  20978. }
  20979. props[1] = 'format';
  20980. // return by copy so changes won't be made accidentally to the in-memory model
  20981. return (label || lookup[props.join('-')]).concat(); /*Array*/
  20982. };
  20983. dojo.date.locale.isWeekend = function(/*Date?*/dateObject, /*String?*/locale){
  20984. // summary:
  20985. // Determines if the date falls on a weekend, according to local custom.
  20986. var weekend = cldr.getWeekend(locale),
  20987. day = (dateObject || new Date()).getDay();
  20988. if(weekend.end < weekend.start){
  20989. weekend.end += 7;
  20990. if(day < weekend.start){ day += 7; }
  20991. }
  20992. return day >= weekend.start && day <= weekend.end; // Boolean
  20993. };
  20994. // These are used only by format and strftime. Do they need to be public? Which module should they go in?
  20995. dojo.date.locale._getDayOfYear = function(/*Date*/dateObject){
  20996. // summary: gets the day of the year as represented by dateObject
  20997. return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject) + 1; // Number
  20998. };
  20999. dojo.date.locale._getWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDayOfWeek){
  21000. if(arguments.length == 1){ firstDayOfWeek = 0; } // Sunday
  21001. var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay(),
  21002. adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
  21003. week = Math.floor((dojo.date.locale._getDayOfYear(dateObject) + adj - 1) / 7);
  21004. // if year starts on the specified day, start counting weeks at 1
  21005. if(firstDayOfYear == firstDayOfWeek){ week++; }
  21006. return week; // Number
  21007. };
  21008. return dojo.date.locale;
  21009. });
  21010. },
  21011. 'dijit/tree/_dndContainer':function(){
  21012. define("dijit/tree/_dndContainer", [
  21013. "dojo/aspect", // aspect.after
  21014. "dojo/_base/declare", // declare
  21015. "dojo/dom-class", // domClass.add domClass.remove domClass.replace
  21016. "dojo/_base/event", // event.stop
  21017. "dojo/_base/lang", // lang.getObject lang.mixin lang.hitch
  21018. "dojo/mouse", // mouse.enter, mouse.leave
  21019. "dojo/on"
  21020. ], function(aspect, declare, domClass, event, lang, mouse, on){
  21021. // module:
  21022. // dijit/tree/_dndContainer
  21023. // summary:
  21024. // This is a base class for `dijit.tree._dndSelector`, and isn't meant to be used directly.
  21025. // It's modeled after `dojo.dnd.Container`.
  21026. return declare("dijit.tree._dndContainer", null, {
  21027. // summary:
  21028. // This is a base class for `dijit.tree._dndSelector`, and isn't meant to be used directly.
  21029. // It's modeled after `dojo.dnd.Container`.
  21030. // tags:
  21031. // protected
  21032. /*=====
  21033. // current: DomNode
  21034. // The currently hovered TreeNode.rowNode (which is the DOM node
  21035. // associated w/a given node in the tree, excluding it's descendants)
  21036. current: null,
  21037. =====*/
  21038. constructor: function(tree, params){
  21039. // summary:
  21040. // A constructor of the Container
  21041. // tree: Node
  21042. // Node or node's id to build the container on
  21043. // params: dijit.tree.__SourceArgs
  21044. // A dict of parameters, which gets mixed into the object
  21045. // tags:
  21046. // private
  21047. this.tree = tree;
  21048. this.node = tree.domNode; // TODO: rename; it's not a TreeNode but the whole Tree
  21049. lang.mixin(this, params);
  21050. // class-specific variables
  21051. this.current = null; // current TreeNode's DOM node
  21052. // states
  21053. this.containerState = "";
  21054. domClass.add(this.node, "dojoDndContainer");
  21055. // set up events
  21056. this.events = [
  21057. // container level events
  21058. on(this.node, mouse.enter, lang.hitch(this, "onOverEvent")),
  21059. on(this.node, mouse.leave, lang.hitch(this, "onOutEvent")),
  21060. // switching between TreeNodes
  21061. aspect.after(this.tree, "_onNodeMouseEnter", lang.hitch(this, "onMouseOver"), true),
  21062. aspect.after(this.tree, "_onNodeMouseLeave", lang.hitch(this, "onMouseOut"), true),
  21063. // cancel text selection and text dragging
  21064. on(this.node, "dragstart", lang.hitch(event, "stop")),
  21065. on(this.node, "selectstart", lang.hitch(event, "stop"))
  21066. ];
  21067. },
  21068. destroy: function(){
  21069. // summary:
  21070. // Prepares this object to be garbage-collected
  21071. var h;
  21072. while(h = this.events.pop()){ h.remove(); }
  21073. // this.clearItems();
  21074. this.node = this.parent = null;
  21075. },
  21076. // mouse events
  21077. onMouseOver: function(widget /*===== , evt =====*/){
  21078. // summary:
  21079. // Called when mouse is moved over a TreeNode
  21080. // widget: TreeNode
  21081. // evt: Event
  21082. // tags:
  21083. // protected
  21084. this.current = widget;
  21085. },
  21086. onMouseOut: function(/*===== widget, evt =====*/){
  21087. // summary:
  21088. // Called when mouse is moved away from a TreeNode
  21089. // widget: TreeNode
  21090. // evt: Event
  21091. // tags:
  21092. // protected
  21093. this.current = null;
  21094. },
  21095. _changeState: function(type, newState){
  21096. // summary:
  21097. // Changes a named state to new state value
  21098. // type: String
  21099. // A name of the state to change
  21100. // newState: String
  21101. // new state
  21102. var prefix = "dojoDnd" + type;
  21103. var state = type.toLowerCase() + "State";
  21104. //domClass.replace(this.node, prefix + newState, prefix + this[state]);
  21105. domClass.replace(this.node, prefix + newState, prefix + this[state]);
  21106. this[state] = newState;
  21107. },
  21108. _addItemClass: function(node, type){
  21109. // summary:
  21110. // Adds a class with prefix "dojoDndItem"
  21111. // node: Node
  21112. // A node
  21113. // type: String
  21114. // A variable suffix for a class name
  21115. domClass.add(node, "dojoDndItem" + type);
  21116. },
  21117. _removeItemClass: function(node, type){
  21118. // summary:
  21119. // Removes a class with prefix "dojoDndItem"
  21120. // node: Node
  21121. // A node
  21122. // type: String
  21123. // A variable suffix for a class name
  21124. domClass.remove(node, "dojoDndItem" + type);
  21125. },
  21126. onOverEvent: function(){
  21127. // summary:
  21128. // This function is called once, when mouse is over our container
  21129. // tags:
  21130. // protected
  21131. this._changeState("Container", "Over");
  21132. },
  21133. onOutEvent: function(){
  21134. // summary:
  21135. // This function is called once, when mouse is out of our container
  21136. // tags:
  21137. // protected
  21138. this._changeState("Container", "");
  21139. }
  21140. });
  21141. });
  21142. },
  21143. 'dijit/_base/wai':function(){
  21144. define("dijit/_base/wai", [
  21145. "dojo/dom-attr", // domAttr.attr
  21146. "dojo/_base/lang", // lang.mixin
  21147. "..", // export symbols to dijit
  21148. "../hccss" // not using this module directly, but loading it sets CSS flag on <html>
  21149. ], function(domAttr, lang, dijit){
  21150. // module:
  21151. // dijit/_base/wai
  21152. // summary:
  21153. // Deprecated methods for setting/getting wai roles and states.
  21154. // New code should call setAttribute()/getAttribute() directly.
  21155. //
  21156. // Also loads hccss to apply dijit_a11y class to root node if machine is in high-contrast mode.
  21157. lang.mixin(dijit, {
  21158. hasWaiRole: function(/*Element*/ elem, /*String?*/ role){
  21159. // summary:
  21160. // Determines if an element has a particular role.
  21161. // returns:
  21162. // True if elem has the specific role attribute and false if not.
  21163. // For backwards compatibility if role parameter not provided,
  21164. // returns true if has a role
  21165. var waiRole = this.getWaiRole(elem);
  21166. return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0);
  21167. },
  21168. getWaiRole: function(/*Element*/ elem){
  21169. // summary:
  21170. // Gets the role for an element (which should be a wai role).
  21171. // returns:
  21172. // The role of elem or an empty string if elem
  21173. // does not have a role.
  21174. return lang.trim((domAttr.get(elem, "role") || "").replace("wairole:",""));
  21175. },
  21176. setWaiRole: function(/*Element*/ elem, /*String*/ role){
  21177. // summary:
  21178. // Sets the role on an element.
  21179. // description:
  21180. // Replace existing role attribute with new role.
  21181. domAttr.set(elem, "role", role);
  21182. },
  21183. removeWaiRole: function(/*Element*/ elem, /*String*/ role){
  21184. // summary:
  21185. // Removes the specified role from an element.
  21186. // Removes role attribute if no specific role provided (for backwards compat.)
  21187. var roleValue = domAttr.get(elem, "role");
  21188. if(!roleValue){ return; }
  21189. if(role){
  21190. var t = lang.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
  21191. domAttr.set(elem, "role", t);
  21192. }else{
  21193. elem.removeAttribute("role");
  21194. }
  21195. },
  21196. hasWaiState: function(/*Element*/ elem, /*String*/ state){
  21197. // summary:
  21198. // Determines if an element has a given state.
  21199. // description:
  21200. // Checks for an attribute called "aria-"+state.
  21201. // returns:
  21202. // true if elem has a value for the given state and
  21203. // false if it does not.
  21204. return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state);
  21205. },
  21206. getWaiState: function(/*Element*/ elem, /*String*/ state){
  21207. // summary:
  21208. // Gets the value of a state on an element.
  21209. // description:
  21210. // Checks for an attribute called "aria-"+state.
  21211. // returns:
  21212. // The value of the requested state on elem
  21213. // or an empty string if elem has no value for state.
  21214. return elem.getAttribute("aria-"+state) || "";
  21215. },
  21216. setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
  21217. // summary:
  21218. // Sets a state on an element.
  21219. // description:
  21220. // Sets an attribute called "aria-"+state.
  21221. elem.setAttribute("aria-"+state, value);
  21222. },
  21223. removeWaiState: function(/*Element*/ elem, /*String*/ state){
  21224. // summary:
  21225. // Removes a state from an element.
  21226. // description:
  21227. // Sets an attribute called "aria-"+state.
  21228. elem.removeAttribute("aria-"+state);
  21229. }
  21230. });
  21231. return dijit;
  21232. });
  21233. },
  21234. 'dojox/string/sprintf':function(){
  21235. define("dojox/string/sprintf", [
  21236. "dojo/_base/kernel", // dojo.getObject, dojo.mixin
  21237. "dojo/_base/lang", // dojo.extend
  21238. "dojo/_base/sniff", // dojo.isOpera
  21239. "./tokenize"
  21240. ], function(dojo, lang, has, tokenize){
  21241. var strLib = lang.getObject("string", true, dojox);
  21242. strLib.sprintf = function(/*String*/ format, /*mixed...*/ filler){
  21243. for(var args = [], i = 1; i < arguments.length; i++){
  21244. args.push(arguments[i]);
  21245. }
  21246. var formatter = new strLib.sprintf.Formatter(format);
  21247. return formatter.format.apply(formatter, args);
  21248. };
  21249. strLib.sprintf.Formatter = function(/*String*/ format){
  21250. var tokens = [];
  21251. this._mapped = false;
  21252. this._format = format;
  21253. this._tokens = tokenize(format, this._re, this._parseDelim, this);
  21254. };
  21255. lang.extend(strLib.sprintf.Formatter, {
  21256. _re: /\%(?:\(([\w_]+)\)|([1-9]\d*)\$)?([0 +\-\#]*)(\*|\d+)?(\.)?(\*|\d+)?[hlL]?([\%scdeEfFgGiouxX])/g,
  21257. _parseDelim: function(mapping, intmapping, flags, minWidth, period, precision, specifier){
  21258. if(mapping){
  21259. this._mapped = true;
  21260. }
  21261. return {
  21262. mapping: mapping,
  21263. intmapping: intmapping,
  21264. flags: flags,
  21265. _minWidth: minWidth, // May be dependent on parameters
  21266. period: period,
  21267. _precision: precision, // May be dependent on parameters
  21268. specifier: specifier
  21269. };
  21270. },
  21271. _specifiers: {
  21272. b: {
  21273. base: 2,
  21274. isInt: true
  21275. },
  21276. o: {
  21277. base: 8,
  21278. isInt: true
  21279. },
  21280. x: {
  21281. base: 16,
  21282. isInt: true
  21283. },
  21284. X: {
  21285. extend: ["x"],
  21286. toUpper: true
  21287. },
  21288. d: {
  21289. base: 10,
  21290. isInt: true
  21291. },
  21292. i: {
  21293. extend: ["d"]
  21294. },
  21295. u: {
  21296. extend: ["d"],
  21297. isUnsigned: true
  21298. },
  21299. c: {
  21300. setArg: function(token){
  21301. if(!isNaN(token.arg)){
  21302. var num = parseInt(token.arg);
  21303. if(num < 0 || num > 127){
  21304. throw new Error("invalid character code passed to %c in sprintf");
  21305. }
  21306. token.arg = isNaN(num) ? "" + num : String.fromCharCode(num);
  21307. }
  21308. }
  21309. },
  21310. s: {
  21311. setMaxWidth: function(token){
  21312. token.maxWidth = (token.period == ".") ? token.precision : -1;
  21313. }
  21314. },
  21315. e: {
  21316. isDouble: true,
  21317. doubleNotation: "e"
  21318. },
  21319. E: {
  21320. extend: ["e"],
  21321. toUpper: true
  21322. },
  21323. f: {
  21324. isDouble: true,
  21325. doubleNotation: "f"
  21326. },
  21327. F: {
  21328. extend: ["f"]
  21329. },
  21330. g: {
  21331. isDouble: true,
  21332. doubleNotation: "g"
  21333. },
  21334. G: {
  21335. extend: ["g"],
  21336. toUpper: true
  21337. }
  21338. },
  21339. format: function(/*mixed...*/ filler){
  21340. if(this._mapped && typeof filler != "object"){
  21341. throw new Error("format requires a mapping");
  21342. }
  21343. var str = "";
  21344. var position = 0;
  21345. for(var i = 0, token; i < this._tokens.length; i++){
  21346. token = this._tokens[i];
  21347. if(typeof token == "string"){
  21348. str += token;
  21349. }else{
  21350. if(this._mapped){
  21351. if(typeof filler[token.mapping] == "undefined"){
  21352. throw new Error("missing key " + token.mapping);
  21353. }
  21354. token.arg = filler[token.mapping];
  21355. }else{
  21356. if(token.intmapping){
  21357. var position = parseInt(token.intmapping) - 1;
  21358. }
  21359. if(position >= arguments.length){
  21360. throw new Error("got " + arguments.length + " printf arguments, insufficient for '" + this._format + "'");
  21361. }
  21362. token.arg = arguments[position++];
  21363. }
  21364. if(!token.compiled){
  21365. token.compiled = true;
  21366. token.sign = "";
  21367. token.zeroPad = false;
  21368. token.rightJustify = false;
  21369. token.alternative = false;
  21370. var flags = {};
  21371. for(var fi = token.flags.length; fi--;){
  21372. var flag = token.flags.charAt(fi);
  21373. flags[flag] = true;
  21374. switch(flag){
  21375. case " ":
  21376. token.sign = " ";
  21377. break;
  21378. case "+":
  21379. token.sign = "+";
  21380. break;
  21381. case "0":
  21382. token.zeroPad = (flags["-"]) ? false : true;
  21383. break;
  21384. case "-":
  21385. token.rightJustify = true;
  21386. token.zeroPad = false;
  21387. break;
  21388. case "\#":
  21389. token.alternative = true;
  21390. break;
  21391. default:
  21392. throw Error("bad formatting flag '" + token.flags.charAt(fi) + "'");
  21393. }
  21394. }
  21395. token.minWidth = (token._minWidth) ? parseInt(token._minWidth) : 0;
  21396. token.maxWidth = -1;
  21397. token.toUpper = false;
  21398. token.isUnsigned = false;
  21399. token.isInt = false;
  21400. token.isDouble = false;
  21401. token.precision = 1;
  21402. if(token.period == '.'){
  21403. if(token._precision){
  21404. token.precision = parseInt(token._precision);
  21405. }else{
  21406. token.precision = 0;
  21407. }
  21408. }
  21409. var mixins = this._specifiers[token.specifier];
  21410. if(typeof mixins == "undefined"){
  21411. throw new Error("unexpected specifier '" + token.specifier + "'");
  21412. }
  21413. if(mixins.extend){
  21414. lang.mixin(mixins, this._specifiers[mixins.extend]);
  21415. delete mixins.extend;
  21416. }
  21417. lang.mixin(token, mixins);
  21418. }
  21419. if(typeof token.setArg == "function"){
  21420. token.setArg(token);
  21421. }
  21422. if(typeof token.setMaxWidth == "function"){
  21423. token.setMaxWidth(token);
  21424. }
  21425. if(token._minWidth == "*"){
  21426. if(this._mapped){
  21427. throw new Error("* width not supported in mapped formats");
  21428. }
  21429. token.minWidth = parseInt(arguments[position++]);
  21430. if(isNaN(token.minWidth)){
  21431. throw new Error("the argument for * width at position " + position + " is not a number in " + this._format);
  21432. }
  21433. // negative width means rightJustify
  21434. if (token.minWidth < 0) {
  21435. token.rightJustify = true;
  21436. token.minWidth = -token.minWidth;
  21437. }
  21438. }
  21439. if(token._precision == "*" && token.period == "."){
  21440. if(this._mapped){
  21441. throw new Error("* precision not supported in mapped formats");
  21442. }
  21443. token.precision = parseInt(arguments[position++]);
  21444. if(isNaN(token.precision)){
  21445. throw Error("the argument for * precision at position " + position + " is not a number in " + this._format);
  21446. }
  21447. // negative precision means unspecified
  21448. if (token.precision < 0) {
  21449. token.precision = 1;
  21450. token.period = '';
  21451. }
  21452. }
  21453. if(token.isInt){
  21454. // a specified precision means no zero padding
  21455. if(token.period == '.'){
  21456. token.zeroPad = false;
  21457. }
  21458. this.formatInt(token);
  21459. }else if(token.isDouble){
  21460. if(token.period != '.'){
  21461. token.precision = 6;
  21462. }
  21463. this.formatDouble(token);
  21464. }
  21465. this.fitField(token);
  21466. str += "" + token.arg;
  21467. }
  21468. }
  21469. return str;
  21470. },
  21471. _zeros10: '0000000000',
  21472. _spaces10: ' ',
  21473. formatInt: function(token) {
  21474. var i = parseInt(token.arg);
  21475. if(!isFinite(i)){ // isNaN(f) || f == Number.POSITIVE_INFINITY || f == Number.NEGATIVE_INFINITY)
  21476. // allow this only if arg is number
  21477. if(typeof token.arg != "number"){
  21478. throw new Error("format argument '" + token.arg + "' not an integer; parseInt returned " + i);
  21479. }
  21480. //return '' + i;
  21481. i = 0;
  21482. }
  21483. // if not base 10, make negatives be positive
  21484. // otherwise, (-10).toString(16) is '-a' instead of 'fffffff6'
  21485. if(i < 0 && (token.isUnsigned || token.base != 10)){
  21486. i = 0xffffffff + i + 1;
  21487. }
  21488. if(i < 0){
  21489. token.arg = (- i).toString(token.base);
  21490. this.zeroPad(token);
  21491. token.arg = "-" + token.arg;
  21492. }else{
  21493. token.arg = i.toString(token.base);
  21494. // need to make sure that argument 0 with precision==0 is formatted as ''
  21495. if(!i && !token.precision){
  21496. token.arg = "";
  21497. }else{
  21498. this.zeroPad(token);
  21499. }
  21500. if(token.sign){
  21501. token.arg = token.sign + token.arg;
  21502. }
  21503. }
  21504. if(token.base == 16){
  21505. if(token.alternative){
  21506. token.arg = '0x' + token.arg;
  21507. }
  21508. token.arg = token.toUpper ? token.arg.toUpperCase() : token.arg.toLowerCase();
  21509. }
  21510. if(token.base == 8){
  21511. if(token.alternative && token.arg.charAt(0) != '0'){
  21512. token.arg = '0' + token.arg;
  21513. }
  21514. }
  21515. },
  21516. formatDouble: function(token) {
  21517. var f = parseFloat(token.arg);
  21518. if(!isFinite(f)){ // isNaN(f) || f == Number.POSITIVE_INFINITY || f == Number.NEGATIVE_INFINITY)
  21519. // allow this only if arg is number
  21520. if(typeof token.arg != "number"){
  21521. throw new Error("format argument '" + token.arg + "' not a float; parseFloat returned " + f);
  21522. }
  21523. // C99 says that for 'f':
  21524. // infinity -> '[-]inf' or '[-]infinity' ('[-]INF' or '[-]INFINITY' for 'F')
  21525. // NaN -> a string starting with 'nan' ('NAN' for 'F')
  21526. // this is not commonly implemented though.
  21527. //return '' + f;
  21528. f = 0;
  21529. }
  21530. switch(token.doubleNotation) {
  21531. case 'e': {
  21532. token.arg = f.toExponential(token.precision);
  21533. break;
  21534. }
  21535. case 'f': {
  21536. token.arg = f.toFixed(token.precision);
  21537. break;
  21538. }
  21539. case 'g': {
  21540. // C says use 'e' notation if exponent is < -4 or is >= prec
  21541. // ECMAScript for toPrecision says use exponential notation if exponent is >= prec,
  21542. // though step 17 of toPrecision indicates a test for < -6 to force exponential.
  21543. if(Math.abs(f) < 0.0001){
  21544. //print("forcing exponential notation for f=" + f);
  21545. token.arg = f.toExponential(token.precision > 0 ? token.precision - 1 : token.precision);
  21546. }else{
  21547. token.arg = f.toPrecision(token.precision);
  21548. }
  21549. // In C, unlike 'f', 'gG' removes trailing 0s from fractional part, unless alternative format flag ("#").
  21550. // But ECMAScript formats toPrecision as 0.00100000. So remove trailing 0s.
  21551. if(!token.alternative){
  21552. //print("replacing trailing 0 in '" + s + "'");
  21553. token.arg = token.arg.replace(/(\..*[^0])0*/, "$1");
  21554. // if fractional part is entirely 0, remove it and decimal point
  21555. token.arg = token.arg.replace(/\.0*e/, 'e').replace(/\.0$/,'');
  21556. }
  21557. break;
  21558. }
  21559. default: throw new Error("unexpected double notation '" + token.doubleNotation + "'");
  21560. }
  21561. // C says that exponent must have at least two digits.
  21562. // But ECMAScript does not; toExponential results in things like "1.000000e-8" and "1.000000e+8".
  21563. // Note that s.replace(/e([\+\-])(\d)/, "e$10$2") won't work because of the "$10" instead of "$1".
  21564. // And replace(re, func) isn't supported on IE50 or Safari1.
  21565. token.arg = token.arg.replace(/e\+(\d)$/, "e+0$1").replace(/e\-(\d)$/, "e-0$1");
  21566. // Ensure a '0' before the period.
  21567. // Opera implements (0.001).toString() as '0.001', but (0.001).toFixed(1) is '.001'
  21568. if(has("opera")){
  21569. token.arg = token.arg.replace(/^\./, '0.');
  21570. }
  21571. // if alt, ensure a decimal point
  21572. if(token.alternative){
  21573. token.arg = token.arg.replace(/^(\d+)$/,"$1.");
  21574. token.arg = token.arg.replace(/^(\d+)e/,"$1.e");
  21575. }
  21576. if(f >= 0 && token.sign){
  21577. token.arg = token.sign + token.arg;
  21578. }
  21579. token.arg = token.toUpper ? token.arg.toUpperCase() : token.arg.toLowerCase();
  21580. },
  21581. zeroPad: function(token, /*Int*/ length) {
  21582. length = (arguments.length == 2) ? length : token.precision;
  21583. if(typeof token.arg != "string"){
  21584. token.arg = "" + token.arg;
  21585. }
  21586. var tenless = length - 10;
  21587. while(token.arg.length < tenless){
  21588. token.arg = (token.rightJustify) ? token.arg + this._zeros10 : this._zeros10 + token.arg;
  21589. }
  21590. var pad = length - token.arg.length;
  21591. token.arg = (token.rightJustify) ? token.arg + this._zeros10.substring(0, pad) : this._zeros10.substring(0, pad) + token.arg;
  21592. },
  21593. fitField: function(token) {
  21594. if(token.maxWidth >= 0 && token.arg.length > token.maxWidth){
  21595. return token.arg.substring(0, token.maxWidth);
  21596. }
  21597. if(token.zeroPad){
  21598. this.zeroPad(token, token.minWidth);
  21599. return;
  21600. }
  21601. this.spacePad(token);
  21602. },
  21603. spacePad: function(token, /*Int*/ length) {
  21604. length = (arguments.length == 2) ? length : token.minWidth;
  21605. if(typeof token.arg != 'string'){
  21606. token.arg = '' + token.arg;
  21607. }
  21608. var tenless = length - 10;
  21609. while(token.arg.length < tenless){
  21610. token.arg = (token.rightJustify) ? token.arg + this._spaces10 : this._spaces10 + token.arg;
  21611. }
  21612. var pad = length - token.arg.length;
  21613. token.arg = (token.rightJustify) ? token.arg + this._spaces10.substring(0, pad) : this._spaces10.substring(0, pad) + token.arg;
  21614. }
  21615. });
  21616. return strLib.sprintf;
  21617. });
  21618. },
  21619. 'dojox/layout/ExpandoPane':function(){
  21620. require({cache:{
  21621. 'url:dojox/layout/resources/ExpandoPane.html':"<div class=\"dojoxExpandoPane\">\n\t<div dojoAttachPoint=\"titleWrapper\" class=\"dojoxExpandoTitle\">\n\t\t<div class=\"dojoxExpandoIcon\" dojoAttachPoint=\"iconNode\" dojoAttachEvent=\"onclick:toggle\"><span class=\"a11yNode\">X</span></div>\t\t\t\n\t\t<span class=\"dojoxExpandoTitleNode\" dojoAttachPoint=\"titleNode\">${title}</span>\n\t</div>\n\t<div class=\"dojoxExpandoWrapper\" dojoAttachPoint=\"cwrapper\" dojoAttachEvent=\"ondblclick:_trap\">\n\t\t<div class=\"dojoxExpandoContent\" dojoAttachPoint=\"containerNode\"></div>\n\t</div>\n</div>\n"}});
  21622. define("dojox/layout/ExpandoPane", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/declare","dojo/_base/array",
  21623. "dojo/_base/connect","dojo/_base/event","dojo/_base/fx","dojo/dom-style",
  21624. "dojo/dom-class","dojo/dom-geometry","dojo/text!./resources/ExpandoPane.html",
  21625. "dijit/layout/ContentPane","dijit/_TemplatedMixin","dijit/_Contained","dijit/_Container"],
  21626. function(kernel,lang,declare,arrayUtil,connectUtil,eventUtil,baseFx,domStyle,domClass,domGeom,
  21627. template,ContentPane,TemplatedMixin,Contained,Container) {
  21628. /*=====
  21629. var ContentPane = dijit.layout.ContentPane;
  21630. var TemplatedMixin = dijit._TemplatedMixin;
  21631. var Contained = dijit._Contained;
  21632. var Container = dijit._Container;
  21633. =====*/
  21634. kernel.experimental("dojox.layout.ExpandoPane"); // just to show it can be done?
  21635. return declare("dojox.layout.ExpandoPane", [ContentPane, TemplatedMixin, Contained, Container],{
  21636. // summary: An experimental collapsing-pane for dijit.layout.BorderContainer
  21637. //
  21638. // description:
  21639. // Works just like a ContentPane inside of a borderContainer. Will expand/collapse on
  21640. // command, and supports having Layout Children as direct descendants
  21641. //
  21642. //maxHeight: "",
  21643. //maxWidth: "",
  21644. //splitter: false,
  21645. attributeMap: lang.delegate(ContentPane.prototype.attributeMap, {
  21646. title: { node: "titleNode", type: "innerHTML" }
  21647. }),
  21648. templateString: template,
  21649. // easeOut: String|Function
  21650. // easing function used to hide pane
  21651. easeOut: "dojo._DefaultEasing", // FIXME: This won't work with globalless AMD
  21652. // easeIn: String|Function
  21653. // easing function use to show pane
  21654. easeIn: "dojo._DefaultEasing", // FIXME: This won't work with globalless AMD
  21655. // duration: Integer
  21656. // duration to run show/hide animations
  21657. duration: 420,
  21658. // startExpanded: Boolean
  21659. // Does this widget start in an open (true) or closed (false) state
  21660. startExpanded: true,
  21661. // previewOpacity: Float
  21662. // A value from 0 .. 1 indicating the opacity to use on the container
  21663. // when only showing a preview
  21664. previewOpacity: 0.75,
  21665. // previewOnDblClick: Boolean
  21666. // If true, will override the default behavior of a double-click calling a full toggle.
  21667. // If false, a double-click will cause the preview to popup
  21668. previewOnDblClick: false,
  21669. baseClass: "dijitExpandoPane",
  21670. postCreate: function(){
  21671. this.inherited(arguments);
  21672. this._animConnects = [];
  21673. this._isHorizontal = true;
  21674. if(lang.isString(this.easeOut)){
  21675. this.easeOut = lang.getObject(this.easeOut);
  21676. }
  21677. if(lang.isString(this.easeIn)){
  21678. this.easeIn = lang.getObject(this.easeIn);
  21679. }
  21680. var thisClass = "", rtl = !this.isLeftToRight();
  21681. if(this.region){
  21682. switch(this.region){
  21683. case "trailing" :
  21684. case "right" :
  21685. thisClass = rtl ? "Left" : "Right";
  21686. break;
  21687. case "leading" :
  21688. case "left" :
  21689. thisClass = rtl ? "Right" : "Left";
  21690. break;
  21691. case "top" :
  21692. thisClass = "Top";
  21693. break;
  21694. case "bottom" :
  21695. thisClass = "Bottom";
  21696. break;
  21697. }
  21698. domClass.add(this.domNode, "dojoxExpando" + thisClass);
  21699. domClass.add(this.iconNode, "dojoxExpandoIcon" + thisClass);
  21700. this._isHorizontal = /top|bottom/.test(this.region);
  21701. }
  21702. domStyle.set(this.domNode, {
  21703. overflow: "hidden",
  21704. padding:0
  21705. });
  21706. this.connect(this.domNode, "ondblclick", this.previewOnDblClick ? "preview" : "toggle");
  21707. if(this.previewOnDblClick){
  21708. this.connect(this.getParent(), "_layoutChildren", lang.hitch(this, function(){
  21709. this._isonlypreview = false;
  21710. }));
  21711. }
  21712. },
  21713. _startupSizes: function(){
  21714. this._container = this.getParent();
  21715. this._closedSize = this._titleHeight = domGeom.getMarginBox(this.titleWrapper).h;
  21716. if(this.splitter){
  21717. // find our splitter and tie into it's drag logic
  21718. var myid = this.id;
  21719. arrayUtil.forEach(dijit.registry.toArray(), function(w){
  21720. if(w && w.child && w.child.id == myid){
  21721. this.connect(w,"_stopDrag","_afterResize");
  21722. }
  21723. }, this);
  21724. }
  21725. this._currentSize = domGeom.getContentBox(this.domNode); // TODO: can compute this from passed in value to resize(), see _LayoutWidget for example
  21726. this._showSize = this._currentSize[(this._isHorizontal ? "h" : "w")];
  21727. this._setupAnims();
  21728. if(this.startExpanded){
  21729. this._showing = true;
  21730. }else{
  21731. this._showing = false;
  21732. this._hideWrapper();
  21733. this._hideAnim.gotoPercent(99,true);
  21734. }
  21735. this._hasSizes = true;
  21736. },
  21737. _afterResize: function(e){
  21738. var tmp = this._currentSize; // the old size
  21739. this._currentSize = domGeom.getMarginBox(this.domNode); // the new size
  21740. var n = this._currentSize[(this._isHorizontal ? "h" : "w")]
  21741. if(n > this._titleHeight){
  21742. if(!this._showing){
  21743. this._showing = !this._showing;
  21744. this._showEnd();
  21745. }
  21746. this._showSize = n;
  21747. this._setupAnims();
  21748. }else{
  21749. this._showSize = tmp[(this._isHorizontal ? "h" : "w")];
  21750. this._showing = false;
  21751. this._hideWrapper();
  21752. this._hideAnim.gotoPercent(89,true);
  21753. }
  21754. },
  21755. _setupAnims: function(){
  21756. // summary: Create the show and hide animations
  21757. arrayUtil.forEach(this._animConnects, connectUtil.disconnect);
  21758. var _common = {
  21759. node:this.domNode,
  21760. duration:this.duration
  21761. },
  21762. isHorizontal = this._isHorizontal,
  21763. showProps = {},
  21764. hideProps = {},
  21765. dimension = isHorizontal ? "height" : "width"
  21766. ;
  21767. showProps[dimension] = {
  21768. end: this._showSize
  21769. };
  21770. hideProps[dimension] = {
  21771. end: this._closedSize
  21772. };
  21773. this._showAnim = baseFx.animateProperty(lang.mixin(_common,{
  21774. easing:this.easeIn,
  21775. properties: showProps
  21776. }));
  21777. this._hideAnim = baseFx.animateProperty(lang.mixin(_common,{
  21778. easing:this.easeOut,
  21779. properties: hideProps
  21780. }));
  21781. this._animConnects = [
  21782. connectUtil.connect(this._showAnim, "onEnd", this, "_showEnd"),
  21783. connectUtil.connect(this._hideAnim, "onEnd", this, "_hideEnd")
  21784. ];
  21785. },
  21786. preview: function(){
  21787. // summary: Expand this pane in preview mode (does not affect surrounding layout)
  21788. if(!this._showing){
  21789. this._isonlypreview = !this._isonlypreview;
  21790. }
  21791. this.toggle();
  21792. },
  21793. toggle: function(){
  21794. // summary: Toggle this pane's visibility
  21795. if(this._showing){
  21796. this._hideWrapper();
  21797. this._showAnim && this._showAnim.stop();
  21798. this._hideAnim.play();
  21799. }else{
  21800. this._hideAnim && this._hideAnim.stop();
  21801. this._showAnim.play();
  21802. }
  21803. this._showing = !this._showing;
  21804. },
  21805. _hideWrapper: function(){
  21806. // summary: Set the Expando state to "closed"
  21807. domClass.add(this.domNode, "dojoxExpandoClosed");
  21808. domStyle.set(this.cwrapper,{
  21809. visibility: "hidden",
  21810. opacity: "0",
  21811. overflow: "hidden"
  21812. });
  21813. },
  21814. _showEnd: function(){
  21815. // summary: Common animation onEnd code - "unclose"
  21816. domStyle.set(this.cwrapper, {
  21817. opacity: 0,
  21818. visibility:"visible"
  21819. });
  21820. baseFx.anim(this.cwrapper, {
  21821. opacity: this._isonlypreview ? this.previewOpacity : 1
  21822. }, 227);
  21823. domClass.remove(this.domNode, "dojoxExpandoClosed");
  21824. if(!this._isonlypreview){
  21825. setTimeout(lang.hitch(this._container, "layout"), 15);
  21826. }else{
  21827. this._previewShowing = true;
  21828. this.resize();
  21829. }
  21830. },
  21831. _hideEnd: function(){
  21832. // summary: Callback for the hide animation - "close"
  21833. // every time we hide, reset the "only preview" state
  21834. if(!this._isonlypreview){
  21835. setTimeout(lang.hitch(this._container, "layout"), 25);
  21836. }else{
  21837. this._previewShowing = false;
  21838. }
  21839. this._isonlypreview = false;
  21840. },
  21841. resize: function(/* Object? */newSize){
  21842. // summary:
  21843. // we aren't a layout widget, but need to act like one:
  21844. // newSize: Object
  21845. // The size object to resize to
  21846. if(!this._hasSizes){ this._startupSizes(newSize); }
  21847. // compute size of container (ie, size left over after title bar)
  21848. var currentSize = domGeom.getMarginBox(this.domNode);
  21849. this._contentBox = {
  21850. w: newSize && "w" in newSize ? newSize.w : currentSize.w,
  21851. h: (newSize && "h" in newSize ? newSize.h : currentSize.h) - this._titleHeight
  21852. };
  21853. domStyle.set(this.containerNode, "height", this._contentBox.h + "px");
  21854. if(newSize){
  21855. domGeom.setMarginBox(this.domNode, newSize);
  21856. }
  21857. this._layoutChildren();
  21858. },
  21859. _trap: function(e){
  21860. // summary: Trap stray events
  21861. eventUtil.stop(e);
  21862. }
  21863. });
  21864. });
  21865. },
  21866. 'dijit/form/_FormWidget':function(){
  21867. define("dijit/form/_FormWidget", [
  21868. "dojo/_base/declare", // declare
  21869. "dojo/_base/kernel", // kernel.deprecated
  21870. "dojo/ready",
  21871. "../_Widget",
  21872. "../_CssStateMixin",
  21873. "../_TemplatedMixin",
  21874. "./_FormWidgetMixin"
  21875. ], function(declare, kernel, ready, _Widget, _CssStateMixin, _TemplatedMixin, _FormWidgetMixin){
  21876. /*=====
  21877. var _Widget = dijit._Widget;
  21878. var _TemplatedMixin = dijit._TemplatedMixin;
  21879. var _CssStateMixin = dijit._CssStateMixin;
  21880. var _FormWidgetMixin = dijit.form._FormWidgetMixin;
  21881. =====*/
  21882. // module:
  21883. // dijit/form/_FormWidget
  21884. // summary:
  21885. // FormWidget
  21886. // Back compat w/1.6, remove for 2.0
  21887. if(!kernel.isAsync){
  21888. ready(0, function(){
  21889. var requires = ["dijit/form/_FormValueWidget"];
  21890. require(requires); // use indirection so modules not rolled into a build
  21891. });
  21892. }
  21893. return declare("dijit.form._FormWidget", [_Widget, _TemplatedMixin, _CssStateMixin, _FormWidgetMixin], {
  21894. // summary:
  21895. // Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>,
  21896. // which can be children of a <form> node or a `dijit.form.Form` widget.
  21897. //
  21898. // description:
  21899. // Represents a single HTML element.
  21900. // All these widgets should have these attributes just like native HTML input elements.
  21901. // You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
  21902. //
  21903. // They also share some common methods.
  21904. setDisabled: function(/*Boolean*/ disabled){
  21905. // summary:
  21906. // Deprecated. Use set('disabled', ...) instead.
  21907. kernel.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0");
  21908. this.set('disabled', disabled);
  21909. },
  21910. setValue: function(/*String*/ value){
  21911. // summary:
  21912. // Deprecated. Use set('value', ...) instead.
  21913. kernel.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated. Use set('value',"+value+") instead.", "", "2.0");
  21914. this.set('value', value);
  21915. },
  21916. getValue: function(){
  21917. // summary:
  21918. // Deprecated. Use get('value') instead.
  21919. kernel.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0");
  21920. return this.get('value');
  21921. },
  21922. postMixInProperties: function(){
  21923. // Setup name=foo string to be referenced from the template (but only if a name has been specified)
  21924. // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8484, #8660.
  21925. // Regarding escaping, see heading "Attribute values" in
  21926. // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
  21927. this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, "&quot;") + '"') : '';
  21928. this.inherited(arguments);
  21929. },
  21930. // Override automatic assigning type --> focusNode, it causes exception on IE.
  21931. // Instead, type must be specified as ${type} in the template, as part of the original DOM
  21932. _setTypeAttr: null
  21933. });
  21934. });
  21935. },
  21936. 'dojo/DeferredList':function(){
  21937. define("dojo/DeferredList", ["./_base/kernel", "./_base/Deferred", "./_base/array"], function(dojo, Deferred, darray) {
  21938. // module:
  21939. // dojo/DeferredList
  21940. // summary:
  21941. // TODOC
  21942. dojo.DeferredList = function(/*Array*/ list, /*Boolean?*/ fireOnOneCallback, /*Boolean?*/ fireOnOneErrback, /*Boolean?*/ consumeErrors, /*Function?*/ canceller){
  21943. // summary:
  21944. // Provides event handling for a group of Deferred objects.
  21945. // description:
  21946. // DeferredList takes an array of existing deferreds and returns a new deferred of its own
  21947. // this new deferred will typically have its callback fired when all of the deferreds in
  21948. // the given list have fired their own deferreds. The parameters `fireOnOneCallback` and
  21949. // fireOnOneErrback, will fire before all the deferreds as appropriate
  21950. //
  21951. // list:
  21952. // The list of deferreds to be synchronizied with this DeferredList
  21953. // fireOnOneCallback:
  21954. // Will cause the DeferredLists callback to be fired as soon as any
  21955. // of the deferreds in its list have been fired instead of waiting until
  21956. // the entire list has finished
  21957. // fireonOneErrback:
  21958. // Will cause the errback to fire upon any of the deferreds errback
  21959. // canceller:
  21960. // A deferred canceller function, see dojo.Deferred
  21961. var resultList = [];
  21962. Deferred.call(this);
  21963. var self = this;
  21964. if(list.length === 0 && !fireOnOneCallback){
  21965. this.resolve([0, []]);
  21966. }
  21967. var finished = 0;
  21968. darray.forEach(list, function(item, i){
  21969. item.then(function(result){
  21970. if(fireOnOneCallback){
  21971. self.resolve([i, result]);
  21972. }else{
  21973. addResult(true, result);
  21974. }
  21975. },function(error){
  21976. if(fireOnOneErrback){
  21977. self.reject(error);
  21978. }else{
  21979. addResult(false, error);
  21980. }
  21981. if(consumeErrors){
  21982. return null;
  21983. }
  21984. throw error;
  21985. });
  21986. function addResult(succeeded, result){
  21987. resultList[i] = [succeeded, result];
  21988. finished++;
  21989. if(finished === list.length){
  21990. self.resolve(resultList);
  21991. }
  21992. }
  21993. });
  21994. };
  21995. dojo.DeferredList.prototype = new Deferred();
  21996. dojo.DeferredList.prototype.gatherResults = function(deferredList){
  21997. // summary:
  21998. // Gathers the results of the deferreds for packaging
  21999. // as the parameters to the Deferred Lists' callback
  22000. // deferredList: dojo.DeferredList
  22001. // The deferred list from which this function gathers results.
  22002. // returns: dojo.DeferredList
  22003. // The newly created deferred list which packs results as
  22004. // parameters to its callback.
  22005. var d = new dojo.DeferredList(deferredList, false, true, false);
  22006. d.addCallback(function(results){
  22007. var ret = [];
  22008. darray.forEach(results, function(result){
  22009. ret.push(result[1]);
  22010. });
  22011. return ret;
  22012. });
  22013. return d;
  22014. };
  22015. return dojo.DeferredList;
  22016. });
  22017. },
  22018. 'dojo/dnd/common':function(){
  22019. define("dojo/dnd/common", ["../main"], function(dojo) {
  22020. // module:
  22021. // dojo/dnd/common
  22022. // summary:
  22023. // TODOC
  22024. dojo.getObject("dnd", true, dojo);
  22025. dojo.dnd.getCopyKeyState = dojo.isCopyKey;
  22026. dojo.dnd._uniqueId = 0;
  22027. dojo.dnd.getUniqueId = function(){
  22028. // summary:
  22029. // returns a unique string for use with any DOM element
  22030. var id;
  22031. do{
  22032. id = dojo._scopeName + "Unique" + (++dojo.dnd._uniqueId);
  22033. }while(dojo.byId(id));
  22034. return id;
  22035. };
  22036. dojo.dnd._empty = {};
  22037. dojo.dnd.isFormElement = function(/*Event*/ e){
  22038. // summary:
  22039. // returns true if user clicked on a form element
  22040. var t = e.target;
  22041. if(t.nodeType == 3 /*TEXT_NODE*/){
  22042. t = t.parentNode;
  22043. }
  22044. return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0; // Boolean
  22045. };
  22046. return dojo.dnd;
  22047. });
  22048. },
  22049. 'dijit/CheckedMenuItem':function(){
  22050. require({cache:{
  22051. 'url:dijit/templates/CheckedMenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitemcheckbox\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">&#10003;</span>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode,labelNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">&#160;</td>\n</tr>\n"}});
  22052. define("dijit/CheckedMenuItem", [
  22053. "dojo/_base/declare", // declare
  22054. "dojo/dom-class", // domClass.toggle
  22055. "./MenuItem",
  22056. "dojo/text!./templates/CheckedMenuItem.html",
  22057. "./hccss"
  22058. ], function(declare, domClass, MenuItem, template){
  22059. /*=====
  22060. var MenuItem = dijit.MenuItem;
  22061. =====*/
  22062. // module:
  22063. // dijit/CheckedMenuItem
  22064. // summary:
  22065. // A checkbox-like menu item for toggling on and off
  22066. return declare("dijit.CheckedMenuItem", MenuItem, {
  22067. // summary:
  22068. // A checkbox-like menu item for toggling on and off
  22069. templateString: template,
  22070. // checked: Boolean
  22071. // Our checked state
  22072. checked: false,
  22073. _setCheckedAttr: function(/*Boolean*/ checked){
  22074. // summary:
  22075. // Hook so attr('checked', bool) works.
  22076. // Sets the class and state for the check box.
  22077. domClass.toggle(this.domNode, "dijitCheckedMenuItemChecked", checked);
  22078. this.domNode.setAttribute("aria-checked", checked);
  22079. this._set("checked", checked);
  22080. },
  22081. iconClass: "", // override dijitNoIcon
  22082. onChange: function(/*Boolean*/ /*===== checked =====*/){
  22083. // summary:
  22084. // User defined function to handle check/uncheck events
  22085. // tags:
  22086. // callback
  22087. },
  22088. _onClick: function(/*Event*/ e){
  22089. // summary:
  22090. // Clicking this item just toggles its state
  22091. // tags:
  22092. // private
  22093. if(!this.disabled){
  22094. this.set("checked", !this.checked);
  22095. this.onChange(this.checked);
  22096. }
  22097. this.inherited(arguments);
  22098. }
  22099. });
  22100. });
  22101. },
  22102. 'dijit/Viewport':function(){
  22103. define("dijit/Viewport", [
  22104. "dojo/Evented",
  22105. "dojo/on",
  22106. "dojo/ready",
  22107. "dojo/_base/sniff",
  22108. "dojo/_base/window", // global
  22109. "dojo/window" // getBox()
  22110. ], function(Evented, on, ready, has, win, winUtils){
  22111. // module:
  22112. // dijit/Viewport
  22113. /*=====
  22114. return {
  22115. // summary:
  22116. // Utility singleton to watch for viewport resizes, avoiding duplicate notifications
  22117. // which can lead to infinite loops.
  22118. // description:
  22119. // Usage: Viewport.on("resize", myCallback).
  22120. //
  22121. // myCallback() is called without arguments in case it's _WidgetBase.resize(),
  22122. // which would interpret the argument as the size to make the widget.
  22123. };
  22124. =====*/
  22125. var Viewport = new Evented();
  22126. var focusedNode;
  22127. ready(200, function(){
  22128. var oldBox = winUtils.getBox();
  22129. Viewport._rlh = on(win.global, "resize", function(){
  22130. var newBox = winUtils.getBox();
  22131. if(oldBox.h == newBox.h && oldBox.w == newBox.w){ return; }
  22132. oldBox = newBox;
  22133. Viewport.emit("resize");
  22134. });
  22135. // Also catch zoom changes on IE8, since they don't naturally generate resize events
  22136. if(has("ie") == 8){
  22137. var deviceXDPI = screen.deviceXDPI;
  22138. setInterval(function(){
  22139. if(screen.deviceXDPI != deviceXDPI){
  22140. deviceXDPI = screen.deviceXDPI;
  22141. Viewport.emit("resize");
  22142. }
  22143. }, 500);
  22144. }
  22145. // On iOS, keep track of the focused node so we can guess when the keyboard is/isn't being displayed.
  22146. if(has("ios")){
  22147. on(document, "focusin", function(evt){
  22148. focusedNode = evt.target;
  22149. });
  22150. on(document, "focusout", function(evt){
  22151. focusedNode = null;
  22152. });
  22153. }
  22154. });
  22155. Viewport.getEffectiveBox = function(/*Document*/ doc){
  22156. // summary:
  22157. // Get the size of the viewport, or on mobile devices, the part of the viewport not obscured by the
  22158. // virtual keyboard.
  22159. var box = winUtils.getBox(doc);
  22160. // Account for iOS virtual keyboard, if it's being shown. Unfortunately no direct way to check or measure.
  22161. var tag = focusedNode && focusedNode.tagName && focusedNode.tagName.toLowerCase();
  22162. if(has("ios") && focusedNode && !focusedNode.readOnly && (tag == "textarea" || (tag == "input" &&
  22163. /^(color|email|number|password|search|tel|text|url)$/.test(focusedNode.type)))){
  22164. // Box represents the size of the viewport. Some of the viewport is likely covered by the keyboard.
  22165. // Estimate height of visible viewport assuming viewport goes to bottom of screen, but is covered by keyboard.
  22166. box.h *= (orientation == 0 || orientation == 180 ? 0.66 : 0.40);
  22167. // Above measurement will be inaccurate if viewport was scrolled up so far that it ends before the bottom
  22168. // of the screen. In this case, keyboard isn't covering as much of the viewport as we thought.
  22169. // We know the visible size is at least the distance from the top of the viewport to the focused node.
  22170. var rect = focusedNode.getBoundingClientRect();
  22171. box.h = Math.max(box.h, rect.top + rect.height);
  22172. }
  22173. return box;
  22174. };
  22175. return Viewport;
  22176. });
  22177. },
  22178. 'dijit/_base/place':function(){
  22179. define("dijit/_base/place", [
  22180. "dojo/_base/array", // array.forEach
  22181. "dojo/_base/lang", // lang.isArray
  22182. "dojo/window", // windowUtils.getBox
  22183. "../place",
  22184. ".." // export to dijit namespace
  22185. ], function(array, lang, windowUtils, place, dijit){
  22186. // module:
  22187. // dijit/_base/place
  22188. // summary:
  22189. // Back compatibility module, new code should use dijit/place directly instead of using this module.
  22190. dijit.getViewport = function(){
  22191. // summary:
  22192. // Deprecated method to return the dimensions and scroll position of the viewable area of a browser window.
  22193. // New code should use windowUtils.getBox()
  22194. return windowUtils.getBox();
  22195. };
  22196. /*=====
  22197. dijit.placeOnScreen = function(node, pos, corners, padding){
  22198. // summary:
  22199. // Positions one of the node's corners at specified position
  22200. // such that node is fully visible in viewport.
  22201. // Deprecated, new code should use dijit.place.at() instead.
  22202. };
  22203. =====*/
  22204. dijit.placeOnScreen = place.at;
  22205. /*=====
  22206. dijit.placeOnScreenAroundElement = function(node, aroundElement, aroundCorners, layoutNode){
  22207. // summary:
  22208. // Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object
  22209. // for the "around" argument and finds a proper processor to place a node.
  22210. // Deprecated, new code should use dijit.place.around() instead.
  22211. };
  22212. ====*/
  22213. dijit.placeOnScreenAroundElement = function(node, aroundNode, aroundCorners, layoutNode){
  22214. // Convert old style {"BL": "TL", "BR": "TR"} type argument
  22215. // to style needed by dijit.place code:
  22216. // [
  22217. // {aroundCorner: "BL", corner: "TL" },
  22218. // {aroundCorner: "BR", corner: "TR" }
  22219. // ]
  22220. var positions;
  22221. if(lang.isArray(aroundCorners)){
  22222. positions = aroundCorners;
  22223. }else{
  22224. positions = [];
  22225. for(var key in aroundCorners){
  22226. positions.push({aroundCorner: key, corner: aroundCorners[key]});
  22227. }
  22228. }
  22229. return place.around(node, aroundNode, positions, true, layoutNode);
  22230. };
  22231. /*=====
  22232. dijit.placeOnScreenAroundNode = function(node, aroundNode, aroundCorners, layoutNode){
  22233. // summary:
  22234. // Position node adjacent or kitty-corner to aroundNode
  22235. // such that it's fully visible in viewport.
  22236. // Deprecated, new code should use dijit.place.around() instead.
  22237. };
  22238. =====*/
  22239. dijit.placeOnScreenAroundNode = dijit.placeOnScreenAroundElement;
  22240. /*=====
  22241. dijit.placeOnScreenAroundRectangle = function(node, aroundRect, aroundCorners, layoutNode){
  22242. // summary:
  22243. // Like dijit.placeOnScreenAroundNode(), except that the "around"
  22244. // parameter is an arbitrary rectangle on the screen (x, y, width, height)
  22245. // instead of a dom node.
  22246. // Deprecated, new code should use dijit.place.around() instead.
  22247. };
  22248. =====*/
  22249. dijit.placeOnScreenAroundRectangle = dijit.placeOnScreenAroundElement;
  22250. dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
  22251. // summary:
  22252. // Deprecated method, unneeded when using dijit/place directly.
  22253. // Transforms the passed array of preferred positions into a format suitable for
  22254. // passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
  22255. //
  22256. // position: String[]
  22257. // This variable controls the position of the drop down.
  22258. // It's an array of strings with the following values:
  22259. //
  22260. // * before: places drop down to the left of the target node/widget, or to the right in
  22261. // the case of RTL scripts like Hebrew and Arabic
  22262. // * after: places drop down to the right of the target node/widget, or to the left in
  22263. // the case of RTL scripts like Hebrew and Arabic
  22264. // * above: drop down goes above target node
  22265. // * below: drop down goes below target node
  22266. //
  22267. // The list is positions is tried, in order, until a position is found where the drop down fits
  22268. // within the viewport.
  22269. //
  22270. // leftToRight: Boolean
  22271. // Whether the popup will be displaying in leftToRight mode.
  22272. //
  22273. var align = {};
  22274. array.forEach(position, function(pos){
  22275. var ltr = leftToRight;
  22276. switch(pos){
  22277. case "after":
  22278. align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
  22279. break;
  22280. case "before":
  22281. align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
  22282. break;
  22283. case "below-alt":
  22284. ltr = !ltr;
  22285. // fall through
  22286. case "below":
  22287. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  22288. align[ltr ? "BL" : "BR"] = ltr ? "TL" : "TR";
  22289. align[ltr ? "BR" : "BL"] = ltr ? "TR" : "TL";
  22290. break;
  22291. case "above-alt":
  22292. ltr = !ltr;
  22293. // fall through
  22294. case "above":
  22295. default:
  22296. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  22297. align[ltr ? "TL" : "TR"] = ltr ? "BL" : "BR";
  22298. align[ltr ? "TR" : "TL"] = ltr ? "BR" : "BL";
  22299. break;
  22300. }
  22301. });
  22302. return align;
  22303. };
  22304. return dijit;
  22305. });
  22306. },
  22307. 'dijit/MenuSeparator':function(){
  22308. require({cache:{
  22309. 'url:dijit/templates/MenuSeparator.html':"<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>"}});
  22310. define("dijit/MenuSeparator", [
  22311. "dojo/_base/declare", // declare
  22312. "dojo/dom", // dom.setSelectable
  22313. "./_WidgetBase",
  22314. "./_TemplatedMixin",
  22315. "./_Contained",
  22316. "dojo/text!./templates/MenuSeparator.html"
  22317. ], function(declare, dom, _WidgetBase, _TemplatedMixin, _Contained, template){
  22318. /*=====
  22319. var _WidgetBase = dijit._WidgetBase;
  22320. var _TemplatedMixin = dijit._TemplatedMixin;
  22321. var _Contained = dijit._Contained;
  22322. =====*/
  22323. // module:
  22324. // dijit/MenuSeparator
  22325. // summary:
  22326. // A line between two menu items
  22327. return declare("dijit.MenuSeparator", [_WidgetBase, _TemplatedMixin, _Contained], {
  22328. // summary:
  22329. // A line between two menu items
  22330. templateString: template,
  22331. buildRendering: function(){
  22332. this.inherited(arguments);
  22333. dom.setSelectable(this.domNode, false);
  22334. },
  22335. isFocusable: function(){
  22336. // summary:
  22337. // Override to always return false
  22338. // tags:
  22339. // protected
  22340. return false; // Boolean
  22341. }
  22342. });
  22343. });
  22344. },
  22345. 'dojo/require':function(){
  22346. define("dojo/require", ["./_base/loader"], function(loader){
  22347. return {
  22348. dynamic:0,
  22349. normalize:function(id){return id;},
  22350. load:loader.require
  22351. };
  22352. });
  22353. },
  22354. 'dojox/string/Builder':function(){
  22355. define("dojox/string/Builder", ["dojo/_base/lang"],
  22356. function(lang){
  22357. lang.getObject("string", true, dojox).Builder =
  22358. function(/*String?*/str){
  22359. // summary:
  22360. // A fast buffer for creating large strings.
  22361. //
  22362. // length: Number
  22363. // The current length of the internal string.
  22364. // N.B. the public nature of the internal buffer is no longer
  22365. // needed because the IE-specific fork is no longer needed--TRT.
  22366. var b = "";
  22367. this.length = 0;
  22368. this.append = function(/* String... */s){
  22369. // summary: Append all arguments to the end of the buffer
  22370. if(arguments.length>1){
  22371. /*
  22372. This is a loop unroll was designed specifically for Firefox;
  22373. it would seem that static index access on an Arguments
  22374. object is a LOT faster than doing dynamic index access.
  22375. Therefore, we create a buffer string and take advantage
  22376. of JS's switch fallthrough. The peformance of this method
  22377. comes very close to straight up string concatenation (+=).
  22378. If the arguments object length is greater than 9, we fall
  22379. back to standard dynamic access.
  22380. This optimization seems to have no real effect on either
  22381. Safari or Opera, so we just use it for all.
  22382. It turns out also that this loop unroll can increase performance
  22383. significantly with Internet Explorer, particularly when
  22384. as many arguments are provided as possible.
  22385. Loop unroll per suggestion from Kris Zyp, implemented by
  22386. Tom Trenka.
  22387. Note: added empty string to force a string cast if needed.
  22388. */
  22389. var tmp="", l=arguments.length;
  22390. switch(l){
  22391. case 9: tmp=""+arguments[8]+tmp;
  22392. case 8: tmp=""+arguments[7]+tmp;
  22393. case 7: tmp=""+arguments[6]+tmp;
  22394. case 6: tmp=""+arguments[5]+tmp;
  22395. case 5: tmp=""+arguments[4]+tmp;
  22396. case 4: tmp=""+arguments[3]+tmp;
  22397. case 3: tmp=""+arguments[2]+tmp;
  22398. case 2: {
  22399. b+=""+arguments[0]+arguments[1]+tmp;
  22400. break;
  22401. }
  22402. default: {
  22403. var i=0;
  22404. while(i<arguments.length){
  22405. tmp += arguments[i++];
  22406. }
  22407. b += tmp;
  22408. }
  22409. }
  22410. } else {
  22411. b += s;
  22412. }
  22413. this.length = b.length;
  22414. return this; // dojox.string.Builder
  22415. };
  22416. this.concat = function(/*String...*/s){
  22417. // summary:
  22418. // Alias for append.
  22419. return this.append.apply(this, arguments); // dojox.string.Builder
  22420. };
  22421. this.appendArray = function(/*Array*/strings) {
  22422. // summary:
  22423. // Append an array of items to the internal buffer.
  22424. // Changed from String.prototype.concat.apply because of IE.
  22425. return this.append.apply(this, strings); // dojox.string.Builder
  22426. };
  22427. this.clear = function(){
  22428. // summary:
  22429. // Remove all characters from the buffer.
  22430. b = "";
  22431. this.length = 0;
  22432. return this; // dojox.string.Builder
  22433. };
  22434. this.replace = function(/* String */oldStr, /* String */ newStr){
  22435. // summary:
  22436. // Replace instances of one string with another in the buffer.
  22437. b = b.replace(oldStr,newStr);
  22438. this.length = b.length;
  22439. return this; // dojox.string.Builder
  22440. };
  22441. this.remove = function(/* Number */start, /* Number? */len){
  22442. // summary:
  22443. // Remove len characters starting at index start. If len
  22444. // is not provided, the end of the string is assumed.
  22445. if(len===undefined){ len = b.length; }
  22446. if(len == 0){ return this; }
  22447. b = b.substr(0, start) + b.substr(start+len);
  22448. this.length = b.length;
  22449. return this; // dojox.string.Builder
  22450. };
  22451. this.insert = function(/* Number */index, /* String */str){
  22452. // summary:
  22453. // Insert string str starting at index.
  22454. if(index == 0){
  22455. b = str + b;
  22456. }else{
  22457. b = b.slice(0, index) + str + b.slice(index);
  22458. }
  22459. this.length = b.length;
  22460. return this; // dojox.string.Builder
  22461. };
  22462. this.toString = function(){
  22463. // summary:
  22464. // Return the string representation of the internal buffer.
  22465. return b; // String
  22466. };
  22467. // initialize the buffer.
  22468. if(str){ this.append(str); }
  22469. };
  22470. return dojox.string.Builder;
  22471. });
  22472. },
  22473. 'url:dijit/layout/templates/ScrollingTabController.html':"<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerMenuButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\"\n\t\t\tdata-dojo-props=\"containerId: '${containerId}', iconClass: 'dijitTabStripMenuIcon',\n\t\t\t\t\tdropDownPosition: ['below-alt', 'above-alt']\"\n\t\t\tdata-dojo-attach-point=\"_menuBtn\" showLabel=\"false\" title=\"\">&#9660;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideLeftIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_leftBtn\" data-dojo-attach-event=\"onClick: doSlideLeft\">&#9664;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideRightIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_rightBtn\" data-dojo-attach-event=\"onClick: doSlideRight\">&#9654;</div>\n\t<div class='dijitTabListWrapper' data-dojo-attach-point='tablistWrapper'>\n\t\t<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'\n\t\t\t\tdata-dojo-attach-point='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>",
  22474. 'dojox/fx':function(){
  22475. define("dojox/fx", ["./fx/_base"], function(DojoxFx){
  22476. return DojoxFx;
  22477. });
  22478. },
  22479. 'dijit/_base/focus':function(){
  22480. define("dijit/_base/focus", [
  22481. "dojo/_base/array", // array.forEach
  22482. "dojo/dom", // dom.isDescendant
  22483. "dojo/_base/lang", // lang.isArray
  22484. "dojo/topic", // publish
  22485. "dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal
  22486. "../focus",
  22487. ".." // for exporting symbols to dijit
  22488. ], function(array, dom, lang, topic, win, focus, dijit){
  22489. // module:
  22490. // dijit/_base/focus
  22491. // summary:
  22492. // Deprecated module to monitor currently focused node and stack of currently focused widgets.
  22493. // New code should access dijit/focus directly.
  22494. lang.mixin(dijit, {
  22495. // _curFocus: DomNode
  22496. // Currently focused item on screen
  22497. _curFocus: null,
  22498. // _prevFocus: DomNode
  22499. // Previously focused item on screen
  22500. _prevFocus: null,
  22501. isCollapsed: function(){
  22502. // summary:
  22503. // Returns true if there is no text selected
  22504. return dijit.getBookmark().isCollapsed;
  22505. },
  22506. getBookmark: function(){
  22507. // summary:
  22508. // Retrieves a bookmark that can be used with moveToBookmark to return to the same range
  22509. var bm, rg, tg, sel = win.doc.selection, cf = focus.curNode;
  22510. if(win.global.getSelection){
  22511. //W3C Range API for selections.
  22512. sel = win.global.getSelection();
  22513. if(sel){
  22514. if(sel.isCollapsed){
  22515. tg = cf? cf.tagName : "";
  22516. if(tg){
  22517. //Create a fake rangelike item to restore selections.
  22518. tg = tg.toLowerCase();
  22519. if(tg == "textarea" ||
  22520. (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
  22521. sel = {
  22522. start: cf.selectionStart,
  22523. end: cf.selectionEnd,
  22524. node: cf,
  22525. pRange: true
  22526. };
  22527. return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
  22528. }
  22529. }
  22530. bm = {isCollapsed:true};
  22531. if(sel.rangeCount){
  22532. bm.mark = sel.getRangeAt(0).cloneRange();
  22533. }
  22534. }else{
  22535. rg = sel.getRangeAt(0);
  22536. bm = {isCollapsed: false, mark: rg.cloneRange()};
  22537. }
  22538. }
  22539. }else if(sel){
  22540. // If the current focus was a input of some sort and no selection, don't bother saving
  22541. // a native bookmark. This is because it causes issues with dialog/page selection restore.
  22542. // So, we need to create psuedo bookmarks to work with.
  22543. tg = cf ? cf.tagName : "";
  22544. tg = tg.toLowerCase();
  22545. if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
  22546. if(sel.type && sel.type.toLowerCase() == "none"){
  22547. return {
  22548. isCollapsed: true,
  22549. mark: null
  22550. }
  22551. }else{
  22552. rg = sel.createRange();
  22553. return {
  22554. isCollapsed: rg.text && rg.text.length?false:true,
  22555. mark: {
  22556. range: rg,
  22557. pRange: true
  22558. }
  22559. };
  22560. }
  22561. }
  22562. bm = {};
  22563. //'IE' way for selections.
  22564. try{
  22565. // createRange() throws exception when dojo in iframe
  22566. //and nothing selected, see #9632
  22567. rg = sel.createRange();
  22568. bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
  22569. }catch(e){
  22570. bm.isCollapsed = true;
  22571. return bm;
  22572. }
  22573. if(sel.type.toUpperCase() == 'CONTROL'){
  22574. if(rg.length){
  22575. bm.mark=[];
  22576. var i=0,len=rg.length;
  22577. while(i<len){
  22578. bm.mark.push(rg.item(i++));
  22579. }
  22580. }else{
  22581. bm.isCollapsed = true;
  22582. bm.mark = null;
  22583. }
  22584. }else{
  22585. bm.mark = rg.getBookmark();
  22586. }
  22587. }else{
  22588. console.warn("No idea how to store the current selection for this browser!");
  22589. }
  22590. return bm; // Object
  22591. },
  22592. moveToBookmark: function(/*Object*/ bookmark){
  22593. // summary:
  22594. // Moves current selection to a bookmark
  22595. // bookmark:
  22596. // This should be a returned object from dijit.getBookmark()
  22597. var _doc = win.doc,
  22598. mark = bookmark.mark;
  22599. if(mark){
  22600. if(win.global.getSelection){
  22601. //W3C Rangi API (FF, WebKit, Opera, etc)
  22602. var sel = win.global.getSelection();
  22603. if(sel && sel.removeAllRanges){
  22604. if(mark.pRange){
  22605. var n = mark.node;
  22606. n.selectionStart = mark.start;
  22607. n.selectionEnd = mark.end;
  22608. }else{
  22609. sel.removeAllRanges();
  22610. sel.addRange(mark);
  22611. }
  22612. }else{
  22613. console.warn("No idea how to restore selection for this browser!");
  22614. }
  22615. }else if(_doc.selection && mark){
  22616. //'IE' way.
  22617. var rg;
  22618. if(mark.pRange){
  22619. rg = mark.range;
  22620. }else if(lang.isArray(mark)){
  22621. rg = _doc.body.createControlRange();
  22622. //rg.addElement does not have call/apply method, so can not call it directly
  22623. //rg is not available in "range.addElement(item)", so can't use that either
  22624. array.forEach(mark, function(n){
  22625. rg.addElement(n);
  22626. });
  22627. }else{
  22628. rg = _doc.body.createTextRange();
  22629. rg.moveToBookmark(mark);
  22630. }
  22631. rg.select();
  22632. }
  22633. }
  22634. },
  22635. getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
  22636. // summary:
  22637. // Called as getFocus(), this returns an Object showing the current focus
  22638. // and selected text.
  22639. //
  22640. // Called as getFocus(widget), where widget is a (widget representing) a button
  22641. // that was just pressed, it returns where focus was before that button
  22642. // was pressed. (Pressing the button may have either shifted focus to the button,
  22643. // or removed focus altogether.) In this case the selected text is not returned,
  22644. // since it can't be accurately determined.
  22645. //
  22646. // menu: dijit._Widget or {domNode: DomNode} structure
  22647. // The button that was just pressed. If focus has disappeared or moved
  22648. // to this button, returns the previous focus. In this case the bookmark
  22649. // information is already lost, and null is returned.
  22650. //
  22651. // openedForWindow:
  22652. // iframe in which menu was opened
  22653. //
  22654. // returns:
  22655. // A handle to restore focus/selection, to be passed to `dijit.focus`
  22656. var node = !focus.curNode || (menu && dom.isDescendant(focus.curNode, menu.domNode)) ? dijit._prevFocus : focus.curNode;
  22657. return {
  22658. node: node,
  22659. bookmark: node && (node == focus.curNode) && win.withGlobal(openedForWindow || win.global, dijit.getBookmark),
  22660. openedForWindow: openedForWindow
  22661. }; // Object
  22662. },
  22663. // _activeStack: dijit._Widget[]
  22664. // List of currently active widgets (focused widget and it's ancestors)
  22665. _activeStack: [],
  22666. registerIframe: function(/*DomNode*/ iframe){
  22667. // summary:
  22668. // Registers listeners on the specified iframe so that any click
  22669. // or focus event on that iframe (or anything in it) is reported
  22670. // as a focus/click event on the <iframe> itself.
  22671. // description:
  22672. // Currently only used by editor.
  22673. // returns:
  22674. // Handle to pass to unregisterIframe()
  22675. return focus.registerIframe(iframe);
  22676. },
  22677. unregisterIframe: function(/*Object*/ handle){
  22678. // summary:
  22679. // Unregisters listeners on the specified iframe created by registerIframe.
  22680. // After calling be sure to delete or null out the handle itself.
  22681. // handle:
  22682. // Handle returned by registerIframe()
  22683. handle && handle.remove();
  22684. },
  22685. registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
  22686. // summary:
  22687. // Registers listeners on the specified window (either the main
  22688. // window or an iframe's window) to detect when the user has clicked somewhere
  22689. // or focused somewhere.
  22690. // description:
  22691. // Users should call registerIframe() instead of this method.
  22692. // targetWindow:
  22693. // If specified this is the window associated with the iframe,
  22694. // i.e. iframe.contentWindow.
  22695. // effectiveNode:
  22696. // If specified, report any focus events inside targetWindow as
  22697. // an event on effectiveNode, rather than on evt.target.
  22698. // returns:
  22699. // Handle to pass to unregisterWin()
  22700. return focus.registerWin(targetWindow, effectiveNode);
  22701. },
  22702. unregisterWin: function(/*Handle*/ handle){
  22703. // summary:
  22704. // Unregisters listeners on the specified window (either the main
  22705. // window or an iframe's window) according to handle returned from registerWin().
  22706. // After calling be sure to delete or null out the handle itself.
  22707. handle && handle.remove();
  22708. }
  22709. });
  22710. // Override focus singleton's focus function so that dijit.focus()
  22711. // has backwards compatible behavior of restoring selection (although
  22712. // probably no one is using that).
  22713. focus.focus = function(/*Object || DomNode */ handle){
  22714. // summary:
  22715. // Sets the focused node and the selection according to argument.
  22716. // To set focus to an iframe's content, pass in the iframe itself.
  22717. // handle:
  22718. // object returned by get(), or a DomNode
  22719. if(!handle){ return; }
  22720. var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object
  22721. bookmark = handle.bookmark,
  22722. openedForWindow = handle.openedForWindow,
  22723. collapsed = bookmark ? bookmark.isCollapsed : false;
  22724. // Set the focus
  22725. // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
  22726. // but we need to set focus to iframe.contentWindow
  22727. if(node){
  22728. var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node;
  22729. if(focusNode && focusNode.focus){
  22730. try{
  22731. // Gecko throws sometimes if setting focus is impossible,
  22732. // node not displayed or something like that
  22733. focusNode.focus();
  22734. }catch(e){/*quiet*/}
  22735. }
  22736. focus._onFocusNode(node);
  22737. }
  22738. // set the selection
  22739. // do not need to restore if current selection is not empty
  22740. // (use keyboard to select a menu item) or if previous selection was collapsed
  22741. // as it may cause focus shift (Esp in IE).
  22742. if(bookmark && win.withGlobal(openedForWindow || win.global, dijit.isCollapsed) && !collapsed){
  22743. if(openedForWindow){
  22744. openedForWindow.focus();
  22745. }
  22746. try{
  22747. win.withGlobal(openedForWindow || win.global, dijit.moveToBookmark, null, [bookmark]);
  22748. }catch(e2){
  22749. /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
  22750. }
  22751. }
  22752. };
  22753. // For back compatibility, monitor changes to focused node and active widget stack,
  22754. // publishing events and copying changes from focus manager variables into dijit (top level) variables
  22755. focus.watch("curNode", function(name, oldVal, newVal){
  22756. dijit._curFocus = newVal;
  22757. dijit._prevFocus = oldVal;
  22758. if(newVal){
  22759. topic.publish("focusNode", newVal); // publish
  22760. }
  22761. });
  22762. focus.watch("activeStack", function(name, oldVal, newVal){
  22763. dijit._activeStack = newVal;
  22764. });
  22765. focus.on("widget-blur", function(widget, by){
  22766. topic.publish("widgetBlur", widget, by); // publish
  22767. });
  22768. focus.on("widget-focus", function(widget, by){
  22769. topic.publish("widgetFocus", widget, by); // publish
  22770. });
  22771. return dijit;
  22772. });
  22773. },
  22774. 'dijit/tree/dndSource':function(){
  22775. define("dijit/tree/dndSource", [
  22776. "dojo/_base/array", // array.forEach array.indexOf array.map
  22777. "dojo/_base/connect", // isCopyKey
  22778. "dojo/_base/declare", // declare
  22779. "dojo/dom-class", // domClass.add
  22780. "dojo/dom-geometry", // domGeometry.position
  22781. "dojo/_base/lang", // lang.mixin lang.hitch
  22782. "dojo/on", // subscribe
  22783. "dojo/touch",
  22784. "dojo/topic",
  22785. "dojo/dnd/Manager", // DNDManager.manager
  22786. "./_dndSelector"
  22787. ], function(array, connect, declare, domClass, domGeometry, lang, on, touch, topic, DNDManager, _dndSelector){
  22788. // module:
  22789. // dijit/tree/dndSource
  22790. // summary:
  22791. // Handles drag and drop operations (as a source or a target) for `dijit.Tree`
  22792. /*=====
  22793. dijit.tree.__SourceArgs = function(){
  22794. // summary:
  22795. // A dict of parameters for Tree source configuration.
  22796. // isSource: Boolean?
  22797. // Can be used as a DnD source. Defaults to true.
  22798. // accept: String[]
  22799. // List of accepted types (text strings) for a target; defaults to
  22800. // ["text", "treeNode"]
  22801. // copyOnly: Boolean?
  22802. // Copy items, if true, use a state of Ctrl key otherwise,
  22803. // dragThreshold: Number
  22804. // The move delay in pixels before detecting a drag; 0 by default
  22805. // betweenThreshold: Integer
  22806. // Distance from upper/lower edge of node to allow drop to reorder nodes
  22807. this.isSource = isSource;
  22808. this.accept = accept;
  22809. this.autoSync = autoSync;
  22810. this.copyOnly = copyOnly;
  22811. this.dragThreshold = dragThreshold;
  22812. this.betweenThreshold = betweenThreshold;
  22813. }
  22814. =====*/
  22815. return declare("dijit.tree.dndSource", _dndSelector, {
  22816. // summary:
  22817. // Handles drag and drop operations (as a source or a target) for `dijit.Tree`
  22818. // isSource: [private] Boolean
  22819. // Can be used as a DnD source.
  22820. isSource: true,
  22821. // accept: String[]
  22822. // List of accepted types (text strings) for the Tree; defaults to
  22823. // ["text"]
  22824. accept: ["text", "treeNode"],
  22825. // copyOnly: [private] Boolean
  22826. // Copy items, if true, use a state of Ctrl key otherwise
  22827. copyOnly: false,
  22828. // dragThreshold: Number
  22829. // The move delay in pixels before detecting a drag; 5 by default
  22830. dragThreshold: 5,
  22831. // betweenThreshold: Integer
  22832. // Distance from upper/lower edge of node to allow drop to reorder nodes
  22833. betweenThreshold: 0,
  22834. constructor: function(/*dijit.Tree*/ tree, /*dijit.tree.__SourceArgs*/ params){
  22835. // summary:
  22836. // a constructor of the Tree DnD Source
  22837. // tags:
  22838. // private
  22839. if(!params){ params = {}; }
  22840. lang.mixin(this, params);
  22841. this.isSource = typeof params.isSource == "undefined" ? true : params.isSource;
  22842. var type = params.accept instanceof Array ? params.accept : ["text", "treeNode"];
  22843. this.accept = null;
  22844. if(type.length){
  22845. this.accept = {};
  22846. for(var i = 0; i < type.length; ++i){
  22847. this.accept[type[i]] = 1;
  22848. }
  22849. }
  22850. // class-specific variables
  22851. this.isDragging = false;
  22852. this.mouseDown = false;
  22853. this.targetAnchor = null; // DOMNode corresponding to the currently moused over TreeNode
  22854. this.targetBox = null; // coordinates of this.targetAnchor
  22855. this.dropPosition = ""; // whether mouse is over/after/before this.targetAnchor
  22856. this._lastX = 0;
  22857. this._lastY = 0;
  22858. // states
  22859. this.sourceState = "";
  22860. if(this.isSource){
  22861. domClass.add(this.node, "dojoDndSource");
  22862. }
  22863. this.targetState = "";
  22864. if(this.accept){
  22865. domClass.add(this.node, "dojoDndTarget");
  22866. }
  22867. // set up events
  22868. this.topics = [
  22869. topic.subscribe("/dnd/source/over", lang.hitch(this, "onDndSourceOver")),
  22870. topic.subscribe("/dnd/start", lang.hitch(this, "onDndStart")),
  22871. topic.subscribe("/dnd/drop", lang.hitch(this, "onDndDrop")),
  22872. topic.subscribe("/dnd/cancel", lang.hitch(this, "onDndCancel"))
  22873. ];
  22874. },
  22875. // methods
  22876. checkAcceptance: function(/*===== source, nodes =====*/){
  22877. // summary:
  22878. // Checks if the target can accept nodes from this source
  22879. // source: dijit.tree.dndSource
  22880. // The source which provides items
  22881. // nodes: DOMNode[]
  22882. // Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
  22883. // source is a dijit.Tree.
  22884. // tags:
  22885. // extension
  22886. return true; // Boolean
  22887. },
  22888. copyState: function(keyPressed){
  22889. // summary:
  22890. // Returns true, if we need to copy items, false to move.
  22891. // It is separated to be overwritten dynamically, if needed.
  22892. // keyPressed: Boolean
  22893. // The "copy" control key was pressed
  22894. // tags:
  22895. // protected
  22896. return this.copyOnly || keyPressed; // Boolean
  22897. },
  22898. destroy: function(){
  22899. // summary:
  22900. // Prepares the object to be garbage-collected.
  22901. this.inherited(arguments);
  22902. var h;
  22903. while(h = this.topics.pop()){ h.remove(); }
  22904. this.targetAnchor = null;
  22905. },
  22906. _onDragMouse: function(e){
  22907. // summary:
  22908. // Helper method for processing onmousemove/onmouseover events while drag is in progress.
  22909. // Keeps track of current drop target.
  22910. var m = DNDManager.manager(),
  22911. oldTarget = this.targetAnchor, // the TreeNode corresponding to TreeNode mouse was previously over
  22912. newTarget = this.current, // TreeNode corresponding to TreeNode mouse is currently over
  22913. oldDropPosition = this.dropPosition; // the previous drop position (over/before/after)
  22914. // calculate if user is indicating to drop the dragged node before, after, or over
  22915. // (i.e., to become a child of) the target node
  22916. var newDropPosition = "Over";
  22917. if(newTarget && this.betweenThreshold > 0){
  22918. // If mouse is over a new TreeNode, then get new TreeNode's position and size
  22919. if(!this.targetBox || oldTarget != newTarget){
  22920. this.targetBox = domGeometry.position(newTarget.rowNode, true);
  22921. }
  22922. if((e.pageY - this.targetBox.y) <= this.betweenThreshold){
  22923. newDropPosition = "Before";
  22924. }else if((e.pageY - this.targetBox.y) >= (this.targetBox.h - this.betweenThreshold)){
  22925. newDropPosition = "After";
  22926. }
  22927. }
  22928. if(newTarget != oldTarget || newDropPosition != oldDropPosition){
  22929. if(oldTarget){
  22930. this._removeItemClass(oldTarget.rowNode, oldDropPosition);
  22931. }
  22932. if(newTarget){
  22933. this._addItemClass(newTarget.rowNode, newDropPosition);
  22934. }
  22935. // Check if it's ok to drop the dragged node on/before/after the target node.
  22936. if(!newTarget){
  22937. m.canDrop(false);
  22938. }else if(newTarget == this.tree.rootNode && newDropPosition != "Over"){
  22939. // Can't drop before or after tree's root node; the dropped node would just disappear (at least visually)
  22940. m.canDrop(false);
  22941. }else{
  22942. // Guard against dropping onto yourself (TODO: guard against dropping onto your descendant, #7140)
  22943. var model = this.tree.model,
  22944. sameId = false;
  22945. if(m.source == this){
  22946. for(var dragId in this.selection){
  22947. var dragNode = this.selection[dragId];
  22948. if(dragNode.item === newTarget.item){
  22949. sameId = true;
  22950. break;
  22951. }
  22952. }
  22953. }
  22954. if(sameId){
  22955. m.canDrop(false);
  22956. }else if(this.checkItemAcceptance(newTarget.rowNode, m.source, newDropPosition.toLowerCase())
  22957. && !this._isParentChildDrop(m.source, newTarget.rowNode)){
  22958. m.canDrop(true);
  22959. }else{
  22960. m.canDrop(false);
  22961. }
  22962. }
  22963. this.targetAnchor = newTarget;
  22964. this.dropPosition = newDropPosition;
  22965. }
  22966. },
  22967. onMouseMove: function(e){
  22968. // summary:
  22969. // Called for any onmousemove/ontouchmove events over the Tree
  22970. // e: Event
  22971. // onmousemouse/ontouchmove event
  22972. // tags:
  22973. // private
  22974. if(this.isDragging && this.targetState == "Disabled"){ return; }
  22975. this.inherited(arguments);
  22976. var m = DNDManager.manager();
  22977. if(this.isDragging){
  22978. this._onDragMouse(e);
  22979. }else{
  22980. if(this.mouseDown && this.isSource &&
  22981. (Math.abs(e.pageX-this._lastX)>=this.dragThreshold || Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){
  22982. var nodes = this.getSelectedTreeNodes();
  22983. if(nodes.length){
  22984. if(nodes.length > 1){
  22985. //filter out all selected items which has one of their ancestor selected as well
  22986. var seen = this.selection, i = 0, r = [], n, p;
  22987. nextitem: while((n = nodes[i++])){
  22988. for(p = n.getParent(); p && p !== this.tree; p = p.getParent()){
  22989. if(seen[p.id]){ //parent is already selected, skip this node
  22990. continue nextitem;
  22991. }
  22992. }
  22993. //this node does not have any ancestors selected, add it
  22994. r.push(n);
  22995. }
  22996. nodes = r;
  22997. }
  22998. nodes = array.map(nodes, function(n){return n.domNode});
  22999. m.startDrag(this, nodes, this.copyState(connect.isCopyKey(e)));
  23000. }
  23001. }
  23002. }
  23003. },
  23004. onMouseDown: function(e){
  23005. // summary:
  23006. // Event processor for onmousedown/ontouchstart
  23007. // e: Event
  23008. // onmousedown/ontouchend event
  23009. // tags:
  23010. // private
  23011. this.mouseDown = true;
  23012. this.mouseButton = e.button;
  23013. this._lastX = e.pageX;
  23014. this._lastY = e.pageY;
  23015. this.inherited(arguments);
  23016. },
  23017. onMouseUp: function(e){
  23018. // summary:
  23019. // Event processor for onmouseup/ontouchend
  23020. // e: Event
  23021. // onmouseup/ontouchend event
  23022. // tags:
  23023. // private
  23024. if(this.mouseDown){
  23025. this.mouseDown = false;
  23026. this.inherited(arguments);
  23027. }
  23028. },
  23029. onMouseOut: function(){
  23030. // summary:
  23031. // Event processor for when mouse is moved away from a TreeNode
  23032. // tags:
  23033. // private
  23034. this.inherited(arguments);
  23035. this._unmarkTargetAnchor();
  23036. },
  23037. checkItemAcceptance: function(/*===== target, source, position =====*/){
  23038. // summary:
  23039. // Stub function to be overridden if one wants to check for the ability to drop at the node/item level
  23040. // description:
  23041. // In the base case, this is called to check if target can become a child of source.
  23042. // When betweenThreshold is set, position="before" or "after" means that we
  23043. // are asking if the source node can be dropped before/after the target node.
  23044. // target: DOMNode
  23045. // The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
  23046. // Use dijit.getEnclosingWidget(target) to get the TreeNode.
  23047. // source: dijit.tree.dndSource
  23048. // The (set of) nodes we are dropping
  23049. // position: String
  23050. // "over", "before", or "after"
  23051. // tags:
  23052. // extension
  23053. return true;
  23054. },
  23055. // topic event processors
  23056. onDndSourceOver: function(source){
  23057. // summary:
  23058. // Topic event processor for /dnd/source/over, called when detected a current source.
  23059. // source: Object
  23060. // The dijit.tree.dndSource / dojo.dnd.Source which has the mouse over it
  23061. // tags:
  23062. // private
  23063. if(this != source){
  23064. this.mouseDown = false;
  23065. this._unmarkTargetAnchor();
  23066. }else if(this.isDragging){
  23067. var m = DNDManager.manager();
  23068. m.canDrop(false);
  23069. }
  23070. },
  23071. onDndStart: function(source, nodes, copy){
  23072. // summary:
  23073. // Topic event processor for /dnd/start, called to initiate the DnD operation
  23074. // source: Object
  23075. // The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
  23076. // nodes: DomNode[]
  23077. // The list of transferred items, dndTreeNode nodes if dragging from a Tree
  23078. // copy: Boolean
  23079. // Copy items, if true, move items otherwise
  23080. // tags:
  23081. // private
  23082. if(this.isSource){
  23083. this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
  23084. }
  23085. var accepted = this.checkAcceptance(source, nodes);
  23086. this._changeState("Target", accepted ? "" : "Disabled");
  23087. if(this == source){
  23088. DNDManager.manager().overSource(this);
  23089. }
  23090. this.isDragging = true;
  23091. },
  23092. itemCreator: function(nodes /*===== , target, source =====*/){
  23093. // summary:
  23094. // Returns objects passed to `Tree.model.newItem()` based on DnD nodes
  23095. // dropped onto the tree. Developer must override this method to enable
  23096. // dropping from external sources onto this Tree, unless the Tree.model's items
  23097. // happen to look like {id: 123, name: "Apple" } with no other attributes.
  23098. // description:
  23099. // For each node in nodes[], which came from source, create a hash of name/value
  23100. // pairs to be passed to Tree.model.newItem(). Returns array of those hashes.
  23101. // nodes: DomNode[]
  23102. // target: DomNode
  23103. // source: dojo.dnd.Source
  23104. // returns: Object[]
  23105. // Array of name/value hashes for each new item to be added to the Tree, like:
  23106. // | [
  23107. // | { id: 123, label: "apple", foo: "bar" },
  23108. // | { id: 456, label: "pear", zaz: "bam" }
  23109. // | ]
  23110. // tags:
  23111. // extension
  23112. // TODO: for 2.0 refactor so itemCreator() is called once per drag node, and
  23113. // make signature itemCreator(sourceItem, node, target) (or similar).
  23114. return array.map(nodes, function(node){
  23115. return {
  23116. "id": node.id,
  23117. "name": node.textContent || node.innerText || ""
  23118. };
  23119. }); // Object[]
  23120. },
  23121. onDndDrop: function(source, nodes, copy){
  23122. // summary:
  23123. // Topic event processor for /dnd/drop, called to finish the DnD operation.
  23124. // description:
  23125. // Updates data store items according to where node was dragged from and dropped
  23126. // to. The tree will then respond to those data store updates and redraw itself.
  23127. // source: Object
  23128. // The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
  23129. // nodes: DomNode[]
  23130. // The list of transferred items, dndTreeNode nodes if dragging from a Tree
  23131. // copy: Boolean
  23132. // Copy items, if true, move items otherwise
  23133. // tags:
  23134. // protected
  23135. if(this.containerState == "Over"){
  23136. var tree = this.tree,
  23137. model = tree.model,
  23138. target = this.targetAnchor;
  23139. this.isDragging = false;
  23140. // Compute the new parent item
  23141. var newParentItem;
  23142. var insertIndex;
  23143. newParentItem = (target && target.item) || tree.item;
  23144. if(this.dropPosition == "Before" || this.dropPosition == "After"){
  23145. // TODO: if there is no parent item then disallow the drop.
  23146. // Actually this should be checked during onMouseMove too, to make the drag icon red.
  23147. newParentItem = (target.getParent() && target.getParent().item) || tree.item;
  23148. // Compute the insert index for reordering
  23149. insertIndex = target.getIndexInParent();
  23150. if(this.dropPosition == "After"){
  23151. insertIndex = target.getIndexInParent() + 1;
  23152. }
  23153. }else{
  23154. newParentItem = (target && target.item) || tree.item;
  23155. }
  23156. // If necessary, use this variable to hold array of hashes to pass to model.newItem()
  23157. // (one entry in the array for each dragged node).
  23158. var newItemsParams;
  23159. array.forEach(nodes, function(node, idx){
  23160. // dojo.dnd.Item representing the thing being dropped.
  23161. // Don't confuse the use of item here (meaning a DnD item) with the
  23162. // uses below where item means dojo.data item.
  23163. var sourceItem = source.getItem(node.id);
  23164. // Information that's available if the source is another Tree
  23165. // (possibly but not necessarily this tree, possibly but not
  23166. // necessarily the same model as this Tree)
  23167. if(array.indexOf(sourceItem.type, "treeNode") != -1){
  23168. var childTreeNode = sourceItem.data,
  23169. childItem = childTreeNode.item,
  23170. oldParentItem = childTreeNode.getParent().item;
  23171. }
  23172. if(source == this){
  23173. // This is a node from my own tree, and we are moving it, not copying.
  23174. // Remove item from old parent's children attribute.
  23175. // TODO: dijit.tree.dndSelector should implement deleteSelectedNodes()
  23176. // and this code should go there.
  23177. if(typeof insertIndex == "number"){
  23178. if(newParentItem == oldParentItem && childTreeNode.getIndexInParent() < insertIndex){
  23179. insertIndex -= 1;
  23180. }
  23181. }
  23182. model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
  23183. }else if(model.isItem(childItem)){
  23184. // Item from same model
  23185. // (maybe we should only do this branch if the source is a tree?)
  23186. model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
  23187. }else{
  23188. // Get the hash to pass to model.newItem(). A single call to
  23189. // itemCreator() returns an array of hashes, one for each drag source node.
  23190. if(!newItemsParams){
  23191. newItemsParams = this.itemCreator(nodes, target.rowNode, source);
  23192. }
  23193. // Create new item in the tree, based on the drag source.
  23194. model.newItem(newItemsParams[idx], newParentItem, insertIndex);
  23195. }
  23196. }, this);
  23197. // Expand the target node (if it's currently collapsed) so the user can see
  23198. // where their node was dropped. In particular since that node is still selected.
  23199. this.tree._expandNode(target);
  23200. }
  23201. this.onDndCancel();
  23202. },
  23203. onDndCancel: function(){
  23204. // summary:
  23205. // Topic event processor for /dnd/cancel, called to cancel the DnD operation
  23206. // tags:
  23207. // private
  23208. this._unmarkTargetAnchor();
  23209. this.isDragging = false;
  23210. this.mouseDown = false;
  23211. delete this.mouseButton;
  23212. this._changeState("Source", "");
  23213. this._changeState("Target", "");
  23214. },
  23215. // When focus moves in/out of the entire Tree
  23216. onOverEvent: function(){
  23217. // summary:
  23218. // This method is called when mouse is moved over our container (like onmouseenter)
  23219. // tags:
  23220. // private
  23221. this.inherited(arguments);
  23222. DNDManager.manager().overSource(this);
  23223. },
  23224. onOutEvent: function(){
  23225. // summary:
  23226. // This method is called when mouse is moved out of our container (like onmouseleave)
  23227. // tags:
  23228. // private
  23229. this._unmarkTargetAnchor();
  23230. var m = DNDManager.manager();
  23231. if(this.isDragging){
  23232. m.canDrop(false);
  23233. }
  23234. m.outSource(this);
  23235. this.inherited(arguments);
  23236. },
  23237. _isParentChildDrop: function(source, targetRow){
  23238. // summary:
  23239. // Checks whether the dragged items are parent rows in the tree which are being
  23240. // dragged into their own children.
  23241. //
  23242. // source:
  23243. // The DragSource object.
  23244. //
  23245. // targetRow:
  23246. // The tree row onto which the dragged nodes are being dropped.
  23247. //
  23248. // tags:
  23249. // private
  23250. // If the dragged object is not coming from the tree this widget belongs to,
  23251. // it cannot be invalid.
  23252. if(!source.tree || source.tree != this.tree){
  23253. return false;
  23254. }
  23255. var root = source.tree.domNode;
  23256. var ids = source.selection;
  23257. var node = targetRow.parentNode;
  23258. // Iterate up the DOM hierarchy from the target drop row,
  23259. // checking of any of the dragged nodes have the same ID.
  23260. while(node != root && !ids[node.id]){
  23261. node = node.parentNode;
  23262. }
  23263. return node.id && ids[node.id];
  23264. },
  23265. _unmarkTargetAnchor: function(){
  23266. // summary:
  23267. // Removes hover class of the current target anchor
  23268. // tags:
  23269. // private
  23270. if(!this.targetAnchor){ return; }
  23271. this._removeItemClass(this.targetAnchor.rowNode, this.dropPosition);
  23272. this.targetAnchor = null;
  23273. this.targetBox = null;
  23274. this.dropPosition = null;
  23275. },
  23276. _markDndStatus: function(copy){
  23277. // summary:
  23278. // Changes source's state based on "copy" status
  23279. this._changeState("Source", copy ? "Copied" : "Moved");
  23280. }
  23281. });
  23282. });
  23283. },
  23284. 'dijit/a11y':function(){
  23285. define("dijit/a11y", [
  23286. "dojo/_base/array", // array.forEach array.map
  23287. "dojo/dom", // dom.byId
  23288. "dojo/dom-attr", // domAttr.attr domAttr.has
  23289. "dojo/dom-style", // domStyle.style
  23290. "dojo/_base/lang", // lang.mixin()
  23291. "dojo/_base/sniff", // has("ie") 1
  23292. "./main" // for exporting methods to dijit namespace
  23293. ], function(array, dom, domAttr, domStyle, lang, has, dijit){
  23294. // module:
  23295. // dijit/a11y
  23296. var undefined;
  23297. var a11y = {
  23298. // summary:
  23299. // Accessibility utility functions (keyboard, tab stops, etc.)
  23300. _isElementShown: function(/*Element*/ elem){
  23301. var s = domStyle.get(elem);
  23302. return (s.visibility != "hidden")
  23303. && (s.visibility != "collapsed")
  23304. && (s.display != "none")
  23305. && (domAttr.get(elem, "type") != "hidden");
  23306. },
  23307. hasDefaultTabStop: function(/*Element*/ elem){
  23308. // summary:
  23309. // Tests if element is tab-navigable even without an explicit tabIndex setting
  23310. // No explicit tabIndex setting, need to investigate node type
  23311. switch(elem.nodeName.toLowerCase()){
  23312. case "a":
  23313. // An <a> w/out a tabindex is only navigable if it has an href
  23314. return domAttr.has(elem, "href");
  23315. case "area":
  23316. case "button":
  23317. case "input":
  23318. case "object":
  23319. case "select":
  23320. case "textarea":
  23321. // These are navigable by default
  23322. return true;
  23323. case "iframe":
  23324. // If it's an editor <iframe> then it's tab navigable.
  23325. var body;
  23326. try{
  23327. // non-IE
  23328. var contentDocument = elem.contentDocument;
  23329. if("designMode" in contentDocument && contentDocument.designMode == "on"){
  23330. return true;
  23331. }
  23332. body = contentDocument.body;
  23333. }catch(e1){
  23334. // contentWindow.document isn't accessible within IE7/8
  23335. // if the iframe.src points to a foreign url and this
  23336. // page contains an element, that could get focus
  23337. try{
  23338. body = elem.contentWindow.document.body;
  23339. }catch(e2){
  23340. return false;
  23341. }
  23342. }
  23343. return body && (body.contentEditable == 'true' ||
  23344. (body.firstChild && body.firstChild.contentEditable == 'true'));
  23345. default:
  23346. return elem.contentEditable == 'true';
  23347. }
  23348. },
  23349. effectiveTabIndex: function(/*Element*/ elem){
  23350. // summary:
  23351. // Returns effective tabIndex of an element, either a number, or undefined if element isn't focusable.
  23352. if(domAttr.get(elem, "disabled")){
  23353. return undefined;
  23354. }else if(domAttr.has(elem, "tabIndex")){
  23355. // Explicit tab index setting
  23356. return +domAttr.get(elem, "tabIndex");// + to convert string --> number
  23357. }else{
  23358. // No explicit tabIndex setting, so depends on node type
  23359. return a11y.hasDefaultTabStop(elem) ? 0 : undefined;
  23360. }
  23361. },
  23362. isTabNavigable: function(/*Element*/ elem){
  23363. // summary:
  23364. // Tests if an element is tab-navigable
  23365. return a11y.effectiveTabIndex(elem) >= 0;
  23366. },
  23367. isFocusable: function(/*Element*/ elem){
  23368. // summary:
  23369. // Tests if an element is focusable by tabbing to it, or clicking it with the mouse.
  23370. return a11y.effectiveTabIndex(elem) >= -1;
  23371. },
  23372. _getTabNavigable: function(/*DOMNode*/ root){
  23373. // summary:
  23374. // Finds descendants of the specified root node.
  23375. // description:
  23376. // Finds the following descendants of the specified root node:
  23377. //
  23378. // - the first tab-navigable element in document order
  23379. // without a tabIndex or with tabIndex="0"
  23380. // - the last tab-navigable element in document order
  23381. // without a tabIndex or with tabIndex="0"
  23382. // - the first element in document order with the lowest
  23383. // positive tabIndex value
  23384. // - the last element in document order with the highest
  23385. // positive tabIndex value
  23386. var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {};
  23387. function radioName(node){
  23388. // If this element is part of a radio button group, return the name for that group.
  23389. return node && node.tagName.toLowerCase() == "input" &&
  23390. node.type && node.type.toLowerCase() == "radio" &&
  23391. node.name && node.name.toLowerCase();
  23392. }
  23393. var shown = a11y._isElementShown, effectiveTabIndex = a11y.effectiveTabIndex;
  23394. var walkTree = function(/*DOMNode*/ parent){
  23395. for(var child = parent.firstChild; child; child = child.nextSibling){
  23396. // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
  23397. // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
  23398. if(child.nodeType != 1 || (has("ie") <= 9 && child.scopeName !== "HTML") || !shown(child)){
  23399. continue;
  23400. }
  23401. var tabindex = effectiveTabIndex(child);
  23402. if(tabindex >= 0){
  23403. if(tabindex == 0){
  23404. if(!first){
  23405. first = child;
  23406. }
  23407. last = child;
  23408. }else if(tabindex > 0){
  23409. if(!lowest || tabindex < lowestTabindex){
  23410. lowestTabindex = tabindex;
  23411. lowest = child;
  23412. }
  23413. if(!highest || tabindex >= highestTabindex){
  23414. highestTabindex = tabindex;
  23415. highest = child;
  23416. }
  23417. }
  23418. var rn = radioName(child);
  23419. if(domAttr.get(child, "checked") && rn){
  23420. radioSelected[rn] = child;
  23421. }
  23422. }
  23423. if(child.nodeName.toUpperCase() != 'SELECT'){
  23424. walkTree(child);
  23425. }
  23426. }
  23427. };
  23428. if(shown(root)){
  23429. walkTree(root);
  23430. }
  23431. function rs(node){
  23432. // substitute checked radio button for unchecked one, if there is a checked one with the same name.
  23433. return radioSelected[radioName(node)] || node;
  23434. }
  23435. return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) };
  23436. },
  23437. getFirstInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){
  23438. // summary:
  23439. // Finds the descendant of the specified root node
  23440. // that is first in the tabbing order
  23441. var elems = a11y._getTabNavigable(dom.byId(root, doc));
  23442. return elems.lowest ? elems.lowest : elems.first; // DomNode
  23443. },
  23444. getLastInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){
  23445. // summary:
  23446. // Finds the descendant of the specified root node
  23447. // that is last in the tabbing order
  23448. var elems = a11y._getTabNavigable(dom.byId(root, doc));
  23449. return elems.last ? elems.last : elems.highest; // DomNode
  23450. }
  23451. };
  23452. 1 && lang.mixin(dijit, a11y);
  23453. return a11y;
  23454. });
  23455. },
  23456. 'dijit/form/_ToggleButtonMixin':function(){
  23457. define("dijit/form/_ToggleButtonMixin", [
  23458. "dojo/_base/declare", // declare
  23459. "dojo/dom-attr" // domAttr.set
  23460. ], function(declare, domAttr){
  23461. // module:
  23462. // dijit/form/_ToggleButtonMixin
  23463. // summary:
  23464. // A mixin to provide functionality to allow a button that can be in two states (checked or not).
  23465. return declare("dijit.form._ToggleButtonMixin", null, {
  23466. // summary:
  23467. // A mixin to provide functionality to allow a button that can be in two states (checked or not).
  23468. // checked: Boolean
  23469. // Corresponds to the native HTML <input> element's attribute.
  23470. // In markup, specified as "checked='checked'" or just "checked".
  23471. // True if the button is depressed, or the checkbox is checked,
  23472. // or the radio button is selected, etc.
  23473. checked: false,
  23474. // aria-pressed for toggle buttons, and aria-checked for checkboxes
  23475. _aria_attr: "aria-pressed",
  23476. _onClick: function(/*Event*/ evt){
  23477. var original = this.checked;
  23478. this._set('checked', !original); // partially set the toggled value, assuming the toggle will work, so it can be overridden in the onclick handler
  23479. var ret = this.inherited(arguments); // the user could reset the value here
  23480. this.set('checked', ret ? this.checked : original); // officially set the toggled or user value, or reset it back
  23481. return ret;
  23482. },
  23483. _setCheckedAttr: function(/*Boolean*/ value, /*Boolean?*/ priorityChange){
  23484. this._set("checked", value);
  23485. domAttr.set(this.focusNode || this.domNode, "checked", value);
  23486. (this.focusNode || this.domNode).setAttribute(this._aria_attr, value ? "true" : "false"); // aria values should be strings
  23487. this._handleOnChange(value, priorityChange);
  23488. },
  23489. reset: function(){
  23490. // summary:
  23491. // Reset the widget's value to what it was at initialization time
  23492. this._hasBeenBlurred = false;
  23493. // set checked state to original setting
  23494. this.set('checked', this.params.checked || false);
  23495. }
  23496. });
  23497. });
  23498. },
  23499. 'dojo/dnd/Container':function(){
  23500. define("dojo/dnd/Container", ["../main", "../Evented", "./common", "../parser"], function(dojo, Evented) {
  23501. // module:
  23502. // dojo/dnd/Container
  23503. // summary:
  23504. // TODOC
  23505. /*
  23506. Container states:
  23507. "" - normal state
  23508. "Over" - mouse over a container
  23509. Container item states:
  23510. "" - normal state
  23511. "Over" - mouse over a container item
  23512. */
  23513. /*=====
  23514. dojo.declare("dojo.dnd.__ContainerArgs", [], {
  23515. creator: function(){
  23516. // summary:
  23517. // a creator function, which takes a data item, and returns an object like that:
  23518. // {node: newNode, data: usedData, type: arrayOfStrings}
  23519. },
  23520. // skipForm: Boolean
  23521. // don't start the drag operation, if clicked on form elements
  23522. skipForm: false,
  23523. // dropParent: Node||String
  23524. // node or node's id to use as the parent node for dropped items
  23525. // (must be underneath the 'node' parameter in the DOM)
  23526. dropParent: null,
  23527. // _skipStartup: Boolean
  23528. // skip startup(), which collects children, for deferred initialization
  23529. // (this is used in the markup mode)
  23530. _skipStartup: false
  23531. });
  23532. dojo.dnd.Item = function(){
  23533. // summary:
  23534. // Represents (one of) the source node(s) being dragged.
  23535. // Contains (at least) the "type" and "data" attributes.
  23536. // type: String[]
  23537. // Type(s) of this item, by default this is ["text"]
  23538. // data: Object
  23539. // Logical representation of the object being dragged.
  23540. // If the drag object's type is "text" then data is a String,
  23541. // if it's another type then data could be a different Object,
  23542. // perhaps a name/value hash.
  23543. this.type = type;
  23544. this.data = data;
  23545. }
  23546. =====*/
  23547. dojo.declare("dojo.dnd.Container", Evented, {
  23548. // summary:
  23549. // a Container object, which knows when mouse hovers over it,
  23550. // and over which element it hovers
  23551. // object attributes (for markup)
  23552. skipForm: false,
  23553. /*=====
  23554. // current: DomNode
  23555. // The DOM node the mouse is currently hovered over
  23556. current: null,
  23557. // map: Hash<String, dojo.dnd.Item>
  23558. // Map from an item's id (which is also the DOMNode's id) to
  23559. // the dojo.dnd.Item itself.
  23560. map: {},
  23561. =====*/
  23562. constructor: function(node, params){
  23563. // summary:
  23564. // a constructor of the Container
  23565. // node: Node
  23566. // node or node's id to build the container on
  23567. // params: dojo.dnd.__ContainerArgs
  23568. // a dictionary of parameters
  23569. this.node = dojo.byId(node);
  23570. if(!params){ params = {}; }
  23571. this.creator = params.creator || null;
  23572. this.skipForm = params.skipForm;
  23573. this.parent = params.dropParent && dojo.byId(params.dropParent);
  23574. // class-specific variables
  23575. this.map = {};
  23576. this.current = null;
  23577. // states
  23578. this.containerState = "";
  23579. dojo.addClass(this.node, "dojoDndContainer");
  23580. // mark up children
  23581. if(!(params && params._skipStartup)){
  23582. this.startup();
  23583. }
  23584. // set up events
  23585. this.events = [
  23586. dojo.connect(this.node, "onmouseover", this, "onMouseOver"),
  23587. dojo.connect(this.node, "onmouseout", this, "onMouseOut"),
  23588. // cancel text selection and text dragging
  23589. dojo.connect(this.node, "ondragstart", this, "onSelectStart"),
  23590. dojo.connect(this.node, "onselectstart", this, "onSelectStart")
  23591. ];
  23592. },
  23593. // object attributes (for markup)
  23594. creator: function(){
  23595. // summary:
  23596. // creator function, dummy at the moment
  23597. },
  23598. // abstract access to the map
  23599. getItem: function(/*String*/ key){
  23600. // summary:
  23601. // returns a data item by its key (id)
  23602. return this.map[key]; // dojo.dnd.Item
  23603. },
  23604. setItem: function(/*String*/ key, /*dojo.dnd.Item*/ data){
  23605. // summary:
  23606. // associates a data item with its key (id)
  23607. this.map[key] = data;
  23608. },
  23609. delItem: function(/*String*/ key){
  23610. // summary:
  23611. // removes a data item from the map by its key (id)
  23612. delete this.map[key];
  23613. },
  23614. forInItems: function(/*Function*/ f, /*Object?*/ o){
  23615. // summary:
  23616. // iterates over a data map skipping members that
  23617. // are present in the empty object (IE and/or 3rd-party libraries).
  23618. o = o || dojo.global;
  23619. var m = this.map, e = dojo.dnd._empty;
  23620. for(var i in m){
  23621. if(i in e){ continue; }
  23622. f.call(o, m[i], i, this);
  23623. }
  23624. return o; // Object
  23625. },
  23626. clearItems: function(){
  23627. // summary:
  23628. // removes all data items from the map
  23629. this.map = {};
  23630. },
  23631. // methods
  23632. getAllNodes: function(){
  23633. // summary:
  23634. // returns a list (an array) of all valid child nodes
  23635. return dojo.query("> .dojoDndItem", this.parent); // NodeList
  23636. },
  23637. sync: function(){
  23638. // summary:
  23639. // sync up the node list with the data map
  23640. var map = {};
  23641. this.getAllNodes().forEach(function(node){
  23642. if(node.id){
  23643. var item = this.getItem(node.id);
  23644. if(item){
  23645. map[node.id] = item;
  23646. return;
  23647. }
  23648. }else{
  23649. node.id = dojo.dnd.getUniqueId();
  23650. }
  23651. var type = node.getAttribute("dndType"),
  23652. data = node.getAttribute("dndData");
  23653. map[node.id] = {
  23654. data: data || node.innerHTML,
  23655. type: type ? type.split(/\s*,\s*/) : ["text"]
  23656. };
  23657. }, this);
  23658. this.map = map;
  23659. return this; // self
  23660. },
  23661. insertNodes: function(data, before, anchor){
  23662. // summary:
  23663. // inserts an array of new nodes before/after an anchor node
  23664. // data: Array
  23665. // a list of data items, which should be processed by the creator function
  23666. // before: Boolean
  23667. // insert before the anchor, if true, and after the anchor otherwise
  23668. // anchor: Node
  23669. // the anchor node to be used as a point of insertion
  23670. if(!this.parent.firstChild){
  23671. anchor = null;
  23672. }else if(before){
  23673. if(!anchor){
  23674. anchor = this.parent.firstChild;
  23675. }
  23676. }else{
  23677. if(anchor){
  23678. anchor = anchor.nextSibling;
  23679. }
  23680. }
  23681. if(anchor){
  23682. for(var i = 0; i < data.length; ++i){
  23683. var t = this._normalizedCreator(data[i]);
  23684. this.setItem(t.node.id, {data: t.data, type: t.type});
  23685. this.parent.insertBefore(t.node, anchor);
  23686. }
  23687. }else{
  23688. for(var i = 0; i < data.length; ++i){
  23689. var t = this._normalizedCreator(data[i]);
  23690. this.setItem(t.node.id, {data: t.data, type: t.type});
  23691. this.parent.appendChild(t.node);
  23692. }
  23693. }
  23694. return this; // self
  23695. },
  23696. destroy: function(){
  23697. // summary:
  23698. // prepares this object to be garbage-collected
  23699. dojo.forEach(this.events, dojo.disconnect);
  23700. this.clearItems();
  23701. this.node = this.parent = this.current = null;
  23702. },
  23703. // markup methods
  23704. markupFactory: function(params, node, ctor){
  23705. params._skipStartup = true;
  23706. return new ctor(node, params);
  23707. },
  23708. startup: function(){
  23709. // summary:
  23710. // collects valid child items and populate the map
  23711. // set up the real parent node
  23712. if(!this.parent){
  23713. // use the standard algorithm, if not assigned
  23714. this.parent = this.node;
  23715. if(this.parent.tagName.toLowerCase() == "table"){
  23716. var c = this.parent.getElementsByTagName("tbody");
  23717. if(c && c.length){ this.parent = c[0]; }
  23718. }
  23719. }
  23720. this.defaultCreator = dojo.dnd._defaultCreator(this.parent);
  23721. // process specially marked children
  23722. this.sync();
  23723. },
  23724. // mouse events
  23725. onMouseOver: function(e){
  23726. // summary:
  23727. // event processor for onmouseover
  23728. // e: Event
  23729. // mouse event
  23730. var n = e.relatedTarget;
  23731. while(n){
  23732. if(n == this.node){ break; }
  23733. try{
  23734. n = n.parentNode;
  23735. }catch(x){
  23736. n = null;
  23737. }
  23738. }
  23739. if(!n){
  23740. this._changeState("Container", "Over");
  23741. this.onOverEvent();
  23742. }
  23743. n = this._getChildByEvent(e);
  23744. if(this.current == n){ return; }
  23745. if(this.current){ this._removeItemClass(this.current, "Over"); }
  23746. if(n){ this._addItemClass(n, "Over"); }
  23747. this.current = n;
  23748. },
  23749. onMouseOut: function(e){
  23750. // summary:
  23751. // event processor for onmouseout
  23752. // e: Event
  23753. // mouse event
  23754. for(var n = e.relatedTarget; n;){
  23755. if(n == this.node){ return; }
  23756. try{
  23757. n = n.parentNode;
  23758. }catch(x){
  23759. n = null;
  23760. }
  23761. }
  23762. if(this.current){
  23763. this._removeItemClass(this.current, "Over");
  23764. this.current = null;
  23765. }
  23766. this._changeState("Container", "");
  23767. this.onOutEvent();
  23768. },
  23769. onSelectStart: function(e){
  23770. // summary:
  23771. // event processor for onselectevent and ondragevent
  23772. // e: Event
  23773. // mouse event
  23774. if(!this.skipForm || !dojo.dnd.isFormElement(e)){
  23775. dojo.stopEvent(e);
  23776. }
  23777. },
  23778. // utilities
  23779. onOverEvent: function(){
  23780. // summary:
  23781. // this function is called once, when mouse is over our container
  23782. },
  23783. onOutEvent: function(){
  23784. // summary:
  23785. // this function is called once, when mouse is out of our container
  23786. },
  23787. _changeState: function(type, newState){
  23788. // summary:
  23789. // changes a named state to new state value
  23790. // type: String
  23791. // a name of the state to change
  23792. // newState: String
  23793. // new state
  23794. var prefix = "dojoDnd" + type;
  23795. var state = type.toLowerCase() + "State";
  23796. //dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
  23797. dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
  23798. this[state] = newState;
  23799. },
  23800. _addItemClass: function(node, type){
  23801. // summary:
  23802. // adds a class with prefix "dojoDndItem"
  23803. // node: Node
  23804. // a node
  23805. // type: String
  23806. // a variable suffix for a class name
  23807. dojo.addClass(node, "dojoDndItem" + type);
  23808. },
  23809. _removeItemClass: function(node, type){
  23810. // summary:
  23811. // removes a class with prefix "dojoDndItem"
  23812. // node: Node
  23813. // a node
  23814. // type: String
  23815. // a variable suffix for a class name
  23816. dojo.removeClass(node, "dojoDndItem" + type);
  23817. },
  23818. _getChildByEvent: function(e){
  23819. // summary:
  23820. // gets a child, which is under the mouse at the moment, or null
  23821. // e: Event
  23822. // a mouse event
  23823. var node = e.target;
  23824. if(node){
  23825. for(var parent = node.parentNode; parent; node = parent, parent = node.parentNode){
  23826. if(parent == this.parent && dojo.hasClass(node, "dojoDndItem")){ return node; }
  23827. }
  23828. }
  23829. return null;
  23830. },
  23831. _normalizedCreator: function(/*dojo.dnd.Item*/ item, /*String*/ hint){
  23832. // summary:
  23833. // adds all necessary data to the output of the user-supplied creator function
  23834. var t = (this.creator || this.defaultCreator).call(this, item, hint);
  23835. if(!dojo.isArray(t.type)){ t.type = ["text"]; }
  23836. if(!t.node.id){ t.node.id = dojo.dnd.getUniqueId(); }
  23837. dojo.addClass(t.node, "dojoDndItem");
  23838. return t;
  23839. }
  23840. });
  23841. dojo.dnd._createNode = function(tag){
  23842. // summary:
  23843. // returns a function, which creates an element of given tag
  23844. // (SPAN by default) and sets its innerHTML to given text
  23845. // tag: String
  23846. // a tag name or empty for SPAN
  23847. if(!tag){ return dojo.dnd._createSpan; }
  23848. return function(text){ // Function
  23849. return dojo.create(tag, {innerHTML: text}); // Node
  23850. };
  23851. };
  23852. dojo.dnd._createTrTd = function(text){
  23853. // summary:
  23854. // creates a TR/TD structure with given text as an innerHTML of TD
  23855. // text: String
  23856. // a text for TD
  23857. var tr = dojo.create("tr");
  23858. dojo.create("td", {innerHTML: text}, tr);
  23859. return tr; // Node
  23860. };
  23861. dojo.dnd._createSpan = function(text){
  23862. // summary:
  23863. // creates a SPAN element with given text as its innerHTML
  23864. // text: String
  23865. // a text for SPAN
  23866. return dojo.create("span", {innerHTML: text}); // Node
  23867. };
  23868. // dojo.dnd._defaultCreatorNodes: Object
  23869. // a dictionary that maps container tag names to child tag names
  23870. dojo.dnd._defaultCreatorNodes = {ul: "li", ol: "li", div: "div", p: "div"};
  23871. dojo.dnd._defaultCreator = function(node){
  23872. // summary:
  23873. // takes a parent node, and returns an appropriate creator function
  23874. // node: Node
  23875. // a container node
  23876. var tag = node.tagName.toLowerCase();
  23877. var c = tag == "tbody" || tag == "thead" ? dojo.dnd._createTrTd :
  23878. dojo.dnd._createNode(dojo.dnd._defaultCreatorNodes[tag]);
  23879. return function(item, hint){ // Function
  23880. var isObj = item && dojo.isObject(item), data, type, n;
  23881. if(isObj && item.tagName && item.nodeType && item.getAttribute){
  23882. // process a DOM node
  23883. data = item.getAttribute("dndData") || item.innerHTML;
  23884. type = item.getAttribute("dndType");
  23885. type = type ? type.split(/\s*,\s*/) : ["text"];
  23886. n = item; // this node is going to be moved rather than copied
  23887. }else{
  23888. // process a DnD item object or a string
  23889. data = (isObj && item.data) ? item.data : item;
  23890. type = (isObj && item.type) ? item.type : ["text"];
  23891. n = (hint == "avatar" ? dojo.dnd._createSpan : c)(String(data));
  23892. }
  23893. if(!n.id){
  23894. n.id = dojo.dnd.getUniqueId();
  23895. }
  23896. return {node: n, data: data, type: type};
  23897. };
  23898. };
  23899. return dojo.dnd.Container;
  23900. });
  23901. },
  23902. 'dijit/_Widget':function(){
  23903. define("dijit/_Widget", [
  23904. "dojo/aspect", // aspect.around
  23905. "dojo/_base/config", // config.isDebug
  23906. "dojo/_base/connect", // connect.connect
  23907. "dojo/_base/declare", // declare
  23908. "dojo/_base/kernel", // kernel.deprecated
  23909. "dojo/_base/lang", // lang.hitch
  23910. "dojo/query",
  23911. "dojo/ready",
  23912. "./registry", // registry.byNode
  23913. "./_WidgetBase",
  23914. "./_OnDijitClickMixin",
  23915. "./_FocusMixin",
  23916. "dojo/uacss", // browser sniffing (included for back-compat; subclasses may be using)
  23917. "./hccss" // high contrast mode sniffing (included to set CSS classes on <body>, module ret value unused)
  23918. ], function(aspect, config, connect, declare, kernel, lang, query, ready,
  23919. registry, _WidgetBase, _OnDijitClickMixin, _FocusMixin){
  23920. /*=====
  23921. var _WidgetBase = dijit._WidgetBase;
  23922. var _OnDijitClickMixin = dijit._OnDijitClickMixin;
  23923. var _FocusMixin = dijit._FocusMixin;
  23924. =====*/
  23925. // module:
  23926. // dijit/_Widget
  23927. // summary:
  23928. // Old base for widgets. New widgets should extend _WidgetBase instead
  23929. function connectToDomNode(){
  23930. // summary:
  23931. // If user connects to a widget method === this function, then they will
  23932. // instead actually be connecting the equivalent event on this.domNode
  23933. }
  23934. // Trap dojo.connect() calls to connectToDomNode methods, and redirect to _Widget.on()
  23935. function aroundAdvice(originalConnect){
  23936. return function(obj, event, scope, method){
  23937. if(obj && typeof event == "string" && obj[event] == connectToDomNode){
  23938. return obj.on(event.substring(2).toLowerCase(), lang.hitch(scope, method));
  23939. }
  23940. return originalConnect.apply(connect, arguments);
  23941. };
  23942. }
  23943. aspect.around(connect, "connect", aroundAdvice);
  23944. if(kernel.connect){
  23945. aspect.around(kernel, "connect", aroundAdvice);
  23946. }
  23947. var _Widget = declare("dijit._Widget", [_WidgetBase, _OnDijitClickMixin, _FocusMixin], {
  23948. // summary:
  23949. // Base class for all Dijit widgets.
  23950. //
  23951. // Extends _WidgetBase, adding support for:
  23952. // - declaratively/programatically specifying widget initialization parameters like
  23953. // onMouseMove="foo" that call foo when this.domNode gets a mousemove event
  23954. // - ondijitclick
  23955. // Support new data-dojo-attach-event="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress
  23956. // - focus related functions
  23957. // In particular, the onFocus()/onBlur() callbacks. Driven internally by
  23958. // dijit/_base/focus.js.
  23959. // - deprecated methods
  23960. // - onShow(), onHide(), onClose()
  23961. //
  23962. // Also, by loading code in dijit/_base, turns on:
  23963. // - browser sniffing (putting browser id like .dj_ie on <html> node)
  23964. // - high contrast mode sniffing (add .dijit_a11y class to <body> if machine is in high contrast mode)
  23965. ////////////////// DEFERRED CONNECTS ///////////////////
  23966. onClick: connectToDomNode,
  23967. /*=====
  23968. onClick: function(event){
  23969. // summary:
  23970. // Connect to this function to receive notifications of mouse click events.
  23971. // event:
  23972. // mouse Event
  23973. // tags:
  23974. // callback
  23975. },
  23976. =====*/
  23977. onDblClick: connectToDomNode,
  23978. /*=====
  23979. onDblClick: function(event){
  23980. // summary:
  23981. // Connect to this function to receive notifications of mouse double click events.
  23982. // event:
  23983. // mouse Event
  23984. // tags:
  23985. // callback
  23986. },
  23987. =====*/
  23988. onKeyDown: connectToDomNode,
  23989. /*=====
  23990. onKeyDown: function(event){
  23991. // summary:
  23992. // Connect to this function to receive notifications of keys being pressed down.
  23993. // event:
  23994. // key Event
  23995. // tags:
  23996. // callback
  23997. },
  23998. =====*/
  23999. onKeyPress: connectToDomNode,
  24000. /*=====
  24001. onKeyPress: function(event){
  24002. // summary:
  24003. // Connect to this function to receive notifications of printable keys being typed.
  24004. // event:
  24005. // key Event
  24006. // tags:
  24007. // callback
  24008. },
  24009. =====*/
  24010. onKeyUp: connectToDomNode,
  24011. /*=====
  24012. onKeyUp: function(event){
  24013. // summary:
  24014. // Connect to this function to receive notifications of keys being released.
  24015. // event:
  24016. // key Event
  24017. // tags:
  24018. // callback
  24019. },
  24020. =====*/
  24021. onMouseDown: connectToDomNode,
  24022. /*=====
  24023. onMouseDown: function(event){
  24024. // summary:
  24025. // Connect to this function to receive notifications of when the mouse button is pressed down.
  24026. // event:
  24027. // mouse Event
  24028. // tags:
  24029. // callback
  24030. },
  24031. =====*/
  24032. onMouseMove: connectToDomNode,
  24033. /*=====
  24034. onMouseMove: function(event){
  24035. // summary:
  24036. // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
  24037. // event:
  24038. // mouse Event
  24039. // tags:
  24040. // callback
  24041. },
  24042. =====*/
  24043. onMouseOut: connectToDomNode,
  24044. /*=====
  24045. onMouseOut: function(event){
  24046. // summary:
  24047. // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
  24048. // event:
  24049. // mouse Event
  24050. // tags:
  24051. // callback
  24052. },
  24053. =====*/
  24054. onMouseOver: connectToDomNode,
  24055. /*=====
  24056. onMouseOver: function(event){
  24057. // summary:
  24058. // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
  24059. // event:
  24060. // mouse Event
  24061. // tags:
  24062. // callback
  24063. },
  24064. =====*/
  24065. onMouseLeave: connectToDomNode,
  24066. /*=====
  24067. onMouseLeave: function(event){
  24068. // summary:
  24069. // Connect to this function to receive notifications of when the mouse moves off of this widget.
  24070. // event:
  24071. // mouse Event
  24072. // tags:
  24073. // callback
  24074. },
  24075. =====*/
  24076. onMouseEnter: connectToDomNode,
  24077. /*=====
  24078. onMouseEnter: function(event){
  24079. // summary:
  24080. // Connect to this function to receive notifications of when the mouse moves onto this widget.
  24081. // event:
  24082. // mouse Event
  24083. // tags:
  24084. // callback
  24085. },
  24086. =====*/
  24087. onMouseUp: connectToDomNode,
  24088. /*=====
  24089. onMouseUp: function(event){
  24090. // summary:
  24091. // Connect to this function to receive notifications of when the mouse button is released.
  24092. // event:
  24093. // mouse Event
  24094. // tags:
  24095. // callback
  24096. },
  24097. =====*/
  24098. constructor: function(params){
  24099. // extract parameters like onMouseMove that should connect directly to this.domNode
  24100. this._toConnect = {};
  24101. for(var name in params){
  24102. if(this[name] === connectToDomNode){
  24103. this._toConnect[name.replace(/^on/, "").toLowerCase()] = params[name];
  24104. delete params[name];
  24105. }
  24106. }
  24107. },
  24108. postCreate: function(){
  24109. this.inherited(arguments);
  24110. // perform connection from this.domNode to user specified handlers (ex: onMouseMove)
  24111. for(var name in this._toConnect){
  24112. this.on(name, this._toConnect[name]);
  24113. }
  24114. delete this._toConnect;
  24115. },
  24116. on: function(/*String*/ type, /*Function*/ func){
  24117. if(this[this._onMap(type)] === connectToDomNode){
  24118. // Use connect.connect() rather than on() to get handling for "onmouseenter" on non-IE, etc.
  24119. // Also, need to specify context as "this" rather than the default context of the DOMNode
  24120. return connect.connect(this.domNode, type.toLowerCase(), this, func);
  24121. }
  24122. return this.inherited(arguments);
  24123. },
  24124. _setFocusedAttr: function(val){
  24125. // Remove this method in 2.0 (or sooner), just here to set _focused == focused, for back compat
  24126. // (but since it's a private variable we aren't required to keep supporting it).
  24127. this._focused = val;
  24128. this._set("focused", val);
  24129. },
  24130. ////////////////// DEPRECATED METHODS ///////////////////
  24131. setAttribute: function(/*String*/ attr, /*anything*/ value){
  24132. // summary:
  24133. // Deprecated. Use set() instead.
  24134. // tags:
  24135. // deprecated
  24136. kernel.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
  24137. this.set(attr, value);
  24138. },
  24139. attr: function(/*String|Object*/name, /*Object?*/value){
  24140. // summary:
  24141. // Set or get properties on a widget instance.
  24142. // name:
  24143. // The property to get or set. If an object is passed here and not
  24144. // a string, its keys are used as names of attributes to be set
  24145. // and the value of the object as values to set in the widget.
  24146. // value:
  24147. // Optional. If provided, attr() operates as a setter. If omitted,
  24148. // the current value of the named property is returned.
  24149. // description:
  24150. // This method is deprecated, use get() or set() directly.
  24151. // Print deprecation warning but only once per calling function
  24152. if(config.isDebug){
  24153. var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
  24154. caller = (arguments.callee.caller || "unknown caller").toString();
  24155. if(!alreadyCalledHash[caller]){
  24156. kernel.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
  24157. caller, "", "2.0");
  24158. alreadyCalledHash[caller] = true;
  24159. }
  24160. }
  24161. var args = arguments.length;
  24162. if(args >= 2 || typeof name === "object"){ // setter
  24163. return this.set.apply(this, arguments);
  24164. }else{ // getter
  24165. return this.get(name);
  24166. }
  24167. },
  24168. getDescendants: function(){
  24169. // summary:
  24170. // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
  24171. // This method should generally be avoided as it returns widgets declared in templates, which are
  24172. // supposed to be internal/hidden, but it's left here for back-compat reasons.
  24173. kernel.deprecated(this.declaredClass+"::getDescendants() is deprecated. Use getChildren() instead.", "", "2.0");
  24174. return this.containerNode ? query('[widgetId]', this.containerNode).map(registry.byNode) : []; // dijit._Widget[]
  24175. },
  24176. ////////////////// MISCELLANEOUS METHODS ///////////////////
  24177. _onShow: function(){
  24178. // summary:
  24179. // Internal method called when this widget is made visible.
  24180. // See `onShow` for details.
  24181. this.onShow();
  24182. },
  24183. onShow: function(){
  24184. // summary:
  24185. // Called when this widget becomes the selected pane in a
  24186. // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
  24187. // `dijit.layout.AccordionContainer`, etc.
  24188. //
  24189. // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
  24190. // tags:
  24191. // callback
  24192. },
  24193. onHide: function(){
  24194. // summary:
  24195. // Called when another widget becomes the selected pane in a
  24196. // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
  24197. // `dijit.layout.AccordionContainer`, etc.
  24198. //
  24199. // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
  24200. // tags:
  24201. // callback
  24202. },
  24203. onClose: function(){
  24204. // summary:
  24205. // Called when this widget is being displayed as a popup (ex: a Calendar popped
  24206. // up from a DateTextBox), and it is hidden.
  24207. // This is called from the dijit.popup code, and should not be called directly.
  24208. //
  24209. // Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
  24210. // Callback if a user tries to close the child. Child will be closed if this function returns true.
  24211. // tags:
  24212. // extension
  24213. return true; // Boolean
  24214. }
  24215. });
  24216. // For back-compat, remove in 2.0.
  24217. if(!kernel.isAsync){
  24218. ready(0, function(){
  24219. var requires = ["dijit/_base"];
  24220. require(requires); // use indirection so modules not rolled into a build
  24221. });
  24222. }
  24223. return _Widget;
  24224. });
  24225. },
  24226. 'dojo/touch':function(){
  24227. define("dojo/touch", ["./_base/kernel", "./aspect", "./dom", "./on", "./has", "./mouse", "./domReady", "./_base/window"],
  24228. function(dojo, aspect, dom, on, has, mouse, domReady, win){
  24229. // module:
  24230. // dojo/touch
  24231. var hasTouch = has("touch");
  24232. // TODO: get iOS version from dojo/sniff after #15827 is fixed
  24233. var ios4 = false;
  24234. if(has("ios")){
  24235. var ua = navigator.userAgent;
  24236. var v = ua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1";
  24237. var os = parseFloat(v.replace(/_/, '.').replace(/_/g, ''));
  24238. ios4 = os < 5;
  24239. }
  24240. // Time of most recent touchstart or touchmove event
  24241. var lastTouch;
  24242. function dualEvent(mouseType, touchType){
  24243. // Returns synthetic event that listens for both the specified mouse event and specified touch event.
  24244. // But ignore fake mouse events that were generated due to the user touching the screen.
  24245. if(hasTouch){
  24246. return function(node, listener){
  24247. var handle1 = on(node, touchType, listener),
  24248. handle2 = on(node, mouseType, function(evt){
  24249. if(!lastTouch || (new Date()).getTime() > lastTouch + 1000){
  24250. listener.call(this, evt);
  24251. }
  24252. });
  24253. return {
  24254. remove: function(){
  24255. handle1.remove();
  24256. handle2.remove();
  24257. }
  24258. };
  24259. };
  24260. }else{
  24261. // Avoid creating listeners for touch events on performance sensitive older browsers like IE6
  24262. return function(node, listener){
  24263. return on(node, mouseType, listener);
  24264. }
  24265. }
  24266. }
  24267. var touchmove, hoveredNode;
  24268. if(hasTouch){
  24269. domReady(function(){
  24270. // Keep track of currently hovered node
  24271. hoveredNode = win.body(); // currently hovered node
  24272. win.doc.addEventListener("touchstart", function(evt){
  24273. lastTouch = (new Date()).getTime();
  24274. // Precede touchstart event with touch.over event. DnD depends on this.
  24275. // Use addEventListener(cb, true) to run cb before any touchstart handlers on node run,
  24276. // and to ensure this code runs even if the listener on the node does event.stop().
  24277. var oldNode = hoveredNode;
  24278. hoveredNode = evt.target;
  24279. on.emit(oldNode, "dojotouchout", {
  24280. target: oldNode,
  24281. relatedTarget: hoveredNode,
  24282. bubbles: true
  24283. });
  24284. on.emit(hoveredNode, "dojotouchover", {
  24285. target: hoveredNode,
  24286. relatedTarget: oldNode,
  24287. bubbles: true
  24288. });
  24289. }, true);
  24290. // Fire synthetic touchover and touchout events on nodes since the browser won't do it natively.
  24291. on(win.doc, "touchmove", function(evt){
  24292. lastTouch = (new Date()).getTime();
  24293. var newNode = win.doc.elementFromPoint(
  24294. evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords
  24295. evt.pageY - (ios4 ? 0 : win.global.pageYOffset)
  24296. );
  24297. if(newNode && hoveredNode !== newNode){
  24298. // touch out on the old node
  24299. on.emit(hoveredNode, "dojotouchout", {
  24300. target: hoveredNode,
  24301. relatedTarget: newNode,
  24302. bubbles: true
  24303. });
  24304. // touchover on the new node
  24305. on.emit(newNode, "dojotouchover", {
  24306. target: newNode,
  24307. relatedTarget: hoveredNode,
  24308. bubbles: true
  24309. });
  24310. hoveredNode = newNode;
  24311. }
  24312. });
  24313. });
  24314. // Define synthetic touch.move event that unlike the native touchmove, fires for the node the finger is
  24315. // currently dragging over rather than the node where the touch started.
  24316. touchmove = function(node, listener){
  24317. return on(win.doc, "touchmove", function(evt){
  24318. if(node === win.doc || dom.isDescendant(hoveredNode, node)){
  24319. evt.target = hoveredNode;
  24320. listener.call(this, evt);
  24321. }
  24322. });
  24323. };
  24324. }
  24325. //device neutral events - touch.press|move|release|cancel/over/out
  24326. var touch = {
  24327. press: dualEvent("mousedown", "touchstart"),
  24328. move: dualEvent("mousemove", touchmove),
  24329. release: dualEvent("mouseup", "touchend"),
  24330. cancel: dualEvent(mouse.leave, "touchcancel"),
  24331. over: dualEvent("mouseover", "dojotouchover"),
  24332. out: dualEvent("mouseout", "dojotouchout"),
  24333. enter: mouse._eventHandler(dualEvent("mouseover","dojotouchover")),
  24334. leave: mouse._eventHandler(dualEvent("mouseout", "dojotouchout"))
  24335. };
  24336. /*=====
  24337. touch = {
  24338. // summary:
  24339. // This module provides unified touch event handlers by exporting
  24340. // press, move, release and cancel which can also run well on desktop.
  24341. // Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
  24342. //
  24343. // example:
  24344. // Used with dojo.on
  24345. // | define(["dojo/on", "dojo/touch"], function(on, touch){
  24346. // | on(node, touch.press, function(e){});
  24347. // | on(node, touch.move, function(e){});
  24348. // | on(node, touch.release, function(e){});
  24349. // | on(node, touch.cancel, function(e){});
  24350. // example:
  24351. // Used with touch.* directly
  24352. // | touch.press(node, function(e){});
  24353. // | touch.move(node, function(e){});
  24354. // | touch.release(node, function(e){});
  24355. // | touch.cancel(node, function(e){});
  24356. press: function(node, listener){
  24357. // summary:
  24358. // Register a listener to 'touchstart'|'mousedown' for the given node
  24359. // node: Dom
  24360. // Target node to listen to
  24361. // listener: Function
  24362. // Callback function
  24363. // returns:
  24364. // A handle which will be used to remove the listener by handle.remove()
  24365. },
  24366. move: function(node, listener){
  24367. // summary:
  24368. // Register a listener to 'touchmove'|'mousemove' for the given node
  24369. // node: Dom
  24370. // Target node to listen to
  24371. // listener: Function
  24372. // Callback function
  24373. // returns:
  24374. // A handle which will be used to remove the listener by handle.remove()
  24375. },
  24376. release: function(node, listener){
  24377. // summary:
  24378. // Register a listener to 'touchend'|'mouseup' for the given node
  24379. // node: Dom
  24380. // Target node to listen to
  24381. // listener: Function
  24382. // Callback function
  24383. // returns:
  24384. // A handle which will be used to remove the listener by handle.remove()
  24385. },
  24386. cancel: function(node, listener){
  24387. // summary:
  24388. // Register a listener to 'touchcancel'|'mouseleave' for the given node
  24389. // node: Dom
  24390. // Target node to listen to
  24391. // listener: Function
  24392. // Callback function
  24393. // returns:
  24394. // A handle which will be used to remove the listener by handle.remove()
  24395. },
  24396. over: function(node, listener){
  24397. // summary:
  24398. // Register a listener to 'mouseover' or touch equivalent for the given node
  24399. // node: Dom
  24400. // Target node to listen to
  24401. // listener: Function
  24402. // Callback function
  24403. // returns:
  24404. // A handle which will be used to remove the listener by handle.remove()
  24405. },
  24406. out: function(node, listener){
  24407. // summary:
  24408. // Register a listener to 'mouseout' or touch equivalent for the given node
  24409. // node: Dom
  24410. // Target node to listen to
  24411. // listener: Function
  24412. // Callback function
  24413. // returns:
  24414. // A handle which will be used to remove the listener by handle.remove()
  24415. },
  24416. enter: function(node, listener){
  24417. // summary:
  24418. // Register a listener to mouse.enter or touch equivalent for the given node
  24419. // node: Dom
  24420. // Target node to listen to
  24421. // listener: Function
  24422. // Callback function
  24423. // returns:
  24424. // A handle which will be used to remove the listener by handle.remove()
  24425. },
  24426. leave: function(node, listener){
  24427. // summary:
  24428. // Register a listener to mouse.leave or touch equivalent for the given node
  24429. // node: Dom
  24430. // Target node to listen to
  24431. // listener: Function
  24432. // Callback function
  24433. // returns:
  24434. // A handle which will be used to remove the listener by handle.remove()
  24435. }
  24436. };
  24437. =====*/
  24438. 1 && (dojo.touch = touch);
  24439. return touch;
  24440. });
  24441. },
  24442. 'dojo/fx':function(){
  24443. define("dojo/fx", [
  24444. "./_base/lang",
  24445. "./Evented",
  24446. "./_base/kernel",
  24447. "./_base/array",
  24448. "./_base/connect",
  24449. "./_base/fx",
  24450. "./dom",
  24451. "./dom-style",
  24452. "./dom-geometry",
  24453. "./ready",
  24454. "require" // for context sensitive loading of Toggler
  24455. ], function(lang, Evented, dojo, arrayUtil, connect, baseFx, dom, domStyle, geom, ready, require) {
  24456. // module:
  24457. // dojo/fx
  24458. // summary:
  24459. // TODOC
  24460. /*=====
  24461. dojo.fx = {
  24462. // summary: Effects library on top of Base animations
  24463. };
  24464. var coreFx = dojo.fx;
  24465. =====*/
  24466. // For back-compat, remove in 2.0.
  24467. if(!dojo.isAsync){
  24468. ready(0, function(){
  24469. var requires = ["./fx/Toggler"];
  24470. require(requires); // use indirection so modules not rolled into a build
  24471. });
  24472. }
  24473. var coreFx = dojo.fx = {};
  24474. var _baseObj = {
  24475. _fire: function(evt, args){
  24476. if(this[evt]){
  24477. this[evt].apply(this, args||[]);
  24478. }
  24479. return this;
  24480. }
  24481. };
  24482. var _chain = function(animations){
  24483. this._index = -1;
  24484. this._animations = animations||[];
  24485. this._current = this._onAnimateCtx = this._onEndCtx = null;
  24486. this.duration = 0;
  24487. arrayUtil.forEach(this._animations, function(a){
  24488. this.duration += a.duration;
  24489. if(a.delay){ this.duration += a.delay; }
  24490. }, this);
  24491. };
  24492. _chain.prototype = new Evented();
  24493. lang.extend(_chain, {
  24494. _onAnimate: function(){
  24495. this._fire("onAnimate", arguments);
  24496. },
  24497. _onEnd: function(){
  24498. connect.disconnect(this._onAnimateCtx);
  24499. connect.disconnect(this._onEndCtx);
  24500. this._onAnimateCtx = this._onEndCtx = null;
  24501. if(this._index + 1 == this._animations.length){
  24502. this._fire("onEnd");
  24503. }else{
  24504. // switch animations
  24505. this._current = this._animations[++this._index];
  24506. this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
  24507. this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
  24508. this._current.play(0, true);
  24509. }
  24510. },
  24511. play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
  24512. if(!this._current){ this._current = this._animations[this._index = 0]; }
  24513. if(!gotoStart && this._current.status() == "playing"){ return this; }
  24514. var beforeBegin = connect.connect(this._current, "beforeBegin", this, function(){
  24515. this._fire("beforeBegin");
  24516. }),
  24517. onBegin = connect.connect(this._current, "onBegin", this, function(arg){
  24518. this._fire("onBegin", arguments);
  24519. }),
  24520. onPlay = connect.connect(this._current, "onPlay", this, function(arg){
  24521. this._fire("onPlay", arguments);
  24522. connect.disconnect(beforeBegin);
  24523. connect.disconnect(onBegin);
  24524. connect.disconnect(onPlay);
  24525. });
  24526. if(this._onAnimateCtx){
  24527. connect.disconnect(this._onAnimateCtx);
  24528. }
  24529. this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
  24530. if(this._onEndCtx){
  24531. connect.disconnect(this._onEndCtx);
  24532. }
  24533. this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
  24534. this._current.play.apply(this._current, arguments);
  24535. return this;
  24536. },
  24537. pause: function(){
  24538. if(this._current){
  24539. var e = connect.connect(this._current, "onPause", this, function(arg){
  24540. this._fire("onPause", arguments);
  24541. connect.disconnect(e);
  24542. });
  24543. this._current.pause();
  24544. }
  24545. return this;
  24546. },
  24547. gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
  24548. this.pause();
  24549. var offset = this.duration * percent;
  24550. this._current = null;
  24551. arrayUtil.some(this._animations, function(a){
  24552. if(a.duration <= offset){
  24553. this._current = a;
  24554. return true;
  24555. }
  24556. offset -= a.duration;
  24557. return false;
  24558. });
  24559. if(this._current){
  24560. this._current.gotoPercent(offset / this._current.duration, andPlay);
  24561. }
  24562. return this;
  24563. },
  24564. stop: function(/*boolean?*/ gotoEnd){
  24565. if(this._current){
  24566. if(gotoEnd){
  24567. for(; this._index + 1 < this._animations.length; ++this._index){
  24568. this._animations[this._index].stop(true);
  24569. }
  24570. this._current = this._animations[this._index];
  24571. }
  24572. var e = connect.connect(this._current, "onStop", this, function(arg){
  24573. this._fire("onStop", arguments);
  24574. connect.disconnect(e);
  24575. });
  24576. this._current.stop();
  24577. }
  24578. return this;
  24579. },
  24580. status: function(){
  24581. return this._current ? this._current.status() : "stopped";
  24582. },
  24583. destroy: function(){
  24584. if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); }
  24585. if(this._onEndCtx){ connect.disconnect(this._onEndCtx); }
  24586. }
  24587. });
  24588. lang.extend(_chain, _baseObj);
  24589. coreFx.chain = /*===== dojo.fx.chain = =====*/ function(/*dojo.Animation[]*/ animations){
  24590. // summary:
  24591. // Chain a list of `dojo.Animation`s to run in sequence
  24592. //
  24593. // description:
  24594. // Return a `dojo.Animation` which will play all passed
  24595. // `dojo.Animation` instances in sequence, firing its own
  24596. // synthesized events simulating a single animation. (eg:
  24597. // onEnd of this animation means the end of the chain,
  24598. // not the individual animations within)
  24599. //
  24600. // example:
  24601. // Once `node` is faded out, fade in `otherNode`
  24602. // | dojo.fx.chain([
  24603. // | dojo.fadeIn({ node:node }),
  24604. // | dojo.fadeOut({ node:otherNode })
  24605. // | ]).play();
  24606. //
  24607. return new _chain(animations); // dojo.Animation
  24608. };
  24609. var _combine = function(animations){
  24610. this._animations = animations||[];
  24611. this._connects = [];
  24612. this._finished = 0;
  24613. this.duration = 0;
  24614. arrayUtil.forEach(animations, function(a){
  24615. var duration = a.duration;
  24616. if(a.delay){ duration += a.delay; }
  24617. if(this.duration < duration){ this.duration = duration; }
  24618. this._connects.push(connect.connect(a, "onEnd", this, "_onEnd"));
  24619. }, this);
  24620. this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration});
  24621. var self = this;
  24622. arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"],
  24623. function(evt){
  24624. self._connects.push(connect.connect(self._pseudoAnimation, evt,
  24625. function(){ self._fire(evt, arguments); }
  24626. ));
  24627. }
  24628. );
  24629. };
  24630. lang.extend(_combine, {
  24631. _doAction: function(action, args){
  24632. arrayUtil.forEach(this._animations, function(a){
  24633. a[action].apply(a, args);
  24634. });
  24635. return this;
  24636. },
  24637. _onEnd: function(){
  24638. if(++this._finished > this._animations.length){
  24639. this._fire("onEnd");
  24640. }
  24641. },
  24642. _call: function(action, args){
  24643. var t = this._pseudoAnimation;
  24644. t[action].apply(t, args);
  24645. },
  24646. play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
  24647. this._finished = 0;
  24648. this._doAction("play", arguments);
  24649. this._call("play", arguments);
  24650. return this;
  24651. },
  24652. pause: function(){
  24653. this._doAction("pause", arguments);
  24654. this._call("pause", arguments);
  24655. return this;
  24656. },
  24657. gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
  24658. var ms = this.duration * percent;
  24659. arrayUtil.forEach(this._animations, function(a){
  24660. a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
  24661. });
  24662. this._call("gotoPercent", arguments);
  24663. return this;
  24664. },
  24665. stop: function(/*boolean?*/ gotoEnd){
  24666. this._doAction("stop", arguments);
  24667. this._call("stop", arguments);
  24668. return this;
  24669. },
  24670. status: function(){
  24671. return this._pseudoAnimation.status();
  24672. },
  24673. destroy: function(){
  24674. arrayUtil.forEach(this._connects, connect.disconnect);
  24675. }
  24676. });
  24677. lang.extend(_combine, _baseObj);
  24678. coreFx.combine = /*===== dojo.fx.combine = =====*/ function(/*dojo.Animation[]*/ animations){
  24679. // summary:
  24680. // Combine a list of `dojo.Animation`s to run in parallel
  24681. //
  24682. // description:
  24683. // Combine an array of `dojo.Animation`s to run in parallel,
  24684. // providing a new `dojo.Animation` instance encompasing each
  24685. // animation, firing standard animation events.
  24686. //
  24687. // example:
  24688. // Fade out `node` while fading in `otherNode` simultaneously
  24689. // | dojo.fx.combine([
  24690. // | dojo.fadeIn({ node:node }),
  24691. // | dojo.fadeOut({ node:otherNode })
  24692. // | ]).play();
  24693. //
  24694. // example:
  24695. // When the longest animation ends, execute a function:
  24696. // | var anim = dojo.fx.combine([
  24697. // | dojo.fadeIn({ node: n, duration:700 }),
  24698. // | dojo.fadeOut({ node: otherNode, duration: 300 })
  24699. // | ]);
  24700. // | dojo.connect(anim, "onEnd", function(){
  24701. // | // overall animation is done.
  24702. // | });
  24703. // | anim.play(); // play the animation
  24704. //
  24705. return new _combine(animations); // dojo.Animation
  24706. };
  24707. coreFx.wipeIn = /*===== dojo.fx.wipeIn = =====*/ function(/*Object*/ args){
  24708. // summary:
  24709. // Expand a node to it's natural height.
  24710. //
  24711. // description:
  24712. // Returns an animation that will expand the
  24713. // node defined in 'args' object from it's current height to
  24714. // it's natural height (with no scrollbar).
  24715. // Node must have no margin/border/padding.
  24716. //
  24717. // args: Object
  24718. // A hash-map of standard `dojo.Animation` constructor properties
  24719. // (such as easing: node: duration: and so on)
  24720. //
  24721. // example:
  24722. // | dojo.fx.wipeIn({
  24723. // | node:"someId"
  24724. // | }).play()
  24725. var node = args.node = dom.byId(args.node), s = node.style, o;
  24726. var anim = baseFx.animateProperty(lang.mixin({
  24727. properties: {
  24728. height: {
  24729. // wrapped in functions so we wait till the last second to query (in case value has changed)
  24730. start: function(){
  24731. // start at current [computed] height, but use 1px rather than 0
  24732. // because 0 causes IE to display the whole panel
  24733. o = s.overflow;
  24734. s.overflow = "hidden";
  24735. if(s.visibility == "hidden" || s.display == "none"){
  24736. s.height = "1px";
  24737. s.display = "";
  24738. s.visibility = "";
  24739. return 1;
  24740. }else{
  24741. var height = domStyle.get(node, "height");
  24742. return Math.max(height, 1);
  24743. }
  24744. },
  24745. end: function(){
  24746. return node.scrollHeight;
  24747. }
  24748. }
  24749. }
  24750. }, args));
  24751. var fini = function(){
  24752. s.height = "auto";
  24753. s.overflow = o;
  24754. };
  24755. connect.connect(anim, "onStop", fini);
  24756. connect.connect(anim, "onEnd", fini);
  24757. return anim; // dojo.Animation
  24758. };
  24759. coreFx.wipeOut = /*===== dojo.fx.wipeOut = =====*/ function(/*Object*/ args){
  24760. // summary:
  24761. // Shrink a node to nothing and hide it.
  24762. //
  24763. // description:
  24764. // Returns an animation that will shrink node defined in "args"
  24765. // from it's current height to 1px, and then hide it.
  24766. //
  24767. // args: Object
  24768. // A hash-map of standard `dojo.Animation` constructor properties
  24769. // (such as easing: node: duration: and so on)
  24770. //
  24771. // example:
  24772. // | dojo.fx.wipeOut({ node:"someId" }).play()
  24773. var node = args.node = dom.byId(args.node), s = node.style, o;
  24774. var anim = baseFx.animateProperty(lang.mixin({
  24775. properties: {
  24776. height: {
  24777. end: 1 // 0 causes IE to display the whole panel
  24778. }
  24779. }
  24780. }, args));
  24781. connect.connect(anim, "beforeBegin", function(){
  24782. o = s.overflow;
  24783. s.overflow = "hidden";
  24784. s.display = "";
  24785. });
  24786. var fini = function(){
  24787. s.overflow = o;
  24788. s.height = "auto";
  24789. s.display = "none";
  24790. };
  24791. connect.connect(anim, "onStop", fini);
  24792. connect.connect(anim, "onEnd", fini);
  24793. return anim; // dojo.Animation
  24794. };
  24795. coreFx.slideTo = /*===== dojo.fx.slideTo = =====*/ function(/*Object*/ args){
  24796. // summary:
  24797. // Slide a node to a new top/left position
  24798. //
  24799. // description:
  24800. // Returns an animation that will slide "node"
  24801. // defined in args Object from its current position to
  24802. // the position defined by (args.left, args.top).
  24803. //
  24804. // args: Object
  24805. // A hash-map of standard `dojo.Animation` constructor properties
  24806. // (such as easing: node: duration: and so on). Special args members
  24807. // are `top` and `left`, which indicate the new position to slide to.
  24808. //
  24809. // example:
  24810. // | .slideTo({ node: node, left:"40", top:"50", units:"px" }).play()
  24811. var node = args.node = dom.byId(args.node),
  24812. top = null, left = null;
  24813. var init = (function(n){
  24814. return function(){
  24815. var cs = domStyle.getComputedStyle(n);
  24816. var pos = cs.position;
  24817. top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
  24818. left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
  24819. if(pos != 'absolute' && pos != 'relative'){
  24820. var ret = geom.position(n, true);
  24821. top = ret.y;
  24822. left = ret.x;
  24823. n.style.position="absolute";
  24824. n.style.top=top+"px";
  24825. n.style.left=left+"px";
  24826. }
  24827. };
  24828. })(node);
  24829. init();
  24830. var anim = baseFx.animateProperty(lang.mixin({
  24831. properties: {
  24832. top: args.top || 0,
  24833. left: args.left || 0
  24834. }
  24835. }, args));
  24836. connect.connect(anim, "beforeBegin", anim, init);
  24837. return anim; // dojo.Animation
  24838. };
  24839. return coreFx;
  24840. });
  24841. },
  24842. 'dijit/_DialogMixin':function(){
  24843. define("dijit/_DialogMixin", [
  24844. "dojo/_base/declare", // declare
  24845. "./a11y" // _getTabNavigable
  24846. ], function(declare, a11y){
  24847. // module:
  24848. // dijit/_DialogMixin
  24849. // summary:
  24850. // _DialogMixin provides functions useful to Dialog and TooltipDialog
  24851. return declare("dijit._DialogMixin", null, {
  24852. // summary:
  24853. // This provides functions useful to Dialog and TooltipDialog
  24854. execute: function(/*Object*/ /*===== formContents =====*/){
  24855. // summary:
  24856. // Callback when the user hits the submit button.
  24857. // Override this method to handle Dialog execution.
  24858. // description:
  24859. // After the user has pressed the submit button, the Dialog
  24860. // first calls onExecute() to notify the container to hide the
  24861. // dialog and restore focus to wherever it used to be.
  24862. //
  24863. // *Then* this method is called.
  24864. // type:
  24865. // callback
  24866. },
  24867. onCancel: function(){
  24868. // summary:
  24869. // Called when user has pressed the Dialog's cancel button, to notify container.
  24870. // description:
  24871. // Developer shouldn't override or connect to this method;
  24872. // it's a private communication device between the TooltipDialog
  24873. // and the thing that opened it (ex: `dijit.form.DropDownButton`)
  24874. // type:
  24875. // protected
  24876. },
  24877. onExecute: function(){
  24878. // summary:
  24879. // Called when user has pressed the dialog's OK button, to notify container.
  24880. // description:
  24881. // Developer shouldn't override or connect to this method;
  24882. // it's a private communication device between the TooltipDialog
  24883. // and the thing that opened it (ex: `dijit.form.DropDownButton`)
  24884. // type:
  24885. // protected
  24886. },
  24887. _onSubmit: function(){
  24888. // summary:
  24889. // Callback when user hits submit button
  24890. // type:
  24891. // protected
  24892. this.onExecute(); // notify container that we are about to execute
  24893. this.execute(this.get('value'));
  24894. },
  24895. _getFocusItems: function(){
  24896. // summary:
  24897. // Finds focusable items in dialog,
  24898. // and sets this._firstFocusItem and this._lastFocusItem
  24899. // tags:
  24900. // protected
  24901. var elems = a11y._getTabNavigable(this.containerNode);
  24902. this._firstFocusItem = elems.lowest || elems.first || this.closeButtonNode || this.domNode;
  24903. this._lastFocusItem = elems.last || elems.highest || this._firstFocusItem;
  24904. }
  24905. });
  24906. });
  24907. },
  24908. 'dijit/Tree':function(){
  24909. require({cache:{
  24910. 'url:dijit/templates/TreeNode.html':"<div class=\"dijitTreeNode\" role=\"presentation\"\n\t><div data-dojo-attach-point=\"rowNode\" class=\"dijitTreeRow\" role=\"presentation\" data-dojo-attach-event=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick\"\n\t\t><img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"expandoNode\" class=\"dijitTreeExpando\" role=\"presentation\"\n\t\t/><span data-dojo-attach-point=\"expandoNodeText\" class=\"dijitExpandoText\" role=\"presentation\"\n\t\t></span\n\t\t><span data-dojo-attach-point=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" role=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"labelNode\" class=\"dijitTreeLabel\" role=\"treeitem\" tabindex=\"-1\" aria-selected=\"false\" data-dojo-attach-event=\"onfocus:_onLabelFocus\"></span>\n\t\t</span\n\t></div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitTreeContainer\" role=\"presentation\" style=\"display: none;\"></div>\n</div>\n",
  24911. 'url:dijit/templates/Tree.html':"<div class=\"dijitTree dijitTreeContainer\" role=\"tree\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" data-dojo-attach-point=\"indentDetector\"></div>\n</div>\n"}});
  24912. define("dijit/Tree", [
  24913. "dojo/_base/array", // array.filter array.forEach array.map
  24914. "dojo/_base/connect", // connect.isCopyKey()
  24915. "dojo/cookie", // cookie
  24916. "dojo/_base/declare", // declare
  24917. "dojo/_base/Deferred", // Deferred
  24918. "dojo/DeferredList", // DeferredList
  24919. "dojo/dom", // dom.isDescendant
  24920. "dojo/dom-class", // domClass.add domClass.remove domClass.replace domClass.toggle
  24921. "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.position
  24922. "dojo/dom-style",// domStyle.set
  24923. "dojo/_base/event", // event.stop
  24924. "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut
  24925. "dojo/_base/kernel", // kernel.deprecated
  24926. "dojo/keys", // arrows etc.
  24927. "dojo/_base/lang", // lang.getObject lang.mixin lang.hitch
  24928. "dojo/on",
  24929. "dojo/topic",
  24930. "./focus",
  24931. "./registry", // registry.getEnclosingWidget(), manager.defaultDuration
  24932. "./_base/manager", // manager.getEnclosingWidget(), manager.defaultDuration
  24933. "./_Widget",
  24934. "./_TemplatedMixin",
  24935. "./_Container",
  24936. "./_Contained",
  24937. "./_CssStateMixin",
  24938. "dojo/text!./templates/TreeNode.html",
  24939. "dojo/text!./templates/Tree.html",
  24940. "./tree/TreeStoreModel",
  24941. "./tree/ForestStoreModel",
  24942. "./tree/_dndSelector"
  24943. ], function(array, connect, cookie, declare, Deferred, DeferredList,
  24944. dom, domClass, domGeometry, domStyle, event, fxUtils, kernel, keys, lang, on, topic,
  24945. focus, registry, manager, _Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin,
  24946. treeNodeTemplate, treeTemplate, TreeStoreModel, ForestStoreModel, _dndSelector){
  24947. /*=====
  24948. var _Widget = dijit._Widget;
  24949. var _TemplatedMixin = dijit._TemplatedMixin;
  24950. var _CssStateMixin = dijit._CssStateMixin;
  24951. var _Container = dijit._Container;
  24952. var _Contained = dijit._Contained;
  24953. =====*/
  24954. // module:
  24955. // dijit/Tree
  24956. // summary:
  24957. // dijit.Tree widget, and internal dijit._TreeNode widget
  24958. var TreeNode = declare(
  24959. "dijit._TreeNode",
  24960. [_Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin],
  24961. {
  24962. // summary:
  24963. // Single node within a tree. This class is used internally
  24964. // by Tree and should not be accessed directly.
  24965. // tags:
  24966. // private
  24967. // item: [const] Item
  24968. // the dojo.data entry this tree represents
  24969. item: null,
  24970. // isTreeNode: [protected] Boolean
  24971. // Indicates that this is a TreeNode. Used by `dijit.Tree` only,
  24972. // should not be accessed directly.
  24973. isTreeNode: true,
  24974. // label: String
  24975. // Text of this tree node
  24976. label: "",
  24977. _setLabelAttr: {node: "labelNode", type: "innerText"},
  24978. // isExpandable: [private] Boolean
  24979. // This node has children, so show the expando node (+ sign)
  24980. isExpandable: null,
  24981. // isExpanded: [readonly] Boolean
  24982. // This node is currently expanded (ie, opened)
  24983. isExpanded: false,
  24984. // state: [private] String
  24985. // Dynamic loading-related stuff.
  24986. // When an empty folder node appears, it is "UNCHECKED" first,
  24987. // then after dojo.data query it becomes "LOADING" and, finally "LOADED"
  24988. state: "UNCHECKED",
  24989. templateString: treeNodeTemplate,
  24990. baseClass: "dijitTreeNode",
  24991. // For hover effect for tree node, and focus effect for label
  24992. cssStateNodes: {
  24993. rowNode: "dijitTreeRow",
  24994. labelNode: "dijitTreeLabel"
  24995. },
  24996. // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here
  24997. _setTooltipAttr: {node: "rowNode", type: "attribute", attribute: "title"},
  24998. buildRendering: function(){
  24999. this.inherited(arguments);
  25000. // set expand icon for leaf
  25001. this._setExpando();
  25002. // set icon and label class based on item
  25003. this._updateItemClasses(this.item);
  25004. if(this.isExpandable){
  25005. this.labelNode.setAttribute("aria-expanded", this.isExpanded);
  25006. }
  25007. //aria-selected should be false on all selectable elements.
  25008. this.setSelected(false);
  25009. },
  25010. _setIndentAttr: function(indent){
  25011. // summary:
  25012. // Tell this node how many levels it should be indented
  25013. // description:
  25014. // 0 for top level nodes, 1 for their children, 2 for their
  25015. // grandchildren, etc.
  25016. // Math.max() is to prevent negative padding on hidden root node (when indent == -1)
  25017. var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px";
  25018. domStyle.set(this.domNode, "backgroundPosition", pixels + " 0px");
  25019. domStyle.set(this.rowNode, this.isLeftToRight() ? "paddingLeft" : "paddingRight", pixels);
  25020. array.forEach(this.getChildren(), function(child){
  25021. child.set("indent", indent+1);
  25022. });
  25023. this._set("indent", indent);
  25024. },
  25025. markProcessing: function(){
  25026. // summary:
  25027. // Visually denote that tree is loading data, etc.
  25028. // tags:
  25029. // private
  25030. this.state = "LOADING";
  25031. this._setExpando(true);
  25032. },
  25033. unmarkProcessing: function(){
  25034. // summary:
  25035. // Clear markup from markProcessing() call
  25036. // tags:
  25037. // private
  25038. this._setExpando(false);
  25039. },
  25040. _updateItemClasses: function(item){
  25041. // summary:
  25042. // Set appropriate CSS classes for icon and label dom node
  25043. // (used to allow for item updates to change respective CSS)
  25044. // tags:
  25045. // private
  25046. var tree = this.tree, model = tree.model;
  25047. if(tree._v10Compat && item === model.root){
  25048. // For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0)
  25049. item = null;
  25050. }
  25051. this._applyClassAndStyle(item, "icon", "Icon");
  25052. this._applyClassAndStyle(item, "label", "Label");
  25053. this._applyClassAndStyle(item, "row", "Row");
  25054. },
  25055. _applyClassAndStyle: function(item, lower, upper){
  25056. // summary:
  25057. // Set the appropriate CSS classes and styles for labels, icons and rows.
  25058. //
  25059. // item:
  25060. // The data item.
  25061. //
  25062. // lower:
  25063. // The lower case attribute to use, e.g. 'icon', 'label' or 'row'.
  25064. //
  25065. // upper:
  25066. // The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'.
  25067. //
  25068. // tags:
  25069. // private
  25070. var clsName = "_" + lower + "Class";
  25071. var nodeName = lower + "Node";
  25072. var oldCls = this[clsName];
  25073. this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded);
  25074. domClass.replace(this[nodeName], this[clsName] || "", oldCls || "");
  25075. domStyle.set(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {});
  25076. },
  25077. _updateLayout: function(){
  25078. // summary:
  25079. // Set appropriate CSS classes for this.domNode
  25080. // tags:
  25081. // private
  25082. var parent = this.getParent();
  25083. if(!parent || !parent.rowNode || parent.rowNode.style.display == "none"){
  25084. /* if we are hiding the root node then make every first level child look like a root node */
  25085. domClass.add(this.domNode, "dijitTreeIsRoot");
  25086. }else{
  25087. domClass.toggle(this.domNode, "dijitTreeIsLast", !this.getNextSibling());
  25088. }
  25089. },
  25090. _setExpando: function(/*Boolean*/ processing){
  25091. // summary:
  25092. // Set the right image for the expando node
  25093. // tags:
  25094. // private
  25095. var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened",
  25096. "dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"],
  25097. _a11yStates = ["*","-","+","*"],
  25098. idx = processing ? 0 : (this.isExpandable ? (this.isExpanded ? 1 : 2) : 3);
  25099. // apply the appropriate class to the expando node
  25100. domClass.replace(this.expandoNode, styles[idx], styles);
  25101. // provide a non-image based indicator for images-off mode
  25102. this.expandoNodeText.innerHTML = _a11yStates[idx];
  25103. },
  25104. expand: function(){
  25105. // summary:
  25106. // Show my children
  25107. // returns:
  25108. // Deferred that fires when expansion is complete
  25109. // If there's already an expand in progress or we are already expanded, just return
  25110. if(this._expandDeferred){
  25111. return this._expandDeferred; // dojo.Deferred
  25112. }
  25113. // cancel in progress collapse operation
  25114. this._wipeOut && this._wipeOut.stop();
  25115. // All the state information for when a node is expanded, maybe this should be
  25116. // set when the animation completes instead
  25117. this.isExpanded = true;
  25118. this.labelNode.setAttribute("aria-expanded", "true");
  25119. if(this.tree.showRoot || this !== this.tree.rootNode){
  25120. this.containerNode.setAttribute("role", "group");
  25121. }
  25122. domClass.add(this.contentNode,'dijitTreeContentExpanded');
  25123. this._setExpando();
  25124. this._updateItemClasses(this.item);
  25125. if(this == this.tree.rootNode){
  25126. this.tree.domNode.setAttribute("aria-expanded", "true");
  25127. }
  25128. var def,
  25129. wipeIn = fxUtils.wipeIn({
  25130. node: this.containerNode, duration: manager.defaultDuration,
  25131. onEnd: function(){
  25132. def.callback(true);
  25133. }
  25134. });
  25135. // Deferred that fires when expand is complete
  25136. def = (this._expandDeferred = new Deferred(function(){
  25137. // Canceller
  25138. wipeIn.stop();
  25139. }));
  25140. wipeIn.play();
  25141. return def; // dojo.Deferred
  25142. },
  25143. collapse: function(){
  25144. // summary:
  25145. // Collapse this node (if it's expanded)
  25146. if(!this.isExpanded){ return; }
  25147. // cancel in progress expand operation
  25148. if(this._expandDeferred){
  25149. this._expandDeferred.cancel();
  25150. delete this._expandDeferred;
  25151. }
  25152. this.isExpanded = false;
  25153. this.labelNode.setAttribute("aria-expanded", "false");
  25154. if(this == this.tree.rootNode){
  25155. this.tree.domNode.setAttribute("aria-expanded", "false");
  25156. }
  25157. domClass.remove(this.contentNode,'dijitTreeContentExpanded');
  25158. this._setExpando();
  25159. this._updateItemClasses(this.item);
  25160. if(!this._wipeOut){
  25161. this._wipeOut = fxUtils.wipeOut({
  25162. node: this.containerNode, duration: manager.defaultDuration
  25163. });
  25164. }
  25165. this._wipeOut.play();
  25166. },
  25167. // indent: Integer
  25168. // Levels from this node to the root node
  25169. indent: 0,
  25170. setChildItems: function(/* Object[] */ items){
  25171. // summary:
  25172. // Sets the child items of this node, removing/adding nodes
  25173. // from current children to match specified items[] array.
  25174. // Also, if this.persist == true, expands any children that were previously
  25175. // opened.
  25176. // returns:
  25177. // Deferred object that fires after all previously opened children
  25178. // have been expanded again (or fires instantly if there are no such children).
  25179. var tree = this.tree,
  25180. model = tree.model,
  25181. defs = []; // list of deferreds that need to fire before I am complete
  25182. // Orphan all my existing children.
  25183. // If items contains some of the same items as before then we will reattach them.
  25184. // Don't call this.removeChild() because that will collapse the tree etc.
  25185. array.forEach(this.getChildren(), function(child){
  25186. _Container.prototype.removeChild.call(this, child);
  25187. }, this);
  25188. this.state = "LOADED";
  25189. if(items && items.length > 0){
  25190. this.isExpandable = true;
  25191. // Create _TreeNode widget for each specified tree node, unless one already
  25192. // exists and isn't being used (presumably it's from a DnD move and was recently
  25193. // released
  25194. array.forEach(items, function(item){
  25195. var id = model.getIdentity(item),
  25196. existingNodes = tree._itemNodesMap[id],
  25197. node;
  25198. if(existingNodes){
  25199. for(var i=0;i<existingNodes.length;i++){
  25200. if(existingNodes[i] && !existingNodes[i].getParent()){
  25201. node = existingNodes[i];
  25202. node.set('indent', this.indent+1);
  25203. break;
  25204. }
  25205. }
  25206. }
  25207. if(!node){
  25208. node = this.tree._createTreeNode({
  25209. item: item,
  25210. tree: tree,
  25211. isExpandable: model.mayHaveChildren(item),
  25212. label: tree.getLabel(item),
  25213. tooltip: tree.getTooltip(item),
  25214. dir: tree.dir,
  25215. lang: tree.lang,
  25216. textDir: tree.textDir,
  25217. indent: this.indent + 1
  25218. });
  25219. if(existingNodes){
  25220. existingNodes.push(node);
  25221. }else{
  25222. tree._itemNodesMap[id] = [node];
  25223. }
  25224. }
  25225. this.addChild(node);
  25226. // If node was previously opened then open it again now (this may trigger
  25227. // more data store accesses, recursively)
  25228. if(this.tree.autoExpand || this.tree._state(node)){
  25229. defs.push(tree._expandNode(node));
  25230. }
  25231. }, this);
  25232. // note that updateLayout() needs to be called on each child after
  25233. // _all_ the children exist
  25234. array.forEach(this.getChildren(), function(child){
  25235. child._updateLayout();
  25236. });
  25237. }else{
  25238. this.isExpandable=false;
  25239. }
  25240. if(this._setExpando){
  25241. // change expando to/from dot or + icon, as appropriate
  25242. this._setExpando(false);
  25243. }
  25244. // Set leaf icon or folder icon, as appropriate
  25245. this._updateItemClasses(this.item);
  25246. // On initial tree show, make the selected TreeNode as either the root node of the tree,
  25247. // or the first child, if the root node is hidden
  25248. if(this == tree.rootNode){
  25249. var fc = this.tree.showRoot ? this : this.getChildren()[0];
  25250. if(fc){
  25251. fc.setFocusable(true);
  25252. tree.lastFocused = fc;
  25253. }else{
  25254. // fallback: no nodes in tree so focus on Tree <div> itself
  25255. tree.domNode.setAttribute("tabIndex", "0");
  25256. }
  25257. }
  25258. return new DeferredList(defs); // dojo.Deferred
  25259. },
  25260. getTreePath: function(){
  25261. var node = this;
  25262. var path = [];
  25263. while(node && node !== this.tree.rootNode){
  25264. path.unshift(node.item);
  25265. node = node.getParent();
  25266. }
  25267. path.unshift(this.tree.rootNode.item);
  25268. return path;
  25269. },
  25270. getIdentity: function(){
  25271. return this.tree.model.getIdentity(this.item);
  25272. },
  25273. removeChild: function(/* treeNode */ node){
  25274. this.inherited(arguments);
  25275. var children = this.getChildren();
  25276. if(children.length == 0){
  25277. this.isExpandable = false;
  25278. this.collapse();
  25279. }
  25280. array.forEach(children, function(child){
  25281. child._updateLayout();
  25282. });
  25283. },
  25284. makeExpandable: function(){
  25285. // summary:
  25286. // if this node wasn't already showing the expando node,
  25287. // turn it into one and call _setExpando()
  25288. // TODO: hmm this isn't called from anywhere, maybe should remove it for 2.0
  25289. this.isExpandable = true;
  25290. this._setExpando(false);
  25291. },
  25292. _onLabelFocus: function(){
  25293. // summary:
  25294. // Called when this row is focused (possibly programatically)
  25295. // Note that we aren't using _onFocus() builtin to dijit
  25296. // because it's called when focus is moved to a descendant TreeNode.
  25297. // tags:
  25298. // private
  25299. this.tree._onNodeFocus(this);
  25300. },
  25301. setSelected: function(/*Boolean*/ selected){
  25302. // summary:
  25303. // A Tree has a (single) currently selected node.
  25304. // Mark that this node is/isn't that currently selected node.
  25305. // description:
  25306. // In particular, setting a node as selected involves setting tabIndex
  25307. // so that when user tabs to the tree, focus will go to that node (only).
  25308. this.labelNode.setAttribute("aria-selected", selected);
  25309. domClass.toggle(this.rowNode, "dijitTreeRowSelected", selected);
  25310. },
  25311. setFocusable: function(/*Boolean*/ selected){
  25312. // summary:
  25313. // A Tree has a (single) node that's focusable.
  25314. // Mark that this node is/isn't that currently focsuable node.
  25315. // description:
  25316. // In particular, setting a node as selected involves setting tabIndex
  25317. // so that when user tabs to the tree, focus will go to that node (only).
  25318. this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
  25319. },
  25320. _onClick: function(evt){
  25321. // summary:
  25322. // Handler for onclick event on a node
  25323. // tags:
  25324. // private
  25325. this.tree._onClick(this, evt);
  25326. },
  25327. _onDblClick: function(evt){
  25328. // summary:
  25329. // Handler for ondblclick event on a node
  25330. // tags:
  25331. // private
  25332. this.tree._onDblClick(this, evt);
  25333. },
  25334. _onMouseEnter: function(evt){
  25335. // summary:
  25336. // Handler for onmouseenter event on a node
  25337. // tags:
  25338. // private
  25339. this.tree._onNodeMouseEnter(this, evt);
  25340. },
  25341. _onMouseLeave: function(evt){
  25342. // summary:
  25343. // Handler for onmouseenter event on a node
  25344. // tags:
  25345. // private
  25346. this.tree._onNodeMouseLeave(this, evt);
  25347. },
  25348. _setTextDirAttr: function(textDir){
  25349. if(textDir &&((this.textDir != textDir) || !this._created)){
  25350. this._set("textDir", textDir);
  25351. this.applyTextDir(this.labelNode, this.labelNode.innerText || this.labelNode.textContent || "");
  25352. array.forEach(this.getChildren(), function(childNode){
  25353. childNode.set("textDir", textDir);
  25354. }, this);
  25355. }
  25356. }
  25357. });
  25358. var Tree = declare("dijit.Tree", [_Widget, _TemplatedMixin], {
  25359. // summary:
  25360. // This widget displays hierarchical data from a store.
  25361. // store: [deprecated] String||dojo.data.Store
  25362. // Deprecated. Use "model" parameter instead.
  25363. // The store to get data to display in the tree.
  25364. store: null,
  25365. // model: dijit.Tree.model
  25366. // Interface to read tree data, get notifications of changes to tree data,
  25367. // and for handling drop operations (i.e drag and drop onto the tree)
  25368. model: null,
  25369. // query: [deprecated] anything
  25370. // Deprecated. User should specify query to the model directly instead.
  25371. // Specifies datastore query to return the root item or top items for the tree.
  25372. query: null,
  25373. // label: [deprecated] String
  25374. // Deprecated. Use dijit.tree.ForestStoreModel directly instead.
  25375. // Used in conjunction with query parameter.
  25376. // If a query is specified (rather than a root node id), and a label is also specified,
  25377. // then a fake root node is created and displayed, with this label.
  25378. label: "",
  25379. // showRoot: [const] Boolean
  25380. // Should the root node be displayed, or hidden?
  25381. showRoot: true,
  25382. // childrenAttr: [deprecated] String[]
  25383. // Deprecated. This information should be specified in the model.
  25384. // One ore more attributes that holds children of a tree node
  25385. childrenAttr: ["children"],
  25386. // paths: String[][] or Item[][]
  25387. // Full paths from rootNode to selected nodes expressed as array of items or array of ids.
  25388. // Since setting the paths may be asynchronous (because ofwaiting on dojo.data), set("paths", ...)
  25389. // returns a Deferred to indicate when the set is complete.
  25390. paths: [],
  25391. // path: String[] or Item[]
  25392. // Backward compatible singular variant of paths.
  25393. path: [],
  25394. // selectedItems: [readonly] Item[]
  25395. // The currently selected items in this tree.
  25396. // This property can only be set (via set('selectedItems', ...)) when that item is already
  25397. // visible in the tree. (I.e. the tree has already been expanded to show that node.)
  25398. // Should generally use `paths` attribute to set the selected items instead.
  25399. selectedItems: null,
  25400. // selectedItem: [readonly] Item
  25401. // Backward compatible singular variant of selectedItems.
  25402. selectedItem: null,
  25403. // openOnClick: Boolean
  25404. // If true, clicking a folder node's label will open it, rather than calling onClick()
  25405. openOnClick: false,
  25406. // openOnDblClick: Boolean
  25407. // If true, double-clicking a folder node's label will open it, rather than calling onDblClick()
  25408. openOnDblClick: false,
  25409. templateString: treeTemplate,
  25410. // persist: Boolean
  25411. // Enables/disables use of cookies for state saving.
  25412. persist: true,
  25413. // autoExpand: Boolean
  25414. // Fully expand the tree on load. Overrides `persist`.
  25415. autoExpand: false,
  25416. // dndController: [protected] Function|String
  25417. // Class to use as as the dnd controller. Specifying this class enables DnD.
  25418. // Generally you should specify this as dijit.tree.dndSource.
  25419. // Setting of dijit.tree._dndSelector handles selection only (no actual DnD).
  25420. dndController: _dndSelector,
  25421. // parameters to pull off of the tree and pass on to the dndController as its params
  25422. dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold"],
  25423. //declare the above items so they can be pulled from the tree's markup
  25424. // onDndDrop: [protected] Function
  25425. // Parameter to dndController, see `dijit.tree.dndSource.onDndDrop`.
  25426. // Generally this doesn't need to be set.
  25427. onDndDrop: null,
  25428. /*=====
  25429. itemCreator: function(nodes, target, source){
  25430. // summary:
  25431. // Returns objects passed to `Tree.model.newItem()` based on DnD nodes
  25432. // dropped onto the tree. Developer must override this method to enable
  25433. // dropping from external sources onto this Tree, unless the Tree.model's items
  25434. // happen to look like {id: 123, name: "Apple" } with no other attributes.
  25435. // description:
  25436. // For each node in nodes[], which came from source, create a hash of name/value
  25437. // pairs to be passed to Tree.model.newItem(). Returns array of those hashes.
  25438. // nodes: DomNode[]
  25439. // The DOMNodes dragged from the source container
  25440. // target: DomNode
  25441. // The target TreeNode.rowNode
  25442. // source: dojo.dnd.Source
  25443. // The source container the nodes were dragged from, perhaps another Tree or a plain dojo.dnd.Source
  25444. // returns: Object[]
  25445. // Array of name/value hashes for each new item to be added to the Tree, like:
  25446. // | [
  25447. // | { id: 123, label: "apple", foo: "bar" },
  25448. // | { id: 456, label: "pear", zaz: "bam" }
  25449. // | ]
  25450. // tags:
  25451. // extension
  25452. return [{}];
  25453. },
  25454. =====*/
  25455. itemCreator: null,
  25456. // onDndCancel: [protected] Function
  25457. // Parameter to dndController, see `dijit.tree.dndSource.onDndCancel`.
  25458. // Generally this doesn't need to be set.
  25459. onDndCancel: null,
  25460. /*=====
  25461. checkAcceptance: function(source, nodes){
  25462. // summary:
  25463. // Checks if the Tree itself can accept nodes from this source
  25464. // source: dijit.tree._dndSource
  25465. // The source which provides items
  25466. // nodes: DOMNode[]
  25467. // Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
  25468. // source is a dijit.Tree.
  25469. // tags:
  25470. // extension
  25471. return true; // Boolean
  25472. },
  25473. =====*/
  25474. checkAcceptance: null,
  25475. /*=====
  25476. checkItemAcceptance: function(target, source, position){
  25477. // summary:
  25478. // Stub function to be overridden if one wants to check for the ability to drop at the node/item level
  25479. // description:
  25480. // In the base case, this is called to check if target can become a child of source.
  25481. // When betweenThreshold is set, position="before" or "after" means that we
  25482. // are asking if the source node can be dropped before/after the target node.
  25483. // target: DOMNode
  25484. // The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
  25485. // Use dijit.getEnclosingWidget(target) to get the TreeNode.
  25486. // source: dijit.tree.dndSource
  25487. // The (set of) nodes we are dropping
  25488. // position: String
  25489. // "over", "before", or "after"
  25490. // tags:
  25491. // extension
  25492. return true; // Boolean
  25493. },
  25494. =====*/
  25495. checkItemAcceptance: null,
  25496. // dragThreshold: Integer
  25497. // Number of pixels mouse moves before it's considered the start of a drag operation
  25498. dragThreshold: 5,
  25499. // betweenThreshold: Integer
  25500. // Set to a positive value to allow drag and drop "between" nodes.
  25501. //
  25502. // If during DnD mouse is over a (target) node but less than betweenThreshold
  25503. // pixels from the bottom edge, dropping the the dragged node will make it
  25504. // the next sibling of the target node, rather than the child.
  25505. //
  25506. // Similarly, if mouse is over a target node but less that betweenThreshold
  25507. // pixels from the top edge, dropping the dragged node will make it
  25508. // the target node's previous sibling rather than the target node's child.
  25509. betweenThreshold: 0,
  25510. // _nodePixelIndent: Integer
  25511. // Number of pixels to indent tree nodes (relative to parent node).
  25512. // Default is 19 but can be overridden by setting CSS class dijitTreeIndent
  25513. // and calling resize() or startup() on tree after it's in the DOM.
  25514. _nodePixelIndent: 19,
  25515. _publish: function(/*String*/ topicName, /*Object*/ message){
  25516. // summary:
  25517. // Publish a message for this widget/topic
  25518. topic.publish(this.id, lang.mixin({tree: this, event: topicName}, message || {})); // publish
  25519. },
  25520. postMixInProperties: function(){
  25521. this.tree = this;
  25522. if(this.autoExpand){
  25523. // There's little point in saving opened/closed state of nodes for a Tree
  25524. // that initially opens all it's nodes.
  25525. this.persist = false;
  25526. }
  25527. this._itemNodesMap={};
  25528. if(!this.cookieName && this.id){
  25529. this.cookieName = this.id + "SaveStateCookie";
  25530. }
  25531. this._loadDeferred = new Deferred();
  25532. this.inherited(arguments);
  25533. },
  25534. postCreate: function(){
  25535. this._initState();
  25536. // Catch events on TreeNodes
  25537. var self = this;
  25538. this._connects.push(
  25539. on(this.domNode, on.selector(".dijitTreeNode", "keypress"), function(evt){
  25540. self._onKeyPress(registry.byNode(this), evt);
  25541. }),
  25542. on(this.domNode, on.selector(".dijitTreeNode", "keydown"), function(evt){
  25543. self._onKeyDown(registry.byNode(this), evt);
  25544. })
  25545. );
  25546. // Create glue between store and Tree, if not specified directly by user
  25547. if(!this.model){
  25548. this._store2model();
  25549. }
  25550. // monitor changes to items
  25551. this.connect(this.model, "onChange", "_onItemChange");
  25552. this.connect(this.model, "onChildrenChange", "_onItemChildrenChange");
  25553. this.connect(this.model, "onDelete", "_onItemDelete");
  25554. this._load();
  25555. this.inherited(arguments);
  25556. if(this.dndController){
  25557. if(lang.isString(this.dndController)){
  25558. this.dndController = lang.getObject(this.dndController);
  25559. }
  25560. var params={};
  25561. for(var i=0; i<this.dndParams.length;i++){
  25562. if(this[this.dndParams[i]]){
  25563. params[this.dndParams[i]] = this[this.dndParams[i]];
  25564. }
  25565. }
  25566. this.dndController = new this.dndController(this, params);
  25567. }
  25568. },
  25569. _store2model: function(){
  25570. // summary:
  25571. // User specified a store&query rather than model, so create model from store/query
  25572. this._v10Compat = true;
  25573. kernel.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query");
  25574. var modelParams = {
  25575. id: this.id + "_ForestStoreModel",
  25576. store: this.store,
  25577. query: this.query,
  25578. childrenAttrs: this.childrenAttr
  25579. };
  25580. // Only override the model's mayHaveChildren() method if the user has specified an override
  25581. if(this.params.mayHaveChildren){
  25582. modelParams.mayHaveChildren = lang.hitch(this, "mayHaveChildren");
  25583. }
  25584. if(this.params.getItemChildren){
  25585. modelParams.getChildren = lang.hitch(this, function(item, onComplete, onError){
  25586. this.getItemChildren((this._v10Compat && item === this.model.root) ? null : item, onComplete, onError);
  25587. });
  25588. }
  25589. this.model = new ForestStoreModel(modelParams);
  25590. // For backwards compatibility, the visibility of the root node is controlled by
  25591. // whether or not the user has specified a label
  25592. this.showRoot = Boolean(this.label);
  25593. },
  25594. onLoad: function(){
  25595. // summary:
  25596. // Called when tree finishes loading and expanding.
  25597. // description:
  25598. // If persist == true the loading may encompass many levels of fetches
  25599. // from the data store, each asynchronous. Waits for all to finish.
  25600. // tags:
  25601. // callback
  25602. },
  25603. _load: function(){
  25604. // summary:
  25605. // Initial load of the tree.
  25606. // Load root node (possibly hidden) and it's children.
  25607. this.model.getRoot(
  25608. lang.hitch(this, function(item){
  25609. var rn = (this.rootNode = this.tree._createTreeNode({
  25610. item: item,
  25611. tree: this,
  25612. isExpandable: true,
  25613. label: this.label || this.getLabel(item),
  25614. textDir: this.textDir,
  25615. indent: this.showRoot ? 0 : -1
  25616. }));
  25617. if(!this.showRoot){
  25618. rn.rowNode.style.display="none";
  25619. // if root is not visible, move tree role to the invisible
  25620. // root node's containerNode, see #12135
  25621. this.domNode.setAttribute("role", "presentation");
  25622. rn.labelNode.setAttribute("role", "presentation");
  25623. rn.containerNode.setAttribute("role", "tree");
  25624. }
  25625. this.domNode.appendChild(rn.domNode);
  25626. var identity = this.model.getIdentity(item);
  25627. if(this._itemNodesMap[identity]){
  25628. this._itemNodesMap[identity].push(rn);
  25629. }else{
  25630. this._itemNodesMap[identity] = [rn];
  25631. }
  25632. rn._updateLayout(); // sets "dijitTreeIsRoot" CSS classname
  25633. // load top level children and then fire onLoad() event
  25634. this._expandNode(rn).addCallback(lang.hitch(this, function(){
  25635. this._loadDeferred.callback(true);
  25636. this.onLoad();
  25637. }));
  25638. }),
  25639. function(err){
  25640. console.error(this, ": error loading root: ", err);
  25641. }
  25642. );
  25643. },
  25644. getNodesByItem: function(/*Item or id*/ item){
  25645. // summary:
  25646. // Returns all tree nodes that refer to an item
  25647. // returns:
  25648. // Array of tree nodes that refer to passed item
  25649. if(!item){ return []; }
  25650. var identity = lang.isString(item) ? item : this.model.getIdentity(item);
  25651. // return a copy so widget don't get messed up by changes to returned array
  25652. return [].concat(this._itemNodesMap[identity]);
  25653. },
  25654. _setSelectedItemAttr: function(/*Item or id*/ item){
  25655. this.set('selectedItems', [item]);
  25656. },
  25657. _setSelectedItemsAttr: function(/*Items or ids*/ items){
  25658. // summary:
  25659. // Select tree nodes related to passed items.
  25660. // WARNING: if model use multi-parented items or desired tree node isn't already loaded
  25661. // behavior is undefined. Use set('paths', ...) instead.
  25662. var tree = this;
  25663. this._loadDeferred.addCallback( lang.hitch(this, function(){
  25664. var identities = array.map(items, function(item){
  25665. return (!item || lang.isString(item)) ? item : tree.model.getIdentity(item);
  25666. });
  25667. var nodes = [];
  25668. array.forEach(identities, function(id){
  25669. nodes = nodes.concat(tree._itemNodesMap[id] || []);
  25670. });
  25671. this.set('selectedNodes', nodes);
  25672. }));
  25673. },
  25674. _setPathAttr: function(/*Item[] || String[]*/ path){
  25675. // summary:
  25676. // Singular variant of _setPathsAttr
  25677. if(path.length){
  25678. return this.set("paths", [path]);
  25679. }else{
  25680. // Empty list is interpreted as "select nothing"
  25681. return this.set("paths", []);
  25682. }
  25683. },
  25684. _setPathsAttr: function(/*Item[][] || String[][]*/ paths){
  25685. // summary:
  25686. // Select the tree nodes identified by passed paths.
  25687. // paths:
  25688. // Array of arrays of items or item id's
  25689. // returns:
  25690. // Deferred to indicate when the set is complete
  25691. var tree = this;
  25692. // We may need to wait for some nodes to expand, so setting
  25693. // each path will involve a Deferred. We bring those deferreds
  25694. // together witha DeferredList.
  25695. return new DeferredList(array.map(paths, function(path){
  25696. var d = new Deferred();
  25697. // normalize path to use identity
  25698. path = array.map(path, function(item){
  25699. return lang.isString(item) ? item : tree.model.getIdentity(item);
  25700. });
  25701. if(path.length){
  25702. // Wait for the tree to load, if it hasn't already.
  25703. tree._loadDeferred.addCallback(function(){ selectPath(path, [tree.rootNode], d); });
  25704. }else{
  25705. d.errback("Empty path");
  25706. }
  25707. return d;
  25708. })).addCallback(setNodes);
  25709. function selectPath(path, nodes, def){
  25710. // Traverse path; the next path component should be among "nodes".
  25711. var nextPath = path.shift();
  25712. var nextNode = array.filter(nodes, function(node){
  25713. return node.getIdentity() == nextPath;
  25714. })[0];
  25715. if(!!nextNode){
  25716. if(path.length){
  25717. tree._expandNode(nextNode).addCallback(function(){ selectPath(path, nextNode.getChildren(), def); });
  25718. }else{
  25719. //Successfully reached the end of this path
  25720. def.callback(nextNode);
  25721. }
  25722. }else{
  25723. def.errback("Could not expand path at " + nextPath);
  25724. }
  25725. }
  25726. function setNodes(newNodes){
  25727. //After all expansion is finished, set the selection to
  25728. //the set of nodes successfully found.
  25729. tree.set("selectedNodes", array.map(
  25730. array.filter(newNodes,function(x){return x[0];}),
  25731. function(x){return x[1];}));
  25732. }
  25733. },
  25734. _setSelectedNodeAttr: function(node){
  25735. this.set('selectedNodes', [node]);
  25736. },
  25737. _setSelectedNodesAttr: function(nodes){
  25738. this._loadDeferred.addCallback( lang.hitch(this, function(){
  25739. this.dndController.setSelection(nodes);
  25740. }));
  25741. },
  25742. ////////////// Data store related functions //////////////////////
  25743. // These just get passed to the model; they are here for back-compat
  25744. mayHaveChildren: function(/*dojo.data.Item*/ /*===== item =====*/){
  25745. // summary:
  25746. // Deprecated. This should be specified on the model itself.
  25747. //
  25748. // Overridable function to tell if an item has or may have children.
  25749. // Controls whether or not +/- expando icon is shown.
  25750. // (For efficiency reasons we may not want to check if an element actually
  25751. // has children until user clicks the expando node)
  25752. // tags:
  25753. // deprecated
  25754. },
  25755. getItemChildren: function(/*===== parentItem, onComplete =====*/){
  25756. // summary:
  25757. // Deprecated. This should be specified on the model itself.
  25758. //
  25759. // Overridable function that return array of child items of given parent item,
  25760. // or if parentItem==null then return top items in tree
  25761. // tags:
  25762. // deprecated
  25763. },
  25764. ///////////////////////////////////////////////////////
  25765. // Functions for converting an item to a TreeNode
  25766. getLabel: function(/*dojo.data.Item*/ item){
  25767. // summary:
  25768. // Overridable function to get the label for a tree node (given the item)
  25769. // tags:
  25770. // extension
  25771. return this.model.getLabel(item); // String
  25772. },
  25773. getIconClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
  25774. // summary:
  25775. // Overridable function to return CSS class name to display icon
  25776. // tags:
  25777. // extension
  25778. return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf"
  25779. },
  25780. getLabelClass: function(/*===== item, opened =====*/){
  25781. // summary:
  25782. // Overridable function to return CSS class name to display label
  25783. // item: dojo.data.Item
  25784. // opened: Boolean
  25785. // returns: String
  25786. // CSS class name
  25787. // tags:
  25788. // extension
  25789. },
  25790. getRowClass: function(/*===== item, opened =====*/){
  25791. // summary:
  25792. // Overridable function to return CSS class name to display row
  25793. // item: dojo.data.Item
  25794. // opened: Boolean
  25795. // returns: String
  25796. // CSS class name
  25797. // tags:
  25798. // extension
  25799. },
  25800. getIconStyle: function(/*===== item, opened =====*/){
  25801. // summary:
  25802. // Overridable function to return CSS styles to display icon
  25803. // item: dojo.data.Item
  25804. // opened: Boolean
  25805. // returns: Object
  25806. // Object suitable for input to dojo.style() like {backgroundImage: "url(...)"}
  25807. // tags:
  25808. // extension
  25809. },
  25810. getLabelStyle: function(/*===== item, opened =====*/){
  25811. // summary:
  25812. // Overridable function to return CSS styles to display label
  25813. // item: dojo.data.Item
  25814. // opened: Boolean
  25815. // returns:
  25816. // Object suitable for input to dojo.style() like {color: "red", background: "green"}
  25817. // tags:
  25818. // extension
  25819. },
  25820. getRowStyle: function(/*===== item, opened =====*/){
  25821. // summary:
  25822. // Overridable function to return CSS styles to display row
  25823. // item: dojo.data.Item
  25824. // opened: Boolean
  25825. // returns:
  25826. // Object suitable for input to dojo.style() like {background-color: "#bbb"}
  25827. // tags:
  25828. // extension
  25829. },
  25830. getTooltip: function(/*dojo.data.Item*/ /*===== item =====*/){
  25831. // summary:
  25832. // Overridable function to get the tooltip for a tree node (given the item)
  25833. // tags:
  25834. // extension
  25835. return ""; // String
  25836. },
  25837. /////////// Keyboard and Mouse handlers ////////////////////
  25838. _onKeyPress: function(/*dijit.TreeNode*/ treeNode, /*Event*/ e){
  25839. // summary:
  25840. // Handles keystrokes for printable keys, doing search navigation
  25841. if(e.charCode <= 32){
  25842. // Avoid duplicate events on firefox (this is an arrow key that will be handled by keydown handler)
  25843. return;
  25844. }
  25845. if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){
  25846. var c = String.fromCharCode(e.charCode);
  25847. this._onLetterKeyNav( { node: treeNode, key: c.toLowerCase() } );
  25848. event.stop(e);
  25849. }
  25850. },
  25851. _onKeyDown: function(/*dijit.TreeNode*/ treeNode, /*Event*/ e){
  25852. // summary:
  25853. // Handles arrow, space, and enter keys
  25854. var key = e.keyCode;
  25855. var map = this._keyHandlerMap;
  25856. if(!map){
  25857. // setup table mapping keys to events
  25858. map = {};
  25859. map[keys.ENTER]="_onEnterKey";
  25860. //On WebKit based browsers, the combination ctrl-enter
  25861. //does not get passed through. To allow accessible
  25862. //multi-select on those browsers, the space key is
  25863. //also used for selection.
  25864. map[keys.SPACE]= map[" "] = "_onEnterKey";
  25865. map[this.isLeftToRight() ? keys.LEFT_ARROW : keys.RIGHT_ARROW]="_onLeftArrow";
  25866. map[this.isLeftToRight() ? keys.RIGHT_ARROW : keys.LEFT_ARROW]="_onRightArrow";
  25867. map[keys.UP_ARROW]="_onUpArrow";
  25868. map[keys.DOWN_ARROW]="_onDownArrow";
  25869. map[keys.HOME]="_onHomeKey";
  25870. map[keys.END]="_onEndKey";
  25871. this._keyHandlerMap = map;
  25872. }
  25873. if(this._keyHandlerMap[key]){
  25874. // clear record of recent printables (being saved for multi-char letter navigation),
  25875. // because "a", down-arrow, "b" shouldn't search for "ab"
  25876. if(this._curSearch){
  25877. clearTimeout(this._curSearch.timer);
  25878. delete this._curSearch;
  25879. }
  25880. this[this._keyHandlerMap[key]]( { node: treeNode, item: treeNode.item, evt: e } );
  25881. event.stop(e);
  25882. }
  25883. },
  25884. _onEnterKey: function(/*Object*/ message){
  25885. this._publish("execute", { item: message.item, node: message.node } );
  25886. this.dndController.userSelect(message.node, connect.isCopyKey( message.evt ), message.evt.shiftKey);
  25887. this.onClick(message.item, message.node, message.evt);
  25888. },
  25889. _onDownArrow: function(/*Object*/ message){
  25890. // summary:
  25891. // down arrow pressed; get next visible node, set focus there
  25892. var node = this._getNextNode(message.node);
  25893. if(node && node.isTreeNode){
  25894. this.focusNode(node);
  25895. }
  25896. },
  25897. _onUpArrow: function(/*Object*/ message){
  25898. // summary:
  25899. // Up arrow pressed; move to previous visible node
  25900. var node = message.node;
  25901. // if younger siblings
  25902. var previousSibling = node.getPreviousSibling();
  25903. if(previousSibling){
  25904. node = previousSibling;
  25905. // if the previous node is expanded, dive in deep
  25906. while(node.isExpandable && node.isExpanded && node.hasChildren()){
  25907. // move to the last child
  25908. var children = node.getChildren();
  25909. node = children[children.length-1];
  25910. }
  25911. }else{
  25912. // if this is the first child, return the parent
  25913. // unless the parent is the root of a tree with a hidden root
  25914. var parent = node.getParent();
  25915. if(!(!this.showRoot && parent === this.rootNode)){
  25916. node = parent;
  25917. }
  25918. }
  25919. if(node && node.isTreeNode){
  25920. this.focusNode(node);
  25921. }
  25922. },
  25923. _onRightArrow: function(/*Object*/ message){
  25924. // summary:
  25925. // Right arrow pressed; go to child node
  25926. var node = message.node;
  25927. // if not expanded, expand, else move to 1st child
  25928. if(node.isExpandable && !node.isExpanded){
  25929. this._expandNode(node);
  25930. }else if(node.hasChildren()){
  25931. node = node.getChildren()[0];
  25932. if(node && node.isTreeNode){
  25933. this.focusNode(node);
  25934. }
  25935. }
  25936. },
  25937. _onLeftArrow: function(/*Object*/ message){
  25938. // summary:
  25939. // Left arrow pressed.
  25940. // If not collapsed, collapse, else move to parent.
  25941. var node = message.node;
  25942. if(node.isExpandable && node.isExpanded){
  25943. this._collapseNode(node);
  25944. }else{
  25945. var parent = node.getParent();
  25946. if(parent && parent.isTreeNode && !(!this.showRoot && parent === this.rootNode)){
  25947. this.focusNode(parent);
  25948. }
  25949. }
  25950. },
  25951. _onHomeKey: function(){
  25952. // summary:
  25953. // Home key pressed; get first visible node, and set focus there
  25954. var node = this._getRootOrFirstNode();
  25955. if(node){
  25956. this.focusNode(node);
  25957. }
  25958. },
  25959. _onEndKey: function(){
  25960. // summary:
  25961. // End key pressed; go to last visible node.
  25962. var node = this.rootNode;
  25963. while(node.isExpanded){
  25964. var c = node.getChildren();
  25965. node = c[c.length - 1];
  25966. }
  25967. if(node && node.isTreeNode){
  25968. this.focusNode(node);
  25969. }
  25970. },
  25971. // multiCharSearchDuration: Number
  25972. // If multiple characters are typed where each keystroke happens within
  25973. // multiCharSearchDuration of the previous keystroke,
  25974. // search for nodes matching all the keystrokes.
  25975. //
  25976. // For example, typing "ab" will search for entries starting with
  25977. // "ab" unless the delay between "a" and "b" is greater than multiCharSearchDuration.
  25978. multiCharSearchDuration: 250,
  25979. _onLetterKeyNav: function(message){
  25980. // summary:
  25981. // Called when user presses a prinatable key; search for node starting with recently typed letters.
  25982. // message: Object
  25983. // Like { node: TreeNode, key: 'a' } where key is the key the user pressed.
  25984. // Branch depending on whether this key starts a new search, or modifies an existing search
  25985. var cs = this._curSearch;
  25986. if(cs){
  25987. // We are continuing a search. Ex: user has pressed 'a', and now has pressed
  25988. // 'b', so we want to search for nodes starting w/"ab".
  25989. cs.pattern = cs.pattern + message.key;
  25990. clearTimeout(cs.timer);
  25991. }else{
  25992. // We are starting a new search
  25993. cs = this._curSearch = {
  25994. pattern: message.key,
  25995. startNode: message.node
  25996. };
  25997. }
  25998. // set/reset timer to forget recent keystrokes
  25999. var self = this;
  26000. cs.timer = setTimeout(function(){
  26001. delete self._curSearch;
  26002. }, this.multiCharSearchDuration);
  26003. // Navigate to TreeNode matching keystrokes [entered so far].
  26004. var node = cs.startNode;
  26005. do{
  26006. node = this._getNextNode(node);
  26007. //check for last node, jump to first node if necessary
  26008. if(!node){
  26009. node = this._getRootOrFirstNode();
  26010. }
  26011. }while(node !== cs.startNode && (node.label.toLowerCase().substr(0, cs.pattern.length) != cs.pattern));
  26012. if(node && node.isTreeNode){
  26013. // no need to set focus if back where we started
  26014. if(node !== cs.startNode){
  26015. this.focusNode(node);
  26016. }
  26017. }
  26018. },
  26019. isExpandoNode: function(node, widget){
  26020. // summary:
  26021. // check whether a dom node is the expandoNode for a particular TreeNode widget
  26022. return dom.isDescendant(node, widget.expandoNode);
  26023. },
  26024. _onClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
  26025. // summary:
  26026. // Translates click events into commands for the controller to process
  26027. var domElement = e.target,
  26028. isExpandoClick = this.isExpandoNode(domElement, nodeWidget);
  26029. if( (this.openOnClick && nodeWidget.isExpandable) || isExpandoClick ){
  26030. // expando node was clicked, or label of a folder node was clicked; open it
  26031. if(nodeWidget.isExpandable){
  26032. this._onExpandoClick({node:nodeWidget});
  26033. }
  26034. }else{
  26035. this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
  26036. this.onClick(nodeWidget.item, nodeWidget, e);
  26037. this.focusNode(nodeWidget);
  26038. }
  26039. event.stop(e);
  26040. },
  26041. _onDblClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
  26042. // summary:
  26043. // Translates double-click events into commands for the controller to process
  26044. var domElement = e.target,
  26045. isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText);
  26046. if( (this.openOnDblClick && nodeWidget.isExpandable) ||isExpandoClick ){
  26047. // expando node was clicked, or label of a folder node was clicked; open it
  26048. if(nodeWidget.isExpandable){
  26049. this._onExpandoClick({node:nodeWidget});
  26050. }
  26051. }else{
  26052. this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
  26053. this.onDblClick(nodeWidget.item, nodeWidget, e);
  26054. this.focusNode(nodeWidget);
  26055. }
  26056. event.stop(e);
  26057. },
  26058. _onExpandoClick: function(/*Object*/ message){
  26059. // summary:
  26060. // User clicked the +/- icon; expand or collapse my children.
  26061. var node = message.node;
  26062. // If we are collapsing, we might be hiding the currently focused node.
  26063. // Also, clicking the expando node might have erased focus from the current node.
  26064. // For simplicity's sake just focus on the node with the expando.
  26065. this.focusNode(node);
  26066. if(node.isExpanded){
  26067. this._collapseNode(node);
  26068. }else{
  26069. this._expandNode(node);
  26070. }
  26071. },
  26072. onClick: function(/*===== item, node, evt =====*/){
  26073. // summary:
  26074. // Callback when a tree node is clicked
  26075. // item: dojo.data.Item
  26076. // node: TreeNode
  26077. // evt: Event
  26078. // tags:
  26079. // callback
  26080. },
  26081. onDblClick: function(/*===== item, node, evt =====*/){
  26082. // summary:
  26083. // Callback when a tree node is double-clicked
  26084. // item: dojo.data.Item
  26085. // node: TreeNode
  26086. // evt: Event
  26087. // tags:
  26088. // callback
  26089. },
  26090. onOpen: function(/*===== item, node =====*/){
  26091. // summary:
  26092. // Callback when a node is opened
  26093. // item: dojo.data.Item
  26094. // node: TreeNode
  26095. // tags:
  26096. // callback
  26097. },
  26098. onClose: function(/*===== item, node =====*/){
  26099. // summary:
  26100. // Callback when a node is closed
  26101. // item: dojo.data.Item
  26102. // node: TreeNode
  26103. // tags:
  26104. // callback
  26105. },
  26106. _getNextNode: function(node){
  26107. // summary:
  26108. // Get next visible node
  26109. if(node.isExpandable && node.isExpanded && node.hasChildren()){
  26110. // if this is an expanded node, get the first child
  26111. return node.getChildren()[0]; // _TreeNode
  26112. }else{
  26113. // find a parent node with a sibling
  26114. while(node && node.isTreeNode){
  26115. var returnNode = node.getNextSibling();
  26116. if(returnNode){
  26117. return returnNode; // _TreeNode
  26118. }
  26119. node = node.getParent();
  26120. }
  26121. return null;
  26122. }
  26123. },
  26124. _getRootOrFirstNode: function(){
  26125. // summary:
  26126. // Get first visible node
  26127. return this.showRoot ? this.rootNode : this.rootNode.getChildren()[0];
  26128. },
  26129. _collapseNode: function(/*_TreeNode*/ node){
  26130. // summary:
  26131. // Called when the user has requested to collapse the node
  26132. if(node._expandNodeDeferred){
  26133. delete node._expandNodeDeferred;
  26134. }
  26135. if(node.isExpandable){
  26136. if(node.state == "LOADING"){
  26137. // ignore clicks while we are in the process of loading data
  26138. return;
  26139. }
  26140. node.collapse();
  26141. this.onClose(node.item, node);
  26142. this._state(node, false);
  26143. }
  26144. },
  26145. _expandNode: function(/*_TreeNode*/ node, /*Boolean?*/ recursive){
  26146. // summary:
  26147. // Called when the user has requested to expand the node
  26148. // recursive:
  26149. // Internal flag used when _expandNode() calls itself, don't set.
  26150. // returns:
  26151. // Deferred that fires when the node is loaded and opened and (if persist=true) all it's descendants
  26152. // that were previously opened too
  26153. if(node._expandNodeDeferred && !recursive){
  26154. // there's already an expand in progress (or completed), so just return
  26155. return node._expandNodeDeferred; // dojo.Deferred
  26156. }
  26157. var model = this.model,
  26158. item = node.item,
  26159. _this = this;
  26160. switch(node.state){
  26161. case "UNCHECKED":
  26162. // need to load all the children, and then expand
  26163. node.markProcessing();
  26164. // Setup deferred to signal when the load and expand are finished.
  26165. // Save that deferred in this._expandDeferred as a flag that operation is in progress.
  26166. var def = (node._expandNodeDeferred = new Deferred());
  26167. // Get the children
  26168. model.getChildren(
  26169. item,
  26170. function(items){
  26171. node.unmarkProcessing();
  26172. // Display the children and also start expanding any children that were previously expanded
  26173. // (if this.persist == true). The returned Deferred will fire when those expansions finish.
  26174. var scid = node.setChildItems(items);
  26175. // Call _expandNode() again but this time it will just to do the animation (default branch).
  26176. // The returned Deferred will fire when the animation completes.
  26177. // TODO: seems like I can avoid recursion and just use a deferred to sequence the events?
  26178. var ed = _this._expandNode(node, true);
  26179. // After the above two tasks (setChildItems() and recursive _expandNode()) finish,
  26180. // signal that I am done.
  26181. scid.addCallback(function(){
  26182. ed.addCallback(function(){
  26183. def.callback();
  26184. })
  26185. });
  26186. },
  26187. function(err){
  26188. console.error(_this, ": error loading root children: ", err);
  26189. }
  26190. );
  26191. break;
  26192. default: // "LOADED"
  26193. // data is already loaded; just expand node
  26194. def = (node._expandNodeDeferred = node.expand());
  26195. this.onOpen(node.item, node);
  26196. this._state(node, true);
  26197. }
  26198. return def; // dojo.Deferred
  26199. },
  26200. ////////////////// Miscellaneous functions ////////////////
  26201. focusNode: function(/* _tree.Node */ node){
  26202. // summary:
  26203. // Focus on the specified node (which must be visible)
  26204. // tags:
  26205. // protected
  26206. // set focus so that the label will be voiced using screen readers
  26207. focus.focus(node.labelNode);
  26208. },
  26209. _onNodeFocus: function(/*dijit._Widget*/ node){
  26210. // summary:
  26211. // Called when a TreeNode gets focus, either by user clicking
  26212. // it, or programatically by arrow key handling code.
  26213. // description:
  26214. // It marks that the current node is the selected one, and the previously
  26215. // selected node no longer is.
  26216. if(node && node != this.lastFocused){
  26217. if(this.lastFocused && !this.lastFocused._destroyed){
  26218. // mark that the previously focsable node is no longer focusable
  26219. this.lastFocused.setFocusable(false);
  26220. }
  26221. // mark that the new node is the currently selected one
  26222. node.setFocusable(true);
  26223. this.lastFocused = node;
  26224. }
  26225. },
  26226. _onNodeMouseEnter: function(/*dijit._Widget*/ /*===== node =====*/){
  26227. // summary:
  26228. // Called when mouse is over a node (onmouseenter event),
  26229. // this is monitored by the DND code
  26230. },
  26231. _onNodeMouseLeave: function(/*dijit._Widget*/ /*===== node =====*/){
  26232. // summary:
  26233. // Called when mouse leaves a node (onmouseleave event),
  26234. // this is monitored by the DND code
  26235. },
  26236. //////////////// Events from the model //////////////////////////
  26237. _onItemChange: function(/*Item*/ item){
  26238. // summary:
  26239. // Processes notification of a change to an item's scalar values like label
  26240. var model = this.model,
  26241. identity = model.getIdentity(item),
  26242. nodes = this._itemNodesMap[identity];
  26243. if(nodes){
  26244. var label = this.getLabel(item),
  26245. tooltip = this.getTooltip(item);
  26246. array.forEach(nodes, function(node){
  26247. node.set({
  26248. item: item, // theoretically could be new JS Object representing same item
  26249. label: label,
  26250. tooltip: tooltip
  26251. });
  26252. node._updateItemClasses(item);
  26253. });
  26254. }
  26255. },
  26256. _onItemChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
  26257. // summary:
  26258. // Processes notification of a change to an item's children
  26259. var model = this.model,
  26260. identity = model.getIdentity(parent),
  26261. parentNodes = this._itemNodesMap[identity];
  26262. if(parentNodes){
  26263. array.forEach(parentNodes,function(parentNode){
  26264. parentNode.setChildItems(newChildrenList);
  26265. });
  26266. }
  26267. },
  26268. _onItemDelete: function(/*Item*/ item){
  26269. // summary:
  26270. // Processes notification of a deletion of an item
  26271. var model = this.model,
  26272. identity = model.getIdentity(item),
  26273. nodes = this._itemNodesMap[identity];
  26274. if(nodes){
  26275. array.forEach(nodes,function(node){
  26276. // Remove node from set of selected nodes (if it's selected)
  26277. this.dndController.removeTreeNode(node);
  26278. var parent = node.getParent();
  26279. if(parent){
  26280. // if node has not already been orphaned from a _onSetItem(parent, "children", ..) call...
  26281. parent.removeChild(node);
  26282. }
  26283. node.destroyRecursive();
  26284. }, this);
  26285. delete this._itemNodesMap[identity];
  26286. }
  26287. },
  26288. /////////////// Miscellaneous funcs
  26289. _initState: function(){
  26290. // summary:
  26291. // Load in which nodes should be opened automatically
  26292. this._openedNodes = {};
  26293. if(this.persist && this.cookieName){
  26294. var oreo = cookie(this.cookieName);
  26295. if(oreo){
  26296. array.forEach(oreo.split(','), function(item){
  26297. this._openedNodes[item] = true;
  26298. }, this);
  26299. }
  26300. }
  26301. },
  26302. _state: function(node, expanded){
  26303. // summary:
  26304. // Query or set expanded state for an node
  26305. if(!this.persist){
  26306. return false;
  26307. }
  26308. var path = array.map(node.getTreePath(), function(item){
  26309. return this.model.getIdentity(item);
  26310. }, this).join("/");
  26311. if(arguments.length === 1){
  26312. return this._openedNodes[path];
  26313. }else{
  26314. if(expanded){
  26315. this._openedNodes[path] = true;
  26316. }else{
  26317. delete this._openedNodes[path];
  26318. }
  26319. var ary = [];
  26320. for(var id in this._openedNodes){
  26321. ary.push(id);
  26322. }
  26323. cookie(this.cookieName, ary.join(","), {expires:365});
  26324. }
  26325. },
  26326. destroy: function(){
  26327. if(this._curSearch){
  26328. clearTimeout(this._curSearch.timer);
  26329. delete this._curSearch;
  26330. }
  26331. if(this.rootNode){
  26332. this.rootNode.destroyRecursive();
  26333. }
  26334. if(this.dndController && !lang.isString(this.dndController)){
  26335. this.dndController.destroy();
  26336. }
  26337. this.rootNode = null;
  26338. this.inherited(arguments);
  26339. },
  26340. destroyRecursive: function(){
  26341. // A tree is treated as a leaf, not as a node with children (like a grid),
  26342. // but defining destroyRecursive for back-compat.
  26343. this.destroy();
  26344. },
  26345. resize: function(changeSize){
  26346. if(changeSize){
  26347. domGeometry.setMarginBox(this.domNode, changeSize);
  26348. }
  26349. // The only JS sizing involved w/tree is the indentation, which is specified
  26350. // in CSS and read in through this dummy indentDetector node (tree must be
  26351. // visible and attached to the DOM to read this)
  26352. this._nodePixelIndent = domGeometry.position(this.tree.indentDetector).w;
  26353. if(this.tree.rootNode){
  26354. // If tree has already loaded, then reset indent for all the nodes
  26355. this.tree.rootNode.set('indent', this.showRoot ? 0 : -1);
  26356. }
  26357. },
  26358. _createTreeNode: function(/*Object*/ args){
  26359. // summary:
  26360. // creates a TreeNode
  26361. // description:
  26362. // Developers can override this method to define their own TreeNode class;
  26363. // However it will probably be removed in a future release in favor of a way
  26364. // of just specifying a widget for the label, rather than one that contains
  26365. // the children too.
  26366. return new TreeNode(args);
  26367. },
  26368. _setTextDirAttr: function(textDir){
  26369. if(textDir && this.textDir!= textDir){
  26370. this._set("textDir",textDir);
  26371. this.rootNode.set("textDir", textDir);
  26372. }
  26373. }
  26374. });
  26375. Tree._TreeNode = TreeNode; // for monkey patching
  26376. return Tree;
  26377. });
  26378. },
  26379. 'dojox/layout/ResizeHandle':function(){
  26380. define("dojox/layout/ResizeHandle", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/connect","dojo/_base/array","dojo/_base/event",
  26381. "dojo/_base/fx","dojo/_base/window","dojo/fx","dojo/window","dojo/dom","dojo/dom-class",
  26382. "dojo/dom-geometry","dojo/dom-style","dijit/_base/manager","dijit/_Widget","dijit/_TemplatedMixin",
  26383. "dojo/_base/declare"], function (
  26384. kernel, lang, connect, arrayUtil, eventUtil, fxBase, windowBase, fxUtil, windowUtil,
  26385. domUtil, domClass, domGeometry, domStyle, manager, Widget, TemplatedMixin, declare) {
  26386. kernel.experimental("dojox.layout.ResizeHandle");
  26387. /*=====
  26388. var Widget = dijit._Widget;
  26389. var TemplatedMixin = dijit._TemplatedMixin;
  26390. =====*/
  26391. var ResizeHandle = declare("dojox.layout.ResizeHandle",[Widget, TemplatedMixin],
  26392. {
  26393. // summary: A dragable handle used to resize an attached node.
  26394. //
  26395. // description:
  26396. // The handle on the bottom-right corner of FloatingPane or other widgets that allows
  26397. // the widget to be resized.
  26398. // Typically not used directly.
  26399. //
  26400. // targetId: String
  26401. // id of the Widget OR DomNode that I will size
  26402. targetId: "",
  26403. // targetContainer: DomNode
  26404. // over-ride targetId and attch this handle directly to a reference of a DomNode
  26405. targetContainer: null,
  26406. // resizeAxis: String
  26407. // one of: x|y|xy limit resizing to a single axis, default to xy ...
  26408. resizeAxis: "xy",
  26409. // activeResize: Boolean
  26410. // if true, node will size realtime with mouse movement,
  26411. // if false, node will create virtual node, and only resize target on mouseUp
  26412. activeResize: false,
  26413. // activeResizeClass: String
  26414. // css class applied to virtual resize node.
  26415. activeResizeClass: "dojoxResizeHandleClone",
  26416. // animateSizing: Boolean
  26417. // only applicable if activeResize = false. onMouseup, animate the node to the
  26418. // new size
  26419. animateSizing: true,
  26420. // animateMethod: String
  26421. // one of "chain" or "combine" ... visual effect only. combine will "scale"
  26422. // node to size, "chain" will alter width, then height
  26423. animateMethod: "chain",
  26424. // animateDuration: Integer
  26425. // time in MS to run sizing animation. if animateMethod="chain", total animation
  26426. // playtime is 2*animateDuration
  26427. animateDuration: 225,
  26428. // minHeight: Integer
  26429. // smallest height in px resized node can be
  26430. minHeight: 100,
  26431. // minWidth: Integer
  26432. // smallest width in px resize node can be
  26433. minWidth: 100,
  26434. // constrainMax: Boolean
  26435. // Toggle if this widget cares about the maxHeight and maxWidth
  26436. // parameters.
  26437. constrainMax: false,
  26438. // maxHeight: Integer
  26439. // Largest height size in px the resize node can become.
  26440. maxHeight:0,
  26441. // maxWidth: Integer
  26442. // Largest width size in px the reize node can become.
  26443. maxWidth:0,
  26444. // fixedAspect: Boolean
  26445. // Toggle to enable this widget to maintain the aspect
  26446. // ratio of the attached node.
  26447. fixedAspect: false,
  26448. // intermediateChanges: Boolean
  26449. // Toggle to enable/disable this widget from firing onResize
  26450. // events at every step of a resize. If `activeResize` is true,
  26451. // and this is false, onResize only fires _after_ the drop
  26452. // operation. Animated resizing is not affected by this setting.
  26453. intermediateChanges: false,
  26454. // startTopic: String
  26455. // The name of the topic this resizehandle publishes when resize is starting
  26456. startTopic: "/dojo/resize/start",
  26457. // endTopic: String
  26458. // The name of the topic this resizehandle publishes when resize is complete
  26459. endTopic:"/dojo/resize/stop",
  26460. templateString: '<div dojoAttachPoint="resizeHandle" class="dojoxResizeHandle"><div></div></div>',
  26461. postCreate: function(){
  26462. // summary: setup our one major listener upon creation
  26463. this.connect(this.resizeHandle, "onmousedown", "_beginSizing");
  26464. if(!this.activeResize){
  26465. // there shall be only a single resize rubberbox that at the top
  26466. // level so that we can overlay it on anything whenever the user
  26467. // resizes something. Since there is only one mouse pointer he
  26468. // can't at once resize multiple things interactively.
  26469. this._resizeHelper = manager.byId('dojoxGlobalResizeHelper');
  26470. if(!this._resizeHelper){
  26471. this._resizeHelper = new _ResizeHelper({
  26472. id: 'dojoxGlobalResizeHelper'
  26473. }).placeAt(windowBase.body());
  26474. domClass.add(this._resizeHelper.domNode, this.activeResizeClass);
  26475. }
  26476. }else{ this.animateSizing = false; }
  26477. if(!this.minSize){
  26478. this.minSize = { w: this.minWidth, h: this.minHeight };
  26479. }
  26480. if(this.constrainMax){
  26481. this.maxSize = { w: this.maxWidth, h: this.maxHeight }
  26482. }
  26483. // should we modify the css for the cursor hover to n-resize nw-resize and w-resize?
  26484. this._resizeX = this._resizeY = false;
  26485. var addClass = lang.partial(domClass.add, this.resizeHandle);
  26486. switch(this.resizeAxis.toLowerCase()){
  26487. case "xy" :
  26488. this._resizeX = this._resizeY = true;
  26489. // FIXME: need logic to determine NW or NE class to see
  26490. // based on which [todo] corner is clicked
  26491. addClass("dojoxResizeNW");
  26492. break;
  26493. case "x" :
  26494. this._resizeX = true;
  26495. addClass("dojoxResizeW");
  26496. break;
  26497. case "y" :
  26498. this._resizeY = true;
  26499. addClass("dojoxResizeN");
  26500. break;
  26501. }
  26502. },
  26503. _beginSizing: function(/*Event*/ e){
  26504. // summary: setup movement listeners and calculate initial size
  26505. if(this._isSizing){ return; }
  26506. connect.publish(this.startTopic, [ this ]);
  26507. this.targetWidget = manager.byId(this.targetId);
  26508. this.targetDomNode = this.targetWidget ? this.targetWidget.domNode : domUtil.byId(this.targetId);
  26509. if(this.targetContainer){ this.targetDomNode = this.targetContainer; }
  26510. if(!this.targetDomNode){ return; }
  26511. if(!this.activeResize){
  26512. var c = domGeometry.position(this.targetDomNode, true);
  26513. this._resizeHelper.resize({l: c.x, t: c.y, w: c.w, h: c.h});
  26514. this._resizeHelper.show();
  26515. if(!this.isLeftToRight()){
  26516. this._resizeHelper.startPosition = {l: c.x, t: c.y};
  26517. }
  26518. }
  26519. this._isSizing = true;
  26520. this.startPoint = { x:e.clientX, y:e.clientY };
  26521. // widget.resize() or setting style.width/height expects native box model dimension
  26522. // (in most cases content-box, but it may be border-box if in backcompact mode)
  26523. var style = domStyle.getComputedStyle(this.targetDomNode),
  26524. borderModel = domGeometry.boxModel==='border-model',
  26525. padborder = borderModel?{w:0,h:0}:domGeometry.getPadBorderExtents(this.targetDomNode, style),
  26526. margin = domGeometry.getMarginExtents(this.targetDomNode, style),
  26527. mb;
  26528. mb = this.startSize = {
  26529. w: domStyle.get(this.targetDomNode, 'width', style),
  26530. h: domStyle.get(this.targetDomNode, 'height', style),
  26531. //ResizeHelper.resize expects a bounding box of the
  26532. //border box, so let's keep track of padding/border
  26533. //width/height as well
  26534. pbw: padborder.w, pbh: padborder.h,
  26535. mw: margin.w, mh: margin.h};
  26536. if(!this.isLeftToRight() && dojo.style(this.targetDomNode, "position") == "absolute"){
  26537. var p = domGeometry.position(this.targetDomNode, true);
  26538. this.startPosition = {l: p.x, t: p.y};
  26539. }
  26540. this._pconnects = [
  26541. connect.connect(windowBase.doc,"onmousemove",this,"_updateSizing"),
  26542. connect.connect(windowBase.doc,"onmouseup", this, "_endSizing")
  26543. ];
  26544. eventUtil.stop(e);
  26545. },
  26546. _updateSizing: function(/*Event*/ e){
  26547. // summary: called when moving the ResizeHandle ... determines
  26548. // new size based on settings/position and sets styles.
  26549. if(this.activeResize){
  26550. this._changeSizing(e);
  26551. }else{
  26552. var tmp = this._getNewCoords(e, 'border', this._resizeHelper.startPosition);
  26553. if(tmp === false){ return; }
  26554. this._resizeHelper.resize(tmp);
  26555. }
  26556. e.preventDefault();
  26557. },
  26558. _getNewCoords: function(/* Event */ e, /* String */ box, /* Object */startPosition){
  26559. // On IE, if you move the mouse above/to the left of the object being resized,
  26560. // sometimes clientX/Y aren't set, apparently. Just ignore the event.
  26561. try{
  26562. if(!e.clientX || !e.clientY){ return false; }
  26563. }catch(e){
  26564. // sometimes you get an exception accessing above fields...
  26565. return false;
  26566. }
  26567. this._activeResizeLastEvent = e;
  26568. var dx = (this.isLeftToRight()?1:-1) * (this.startPoint.x - e.clientX),
  26569. dy = this.startPoint.y - e.clientY,
  26570. newW = this.startSize.w - (this._resizeX ? dx : 0),
  26571. newH = this.startSize.h - (this._resizeY ? dy : 0),
  26572. r = this._checkConstraints(newW, newH)
  26573. ;
  26574. startPosition = (startPosition || this.startPosition);
  26575. if(startPosition && this._resizeX){
  26576. // adjust x position for RtoL
  26577. r.l = startPosition.l + dx;
  26578. if(r.w != newW){
  26579. r.l += (newW - r.w);
  26580. }
  26581. r.t = startPosition.t;
  26582. }
  26583. switch(box){
  26584. case 'margin':
  26585. r.w += this.startSize.mw;
  26586. r.h += this.startSize.mh;
  26587. //pass through
  26588. case "border":
  26589. r.w += this.startSize.pbw;
  26590. r.h += this.startSize.pbh;
  26591. break;
  26592. //default: //native, do nothing
  26593. }
  26594. return r; // Object
  26595. },
  26596. _checkConstraints: function(newW, newH){
  26597. // summary: filter through the various possible constaint possibilities.
  26598. // minimum size check
  26599. if(this.minSize){
  26600. var tm = this.minSize;
  26601. if(newW < tm.w){
  26602. newW = tm.w;
  26603. }
  26604. if(newH < tm.h){
  26605. newH = tm.h;
  26606. }
  26607. }
  26608. // maximum size check:
  26609. if(this.constrainMax && this.maxSize){
  26610. var ms = this.maxSize;
  26611. if(newW > ms.w){
  26612. newW = ms.w;
  26613. }
  26614. if(newH > ms.h){
  26615. newH = ms.h;
  26616. }
  26617. }
  26618. if(this.fixedAspect){
  26619. var w = this.startSize.w, h = this.startSize.h,
  26620. delta = w * newH - h * newW;
  26621. if(delta<0){
  26622. newW = newH * w / h;
  26623. }else if(delta>0){
  26624. newH = newW * h / w;
  26625. }
  26626. }
  26627. return { w: newW, h: newH }; // Object
  26628. },
  26629. _changeSizing: function(/*Event*/ e){
  26630. // summary: apply sizing information based on information in (e) to attached node
  26631. var isWidget = this.targetWidget && lang.isFunction(this.targetWidget.resize),
  26632. tmp = this._getNewCoords(e, isWidget && 'margin');
  26633. if(tmp === false){ return; }
  26634. if(isWidget){
  26635. this.targetWidget.resize(tmp);
  26636. }else{
  26637. if(this.animateSizing){
  26638. var anim = fxUtil[this.animateMethod]([
  26639. fxBase.animateProperty({
  26640. node: this.targetDomNode,
  26641. properties: {
  26642. width: { start: this.startSize.w, end: tmp.w }
  26643. },
  26644. duration: this.animateDuration
  26645. }),
  26646. fxBase.animateProperty({
  26647. node: this.targetDomNode,
  26648. properties: {
  26649. height: { start: this.startSize.h, end: tmp.h }
  26650. },
  26651. duration: this.animateDuration
  26652. })
  26653. ]);
  26654. anim.play();
  26655. }else{
  26656. domStyle.set(this.targetDomNode,{
  26657. width: tmp.w + "px",
  26658. height: tmp.h + "px"
  26659. });
  26660. }
  26661. }
  26662. if(this.intermediateChanges){
  26663. this.onResize(e);
  26664. }
  26665. },
  26666. _endSizing: function(/*Event*/ e){
  26667. // summary: disconnect listenrs and cleanup sizing
  26668. arrayUtil.forEach(this._pconnects, connect.disconnect);
  26669. var pub = lang.partial(connect.publish, this.endTopic, [ this ]);
  26670. if(!this.activeResize){
  26671. this._resizeHelper.hide();
  26672. this._changeSizing(e);
  26673. setTimeout(pub, this.animateDuration + 15);
  26674. }else{
  26675. pub();
  26676. }
  26677. this._isSizing = false;
  26678. this.onResize(e);
  26679. },
  26680. onResize: function(e){
  26681. // summary: Stub fired when sizing is done. Fired once
  26682. // after resize, or often when `intermediateChanges` is
  26683. // set to true.
  26684. }
  26685. });
  26686. var _ResizeHelper = dojo.declare("dojox.layout._ResizeHelper", Widget, {
  26687. // summary: A global private resize helper shared between any
  26688. // `dojox.layout.ResizeHandle` with activeSizing off.
  26689. show: function(){
  26690. // summary: show helper to start resizing
  26691. domStyle.set(this.domNode, "display", "");
  26692. },
  26693. hide: function(){
  26694. // summary: hide helper after resizing is complete
  26695. domStyle.set(this.domNode, "display", "none");
  26696. },
  26697. resize: function(/* Object */dim){
  26698. // summary: size the widget and place accordingly
  26699. domGeometry.setMarginBox(this.domNode, dim);
  26700. }
  26701. });
  26702. return ResizeHandle;
  26703. });
  26704. },
  26705. 'dijit/form/_FormValueWidget':function(){
  26706. define("dijit/form/_FormValueWidget", [
  26707. "dojo/_base/declare", // declare
  26708. "dojo/_base/sniff", // has("ie")
  26709. "./_FormWidget",
  26710. "./_FormValueMixin"
  26711. ], function(declare, has, _FormWidget, _FormValueMixin){
  26712. /*=====
  26713. var _FormWidget = dijit.form._FormWidget;
  26714. var _FormValueMixin = dijit.form._FormValueMixin;
  26715. =====*/
  26716. // module:
  26717. // dijit/form/_FormValueWidget
  26718. // summary:
  26719. // FormValueWidget
  26720. return declare("dijit.form._FormValueWidget", [_FormWidget, _FormValueMixin],
  26721. {
  26722. // summary:
  26723. // Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
  26724. // description:
  26725. // Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element,
  26726. // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
  26727. // works as expected.
  26728. // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
  26729. // directly in the template as read by the parser in order to function. IE is known to specifically
  26730. // require the 'name' attribute at element creation time. See #8484, #8660.
  26731. _layoutHackIE7: function(){
  26732. // summary:
  26733. // Work around table sizing bugs on IE7 by forcing redraw
  26734. if(has("ie") == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
  26735. var domNode = this.domNode;
  26736. var parent = domNode.parentNode;
  26737. var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
  26738. var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
  26739. var _this = this;
  26740. while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
  26741. (function ping(){
  26742. var disconnectHandle = _this.connect(parent, "onscroll",
  26743. function(){
  26744. _this.disconnect(disconnectHandle); // only call once
  26745. pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
  26746. setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
  26747. }
  26748. );
  26749. })();
  26750. parent = parent.parentNode;
  26751. }
  26752. }
  26753. }
  26754. });
  26755. });
  26756. },
  26757. '*now':function(r){r(['dojo/i18n!*preload*dojo/nls/buxdojo*["ar","az","bg","ca","cs","da","de","de-de","el","en","en-ca","en-gb","en-us","es","es-es","fi","fi-fi","fr","fr-ca","fr-fr","he","he-il","hr","hu","it","it-it","ja","ja-jp","kk","ko","ko-kr","nl","nl-nl","nb","no","pl","pt","pt-br","pt-pt","ro","ru","sk","sl","sv","th","tr","zh","zh-tw","zh-cn","ROOT"]']);}
  26758. }});
  26759. define("dojo/buxdojo", [], 1);