123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343 |
- require({cache:{
- 'url:dijit/templates/CheckedMenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitemcheckbox\" tabIndex=\"-1\"\r\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\r\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\r\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\r\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">✓</span>\r\n\t</td>\r\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode,labelNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\"> </td>\r\n</tr>\r\n",
- 'dijit/form/TextBox':function(){
- require({cache:{
- 'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\r\n\t\t\t${!nameAttrSetting} type='${type}'\r\n\t/></div\r\n></div>\r\n"}});
- define("dijit/form/TextBox", [
- "dojo/_base/declare", // declare
- "dojo/dom-construct", // domConstruct.create
- "dojo/dom-style", // domStyle.getComputedStyle
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/lang", // lang.hitch
- "dojo/_base/sniff", // has("ie") has("mozilla")
- "dojo/_base/window", // win.doc.selection.createRange
- "./_FormValueWidget",
- "./_TextBoxMixin",
- "dojo/text!./templates/TextBox.html",
- ".." // to export dijit._setSelectionRange, remove in 2.0
- ], function(declare, domConstruct, domStyle, kernel, lang, has, win,
- _FormValueWidget, _TextBoxMixin, template, dijit){
- /*=====
- var _FormValueWidget = dijit.form._FormValueWidget;
- var _TextBoxMixin = dijit.form._TextBoxMixin;
- =====*/
- // module:
- // dijit/form/TextBox
- // summary:
- // A base class for textbox form inputs
- var TextBox = declare(/*====="dijit.form.TextBox", =====*/ [_FormValueWidget, _TextBoxMixin], {
- // summary:
- // A base class for textbox form inputs
- templateString: template,
- _singleNodeTemplate: '<input class="dijit dijitReset dijitLeft dijitInputField" data-dojo-attach-point="textbox,focusNode" autocomplete="off" type="${type}" ${!nameAttrSetting} />',
- _buttonInputDisabled: has("ie") ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events
- baseClass: "dijitTextBox",
- postMixInProperties: function(){
- var type = this.type.toLowerCase();
- if(this.templateString && this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == this.constructor.prototype.templateString)){
- this.templateString = this._singleNodeTemplate;
- }
- this.inherited(arguments);
- },
- _onInput: function(e){
- this.inherited(arguments);
- if(this.intermediateChanges){ // _TextBoxMixin uses onInput
- var _this = this;
- // the setTimeout allows the key to post to the widget input box
- setTimeout(function(){ _this._handleOnChange(_this.get('value'), false); }, 0);
- }
- },
- _setPlaceHolderAttr: function(v){
- this._set("placeHolder", v);
- if(!this._phspan){
- this._attachPoints.push('_phspan');
- // dijitInputField class gives placeHolder same padding as the input field
- // parent node already has dijitInputField class but it doesn't affect this <span>
- // since it's position: absolute.
- this._phspan = domConstruct.create('span',{className:'dijitPlaceHolder dijitInputField'},this.textbox,'after');
- }
- this._phspan.innerHTML="";
- this._phspan.appendChild(document.createTextNode(v));
- this._updatePlaceHolder();
- },
- _updatePlaceHolder: function(){
- if(this._phspan){
- this._phspan.style.display=(this.placeHolder&&!this.focused&&!this.textbox.value)?"":"none";
- }
- },
- _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
- this.inherited(arguments);
- this._updatePlaceHolder();
- },
- getDisplayedValue: function(){
- // summary:
- // Deprecated. Use get('displayedValue') instead.
- // tags:
- // deprecated
- kernel.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use set('displayedValue') instead.", "", "2.0");
- return this.get('displayedValue');
- },
- setDisplayedValue: function(/*String*/ value){
- // summary:
- // Deprecated. Use set('displayedValue', ...) instead.
- // tags:
- // deprecated
- kernel.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0");
- this.set('displayedValue', value);
- },
- _onBlur: function(e){
- if(this.disabled){ return; }
- this.inherited(arguments);
- this._updatePlaceHolder();
- },
- _onFocus: function(/*String*/ by){
- if(this.disabled || this.readOnly){ return; }
- this.inherited(arguments);
- this._updatePlaceHolder();
- }
- });
- if(has("ie")){
- TextBox = declare(/*===== "dijit.form.TextBox.IEMixin", =====*/ TextBox, {
- declaredClass: "dijit.form.TextBox", // for user code referencing declaredClass
- _isTextSelected: function(){
- var range = win.doc.selection.createRange();
- var parent = range.parentElement();
- return parent == this.textbox && range.text.length == 0;
- },
- postCreate: function(){
- this.inherited(arguments);
- // IE INPUT tag fontFamily has to be set directly using STYLE
- // the setTimeout gives IE a chance to render the TextBox and to deal with font inheritance
- setTimeout(lang.hitch(this, function(){
- try{
- var s = domStyle.getComputedStyle(this.domNode); // can throw an exception if widget is immediately destroyed
- if(s){
- var ff = s.fontFamily;
- if(ff){
- var inputs = this.domNode.getElementsByTagName("INPUT");
- if(inputs){
- for(var i=0; i < inputs.length; i++){
- inputs[i].style.fontFamily = ff;
- }
- }
- }
- }
- }catch(e){/*when used in a Dialog, and this is called before the dialog is
- shown, s.fontFamily would trigger "Invalid Argument" error.*/}
- }), 0);
- }
- });
- // Overrides definition of _setSelectionRange from _TextBoxMixin (TODO: move to _TextBoxMixin.js?)
- dijit._setSelectionRange = _TextBoxMixin._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
- if(element.createTextRange){
- var r = element.createTextRange();
- r.collapse(true);
- r.moveStart("character", -99999); // move to 0
- r.moveStart("character", start); // delta from 0 is the correct position
- r.moveEnd("character", stop-start);
- r.select();
- }
- }
- }else if(has("mozilla")){
- TextBox = declare(/*===== "dijit.form.TextBox.MozMixin", =====*/TextBox, {
- declaredClass: "dijit.form.TextBox", // for user code referencing declaredClass
- _onBlur: function(e){
- this.inherited(arguments);
- if(this.selectOnClick){
- // clear selection so that the next mouse click doesn't reselect
- this.textbox.selectionStart = this.textbox.selectionEnd = undefined;
- }
- }
- });
- }else{
- TextBox.prototype.declaredClass = "dijit.form.TextBox";
- }
- lang.setObject("dijit.form.TextBox", TextBox); // don't do direct assignment, it confuses API doc parser
- return TextBox;
- });
- },
- 'dojox/grid/DataGrid':function(){
- define("dojox/grid/DataGrid", [
- "../main",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/json",
- "dojo/_base/sniff",
- "dojo/_base/declare",
- "./_Grid",
- "./DataSelection",
- "dojo/_base/html"
- ], function(dojox, array, lang, json, has, declare, _Grid, DataSelection, html){
- /*=====
- declare("dojox.grid.__DataCellDef", dojox.grid.__CellDef, {
- constructor: function(){
- // field: String?
- // The attribute to read from the dojo.data item for the row.
- // fields: String[]?
- // An array of fields to grab the values of and pass as an array to the grid
- // get: Function?
- // function(rowIndex, item?){} rowIndex is of type Integer, item is of type
- // Object. This function will be called when a cell requests data. Returns
- // the unformatted data for the cell.
- }
- });
- =====*/
- /*=====
- declare("dojox.grid.__DataViewDef", dojox.grid.__ViewDef, {
- constructor: function(){
- // cells: dojox.grid.__DataCellDef[]|Array[dojox.grid.__DataCellDef[]]?
- // The structure of the cells within this grid.
- // defaultCell: dojox.grid.__DataCellDef?
- // A cell definition with default values for all cells in this view. If
- // a property is defined in a cell definition in the "cells" array and
- // this property, the cell definition's property will override this
- // property's property.
- }
- });
- =====*/
- var DataGrid = declare("dojox.grid.DataGrid", _Grid, {
- store: null,
- query: null,
- queryOptions: null,
- fetchText: '...',
- sortFields: null,
-
- // updateDelay: int
- // Time, in milliseconds, to delay updates automatically so that multiple
- // calls to onSet/onNew/onDelete don't keep rerendering the grid. Set
- // to 0 to immediately cause updates. A higher value will result in
- // better performance at the expense of responsiveness of the grid.
- updateDelay: 1,
- /*=====
- // structure: dojox.grid.__DataViewDef|dojox.grid.__DataViewDef[]|dojox.grid.__DataCellDef[]|Array[dojox.grid.__DataCellDef[]]
- // View layout defintion.
- structure: '',
- =====*/
- // You can specify items instead of a query, if you like. They do not need
- // to be loaded - but the must be items in the store
- items: null,
-
- _store_connects: null,
- _by_idty: null,
- _by_idx: null,
- _cache: null,
- _pages: null,
- _pending_requests: null,
- _bop: -1,
- _eop: -1,
- _requests: 0,
- rowCount: 0,
- _isLoaded: false,
- _isLoading: false,
-
- //keepSelection: Boolean
- // Whether keep selection after sort, filter etc.
- keepSelection: false,
-
- postCreate: function(){
- this._pages = [];
- this._store_connects = [];
- this._by_idty = {};
- this._by_idx = [];
- this._cache = [];
- this._pending_requests = {};
- this._setStore(this.store);
- this.inherited(arguments);
- },
-
- destroy: function(){
- this.selection.destroy();
- this.inherited(arguments);
- },
- createSelection: function(){
- this.selection = new DataSelection(this);
- },
- get: function(inRowIndex, inItem){
- // summary: Default data getter.
- // description:
- // Provides data to display in a grid cell. Called in grid cell context.
- // So this.cell.index is the column index.
- // inRowIndex: Integer
- // Row for which to provide data
- // returns:
- // Data to display for a given grid cell.
-
- if(inItem && this.field == "_item" && !this.fields){
- return inItem;
- }else if(inItem && this.fields){
- var ret = [];
- var s = this.grid.store;
- array.forEach(this.fields, function(f){
- ret = ret.concat(s.getValues(inItem, f));
- });
- return ret;
- }else if(!inItem && typeof inRowIndex === "string"){
- return this.inherited(arguments);
- }
- return (!inItem ? this.defaultValue : (!this.field ? this.value : (this.field == "_item" ? inItem : this.grid.store.getValue(inItem, this.field))));
- },
- _checkUpdateStatus: function(){
- if(this.updateDelay > 0){
- var iStarted = false;
- if(this._endUpdateDelay){
- clearTimeout(this._endUpdateDelay);
- delete this._endUpdateDelay;
- iStarted = true;
- }
- if(!this.updating){
- this.beginUpdate();
- iStarted = true;
- }
- if(iStarted){
- var _this = this;
- this._endUpdateDelay = setTimeout(function(){
- delete _this._endUpdateDelay;
- _this.endUpdate();
- }, this.updateDelay);
- }
- }
- },
-
- _onSet: function(item, attribute, oldValue, newValue){
- this._checkUpdateStatus();
- var idx = this.getItemIndex(item);
- if(idx>-1){
- this.updateRow(idx);
- }
- },
-
- _createItem: function(item, index){
- var idty = this._hasIdentity ? this.store.getIdentity(item) : json.toJson(this.query) + ":idx:" + index + ":sort:" + json.toJson(this.getSortProps());
- var o = this._by_idty[idty] = { idty: idty, item: item };
- return o;
- },
- _addItem: function(item, index, noUpdate){
- this._by_idx[index] = this._createItem(item, index);
- if(!noUpdate){
- this.updateRow(index);
- }
- },
- _onNew: function(item, parentInfo){
- this._checkUpdateStatus();
- var rowCount = this.get('rowCount');
- this._addingItem = true;
- this.updateRowCount(rowCount+1);
- this._addingItem = false;
- this._addItem(item, rowCount);
- this.showMessage();
- },
- _onDelete: function(item){
- this._checkUpdateStatus();
- var idx = this._getItemIndex(item, true);
- if(idx >= 0){
- // When a row is deleted, all rest rows are shifted down,
- // and migrate from page to page. If some page is not
- // loaded yet empty rows can migrate to initialized pages
- // without refreshing. It causes empty rows in some pages, see:
- // http://bugs.dojotoolkit.org/ticket/6818
- // this code fix this problem by reseting loaded page info
- this._pages = [];
- this._bop = -1;
- this._eop = -1;
- var o = this._by_idx[idx];
- this._by_idx.splice(idx, 1);
- delete this._by_idty[o.idty];
- this.updateRowCount(this.get('rowCount')-1);
- if(this.get('rowCount') === 0){
- this.showMessage(this.noDataMessage);
- }
- }
- if(this.selection.isSelected(idx)){
- this.selection.deselect(idx);
- this.selection.selected.splice(idx, 1);
- }
- },
- _onRevert: function(){
- this._refresh();
- },
- setStore: function(store, query, queryOptions){
- if(this._requestsPending(0)){
- return;
- }
- this._setQuery(query, queryOptions);
- this._setStore(store);
- this._refresh(true);
- },
-
- setQuery: function(query, queryOptions){
- if(this._requestsPending(0)){
- return;
- }
- this._setQuery(query, queryOptions);
- this._refresh(true);
- },
-
- setItems: function(items){
- this.items = items;
- this._setStore(this.store);
- this._refresh(true);
- },
-
- _setQuery: function(query, queryOptions){
- this.query = query;
- this.queryOptions = queryOptions || this.queryOptions;
- },
- _setStore: function(store){
- if(this.store && this._store_connects){
- array.forEach(this._store_connects, this.disconnect, this);
- }
- this.store = store;
- if(this.store){
- var f = this.store.getFeatures();
- var h = [];
- this._canEdit = !!f["dojo.data.api.Write"] && !!f["dojo.data.api.Identity"];
- this._hasIdentity = !!f["dojo.data.api.Identity"];
- if(!!f["dojo.data.api.Notification"] && !this.items){
- h.push(this.connect(this.store, "onSet", "_onSet"));
- h.push(this.connect(this.store, "onNew", "_onNew"));
- h.push(this.connect(this.store, "onDelete", "_onDelete"));
- }
- if(this._canEdit){
- h.push(this.connect(this.store, "revert", "_onRevert"));
- }
- this._store_connects = h;
- }
- },
- _onFetchBegin: function(size, req){
- if(!this.scroller){ return; }
- if(this.rowCount != size){
- if(req.isRender){
- this.scroller.init(size, this.keepRows, this.rowsPerPage);
- this.rowCount = size;
- this._setAutoHeightAttr(this.autoHeight, true);
- this._skipRowRenormalize = true;
- this.prerender();
- this._skipRowRenormalize = false;
- }else{
- this.updateRowCount(size);
- }
- }
- if(!size){
- this.views.render();
- this._resize();
- this.showMessage(this.noDataMessage);
- this.focus.initFocusView();
- }else{
- this.showMessage();
- }
- },
- _onFetchComplete: function(items, req){
- if(!this.scroller){ return; }
- if(items && items.length > 0){
- //console.log(items);
- array.forEach(items, function(item, idx){
- this._addItem(item, req.start+idx, true);
- }, this);
- this.updateRows(req.start, items.length);
- if(req.isRender){
- this.setScrollTop(0);
- this.postrender();
- }else if(this._lastScrollTop){
- this.setScrollTop(this._lastScrollTop);
- }
- if(has("ie")){
- html.setSelectable(this.domNode, this.selectable);
- }
- }
- delete this._lastScrollTop;
- if(!this._isLoaded){
- this._isLoading = false;
- this._isLoaded = true;
- }
- this._pending_requests[req.start] = false;
- },
- _onFetchError: function(err, req){
- console.log(err);
- delete this._lastScrollTop;
- if(!this._isLoaded){
- this._isLoading = false;
- this._isLoaded = true;
- this.showMessage(this.errorMessage);
- }
- this._pending_requests[req.start] = false;
- this.onFetchError(err, req);
- },
- onFetchError: function(err, req){
- },
- _fetch: function(start, isRender){
- start = start || 0;
- if(this.store && !this._pending_requests[start]){
- if(!this._isLoaded && !this._isLoading){
- this._isLoading = true;
- this.showMessage(this.loadingMessage);
- }
- this._pending_requests[start] = true;
- //console.log("fetch: ", start);
- try{
- if(this.items){
- var items = this.items;
- var store = this.store;
- this.rowsPerPage = items.length;
- var req = {
- start: start,
- count: this.rowsPerPage,
- isRender: isRender
- };
- this._onFetchBegin(items.length, req);
-
- // Load them if we need to
- var waitCount = 0;
- array.forEach(items, function(i){
- if(!store.isItemLoaded(i)){ waitCount++; }
- });
- if(waitCount === 0){
- this._onFetchComplete(items, req);
- }else{
- var onItem = function(item){
- waitCount--;
- if(waitCount === 0){
- this._onFetchComplete(items, req);
- }
- };
- array.forEach(items, function(i){
- if(!store.isItemLoaded(i)){
- store.loadItem({item: i, onItem: onItem, scope: this});
- }
- }, this);
- }
- }else{
- this.store.fetch({
- start: start,
- count: this.rowsPerPage,
- query: this.query,
- sort: this.getSortProps(),
- queryOptions: this.queryOptions,
- isRender: isRender,
- onBegin: lang.hitch(this, "_onFetchBegin"),
- onComplete: lang.hitch(this, "_onFetchComplete"),
- onError: lang.hitch(this, "_onFetchError")
- });
- }
- }catch(e){
- this._onFetchError(e, {start: start, count: this.rowsPerPage});
- }
- }
- },
- _clearData: function(){
- this.updateRowCount(0);
- this._by_idty = {};
- this._by_idx = [];
- this._pages = [];
- this._bop = this._eop = -1;
- this._isLoaded = false;
- this._isLoading = false;
- },
- getItem: function(idx){
- var data = this._by_idx[idx];
- if(!data||(data&&!data.item)){
- this._preparePage(idx);
- return null;
- }
- return data.item;
- },
- getItemIndex: function(item){
- return this._getItemIndex(item, false);
- },
-
- _getItemIndex: function(item, isDeleted){
- if(!isDeleted && !this.store.isItem(item)){
- return -1;
- }
- var idty = this._hasIdentity ? this.store.getIdentity(item) : null;
- for(var i=0, l=this._by_idx.length; i<l; i++){
- var d = this._by_idx[i];
- if(d && ((idty && d.idty == idty) || (d.item === item))){
- return i;
- }
- }
- return -1;
- },
- filter: function(query, reRender){
- this.query = query;
- if(reRender){
- this._clearData();
- }
- this._fetch();
- },
- _getItemAttr: function(idx, attr){
- var item = this.getItem(idx);
- return (!item ? this.fetchText : this.store.getValue(item, attr));
- },
- // rendering
- _render: function(){
- if(this.domNode.parentNode){
- this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
- this.prerender();
- this._fetch(0, true);
- }
- },
- // paging
- _requestsPending: function(inRowIndex){
- return this._pending_requests[inRowIndex];
- },
- _rowToPage: function(inRowIndex){
- return (this.rowsPerPage ? Math.floor(inRowIndex / this.rowsPerPage) : inRowIndex);
- },
- _pageToRow: function(inPageIndex){
- return (this.rowsPerPage ? this.rowsPerPage * inPageIndex : inPageIndex);
- },
- _preparePage: function(inRowIndex){
- if((inRowIndex < this._bop || inRowIndex >= this._eop) && !this._addingItem){
- var pageIndex = this._rowToPage(inRowIndex);
- this._needPage(pageIndex);
- this._bop = pageIndex * this.rowsPerPage;
- this._eop = this._bop + (this.rowsPerPage || this.get('rowCount'));
- }
- },
- _needPage: function(inPageIndex){
- if(!this._pages[inPageIndex]){
- this._pages[inPageIndex] = true;
- this._requestPage(inPageIndex);
- }
- },
- _requestPage: function(inPageIndex){
- var row = this._pageToRow(inPageIndex);
- var count = Math.min(this.rowsPerPage, this.get('rowCount') - row);
- if(count > 0){
- this._requests++;
- if(!this._requestsPending(row)){
- setTimeout(lang.hitch(this, "_fetch", row, false), 1);
- //this.requestRows(row, count);
- }
- }
- },
- getCellName: function(inCell){
- return inCell.field;
- //console.log(inCell);
- },
- _refresh: function(isRender){
- this._clearData();
- this._fetch(0, isRender);
- },
- sort: function(){
- this.edit.apply();
- this._lastScrollTop = this.scrollTop;
- this._refresh();
- },
- canSort: function(){
- return (!this._isLoading);
- },
- getSortProps: function(){
- var c = this.getCell(this.getSortIndex());
- if(!c){
- if(this.sortFields){
- return this.sortFields;
- }
- return null;
- }else{
- var desc = c["sortDesc"];
- var si = !(this.sortInfo>0);
- if(typeof desc == "undefined"){
- desc = si;
- }else{
- desc = si ? !desc : desc;
- }
- return [{ attribute: c.field, descending: desc }];
- }
- },
- styleRowState: function(inRow){
- // summary: Perform row styling
- if(this.store && this.store.getState){
- var states=this.store.getState(inRow.index), c='';
- for(var i=0, ss=["inflight", "error", "inserting"], s; s=ss[i]; i++){
- if(states[s]){
- c = ' dojoxGridRow-' + s;
- break;
- }
- }
- inRow.customClasses += c;
- }
- },
- onStyleRow: function(inRow){
- this.styleRowState(inRow);
- this.inherited(arguments);
- },
- // editing
- canEdit: function(inCell, inRowIndex){
- return this._canEdit;
- },
- _copyAttr: function(idx, attr){
- var row = {};
- var backstop = {};
- var src = this.getItem(idx);
- return this.store.getValue(src, attr);
- },
- doStartEdit: function(inCell, inRowIndex){
- if(!this._cache[inRowIndex]){
- this._cache[inRowIndex] = this._copyAttr(inRowIndex, inCell.field);
- }
- this.onStartEdit(inCell, inRowIndex);
- },
- doApplyCellEdit: function(inValue, inRowIndex, inAttrName){
- this.store.fetchItemByIdentity({
- identity: this._by_idx[inRowIndex].idty,
- onItem: lang.hitch(this, function(item){
- var oldValue = this.store.getValue(item, inAttrName);
- if(typeof oldValue == 'number'){
- inValue = isNaN(inValue) ? inValue : parseFloat(inValue);
- }else if(typeof oldValue == 'boolean'){
- inValue = inValue == 'true' ? true : inValue == 'false' ? false : inValue;
- }else if(oldValue instanceof Date){
- var asDate = new Date(inValue);
- inValue = isNaN(asDate.getTime()) ? inValue : asDate;
- }
- this.store.setValue(item, inAttrName, inValue);
- this.onApplyCellEdit(inValue, inRowIndex, inAttrName);
- })
- });
- },
- doCancelEdit: function(inRowIndex){
- var cache = this._cache[inRowIndex];
- if(cache){
- this.updateRow(inRowIndex);
- delete this._cache[inRowIndex];
- }
- this.onCancelEdit.apply(this, arguments);
- },
- doApplyEdit: function(inRowIndex, inDataAttr){
- var cache = this._cache[inRowIndex];
- /*if(cache){
- var data = this.getItem(inRowIndex);
- if(this.store.getValue(data, inDataAttr) != cache){
- this.update(cache, data, inRowIndex);
- }
- delete this._cache[inRowIndex];
- }*/
- this.onApplyEdit(inRowIndex);
- },
- removeSelectedRows: function(){
- // summary:
- // Remove the selected rows from the grid.
- if(this._canEdit){
- this.edit.apply();
- var fx = lang.hitch(this, function(items){
- if(items.length){
- array.forEach(items, this.store.deleteItem, this.store);
- this.selection.clear();
- }
- });
- if(this.allItemsSelected){
- this.store.fetch({
- query: this.query,
- queryOptions: this.queryOptions,
- onComplete: fx});
- }else{
- fx(this.selection.getSelected());
- }
- }
- }
- });
- DataGrid.cell_markupFactory = function(cellFunc, node, cellDef){
- var field = lang.trim(html.attr(node, "field")||"");
- if(field){
- cellDef.field = field;
- }
- cellDef.field = cellDef.field||cellDef.name;
- var fields = lang.trim(html.attr(node, "fields")||"");
- if(fields){
- cellDef.fields = fields.split(",");
- }
- if(cellFunc){
- cellFunc(node, cellDef);
- }
- };
- DataGrid.markupFactory = function(props, node, ctor, cellFunc){
- return _Grid.markupFactory(props, node, ctor,
- lang.partial(DataGrid.cell_markupFactory, cellFunc));
- };
- return DataGrid;
- });
- },
- 'dijit/_TemplatedMixin':function(){
- define("dijit/_TemplatedMixin", [
- "dojo/_base/lang", // lang.getObject
- "dojo/touch",
- "./_WidgetBase",
- "dojo/string", // string.substitute string.trim
- "dojo/cache", // dojo.cache
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/dom-construct", // domConstruct.destroy, domConstruct.toDom
- "dojo/_base/sniff", // has("ie")
- "dojo/_base/unload", // unload.addOnWindowUnload
- "dojo/_base/window" // win.doc
- ], function(lang, touch, _WidgetBase, string, cache, array, declare, domConstruct, has, unload, win) {
- /*=====
- var _WidgetBase = dijit._WidgetBase;
- =====*/
- // module:
- // dijit/_TemplatedMixin
- // summary:
- // Mixin for widgets that are instantiated from a template
- var _TemplatedMixin = declare("dijit._TemplatedMixin", null, {
- // summary:
- // Mixin for widgets that are instantiated from a template
- // templateString: [protected] String
- // A string that represents the widget template.
- // Use in conjunction with dojo.cache() to load from a file.
- templateString: null,
- // templatePath: [protected deprecated] String
- // Path to template (HTML file) for this widget relative to dojo.baseUrl.
- // Deprecated: use templateString with require([... "dojo/text!..."], ...) instead
- templatePath: null,
- // skipNodeCache: [protected] Boolean
- // If using a cached widget template nodes poses issues for a
- // particular widget class, it can set this property to ensure
- // that its template is always re-built from a string
- _skipNodeCache: false,
- // _earlyTemplatedStartup: Boolean
- // A fallback to preserve the 1.0 - 1.3 behavior of children in
- // templates having their startup called before the parent widget
- // fires postCreate. Defaults to 'false', causing child widgets to
- // have their .startup() called immediately before a parent widget
- // .startup(), but always after the parent .postCreate(). Set to
- // 'true' to re-enable to previous, arguably broken, behavior.
- _earlyTemplatedStartup: false,
- /*=====
- // _attachPoints: [private] String[]
- // List of widget attribute names associated with data-dojo-attach-point=... in the
- // template, ex: ["containerNode", "labelNode"]
- _attachPoints: [],
- =====*/
- /*=====
- // _attachEvents: [private] Handle[]
- // List of connections associated with data-dojo-attach-event=... in the
- // template
- _attachEvents: [],
- =====*/
- constructor: function(){
- this._attachPoints = [];
- this._attachEvents = [];
- },
- _stringRepl: function(tmpl){
- // summary:
- // Does substitution of ${foo} type properties in template string
- // tags:
- // private
- var className = this.declaredClass, _this = this;
- // Cache contains a string because we need to do property replacement
- // do the property replacement
- return string.substitute(tmpl, this, function(value, key){
- if(key.charAt(0) == '!'){ value = lang.getObject(key.substr(1), false, _this); }
- if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
- if(value == null){ return ""; }
- // Substitution keys beginning with ! will skip the transform step,
- // in case a user wishes to insert unescaped markup, e.g. ${!foo}
- return key.charAt(0) == "!" ? value :
- // Safer substitution, see heading "Attribute values" in
- // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
- value.toString().replace(/"/g,"""); //TODO: add &? use encodeXML method?
- }, this);
- },
- buildRendering: function(){
- // summary:
- // Construct the UI for this widget from a template, setting this.domNode.
- // tags:
- // protected
- if(!this.templateString){
- this.templateString = cache(this.templatePath, {sanitize: true});
- }
- // Lookup cached version of template, and download to cache if it
- // isn't there already. Returns either a DomNode or a string, depending on
- // whether or not the template contains ${foo} replacement parameters.
- var cached = _TemplatedMixin.getCachedTemplate(this.templateString, this._skipNodeCache);
- var node;
- if(lang.isString(cached)){
- node = domConstruct.toDom(this._stringRepl(cached));
- if(node.nodeType != 1){
- // Flag common problems such as templates with multiple top level nodes (nodeType == 11)
- throw new Error("Invalid template: " + cached);
- }
- }else{
- // if it's a node, all we have to do is clone it
- node = cached.cloneNode(true);
- }
- this.domNode = node;
- // Call down to _Widget.buildRendering() to get base classes assigned
- // TODO: change the baseClass assignment to _setBaseClassAttr
- this.inherited(arguments);
- // recurse through the node, looking for, and attaching to, our
- // attachment points and events, which should be defined on the template node.
- this._attachTemplateNodes(node, function(n,p){ return n.getAttribute(p); });
- this._beforeFillContent(); // hook for _WidgetsInTemplateMixin
- this._fillContent(this.srcNodeRef);
- },
- _beforeFillContent: function(){
- },
- _fillContent: function(/*DomNode*/ source){
- // summary:
- // Relocate source contents to templated container node.
- // this.containerNode must be able to receive children, or exceptions will be thrown.
- // tags:
- // protected
- var dest = this.containerNode;
- if(source && dest){
- while(source.hasChildNodes()){
- dest.appendChild(source.firstChild);
- }
- }
- },
- _attachTemplateNodes: function(rootNode, getAttrFunc){
- // summary:
- // Iterate through the template and attach functions and nodes accordingly.
- // Alternately, if rootNode is an array of widgets, then will process data-dojo-attach-point
- // etc. for those widgets.
- // description:
- // Map widget properties and functions to the handlers specified in
- // the dom node and it's descendants. This function iterates over all
- // nodes and looks for these properties:
- // * dojoAttachPoint/data-dojo-attach-point
- // * dojoAttachEvent/data-dojo-attach-event
- // rootNode: DomNode|Widget[]
- // the node to search for properties. All children will be searched.
- // getAttrFunc: Function
- // a function which will be used to obtain property for a given
- // DomNode/Widget
- // tags:
- // private
- var nodes = lang.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
- var x = lang.isArray(rootNode) ? 0 : -1;
- for(; x<nodes.length; x++){
- var baseNode = (x == -1) ? rootNode : nodes[x];
- if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){
- continue;
- }
- // Process data-dojo-attach-point
- var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point");
- if(attachPoint){
- var point, points = attachPoint.split(/\s*,\s*/);
- while((point = points.shift())){
- if(lang.isArray(this[point])){
- this[point].push(baseNode);
- }else{
- this[point]=baseNode;
- }
- this._attachPoints.push(point);
- }
- }
- // Process data-dojo-attach-event
- var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event");
- if(attachEvent){
- // NOTE: we want to support attributes that have the form
- // "domEvent: nativeEvent; ..."
- var event, events = attachEvent.split(/\s*,\s*/);
- var trim = lang.trim;
- while((event = events.shift())){
- if(event){
- var thisFunc = null;
- if(event.indexOf(":") != -1){
- // oh, if only JS had tuple assignment
- var funcNameArr = event.split(":");
- event = trim(funcNameArr[0]);
- thisFunc = trim(funcNameArr[1]);
- }else{
- event = trim(event);
- }
- if(!thisFunc){
- thisFunc = event;
- }
- // Map "press", "move" and "release" to keys.touch, keys.move, keys.release
- this._attachEvents.push(this.connect(baseNode, touch[event] || event, thisFunc));
- }
- }
- }
- }
- },
- destroyRendering: function(){
- // Delete all attach points to prevent IE6 memory leaks.
- array.forEach(this._attachPoints, function(point){
- delete this[point];
- }, this);
- this._attachPoints = [];
- // And same for event handlers
- array.forEach(this._attachEvents, this.disconnect, this);
- this._attachEvents = [];
- this.inherited(arguments);
- }
- });
- // key is templateString; object is either string or DOM tree
- _TemplatedMixin._templateCache = {};
- _TemplatedMixin.getCachedTemplate = function(templateString, alwaysUseString){
- // summary:
- // Static method to get a template based on the templatePath or
- // templateString key
- // templateString: String
- // The template
- // alwaysUseString: Boolean
- // Don't cache the DOM tree for this template, even if it doesn't have any variables
- // returns: Mixed
- // Either string (if there are ${} variables that need to be replaced) or just
- // a DOM tree (if the node can be cloned directly)
- // is it already cached?
- var tmplts = _TemplatedMixin._templateCache;
- var key = templateString;
- var cached = tmplts[key];
- if(cached){
- try{
- // 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
- if(!cached.ownerDocument || cached.ownerDocument == win.doc){
- // string or node of the same document
- return cached;
- }
- }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
- domConstruct.destroy(cached);
- }
- templateString = string.trim(templateString);
- if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
- // there are variables in the template so all we can do is cache the string
- return (tmplts[key] = templateString); //String
- }else{
- // there are no variables in the template so we can cache the DOM tree
- var node = domConstruct.toDom(templateString);
- if(node.nodeType != 1){
- throw new Error("Invalid template: " + templateString);
- }
- return (tmplts[key] = node); //Node
- }
- };
- if(has("ie")){
- unload.addOnWindowUnload(function(){
- var cache = _TemplatedMixin._templateCache;
- for(var key in cache){
- var value = cache[key];
- if(typeof value == "object"){ // value is either a string or a DOM node template
- domConstruct.destroy(value);
- }
- delete cache[key];
- }
- });
- }
- // These arguments can be specified for widgets which are used in templates.
- // Since any widget can be specified as sub widgets in template, mix it
- // into the base widget class. (This is a hack, but it's effective.)
- lang.extend(_WidgetBase,{
- dojoAttachEvent: "",
- dojoAttachPoint: ""
- });
- return _TemplatedMixin;
- });
- },
- 'dojox/grid/_FocusManager':function(){
- define("dojox/grid/_FocusManager", [
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/declare",
- "dojo/_base/connect",
- "dojo/_base/event",
- "dojo/_base/sniff",
- "dojo/query",
- "./util",
- "dojo/_base/html"
- ], function(array, lang, declare, connect, event, has, query, util, html){
- // focus management
- return declare("dojox.grid._FocusManager", null, {
- // summary:
- // Controls grid cell focus. Owned by grid and used internally for focusing.
- // Note: grid cell actually receives keyboard input only when cell is being edited.
- constructor: function(inGrid){
- this.grid = inGrid;
- this.cell = null;
- this.rowIndex = -1;
- this._connects = [];
- this._headerConnects = [];
- this.headerMenu = this.grid.headerMenu;
- this._connects.push(connect.connect(this.grid.domNode, "onfocus", this, "doFocus"));
- this._connects.push(connect.connect(this.grid.domNode, "onblur", this, "doBlur"));
- this._connects.push(connect.connect(this.grid.domNode, "mousedown", this, "_mouseDown"));
- this._connects.push(connect.connect(this.grid.domNode, "mouseup", this, "_mouseUp"));
- this._connects.push(connect.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
- this._connects.push(connect.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
- this._connects.push(connect.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
- this._connects.push(connect.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
- this._connects.push(connect.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
- },
- destroy: function(){
- array.forEach(this._connects, connect.disconnect);
- array.forEach(this._headerConnects, connect.disconnect);
- delete this.grid;
- delete this.cell;
- },
- _colHeadNode: null,
- _colHeadFocusIdx: null,
- _contextMenuBindNode: null,
- tabbingOut: false,
- focusClass: "dojoxGridCellFocus",
- focusView: null,
- initFocusView: function(){
- this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
- this._initColumnHeaders();
- },
- isFocusCell: function(inCell, inRowIndex){
- // summary:
- // states if the given cell is focused
- // inCell: object
- // grid cell object
- // inRowIndex: int
- // grid row index
- // returns:
- // true of the given grid cell is focused
- return (this.cell == inCell) && (this.rowIndex == inRowIndex);
- },
- isLastFocusCell: function(){
- if(this.cell){
- return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
- }
- return false;
- },
- isFirstFocusCell: function(){
- if(this.cell){
- return (this.rowIndex === 0) && (this.cell.index === 0);
- }
- return false;
- },
- isNoFocusCell: function(){
- return (this.rowIndex < 0) || !this.cell;
- },
- isNavHeader: function(){
- // summary:
- // states whether currently navigating among column headers.
- // returns:
- // true if focus is on a column header; false otherwise.
- return (!!this._colHeadNode);
- },
- getHeaderIndex: function(){
- // summary:
- // if one of the column headers currently has focus, return its index.
- // returns:
- // index of the focused column header, or -1 if none have focus.
- if(this._colHeadNode){
- return array.indexOf(this._findHeaderCells(), this._colHeadNode);
- }else{
- return -1;
- }
- },
- _focusifyCellNode: function(inBork){
- var n = this.cell && this.cell.getNode(this.rowIndex);
- if(n){
- html.toggleClass(n, this.focusClass, inBork);
- if(inBork){
- var sl = this.scrollIntoView();
- try{
- if(!this.grid.edit.isEditing()){
- util.fire(n, "focus");
- if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
- }
- }catch(e){}
- }
- }
- },
- _delayedCellFocus: function(){
- if(this.isNavHeader()||!this.grid.focused){
- return;
- }
- var n = this.cell && this.cell.getNode(this.rowIndex);
- if(n){
- try{
- if(!this.grid.edit.isEditing()){
- html.toggleClass(n, this.focusClass, true);
- if(this._colHeadNode){
- this.blurHeader();
- }
- util.fire(n, "focus");
- }
- }
- catch(e){}
- }
- },
- _delayedHeaderFocus: function(){
- if(this.isNavHeader()){
- this.focusHeader();
- this.grid.domNode.focus();
- }
- },
- _initColumnHeaders: function(){
- array.forEach(this._headerConnects, connect.disconnect);
- this._headerConnects = [];
- var headers = this._findHeaderCells();
- for(var i = 0; i < headers.length; i++){
- this._headerConnects.push(connect.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
- this._headerConnects.push(connect.connect(headers[i], "onblur", this, "doColHeaderBlur"));
- }
- },
- _findHeaderCells: function(){
- // This should be a one liner:
- // query("th[tabindex=-1]", this.grid.viewsHeaderNode);
- // But there is a bug in query() for IE -- see trac #7037.
- var allHeads = query("th", this.grid.viewsHeaderNode);
- var headers = [];
- for (var i = 0; i < allHeads.length; i++){
- var aHead = allHeads[i];
- var hasTabIdx = html.hasAttr(aHead, "tabIndex");
- var tabindex = html.attr(aHead, "tabIndex");
- if (hasTabIdx && tabindex < 0) {
- headers.push(aHead);
- }
- }
- return headers;
- },
- _setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
- //console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
- this.grid.domNode.setAttribute("aria-activedescendant",colHeaderNode.id);
- if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
- html.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
- }
- html.toggleClass(colHeaderNode,this.focusClass, true);
- this._colHeadNode = colHeaderNode;
- this._colHeadFocusIdx = colFocusIdx;
- this._scrollHeader(this._colHeadFocusIdx);
- },
- scrollIntoView: function(){
- var info = (this.cell ? this._scrollInfo(this.cell) : null);
- if(!info || !info.s){
- return null;
- }
- var rt = this.grid.scroller.findScrollTop(this.rowIndex);
- // place cell within horizontal view
- if(info.n && info.sr){
- if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
- info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
- }else if(info.n.offsetLeft < info.sr.l){
- info.s.scrollLeft = info.n.offsetLeft;
- }
- }
- // place cell within vertical view
- if(info.r && info.sr){
- if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
- this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
- }else if(rt < info.sr.t){
- this.grid.setScrollTop(rt);
- }
- }
- return info.s.scrollLeft;
- },
- _scrollInfo: function(cell, domNode){
- if(cell){
- var cl = cell,
- sbn = cl.view.scrollboxNode,
- sbnr = {
- w: sbn.clientWidth,
- l: sbn.scrollLeft,
- t: sbn.scrollTop,
- h: sbn.clientHeight
- },
- rn = cl.view.getRowNode(this.rowIndex);
- return {
- c: cl,
- s: sbn,
- sr: sbnr,
- n: (domNode ? domNode : cell.getNode(this.rowIndex)),
- r: rn
- };
- }
- return null;
- },
- _scrollHeader: function(currentIdx){
- var info = null;
- if(this._colHeadNode){
- var cell = this.grid.getCell(currentIdx);
- if(!cell){ return; }
- info = this._scrollInfo(cell, cell.getNode(0));
- }
- if(info && info.s && info.sr && info.n){
- // scroll horizontally as needed.
- var scroll = info.sr.l + info.sr.w;
- if(info.n.offsetLeft + info.n.offsetWidth > scroll){
- info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
- }else if(info.n.offsetLeft < info.sr.l){
- info.s.scrollLeft = info.n.offsetLeft;
- }else if(has("ie") <= 7 && cell && cell.view.headerNode){
- // Trac 7158: scroll dojoxGridHeader for IE7 and lower
- cell.view.headerNode.scrollLeft = info.s.scrollLeft;
- }
- }
- },
- _isHeaderHidden: function(){
- // summary:
- // determine if the grid headers are hidden
- // relies on documented technique of setting .dojoxGridHeader { display:none; }
- // returns: Boolean
- // true if headers are hidden
- // false if headers are not hidden
-
- var curView = this.focusView;
- if (!curView){
- // find one so we can determine if headers are hidden
- // there is no focusView after adding items to empty grid (test_data_grid_empty.html)
- for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
- if(cView.headerNode ){
- curView=cView;
- break;
- }
- }
- }
- return (curView && html.getComputedStyle(curView.headerNode).display == "none");
- },
- colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
- var headers = this._findHeaderCells();
- var view = this.focusView;
- if (!view) {
- for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
- // find first view with a tableMap in order to work with empty grid
- if(cView.header.tableMap.map ){
- view=cView;
- break;
- }
- }
- }
- var curHeader = headers[colIdx];
- if (!view || (colIdx == headers.length-1 && colIdx === 0)){
- return; // can't adjust single col. grid
- }
- view.content.baseDecorateEvent(e);
- // need to adjust event with header cell info since focus is no longer on header cell
- e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
- e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
- e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
- if (view.header.canResize(e)){
- var deltaObj = {
- l: delta
- };
- var drag = view.header.colResizeSetup(e,false);
- view.header.doResizeColumn(drag, null, deltaObj);
- view.update();
- }
- },
- styleRow: function(inRow){
- return;
- },
- setFocusIndex: function(inRowIndex, inCellIndex){
- // summary:
- // focuses the given grid cell
- // inRowIndex: int
- // grid row index
- // inCellIndex: int
- // grid cell index
- this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
- },
- setFocusCell: function(inCell, inRowIndex){
- // summary:
- // focuses the given grid cell
- // inCell: object
- // grid cell object
- // inRowIndex: int
- // grid row index
- if(inCell && !this.isFocusCell(inCell, inRowIndex)){
- this.tabbingOut = false;
- if (this._colHeadNode){
- this.blurHeader();
- }
- this._colHeadNode = this._colHeadFocusIdx = null;
- this.focusGridView();
- this._focusifyCellNode(false);
- this.cell = inCell;
- this.rowIndex = inRowIndex;
- this._focusifyCellNode(true);
- }
- // even if this cell isFocusCell, the document focus may need to be rejiggered
- // call opera on delay to prevent keypress from altering focus
- if(has("opera")){
- setTimeout(lang.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
- }else{
- this.grid.onCellFocus(this.cell, this.rowIndex);
- }
- },
- next: function(){
- // summary:
- // focus next grid cell
- if(this.cell){
- var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
- if(col > cc){
- col = 0;
- row++;
- }
- if(row > rc){
- col = cc;
- row = rc;
- }
- if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
- var nextCell = this.grid.getCell(col);
- if (!this.isLastFocusCell() && (!nextCell.editable ||
- this.grid.canEdit && !this.grid.canEdit(nextCell, row))){
- this.cell=nextCell;
- this.rowIndex=row;
- this.next();
- return;
- }
- }
- this.setFocusIndex(row, col);
- }
- },
- previous: function(){
- // summary:
- // focus previous grid cell
- if(this.cell){
- var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
- if(col < 0){
- col = this.grid.layout.cellCount-1;
- row--;
- }
- if(row < 0){
- row = 0;
- col = 0;
- }
- if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
- var prevCell = this.grid.getCell(col);
- if (!this.isFirstFocusCell() && !prevCell.editable){
- this.cell=prevCell;
- this.rowIndex=row;
- this.previous();
- return;
- }
- }
- this.setFocusIndex(row, col);
- }
- },
- move: function(inRowDelta, inColDelta) {
- // summary:
- // focus grid cell or simulate focus to column header based on position relative to current focus
- // inRowDelta: int
- // vertical distance from current focus
- // inColDelta: int
- // horizontal distance from current focus
- var colDir = inColDelta < 0 ? -1 : 1;
- // Handle column headers.
- if(this.isNavHeader()){
- var headers = this._findHeaderCells();
- var savedIdx = currentIdx = array.indexOf(headers, this._colHeadNode);
- currentIdx += inColDelta;
- while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
- // skip over hidden column headers
- currentIdx += colDir;
- }
- if((currentIdx >= 0) && (currentIdx < headers.length)){
- this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
- }
- }else{
- if(this.cell){
- // Handle grid proper.
- var sc = this.grid.scroller,
- r = this.rowIndex,
- rc = this.grid.rowCount-1,
- row = Math.min(rc, Math.max(0, r+inRowDelta));
- if(inRowDelta){
- if(inRowDelta>0){
- if(row > sc.getLastPageRow(sc.page)){
- //need to load additional data, let scroller do that
- this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
- }
- }else if(inRowDelta<0){
- if(row <= sc.getPageRow(sc.page)){
- //need to load additional data, let scroller do that
- this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
- }
- }
- }
- var cc = this.grid.layout.cellCount-1,
- i = this.cell.index,
- col = Math.min(cc, Math.max(0, i+inColDelta));
- var cell = this.grid.getCell(col);
- while(col>=0 && col < cc && cell && cell.hidden === true){
- // skip hidden cells
- col += colDir;
- cell = this.grid.getCell(col);
- }
- if (!cell || cell.hidden === true){
- // don't change col if would move to hidden
- col = i;
- }
- //skip hidden row|cell
- var n = cell.getNode(row);
- if(!n && inRowDelta){
- if((row + inRowDelta) >= 0 && (row + inRowDelta) <= rc){
- this.move(inRowDelta > 0 ? ++inRowDelta : --inRowDelta, inColDelta);
- }
- return;
- }else if((!n || html.style(n, "display") === "none") && inColDelta){
- if((col + inColDelta) >= 0 && (col + inColDelta) <= cc){
- this.move(inRowDelta, inColDelta > 0 ? ++inColDelta : --inColDelta);
- }
- return;
- }
- this.setFocusIndex(row, col);
- if(inRowDelta){
- this.grid.updateRow(r);
- }
- }
- }
- },
- previousKey: function(e){
- if(this.grid.edit.isEditing()){
- event.stop(e);
- this.previous();
- }else if(!this.isNavHeader() && !this._isHeaderHidden()) {
- this.grid.domNode.focus(); // will call doFocus and set focus into header.
- event.stop(e);
- }else{
- this.tabOut(this.grid.domNode);
- if (this._colHeadFocusIdx != null) { // clear grid header focus
- html.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
- this._colHeadFocusIdx = null;
- }
- this._focusifyCellNode(false);
- }
- },
- nextKey: function(e) {
- var isEmpty = (this.grid.rowCount === 0);
- if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
- this.focusHeader();
- event.stop(e);
- }else if(this.isNavHeader()){
- // if tabbing from col header, then go to grid proper.
- this.blurHeader();
- if(!this.findAndFocusGridCell()){
- this.tabOut(this.grid.lastFocusNode);
- }
- this._colHeadNode = this._colHeadFocusIdx= null;
- }else if(this.grid.edit.isEditing()){
- event.stop(e);
- this.next();
- }else{
- this.tabOut(this.grid.lastFocusNode);
- }
- },
- tabOut: function(inFocusNode){
- this.tabbingOut = true;
- inFocusNode.focus();
- },
- focusGridView: function(){
- util.fire(this.focusView, "focus");
- },
- focusGrid: function(inSkipFocusCell){
- this.focusGridView();
- this._focusifyCellNode(true);
- },
- findAndFocusGridCell: function(){
- // summary:
- // find the first focusable grid cell
- // returns: Boolean
- // true if focus was set to a cell
- // false if no cell found to set focus onto
-
- var didFocus = true;
- var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
- if (this.isNoFocusCell() && !isEmpty){
- var cellIdx = 0;
- var cell = this.grid.getCell(cellIdx);
- if (cell.hidden) {
- // if first cell isn't visible, use _colHeadFocusIdx
- // could also use a while loop to find first visible cell - not sure that is worth it
- cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
- }
- this.setFocusIndex(0, cellIdx);
- }
- else if (this.cell && !isEmpty){
- if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
- // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
- // scroll to that row
- this.grid.scrollToRow(this.rowIndex);
- }
- this.focusGrid();
- }else {
- didFocus = false;
- }
- this._colHeadNode = this._colHeadFocusIdx= null;
- return didFocus;
- },
- focusHeader: function(){
- var headerNodes = this._findHeaderCells();
- var saveColHeadFocusIdx = this._colHeadFocusIdx;
- if (this._isHeaderHidden()){
- // grid header is hidden, focus a cell
- this.findAndFocusGridCell();
- }
- else if (!this._colHeadFocusIdx) {
- if (this.isNoFocusCell()) {
- this._colHeadFocusIdx = 0;
- }
- else {
- this._colHeadFocusIdx = this.cell.index;
- }
- }
- this._colHeadNode = headerNodes[this._colHeadFocusIdx];
- while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
- this._colHeadNode.style.display == "none"){
- // skip over hidden column headers
- this._colHeadFocusIdx++;
- this._colHeadNode = headerNodes[this._colHeadFocusIdx];
- }
- if(this._colHeadNode && this._colHeadNode.style.display != "none"){
- // Column header cells know longer receive actual focus. So, for keyboard invocation of
- // contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
- // unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active. Reset
- // the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
- if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
- this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
- this.headerMenu.bindDomNode(this.grid.domNode);
- this._contextMenuBindNode = this.grid.domNode;
- }
- this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
- this._scrollHeader(this._colHeadFocusIdx);
- this._focusifyCellNode(false);
- }else {
- // all col head nodes are hidden - focus the grid
- this.findAndFocusGridCell();
- }
- },
- blurHeader: function(){
- html.removeClass(this._colHeadNode, this.focusClass);
- html.removeAttr(this.grid.domNode,"aria-activedescendant");
- // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
- if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
- var viewsHeader = this.grid.viewsHeaderNode;
- this.headerMenu.unBindDomNode(this.grid.domNode);
- this.headerMenu.bindDomNode(viewsHeader);
- this._contextMenuBindNode = viewsHeader;
- }
- },
- doFocus: function(e){
- // trap focus only for grid dom node
- if(e && e.target != e.currentTarget){
- event.stop(e);
- return;
- }
- // don't change focus if clicking on scroller bar
- if(this._clickFocus){
- return;
- }
- // do not focus for scrolling if grid is about to blur
- if(!this.tabbingOut){
- this.focusHeader();
- }
- this.tabbingOut = false;
- event.stop(e);
- },
- doBlur: function(e){
- event.stop(e); // FF2
- },
- doContextMenu: function(e){
- //stop contextMenu event if no header Menu to prevent default/browser contextMenu
- if (!this.headerMenu){
- event.stop(e);
- }
- },
- doLastNodeFocus: function(e){
- if (this.tabbingOut){
- this._focusifyCellNode(false);
- }else if(this.grid.rowCount >0){
- if (this.isNoFocusCell()){
- this.setFocusIndex(0,0);
- }
- this._focusifyCellNode(true);
- }else {
- this.focusHeader();
- }
- this.tabbingOut = false;
- event.stop(e); // FF2
- },
- doLastNodeBlur: function(e){
- event.stop(e); // FF2
- },
- doColHeaderFocus: function(e){
- this._setActiveColHeader(e.target,html.attr(e.target, "idx"),this._colHeadFocusIdx);
- this._scrollHeader(this.getHeaderIndex());
- event.stop(e);
- },
- doColHeaderBlur: function(e){
- html.toggleClass(e.target, this.focusClass, false);
- },
- _mouseDown: function(e){
- // a flag indicating grid is being focused by clicking
- this._clickFocus = dojo.some(this.grid.views.views, function(v){
- return v.scrollboxNode === e.target;
- });
- },
- _mouseUp: function(e){
- this._clickFocus = false;
- }
- });
- });
- },
- 'dojox/grid/EnhancedGrid':function(){
- define("dojox/grid/EnhancedGrid", [
- "dojo/_base/kernel",
- "../main",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/array",
- "dojo/_base/sniff",
- "dojo/dom",
- "dojo/dom-geometry",
- "dojo/i18n",
- "./DataGrid",
- "./DataSelection",
- "./enhanced/_PluginManager",
- "./enhanced/plugins/_SelectionPreserver",//default loaded plugin
- "dojo/i18n!./enhanced/nls/EnhancedGrid"
- ], function(dojo, dojox, declare, lang, array, has, dom, domGeometry, i18n,
- DataGrid, DataSelection, _PluginManager, _SelectionPreserver){
- dojo.experimental("dojox.grid.EnhancedGrid");
- var EnhancedGrid = declare("dojox.grid.EnhancedGrid", DataGrid, {
- // summary:
- // Provides enhanced features based on DataGrid
- //
- // description:
- // EnhancedGrid features are implemented as plugins that could be loaded on demand.
- // Explicit dojo.require() is needed to use these feature plugins.
- //
- // example:
- // A quick sample to use EnhancedGrid features:
- //
- // Step 1. Load EnhancedGrid and required features
- // | <script type="text/javascript">
- // | dojo.require("dojox.grid.EnhancedGrid");
- // | dojo.require("dojox.grid.enhanced.plugins.DnD");
- // | dojo.require("dojox.grid.enhanced.plugins.Menu");
- // | dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
- // | dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
- // | </script>
- //
- // Step 2. Use EnhancedGrid
- // - Via HTML markup
- // | <div dojoType="dojox.grid.EnhancedGrid" ...
- // | plugins="{nestedSorting: true, dnd: true, indirectSelection: true,
- // | menus:{headerMenu:"headerMenuId", rowMenu:"rowMenuId", cellMenu:"cellMenuId",
- // | selectedRegionMenu:"selectedRegionMenuId"}}">
- // | ...
- // | </div>
- //
- // - Or via JavaScript
- // | <script type="text/javascript">
- // | var grid = new dojox.grid.EnhancedGrid({plugins : {nestedSorting: true, dnd: true, indirectSelection: true,
- // | menus:{headerMenu:"headerMenuId", rowMenu:"rowMenuId", cellMenu:"cellMenuId",selectedRegionMenu:"selectedRegionMenuId"}},
- // | ... }, dojo.byId('gridDiv'));
- // | grid.startup();
- // | </script>
- //
- //
- // Plugin Support
- // [Note: Plugin support is still experimental]
- //
- // You can either customize the default plugins or add new ones, more details please see
- // - dojox.grid.enhanced._PluginManager
- // - dojox.grid.enhanced._Plugin
- // - dojox.grid.enhanced.plugins.*
- //plugins: Object
- // Plugin properties, e.g. {nestedSorting: true, dnd: true, ...}
- plugins: null,
- //pluginMgr: Object
- // Singleton plugin manager
- pluginMgr: null,
- //_pluginMgrClass: Object
- // Default plugin manager class
- _pluginMgrClass: _PluginManager,
- postMixInProperties: function(){
- //load nls bundle
- this._nls = i18n.getLocalization("dojox.grid.enhanced", "EnhancedGrid", this.lang);
- this.inherited(arguments);
- },
- postCreate: function(){
- //create plugin manager
- this.pluginMgr = new this._pluginMgrClass(this);
- this.pluginMgr.preInit();
- this.inherited(arguments);
- this.pluginMgr.postInit();
- },
- plugin: function(/*String*/name){
- // summary:
- // An easier way for getting a plugin, e.g. grid.plugin('dnd')
- return this.pluginMgr.getPlugin(name);
- },
- startup: function(){
- this.inherited(arguments);
- this.pluginMgr.startup();
- },
- createSelection: function(){
- this.selection = new dojox.grid.enhanced.DataSelection(this);
- },
- canSort: function(colIndex, field){
- // summary:
- // Overwritten
- return true;
- },
- doKeyEvent: function(e){
- // summary:
- // Overwritten, see _Grid.doKeyEvent()
- try{
- var view = this.focus.focusView;
- view.content.decorateEvent(e);
- if(!e.cell){ view.header.decorateEvent(e); }
- }catch(e){}
- this.inherited(arguments);
- },
- doApplyCellEdit: function(inValue, inRowIndex, inAttrName){
- // summary:
- // Overwritten, see DataGrid.doApplyCellEdit()
- if(!inAttrName){
- this.invalidated[inRowIndex] = true;
- return;
- }
- this.inherited(arguments);
- },
- mixin: function(target, source){
- var props = {};
- for(var p in source){
- if(p == '_inherited' || p == 'declaredClass' || p == 'constructor' ||
- source['privates'] && source['privates'][p]){
- continue;
- }
- props[p] = source[p];
- }
- lang.mixin(target, props);
- },
- _copyAttr: function(idx, attr){
- // summary:
- // Overwritten, see DataGrid._copyAttr()
- // Fix cell TAB navigation for single click editing
- if(!attr){ return; }
- return this.inherited(arguments);
- },
- _getHeaderHeight: function(){
- // summary:
- // Overwritten, see _Grid._getHeaderHeight()
- // Should include borders/margins of this.viewsHeaderNode
- this.inherited(arguments);
- return domGeometry.getMarginBox(this.viewsHeaderNode).h;
- },
- _fetch: function(start, isRender){
- // summary:
- // Overwritten, see DataGrid._fetch()
- if(this.items){
- return this.inherited(arguments);
- }
- start = start || 0;
- if(this.store && !this._pending_requests[start]){
- if(!this._isLoaded && !this._isLoading){
- this._isLoading = true;
- this.showMessage(this.loadingMessage);
- }
- this._pending_requests[start] = true;
- try{
- var req = {
- start: start,
- count: this.rowsPerPage,
- query: this.query,
- sort: this.getSortProps(),
- queryOptions: this.queryOptions,
- isRender: isRender,
- onBegin: lang.hitch(this, "_onFetchBegin"),
- onComplete: lang.hitch(this, "_onFetchComplete"),
- onError: lang.hitch(this, "_onFetchError")
- };
- this._storeLayerFetch(req);
- }catch(e){
- this._onFetchError(e, {start: start, count: this.rowsPerPage});
- }
- }
- return 0;
- },
- _storeLayerFetch: function(req){
- // summary:
- // Extracted fetch specifically for store layer use
- this.store.fetch(req);
- },
- getCellByField: function(field){
- return array.filter(this.layout.cells, function(cell){
- return cell.field == field;
- })[0];
- },
- onMouseUp: function(e){ },
- createView: function(){
- // summary
- // Overwrite: rewrite getCellX of view.header
- var view = this.inherited(arguments);
- if(has("mozilla")){
- var ascendDom = function(inNode, inWhile){
- for(var n = inNode; n && inWhile(n); n = n.parentNode){}
- return n;
- };//copied from dojox.grid._Builder
- var makeNotTagName = function(inTagName){
- var name = inTagName.toUpperCase();
- return function(node){ return node.tagName != name; };
- };//copied from dojox.grid._Builder
- var func = view.header.getCellX;
- view.header.getCellX = function(e){
- var x = func.call(view.header, e);
- var n = ascendDom(e.target, makeNotTagName("th"));
- if(n && n !== e.target && dom.isDescendant(e.target, n)){ x += n.firstChild.offsetLeft; }
- return x;
- };
- }
- return view;
- },
- destroy: function(){
- // summary:
- // Destroy all resources
- delete this._nls;
- this.pluginMgr.destroy();
- this.inherited(arguments);
- }
- });
- declare("dojox.grid.enhanced.DataSelection", DataSelection, {
- constructor: function(grid){
- if(grid.keepSelection){
- if(this.preserver){
- this.preserver.destroy();
- }
- this.preserver = new _SelectionPreserver(this);
- }
- },
- _range: function(inFrom, inTo){
- this.grid._selectingRange = true;
- this.inherited(arguments);
- this.grid._selectingRange = false;
- this.onChanged();
- },
- deselectAll: function(inItemOrIndex){
- this.grid._selectingRange = true;
- this.inherited(arguments);
- this.grid._selectingRange = false;
- this.onChanged();
- }
- });
- EnhancedGrid.markupFactory = function(props, node, ctor, cellFunc){
- return dojox.grid._Grid.markupFactory(props, node, ctor,
- lang.partial(DataGrid.cell_markupFactory, cellFunc));
- };
- EnhancedGrid.registerPlugin = function(clazz, props){
- _PluginManager.registerPlugin(clazz, props);
- };
- return EnhancedGrid;
- });
- },
- 'dijit/_CssStateMixin':function(){
- define("dijit/_CssStateMixin", [
- "dojo/touch",
- "dojo/_base/array", // array.forEach array.map
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.toggle
- "dojo/_base/lang", // lang.hitch
- "dojo/_base/window" // win.body
- ], function(touch, array, declare, domClass, lang, win){
- // module:
- // dijit/_CssStateMixin
- // summary:
- // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
- // state changes, and also higher-level state changes such becoming disabled or selected.
- return declare("dijit._CssStateMixin", [], {
- // summary:
- // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
- // state changes, and also higher-level state changes such becoming disabled or selected.
- //
- // description:
- // By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically
- // maintain CSS classes on the widget root node (this.domNode) depending on hover,
- // active, focus, etc. state. Ex: with a baseClass of dijitButton, it will apply the classes
- // dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it.
- //
- // It also sets CSS like dijitButtonDisabled based on widget semantic state.
- //
- // By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons
- // within the widget).
- // cssStateNodes: [protected] Object
- // List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus
- //.
- // Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names
- // (like "dijitUpArrowButton"). Example:
- // | {
- // | "upArrowButton": "dijitUpArrowButton",
- // | "downArrowButton": "dijitDownArrowButton"
- // | }
- // The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it
- // is hovered, etc.
- cssStateNodes: {},
- // hovering: [readonly] Boolean
- // True if cursor is over this widget
- hovering: false,
- // active: [readonly] Boolean
- // True if mouse was pressed while over this widget, and hasn't been released yet
- active: false,
- _applyAttributes: function(){
- // This code would typically be in postCreate(), but putting in _applyAttributes() for
- // performance: so the class changes happen before DOM is inserted into the document.
- // Change back to postCreate() in 2.0. See #11635.
- this.inherited(arguments);
- // Automatically monitor mouse events (essentially :hover and :active) on this.domNode
- array.forEach(["onmouseenter", "onmouseleave", touch.press], function(e){
- this.connect(this.domNode, e, "_cssMouseEvent");
- }, this);
- // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node
- array.forEach(["disabled", "readOnly", "checked", "selected", "focused", "state", "hovering", "active"], function(attr){
- this.watch(attr, lang.hitch(this, "_setStateClass"));
- }, this);
- // Events on sub nodes within the widget
- for(var ap in this.cssStateNodes){
- this._trackMouseState(this[ap], this.cssStateNodes[ap]);
- }
- // Set state initially; there's probably no hover/active/focus state but widget might be
- // disabled/readonly/checked/selected so we want to set CSS classes for those conditions.
- this._setStateClass();
- },
- _cssMouseEvent: function(/*Event*/ event){
- // summary:
- // Sets hovering and active properties depending on mouse state,
- // which triggers _setStateClass() to set appropriate CSS classes for this.domNode.
- if(!this.disabled){
- switch(event.type){
- case "mouseenter":
- case "mouseover": // generated on non-IE browsers even though we connected to mouseenter
- this._set("hovering", true);
- this._set("active", this._mouseDown);
- break;
- case "mouseleave":
- case "mouseout": // generated on non-IE browsers even though we connected to mouseleave
- this._set("hovering", false);
- this._set("active", false);
- break;
- case "mousedown":
- case "touchpress":
- this._set("active", true);
- this._mouseDown = true;
- // Set a global event to handle mouseup, so it fires properly
- // even if the cursor leaves this.domNode before the mouse up event.
- // Alternately could set active=false on mouseout.
- var mouseUpConnector = this.connect(win.body(), touch.release, function(){
- this._mouseDown = false;
- this._set("active", false);
- this.disconnect(mouseUpConnector);
- });
- break;
- }
- }
- },
- _setStateClass: function(){
- // summary:
- // Update the visual state of the widget by setting the css classes on this.domNode
- // (or this.stateNode if defined) by combining this.baseClass with
- // various suffixes that represent the current widget state(s).
- //
- // description:
- // In the case where a widget has multiple
- // states, it sets the class based on all possible
- // combinations. For example, an invalid form widget that is being hovered
- // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
- //
- // The widget may have one or more of the following states, determined
- // by this.state, this.checked, this.valid, and this.selected:
- // - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
- // - Incomplete - ValidationTextBox sets this.state to "Incomplete" if the current input value is not finished yet
- // - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
- // - Selected - ex: currently selected tab will have this.selected==true
- //
- // In addition, it may have one or more of the following states,
- // based on this.disabled and flags set in _onMouse (this.active, this.hovering) and from focus manager (this.focused):
- // - Disabled - if the widget is disabled
- // - Active - if the mouse (or space/enter key?) is being pressed down
- // - Focused - if the widget has focus
- // - Hover - if the mouse is over the widget
- // Compute new set of classes
- var newStateClasses = this.baseClass.split(" ");
- function multiply(modifier){
- newStateClasses = newStateClasses.concat(array.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier);
- }
- if(!this.isLeftToRight()){
- // For RTL mode we need to set an addition class like dijitTextBoxRtl.
- multiply("Rtl");
- }
- var checkedState = this.checked == "mixed" ? "Mixed" : (this.checked ? "Checked" : "");
- if(this.checked){
- multiply(checkedState);
- }
- if(this.state){
- multiply(this.state);
- }
- if(this.selected){
- multiply("Selected");
- }
- if(this.disabled){
- multiply("Disabled");
- }else if(this.readOnly){
- multiply("ReadOnly");
- }else{
- if(this.active){
- multiply("Active");
- }else if(this.hovering){
- multiply("Hover");
- }
- }
- if(this.focused){
- multiply("Focused");
- }
- // Remove old state classes and add new ones.
- // For performance concerns we only write into domNode.className once.
- var tn = this.stateNode || this.domNode,
- classHash = {}; // set of all classes (state and otherwise) for node
- array.forEach(tn.className.split(" "), function(c){ classHash[c] = true; });
- if("_stateClasses" in this){
- array.forEach(this._stateClasses, function(c){ delete classHash[c]; });
- }
- array.forEach(newStateClasses, function(c){ classHash[c] = true; });
- var newClasses = [];
- for(var c in classHash){
- newClasses.push(c);
- }
- tn.className = newClasses.join(" ");
- this._stateClasses = newStateClasses;
- },
- _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){
- // summary:
- // Track mouse/focus events on specified node and set CSS class on that node to indicate
- // current state. Usually not called directly, but via cssStateNodes attribute.
- // description:
- // Given class=foo, will set the following CSS class on the node
- // - fooActive: if the user is currently pressing down the mouse button while over the node
- // - fooHover: if the user is hovering the mouse over the node, but not pressing down a button
- // - fooFocus: if the node is focused
- //
- // Note that it won't set any classes if the widget is disabled.
- // node: DomNode
- // Should be a sub-node of the widget, not the top node (this.domNode), since the top node
- // is handled specially and automatically just by mixing in this class.
- // clazz: String
- // CSS class name (ex: dijitSliderUpArrow).
- // Current state of node (initially false)
- // NB: setting specifically to false because domClass.toggle() needs true boolean as third arg
- var hovering=false, active=false, focused=false;
- var self = this,
- cn = lang.hitch(this, "connect", node);
- function setClass(){
- var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly);
- domClass.toggle(node, clazz+"Hover", hovering && !active && !disabled);
- domClass.toggle(node, clazz+"Active", active && !disabled);
- domClass.toggle(node, clazz+"Focused", focused && !disabled);
- }
- // Mouse
- cn("onmouseenter", function(){
- hovering = true;
- setClass();
- });
- cn("onmouseleave", function(){
- hovering = false;
- active = false;
- setClass();
- });
- cn(touch.press, function(){
- active = true;
- setClass();
- });
- cn(touch.release, function(){
- active = false;
- setClass();
- });
- // Focus
- cn("onfocus", function(){
- focused = true;
- setClass();
- });
- cn("onblur", function(){
- focused = false;
- setClass();
- });
- // Just in case widget is enabled/disabled while it has focus/hover/active state.
- // Maybe this is overkill.
- this.watch("disabled", setClass);
- this.watch("readOnly", setClass);
- }
- });
- });
- },
- 'dojo/currency':function(){
- define("dojo/currency", ["./_base/kernel", "./_base/lang", "./_base/array", "./number", "./i18n", "./i18n!./cldr/nls/currency", "./cldr/monetary"], function(dojo, lang, darray, dnumber, i18n, nlsCurrency, cldrMonetary) {
- // module:
- // dojo/currency
- // summary:
- // TODOC
- lang.getObject("currency", true, dojo);
- /*=====
- dojo.currency = {
- // summary: localized formatting and parsing routines for currencies
- //
- // description: extends dojo.number to provide culturally-appropriate formatting of values
- // in various world currencies, including use of a currency symbol. The currencies are specified
- // by a three-letter international symbol in all uppercase, and support for the currencies is
- // provided by the data in `dojo.cldr`. The scripts generating dojo.cldr specify which
- // currency support is included. A fixed number of decimal places is determined based
- // on the currency type and is not determined by the 'pattern' argument. The fractional
- // portion is optional, by default, and variable length decimals are not supported.
- }
- =====*/
- dojo.currency._mixInDefaults = function(options){
- options = options || {};
- options.type = "currency";
- // Get locale-dependent currency data, like the symbol
- var bundle = i18n.getLocalization("dojo.cldr", "currency", options.locale) || {};
- // Mixin locale-independent currency data, like # of places
- var iso = options.currency;
- var data = cldrMonetary.getData(iso);
- darray.forEach(["displayName","symbol","group","decimal"], function(prop){
- data[prop] = bundle[iso+"_"+prop];
- });
- data.fractional = [true, false];
- // Mixin with provided options
- return lang.mixin(data, options);
- };
- /*=====
- dojo.declare("dojo.currency.__FormatOptions", [dojo.number.__FormatOptions], {
- // type: String?
- // Should not be set. Value is assumed to be "currency".
- // symbol: String?
- // localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
- // A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
- // currency: String?
- // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
- // For use with dojo.currency only.
- // places: Number?
- // number of decimal places to show. Default is defined based on which currency is used.
- type: "",
- symbol: "",
- currency: "",
- places: ""
- });
- =====*/
- dojo.currency.format = function(/*Number*/value, /*dojo.currency.__FormatOptions?*/options){
- // summary:
- // Format a Number as a currency, using locale-specific settings
- //
- // description:
- // Create a string from a Number using a known, localized pattern.
- // [Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Elements)
- // appropriate to the locale are chosen from the [CLDR](http://unicode.org/cldr)
- // as well as the appropriate symbols and delimiters and number of decimal places.
- //
- // value:
- // the number to be formatted.
- return dnumber.format(value, dojo.currency._mixInDefaults(options));
- };
- dojo.currency.regexp = function(/*dojo.number.__RegexpOptions?*/options){
- //
- // summary:
- // Builds the regular needed to parse a currency value
- //
- // description:
- // Returns regular expression with positive and negative match, group and decimal separators
- // Note: the options.places default, the number of decimal places to accept, is defined by the currency type.
- return dnumber.regexp(dojo.currency._mixInDefaults(options)); // String
- };
- /*=====
- dojo.declare("dojo.currency.__ParseOptions", [dojo.number.__ParseOptions], {
- // type: String?
- // Should not be set. Value is assumed to be currency.
- // currency: String?
- // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
- // For use with dojo.currency only.
- // symbol: String?
- // localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
- // A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
- // places: Number?
- // fixed number of decimal places to accept. The default is determined based on which currency is used.
- // fractional: Boolean?|Array?
- // Whether to include the fractional portion, where the number of decimal places are implied by the currency
- // or explicit 'places' parameter. The value [true,false] makes the fractional portion optional.
- // By default for currencies, it the fractional portion is optional.
- type: "",
- currency: "",
- symbol: "",
- places: "",
- fractional: ""
- });
- =====*/
- dojo.currency.parse = function(/*String*/expression, /*dojo.currency.__ParseOptions?*/options){
- //
- // summary:
- // Convert a properly formatted currency string to a primitive Number,
- // using locale-specific settings.
- //
- // description:
- // Create a Number from a string using a known, localized pattern.
- // [Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
- // are chosen appropriate to the locale, as well as the appropriate symbols and delimiters
- // and number of decimal places.
- //
- // expression: A string representation of a currency value
- return dnumber.parse(expression, dojo.currency._mixInDefaults(options));
- };
- return dojo.currency;
- });
- },
- 'dijit/_editor/html':function(){
- define("dijit/_editor/html", [
- "dojo/_base/lang", // lang.isString
- "dojo/_base/sniff", // has("ie")
- ".." // for exporting symbols to dijit._editor (remove for 2.0)
- ], function(lang, has, dijit){
- // module:
- // dijit/_editor/html
- // summary:
- // Utility functions used by editor
- lang.getObject("_editor", true, dijit);
- dijit._editor.escapeXml=function(/*String*/str, /*Boolean?*/noSingleQuotes){
- // summary:
- // Adds escape sequences for special characters in XML: &<>"'
- // Optionally skips escapes for single quotes
- str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);
- if(!noSingleQuotes){
- str = str.replace(/'/gm, "'");
- }
- return str; // string
- };
- dijit._editor.getNodeHtml=function(/* DomNode */node){
- var output;
- switch(node.nodeType){
- case 1: //element node
- var lName = node.nodeName.toLowerCase();
- if(!lName || lName.charAt(0) == "/"){
- // IE does some strange things with malformed HTML input, like
- // treating a close tag </span> without an open tag <span>, as
- // a new tag with tagName of /span. Corrupts output HTML, remove
- // them. Other browsers don't prefix tags that way, so will
- // never show up.
- return "";
- }
- output = '<' + lName;
- //store the list of attributes and sort it to have the
- //attributes appear in the dictionary order
- var attrarray = [];
- var attr;
- if(has("ie") && node.outerHTML){
- var s = node.outerHTML;
- s = s.substr(0, s.indexOf('>'))
- .replace(/(['"])[^"']*\1/g, ''); //to make the following regexp safe
- var reg = /(\b\w+)\s?=/g;
- var m, key;
- while((m = reg.exec(s))){
- key = m[1];
- if(key.substr(0,3) != '_dj'){
- if(key == 'src' || key == 'href'){
- if(node.getAttribute('_djrealurl')){
- attrarray.push([key,node.getAttribute('_djrealurl')]);
- continue;
- }
- }
- var val, match;
- switch(key){
- case 'style':
- val = node.style.cssText.toLowerCase();
- break;
- case 'class':
- val = node.className;
- break;
- case 'width':
- if(lName === "img"){
- // This somehow gets lost on IE for IMG tags and the like
- // and we have to find it in outerHTML, known IE oddity.
- match=/width=(\S+)/i.exec(s);
- if(match){
- val = match[1];
- }
- break;
- }
- case 'height':
- if(lName === "img"){
- // This somehow gets lost on IE for IMG tags and the like
- // and we have to find it in outerHTML, known IE oddity.
- match=/height=(\S+)/i.exec(s);
- if(match){
- val = match[1];
- }
- break;
- }
- default:
- val = node.getAttribute(key);
- }
- if(val != null){
- attrarray.push([key, val.toString()]);
- }
- }
- }
- }else{
- var i = 0;
- while((attr = node.attributes[i++])){
- //ignore all attributes starting with _dj which are
- //internal temporary attributes used by the editor
- var n = attr.name;
- if(n.substr(0,3) != '_dj' /*&&
- (attr.specified == undefined || attr.specified)*/){
- var v = attr.value;
- if(n == 'src' || n == 'href'){
- if(node.getAttribute('_djrealurl')){
- v = node.getAttribute('_djrealurl');
- }
- }
- attrarray.push([n,v]);
- }
- }
- }
- attrarray.sort(function(a,b){
- return a[0] < b[0] ? -1 : (a[0] == b[0] ? 0 : 1);
- });
- var j = 0;
- while((attr = attrarray[j++])){
- output += ' ' + attr[0] + '="' +
- (lang.isString(attr[1]) ? dijit._editor.escapeXml(attr[1], true) : attr[1]) + '"';
- }
- if(lName === "script"){
- // Browsers handle script tags differently in how you get content,
- // but innerHTML always seems to work, so insert its content that way
- // Yes, it's bad to allow script tags in the editor code, but some people
- // seem to want to do it, so we need to at least return them right.
- // other plugins/filters can strip them.
- output += '>' + node.innerHTML +'</' + lName + '>';
- }else{
- if(node.childNodes.length){
- output += '>' + dijit._editor.getChildrenHtml(node)+'</' + lName +'>';
- }else{
- switch(lName){
- case 'br':
- case 'hr':
- case 'img':
- case 'input':
- case 'base':
- case 'meta':
- case 'area':
- case 'basefont':
- // These should all be singly closed
- output += ' />';
- break;
- default:
- // Assume XML style separate closure for everything else.
- output += '></' + lName + '>';
- }
- }
- }
- break;
- case 4: // cdata
- case 3: // text
- // FIXME:
- output = dijit._editor.escapeXml(node.nodeValue, true);
- break;
- case 8: //comment
- // FIXME:
- output = '<!--' + dijit._editor.escapeXml(node.nodeValue, true) + '-->';
- break;
- default:
- output = "<!-- Element not recognized - Type: " + node.nodeType + " Name: " + node.nodeName + "-->";
- }
- return output;
- };
- dijit._editor.getChildrenHtml = function(/* DomNode */dom){
- // summary:
- // Returns the html content of a DomNode and children
- var out = "";
- if(!dom){ return out; }
- var nodes = dom["childNodes"] || dom;
- //IE issue.
- //If we have an actual node we can check parent relationships on for IE,
- //We should check, as IE sometimes builds invalid DOMS. If no parent, we can't check
- //And should just process it and hope for the best.
- var checkParent = !has("ie") || nodes !== dom;
- var node, i = 0;
- while((node = nodes[i++])){
- //IE is broken. DOMs are supposed to be a tree. But in the case of malformed HTML, IE generates a graph
- //meaning one node ends up with multiple references (multiple parents). This is totally wrong and invalid, but
- //such is what it is. We have to keep track and check for this because otherise the source output HTML will have dups.
- //No other browser generates a graph. Leave it to IE to break a fundamental DOM rule. So, we check the parent if we can
- //If we can't, nothing more we can do other than walk it.
- if(!checkParent || node.parentNode == dom){
- out += dijit._editor.getNodeHtml(node);
- }
- }
- return out; // String
- };
- return dijit._editor;
- });
- },
- 'dijit/place':function(){
- define("dijit/place", [
- "dojo/_base/array", // array.forEach array.map array.some
- "dojo/dom-geometry", // domGeometry.getMarginBox domGeometry.position
- "dojo/dom-style", // domStyle.getComputedStyle
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/window", // win.body
- "dojo/window", // winUtils.getBox
- "." // dijit (defining dijit.place to match API doc)
- ], function(array, domGeometry, domStyle, kernel, win, winUtils, dijit){
- // module:
- // dijit/place
- // summary:
- // Code to place a popup relative to another node
- function _place(/*DomNode*/ node, choices, layoutNode, aroundNodeCoords){
- // summary:
- // Given a list of spots to put node, put it at the first spot where it fits,
- // of if it doesn't fit anywhere then the place with the least overflow
- // choices: Array
- // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
- // Above example says to put the top-left corner of the node at (10,20)
- // layoutNode: Function(node, aroundNodeCorner, nodeCorner, size)
- // for things like tooltip, they are displayed differently (and have different dimensions)
- // based on their orientation relative to the parent. This adjusts the popup based on orientation.
- // It also passes in the available size for the popup, which is useful for tooltips to
- // tell them that their width is limited to a certain amount. layoutNode() may return a value expressing
- // how much the popup had to be modified to fit into the available space. This is used to determine
- // what the best placement is.
- // aroundNodeCoords: Object
- // Size of aroundNode, ex: {w: 200, h: 50}
- // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
- // viewport over document
- var view = winUtils.getBox();
- // This won't work if the node is inside a <div style="position: relative">,
- // so reattach it to win.doc.body. (Otherwise, the positioning will be wrong
- // and also it might get cutoff)
- if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
- win.body().appendChild(node);
- }
- var best = null;
- array.some(choices, function(choice){
- var corner = choice.corner;
- var pos = choice.pos;
- var overflow = 0;
- // calculate amount of space available given specified position of node
- var spaceAvailable = {
- w: {
- 'L': view.l + view.w - pos.x,
- 'R': pos.x - view.l,
- 'M': view.w
- }[corner.charAt(1)],
- h: {
- 'T': view.t + view.h - pos.y,
- 'B': pos.y - view.t,
- 'M': view.h
- }[corner.charAt(0)]
- };
- // configure node to be displayed in given position relative to button
- // (need to do this in order to get an accurate size for the node, because
- // a tooltip's size changes based on position, due to triangle)
- if(layoutNode){
- var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords);
- overflow = typeof res == "undefined" ? 0 : res;
- }
- // get node's size
- var style = node.style;
- var oldDisplay = style.display;
- var oldVis = style.visibility;
- if(style.display == "none"){
- style.visibility = "hidden";
- style.display = "";
- }
- var mb = domGeometry. getMarginBox(node);
- style.display = oldDisplay;
- style.visibility = oldVis;
- // coordinates and size of node with specified corner placed at pos,
- // and clipped by viewport
- var
- startXpos = {
- 'L': pos.x,
- 'R': pos.x - mb.w,
- 'M': Math.max(view.l, Math.min(view.l + view.w, pos.x + (mb.w >> 1)) - mb.w) // M orientation is more flexible
- }[corner.charAt(1)],
- startYpos = {
- 'T': pos.y,
- 'B': pos.y - mb.h,
- 'M': Math.max(view.t, Math.min(view.t + view.h, pos.y + (mb.h >> 1)) - mb.h)
- }[corner.charAt(0)],
- startX = Math.max(view.l, startXpos),
- startY = Math.max(view.t, startYpos),
- endX = Math.min(view.l + view.w, startXpos + mb.w),
- endY = Math.min(view.t + view.h, startYpos + mb.h),
- width = endX - startX,
- height = endY - startY;
- overflow += (mb.w - width) + (mb.h - height);
- if(best == null || overflow < best.overflow){
- best = {
- corner: corner,
- aroundCorner: choice.aroundCorner,
- x: startX,
- y: startY,
- w: width,
- h: height,
- overflow: overflow,
- spaceAvailable: spaceAvailable
- };
- }
- return !overflow;
- });
- // In case the best position is not the last one we checked, need to call
- // layoutNode() again.
- if(best.overflow && layoutNode){
- layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords);
- }
- // And then position the node. Do this last, after the layoutNode() above
- // has sized the node, due to browser quirks when the viewport is scrolled
- // (specifically that a Tooltip will shrink to fit as though the window was
- // scrolled to the left).
- //
- // In RTL mode, set style.right rather than style.left so in the common case,
- // window resizes move the popup along with the aroundNode.
- var l = domGeometry.isBodyLtr(),
- s = node.style;
- s.top = best.y + "px";
- s[l ? "left" : "right"] = (l ? best.x : view.w - best.x - best.w) + "px";
- s[l ? "right" : "left"] = "auto"; // needed for FF or else tooltip goes to far left
- return best;
- }
- /*=====
- dijit.place.__Position = function(){
- // x: Integer
- // horizontal coordinate in pixels, relative to document body
- // y: Integer
- // vertical coordinate in pixels, relative to document body
- this.x = x;
- this.y = y;
- };
- =====*/
- /*=====
- dijit.place.__Rectangle = function(){
- // x: Integer
- // horizontal offset in pixels, relative to document body
- // y: Integer
- // vertical offset in pixels, relative to document body
- // w: Integer
- // width in pixels. Can also be specified as "width" for backwards-compatibility.
- // h: Integer
- // height in pixels. Can also be specified as "height" from backwards-compatibility.
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- };
- =====*/
- return (dijit.place = {
- // summary:
- // Code to place a DOMNode relative to another DOMNode.
- // Load using require(["dijit/place"], function(place){ ... }).
- at: function(node, pos, corners, padding){
- // summary:
- // Positions one of the node's corners at specified position
- // such that node is fully visible in viewport.
- // description:
- // NOTE: node is assumed to be absolutely or relatively positioned.
- // node: DOMNode
- // The node to position
- // pos: dijit.place.__Position
- // Object like {x: 10, y: 20}
- // corners: String[]
- // Array of Strings representing order to try corners in, like ["TR", "BL"].
- // Possible values are:
- // * "BL" - bottom left
- // * "BR" - bottom right
- // * "TL" - top left
- // * "TR" - top right
- // padding: dijit.place.__Position?
- // optional param to set padding, to put some buffer around the element you want to position.
- // example:
- // Try to place node's top right corner at (10,20).
- // If that makes node go (partially) off screen, then try placing
- // bottom left corner at (10,20).
- // | place(node, {x: 10, y: 20}, ["TR", "BL"])
- var choices = array.map(corners, function(corner){
- var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
- if(padding){
- c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
- c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
- }
- return c;
- });
- return _place(node, choices);
- },
- around: function(
- /*DomNode*/ node,
- /*DomNode || dijit.place.__Rectangle*/ anchor,
- /*String[]*/ positions,
- /*Boolean*/ leftToRight,
- /*Function?*/ layoutNode){
- // summary:
- // Position node adjacent or kitty-corner to anchor
- // such that it's fully visible in viewport.
- //
- // description:
- // Place node such that corner of node touches a corner of
- // aroundNode, and that node is fully visible.
- //
- // anchor:
- // Either a DOMNode or a __Rectangle (object with x, y, width, height).
- //
- // positions:
- // Ordered list of positions to try matching up.
- // * before: places drop down to the left of the anchor node/widget, or to the right in the case
- // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
- // with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
- // * after: places drop down to the right of the anchor node/widget, or to the left in the case
- // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
- // with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
- // * before-centered: centers drop down to the left of the anchor node/widget, or to the right
- // in the case of RTL scripts like Hebrew and Arabic
- // * after-centered: centers drop down to the right of the anchor node/widget, or to the left
- // in the case of RTL scripts like Hebrew and Arabic
- // * above-centered: drop down is centered above anchor node
- // * above: drop down goes above anchor node, left sides aligned
- // * above-alt: drop down goes above anchor node, right sides aligned
- // * below-centered: drop down is centered above anchor node
- // * below: drop down goes below anchor node
- // * below-alt: drop down goes below anchor node, right sides aligned
- //
- // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
- // For things like tooltip, they are displayed differently (and have different dimensions)
- // based on their orientation relative to the parent. This adjusts the popup based on orientation.
- //
- // leftToRight:
- // True if widget is LTR, false if widget is RTL. Affects the behavior of "above" and "below"
- // positions slightly.
- //
- // example:
- // | placeAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'});
- // This will try to position node such that node's top-left corner is at the same position
- // as the bottom left corner of the aroundNode (ie, put node below
- // aroundNode, with left edges aligned). If that fails it will try to put
- // the bottom-right corner of node where the top right corner of aroundNode is
- // (ie, put node above aroundNode, with right edges aligned)
- //
- // if around is a DOMNode (or DOMNode id), convert to coordinates
- var aroundNodePos = (typeof anchor == "string" || "offsetWidth" in anchor)
- ? domGeometry.position(anchor, true)
- : anchor;
- // Compute position and size of visible part of anchor (it may be partially hidden by ancestor nodes w/scrollbars)
- if(anchor.parentNode){
- // ignore nodes between position:relative and position:absolute
- var sawPosAbsolute = domStyle.getComputedStyle(anchor).position == "absolute";
- var parent = anchor.parentNode;
- while(parent && parent.nodeType == 1 && parent.nodeName != "BODY"){ //ignoring the body will help performance
- var parentPos = domGeometry.position(parent, true),
- pcs = domStyle.getComputedStyle(parent);
- if(/relative|absolute/.test(pcs.position)){
- sawPosAbsolute = false;
- }
- if(!sawPosAbsolute && /hidden|auto|scroll/.test(pcs.overflow)){
- var bottomYCoord = Math.min(aroundNodePos.y + aroundNodePos.h, parentPos.y + parentPos.h);
- var rightXCoord = Math.min(aroundNodePos.x + aroundNodePos.w, parentPos.x + parentPos.w);
- aroundNodePos.x = Math.max(aroundNodePos.x, parentPos.x);
- aroundNodePos.y = Math.max(aroundNodePos.y, parentPos.y);
- aroundNodePos.h = bottomYCoord - aroundNodePos.y;
- aroundNodePos.w = rightXCoord - aroundNodePos.x;
- }
- if(pcs.position == "absolute"){
- sawPosAbsolute = true;
- }
- parent = parent.parentNode;
- }
- }
- var x = aroundNodePos.x,
- y = aroundNodePos.y,
- width = "w" in aroundNodePos ? aroundNodePos.w : (aroundNodePos.w = aroundNodePos.width),
- 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);
- // Convert positions arguments into choices argument for _place()
- var choices = [];
- function push(aroundCorner, corner){
- choices.push({
- aroundCorner: aroundCorner,
- corner: corner,
- pos: {
- x: {
- 'L': x,
- 'R': x + width,
- 'M': x + (width >> 1)
- }[aroundCorner.charAt(1)],
- y: {
- 'T': y,
- 'B': y + height,
- 'M': y + (height >> 1)
- }[aroundCorner.charAt(0)]
- }
- })
- }
- array.forEach(positions, function(pos){
- var ltr = leftToRight;
- switch(pos){
- case "above-centered":
- push("TM", "BM");
- break;
- case "below-centered":
- push("BM", "TM");
- break;
- case "after-centered":
- ltr = !ltr;
- // fall through
- case "before-centered":
- push(ltr ? "ML" : "MR", ltr ? "MR" : "ML");
- break;
- case "after":
- ltr = !ltr;
- // fall through
- case "before":
- push(ltr ? "TL" : "TR", ltr ? "TR" : "TL");
- push(ltr ? "BL" : "BR", ltr ? "BR" : "BL");
- break;
- case "below-alt":
- ltr = !ltr;
- // fall through
- case "below":
- // first try to align left borders, next try to align right borders (or reverse for RTL mode)
- push(ltr ? "BL" : "BR", ltr ? "TL" : "TR");
- push(ltr ? "BR" : "BL", ltr ? "TR" : "TL");
- break;
- case "above-alt":
- ltr = !ltr;
- // fall through
- case "above":
- // first try to align left borders, next try to align right borders (or reverse for RTL mode)
- push(ltr ? "TL" : "TR", ltr ? "BL" : "BR");
- push(ltr ? "TR" : "TL", ltr ? "BR" : "BL");
- break;
- default:
- // To assist dijit/_base/place, accept arguments of type {aroundCorner: "BL", corner: "TL"}.
- // Not meant to be used directly.
- push(pos.aroundCorner, pos.corner);
- }
- });
- var position = _place(node, choices, layoutNode, {w: width, h: height});
- position.aroundNodePos = aroundNodePos;
- return position;
- }
- });
- });
- },
- 'dijit/_HasDropDown':function(){
- define("dijit/_HasDropDown", [
- "dojo/_base/declare", // declare
- "dojo/_base/Deferred",
- "dojo/_base/event", // event.stop
- "dojo/dom", // dom.isDescendant
- "dojo/dom-attr", // domAttr.set
- "dojo/dom-class", // domClass.add domClass.contains domClass.remove
- "dojo/dom-geometry", // domGeometry.marginBox domGeometry.position
- "dojo/dom-style", // domStyle.set
- "dojo/has",
- "dojo/keys", // keys.DOWN_ARROW keys.ENTER keys.ESCAPE
- "dojo/_base/lang", // lang.hitch lang.isFunction
- "dojo/touch",
- "dojo/_base/window", // win.doc
- "dojo/window", // winUtils.getBox
- "./registry", // registry.byNode()
- "./focus",
- "./popup",
- "./_FocusMixin"
- ], function(declare, Deferred, event,dom, domAttr, domClass, domGeometry, domStyle, has, keys, lang, touch,
- win, winUtils, registry, focus, popup, _FocusMixin){
- /*=====
- var _FocusMixin = dijit._FocusMixin;
- =====*/
- // module:
- // dijit/_HasDropDown
- // summary:
- // Mixin for widgets that need drop down ability.
- return declare("dijit._HasDropDown", _FocusMixin, {
- // summary:
- // Mixin for widgets that need drop down ability.
- // _buttonNode: [protected] DomNode
- // The button/icon/node to click to display the drop down.
- // Can be set via a data-dojo-attach-point assignment.
- // If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
- _buttonNode: null,
- // _arrowWrapperNode: [protected] DomNode
- // Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
- // on where the drop down is set to be positioned.
- // Can be set via a data-dojo-attach-point assignment.
- // If missing, then _buttonNode will be used.
- _arrowWrapperNode: null,
- // _popupStateNode: [protected] DomNode
- // The node to set the popupActive class on.
- // Can be set via a data-dojo-attach-point assignment.
- // If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
- _popupStateNode: null,
- // _aroundNode: [protected] DomNode
- // The node to display the popup around.
- // Can be set via a data-dojo-attach-point assignment.
- // If missing, then domNode will be used.
- _aroundNode: null,
- // dropDown: [protected] Widget
- // The widget to display as a popup. This widget *must* be
- // defined before the startup function is called.
- dropDown: null,
- // autoWidth: [protected] Boolean
- // Set to true to make the drop down at least as wide as this
- // widget. Set to false if the drop down should just be its
- // default width
- autoWidth: true,
- // forceWidth: [protected] Boolean
- // Set to true to make the drop down exactly as wide as this
- // widget. Overrides autoWidth.
- forceWidth: false,
- // maxHeight: [protected] Integer
- // The max height for our dropdown.
- // Any dropdown taller than this will have scrollbars.
- // Set to 0 for no max height, or -1 to limit height to available space in viewport
- maxHeight: 0,
- // dropDownPosition: [const] String[]
- // This variable controls the position of the drop down.
- // It's an array of strings with the following values:
- //
- // * before: places drop down to the left of the target node/widget, or to the right in
- // the case of RTL scripts like Hebrew and Arabic
- // * after: places drop down to the right of the target node/widget, or to the left in
- // the case of RTL scripts like Hebrew and Arabic
- // * above: drop down goes above target node
- // * below: drop down goes below target node
- //
- // The list is positions is tried, in order, until a position is found where the drop down fits
- // within the viewport.
- //
- dropDownPosition: ["below","above"],
- // _stopClickEvents: Boolean
- // When set to false, the click events will not be stopped, in
- // case you want to use them in your subwidget
- _stopClickEvents: true,
- _onDropDownMouseDown: function(/*Event*/ e){
- // summary:
- // Callback when the user mousedown's on the arrow icon
- if(this.disabled || this.readOnly){ return; }
- // Prevent default to stop things like text selection, but don't stop propogation, so that:
- // 1. TimeTextBox etc. can focusthe <input> on mousedown
- // 2. dropDownButtonActive class applied by _CssStateMixin (on button depress)
- // 3. user defined onMouseDown handler fires
- e.preventDefault();
- this._docHandler = this.connect(win.doc, touch.release, "_onDropDownMouseUp");
- this.toggleDropDown();
- },
- _onDropDownMouseUp: function(/*Event?*/ e){
- // summary:
- // Callback when the user lifts their mouse after mouse down on the arrow icon.
- // If the drop down is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our
- // drop down widget. If the event is missing, then we are not
- // a mouseup event.
- //
- // This is useful for the common mouse movement pattern
- // with native browser <select> nodes:
- // 1. mouse down on the select node (probably on the arrow)
- // 2. move mouse to a menu item while holding down the mouse button
- // 3. mouse up. this selects the menu item as though the user had clicked it.
- if(e && this._docHandler){
- this.disconnect(this._docHandler);
- }
- var dropDown = this.dropDown, overMenu = false;
- if(e && this._opened){
- // This code deals with the corner-case when the drop down covers the original widget,
- // because it's so large. In that case mouse-up shouldn't select a value from the menu.
- // Find out if our target is somewhere in our dropdown widget,
- // but not over our _buttonNode (the clickable node)
- var c = domGeometry.position(this._buttonNode, true);
- if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) ||
- !(e.pageY >= c.y && e.pageY <= c.y + c.h)){
- var t = e.target;
- while(t && !overMenu){
- if(domClass.contains(t, "dijitPopup")){
- overMenu = true;
- }else{
- t = t.parentNode;
- }
- }
- if(overMenu){
- t = e.target;
- if(dropDown.onItemClick){
- var menuItem;
- while(t && !(menuItem = registry.byNode(t))){
- t = t.parentNode;
- }
- if(menuItem && menuItem.onClick && menuItem.getParent){
- menuItem.getParent().onItemClick(menuItem, e);
- }
- }
- return;
- }
- }
- }
- if(this._opened){
- if(dropDown.focus && dropDown.autoFocus !== false){
- // Focus the dropdown widget - do it on a delay so that we
- // don't steal our own focus.
- window.setTimeout(lang.hitch(dropDown, "focus"), 1);
- }
- }else{
- // The drop down arrow icon probably can't receive focus, but widget itself should get focus.
- // setTimeout() needed to make it work on IE (test DateTextBox)
- setTimeout(lang.hitch(this, "focus"), 0);
- }
- if(has("ios")){
- this._justGotMouseUp = true;
- setTimeout(lang.hitch(this, function(){
- this._justGotMouseUp = false;
- }), 0);
- }
- },
- _onDropDownClick: function(/*Event*/ e){
- if(has("ios") && !this._justGotMouseUp){
- // This branch fires on iPhone for ComboBox, because the button node is an <input> and doesn't
- // generate touchstart/touchend events. Pretend we just got a mouse down / mouse up.
- // The if(has("ios") is necessary since IE and desktop safari get spurious onclick events
- // when there are nested tables (specifically, clicking on a table that holds a dijit.form.Select,
- // but not on the Select itself, causes an onclick event on the Select)
- this._onDropDownMouseDown(e);
- this._onDropDownMouseUp(e);
- }
- // The drop down was already opened on mousedown/keydown; just need to call stopEvent().
- if(this._stopClickEvents){
- event.stop(e);
- }
- },
- buildRendering: function(){
- this.inherited(arguments);
- this._buttonNode = this._buttonNode || this.focusNode || this.domNode;
- this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode;
- // Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow
- // based on where drop down will normally appear
- var defaultPos = {
- "after" : this.isLeftToRight() ? "Right" : "Left",
- "before" : this.isLeftToRight() ? "Left" : "Right",
- "above" : "Up",
- "below" : "Down",
- "left" : "Left",
- "right" : "Right"
- }[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down";
- domClass.add(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton");
- },
- postCreate: function(){
- // summary:
- // set up nodes and connect our mouse and keypress events
- this.inherited(arguments);
- this.connect(this._buttonNode, touch.press, "_onDropDownMouseDown");
- this.connect(this._buttonNode, "onclick", "_onDropDownClick");
- this.connect(this.focusNode, "onkeypress", "_onKey");
- this.connect(this.focusNode, "onkeyup", "_onKeyUp");
- },
- destroy: function(){
- if(this.dropDown){
- // Destroy the drop down, unless it's already been destroyed. This can happen because
- // the drop down is a direct child of <body> even though it's logically my child.
- if(!this.dropDown._destroyed){
- this.dropDown.destroyRecursive();
- }
- delete this.dropDown;
- }
- this.inherited(arguments);
- },
- _onKey: function(/*Event*/ e){
- // summary:
- // Callback when the user presses a key while focused on the button node
- if(this.disabled || this.readOnly){ return; }
- var d = this.dropDown, target = e.target;
- if(d && this._opened && d.handleKey){
- if(d.handleKey(e) === false){
- /* false return code means that the drop down handled the key */
- event.stop(e);
- return;
- }
- }
- if(d && this._opened && e.charOrCode == keys.ESCAPE){
- this.closeDropDown();
- event.stop(e);
- }else if(!this._opened &&
- (e.charOrCode == keys.DOWN_ARROW ||
- ( (e.charOrCode == keys.ENTER || e.charOrCode == " ") &&
- //ignore enter and space if the event is for a text input
- ((target.tagName || "").toLowerCase() !== 'input' ||
- (target.type && target.type.toLowerCase() !== 'text'))))){
- // Toggle the drop down, but wait until keyup so that the drop down doesn't
- // get a stray keyup event, or in the case of key-repeat (because user held
- // down key for too long), stray keydown events
- this._toggleOnKeyUp = true;
- event.stop(e);
- }
- },
- _onKeyUp: function(){
- if(this._toggleOnKeyUp){
- delete this._toggleOnKeyUp;
- this.toggleDropDown();
- var d = this.dropDown; // drop down may not exist until toggleDropDown() call
- if(d && d.focus){
- setTimeout(lang.hitch(d, "focus"), 1);
- }
- }
- },
- _onBlur: function(){
- // summary:
- // Called magically when focus has shifted away from this widget and it's dropdown
- // Don't focus on button if the user has explicitly focused on something else (happens
- // when user clicks another control causing the current popup to close)..
- // But if focus is inside of the drop down then reset focus to me, because IE doesn't like
- // it when you display:none a node with focus.
- var focusMe = focus.curNode && this.dropDown && dom.isDescendant(focus.curNode, this.dropDown.domNode);
- this.closeDropDown(focusMe);
- this.inherited(arguments);
- },
- isLoaded: function(){
- // summary:
- // Returns true if the dropdown exists and it's data is loaded. This can
- // be overridden in order to force a call to loadDropDown().
- // tags:
- // protected
- return true;
- },
- loadDropDown: function(/*Function*/ loadCallback){
- // summary:
- // Creates the drop down if it doesn't exist, loads the data
- // if there's an href and it hasn't been loaded yet, and then calls
- // the given callback.
- // tags:
- // protected
- // TODO: for 2.0, change API to return a Deferred, instead of calling loadCallback?
- loadCallback();
- },
- loadAndOpenDropDown: function(){
- // summary:
- // Creates the drop down if it doesn't exist, loads the data
- // if there's an href and it hasn't been loaded yet, and
- // then opens the drop down. This is basically a callback when the
- // user presses the down arrow button to open the drop down.
- // returns: Deferred
- // Deferred for the drop down widget that
- // fires when drop down is created and loaded
- // tags:
- // protected
- var d = new Deferred(),
- afterLoad = lang.hitch(this, function(){
- this.openDropDown();
- d.resolve(this.dropDown);
- });
- if(!this.isLoaded()){
- this.loadDropDown(afterLoad);
- }else{
- afterLoad();
- }
- return d;
- },
- toggleDropDown: function(){
- // summary:
- // Callback when the user presses the down arrow button or presses
- // the down arrow key to open/close the drop down.
- // Toggle the drop-down widget; if it is up, close it, if not, open it
- // tags:
- // protected
- if(this.disabled || this.readOnly){ return; }
- if(!this._opened){
- this.loadAndOpenDropDown();
- }else{
- this.closeDropDown();
- }
- },
- openDropDown: function(){
- // summary:
- // Opens the dropdown for this widget. To be called only when this.dropDown
- // has been created and is ready to display (ie, it's data is loaded).
- // returns:
- // return value of dijit.popup.open()
- // tags:
- // protected
- var dropDown = this.dropDown,
- ddNode = dropDown.domNode,
- aroundNode = this._aroundNode || this.domNode,
- self = this;
- // Prepare our popup's height and honor maxHeight if it exists.
- // TODO: isn't maxHeight dependent on the return value from dijit.popup.open(),
- // ie, dependent on how much space is available (BK)
- if(!this._preparedNode){
- this._preparedNode = true;
- // Check if we have explicitly set width and height on the dropdown widget dom node
- if(ddNode.style.width){
- this._explicitDDWidth = true;
- }
- if(ddNode.style.height){
- this._explicitDDHeight = true;
- }
- }
- // Code for resizing dropdown (height limitation, or increasing width to match my width)
- if(this.maxHeight || this.forceWidth || this.autoWidth){
- var myStyle = {
- display: "",
- visibility: "hidden"
- };
- if(!this._explicitDDWidth){
- myStyle.width = "";
- }
- if(!this._explicitDDHeight){
- myStyle.height = "";
- }
- domStyle.set(ddNode, myStyle);
- // Figure out maximum height allowed (if there is a height restriction)
- var maxHeight = this.maxHeight;
- if(maxHeight == -1){
- // limit height to space available in viewport either above or below my domNode
- // (whichever side has more room)
- var viewport = winUtils.getBox(),
- position = domGeometry.position(aroundNode, false);
- maxHeight = Math.floor(Math.max(position.y, viewport.h - (position.y + position.h)));
- }
- // Attach dropDown to DOM and make make visibility:hidden rather than display:none
- // so we call startup() and also get the size
- popup.moveOffScreen(dropDown);
- if(dropDown.startup && !dropDown._started){
- dropDown.startup(); // this has to be done after being added to the DOM
- }
- // Get size of drop down, and determine if vertical scroll bar needed
- var mb = domGeometry.getMarginSize(ddNode);
- var overHeight = (maxHeight && mb.h > maxHeight);
- domStyle.set(ddNode, {
- overflowX: "hidden",
- overflowY: overHeight ? "auto" : "hidden"
- });
- if(overHeight){
- mb.h = maxHeight;
- if("w" in mb){
- mb.w += 16; // room for vertical scrollbar
- }
- }else{
- delete mb.h;
- }
- // Adjust dropdown width to match or be larger than my width
- if(this.forceWidth){
- mb.w = aroundNode.offsetWidth;
- }else if(this.autoWidth){
- mb.w = Math.max(mb.w, aroundNode.offsetWidth);
- }else{
- delete mb.w;
- }
- // And finally, resize the dropdown to calculated height and width
- if(lang.isFunction(dropDown.resize)){
- dropDown.resize(mb);
- }else{
- domGeometry.setMarginBox(ddNode, mb);
- }
- }
- var retVal = popup.open({
- parent: this,
- popup: dropDown,
- around: aroundNode,
- orient: this.dropDownPosition,
- onExecute: function(){
- self.closeDropDown(true);
- },
- onCancel: function(){
- self.closeDropDown(true);
- },
- onClose: function(){
- domAttr.set(self._popupStateNode, "popupActive", false);
- domClass.remove(self._popupStateNode, "dijitHasDropDownOpen");
- self._opened = false;
- }
- });
- domAttr.set(this._popupStateNode, "popupActive", "true");
- domClass.add(self._popupStateNode, "dijitHasDropDownOpen");
- this._opened=true;
- // TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
- return retVal;
- },
- closeDropDown: function(/*Boolean*/ focus){
- // summary:
- // Closes the drop down on this widget
- // focus:
- // If true, refocuses the button widget
- // tags:
- // protected
- if(this._opened){
- if(focus){ this.focus(); }
- popup.close(this.dropDown);
- this._opened = false;
- }
- }
- });
- });
- },
- 'dijit/_editor/plugins/EnterKeyHandling':function(){
- define("dijit/_editor/plugins/EnterKeyHandling", [
- "dojo/_base/declare", // declare
- "dojo/dom-construct", // domConstruct.destroy domConstruct.place
- "dojo/_base/event", // event.stop
- "dojo/keys", // keys.ENTER
- "dojo/_base/lang",
- "dojo/_base/sniff", // has("ie") has("mozilla") has("webkit")
- "dojo/_base/window", // win.global win.withGlobal
- "dojo/window", // winUtils.scrollIntoView
- "../_Plugin",
- "../RichText",
- "../range",
- "../selection"
- ], function(declare, domConstruct, event, keys, lang, has, win, winUtils, _Plugin, RichText, rangeapi, selectionapi){
- /*=====
- var _Plugin = dijit._editor._Plugin;
- =====*/
- // module:
- // dijit/_editor/plugins/EnterKeyHandling
- // summary:
- // This plugin tries to make all browsers behave consistently with regard to
- // how ENTER behaves in the editor window. It traps the ENTER key and alters
- // the way DOM is constructed in certain cases to try to commonize the generated
- // DOM and behaviors across browsers.
- return declare("dijit._editor.plugins.EnterKeyHandling", _Plugin, {
- // summary:
- // This plugin tries to make all browsers behave consistently with regard to
- // how ENTER behaves in the editor window. It traps the ENTER key and alters
- // the way DOM is constructed in certain cases to try to commonize the generated
- // DOM and behaviors across browsers.
- //
- // description:
- // This plugin has three modes:
- //
- // * blockNodeForEnter=BR
- // * blockNodeForEnter=DIV
- // * blockNodeForEnter=P
- //
- // In blockNodeForEnter=P, the ENTER key starts a new
- // paragraph, and shift-ENTER starts a new line in the current paragraph.
- // For example, the input:
- //
- // | first paragraph <shift-ENTER>
- // | second line of first paragraph <ENTER>
- // | second paragraph
- //
- // will generate:
- //
- // | <p>
- // | first paragraph
- // | <br/>
- // | second line of first paragraph
- // | </p>
- // | <p>
- // | second paragraph
- // | </p>
- //
- // In BR and DIV mode, the ENTER key conceptually goes to a new line in the
- // current paragraph, and users conceptually create a new paragraph by pressing ENTER twice.
- // For example, if the user enters text into an editor like this:
- //
- // | one <ENTER>
- // | two <ENTER>
- // | three <ENTER>
- // | <ENTER>
- // | four <ENTER>
- // | five <ENTER>
- // | six <ENTER>
- //
- // It will appear on the screen as two 'paragraphs' of three lines each. Markupwise, this generates:
- //
- // BR:
- // | one<br/>
- // | two<br/>
- // | three<br/>
- // | <br/>
- // | four<br/>
- // | five<br/>
- // | six<br/>
- //
- // DIV:
- // | <div>one</div>
- // | <div>two</div>
- // | <div>three</div>
- // | <div> </div>
- // | <div>four</div>
- // | <div>five</div>
- // | <div>six</div>
- // blockNodeForEnter: String
- // This property decides the behavior of Enter key. It can be either P,
- // DIV, BR, or empty (which means disable this feature). Anything else
- // will trigger errors. The default is 'BR'
- //
- // See class description for more details.
- blockNodeForEnter: 'BR',
- constructor: function(args){
- if(args){
- if("blockNodeForEnter" in args){
- args.blockNodeForEnter = args.blockNodeForEnter.toUpperCase();
- }
- lang.mixin(this,args);
- }
- },
- setEditor: function(editor){
- // Overrides _Plugin.setEditor().
- if(this.editor === editor){ return; }
- this.editor = editor;
- if(this.blockNodeForEnter == 'BR'){
- // While Moz has a mode tht mostly works, it's still a little different,
- // So, try to just have a common mode and be consistent. Which means
- // we need to enable customUndo, if not already enabled.
- this.editor.customUndo = true;
- editor.onLoadDeferred.then(lang.hitch(this,function(d){
- this.connect(editor.document, "onkeypress", function(e){
- if(e.charOrCode == keys.ENTER){
- // Just do it manually. The handleEnterKey has a shift mode that
- // Always acts like <br>, so just use it.
- var ne = lang.mixin({},e);
- ne.shiftKey = true;
- if(!this.handleEnterKey(ne)){
- event.stop(e);
- }
- }
- });
- if(has("ie") == 9){
- this.connect(editor.document, "onpaste", function(e){
- setTimeout(dojo.hitch(this, function(){
- // Use the old range/selection code to kick IE 9 into updating
- // its range by moving it back, then forward, one 'character'.
- var r = this.editor.document.selection.createRange();
- r.move('character',-1);
- r.select();
- r.move('character',1);
- r.select();
- }),0);
- });
- }
- return d;
- }));
- }else if(this.blockNodeForEnter){
- // add enter key handler
- // FIXME: need to port to the new event code!!
- var h = lang.hitch(this,this.handleEnterKey);
- editor.addKeyHandler(13, 0, 0, h); //enter
- editor.addKeyHandler(13, 0, 1, h); //shift+enter
- this.connect(this.editor,'onKeyPressed','onKeyPressed');
- }
- },
- onKeyPressed: function(){
- // summary:
- // Handler for keypress events.
- // tags:
- // private
- if(this._checkListLater){
- if(win.withGlobal(this.editor.window, 'isCollapsed', dijit)){
- var liparent=win.withGlobal(this.editor.window, 'getAncestorElement', selectionapi, ['LI']);
- if(!liparent){
- // circulate the undo detection code by calling RichText::execCommand directly
- RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter);
- // set the innerHTML of the new block node
- var block = win.withGlobal(this.editor.window, 'getAncestorElement', selectionapi, [this.blockNodeForEnter]);
- if(block){
- block.innerHTML=this.bogusHtmlContent;
- if(has("ie")){
- // move to the start by moving backwards one char
- var r = this.editor.document.selection.createRange();
- r.move('character',-1);
- r.select();
- }
- }else{
- console.error('onKeyPressed: Cannot find the new block node'); // FIXME
- }
- }else{
- if(has("mozilla")){
- if(liparent.parentNode.parentNode.nodeName == 'LI'){
- liparent=liparent.parentNode.parentNode;
- }
- }
- var fc=liparent.firstChild;
- if(fc && fc.nodeType == 1 && (fc.nodeName == 'UL' || fc.nodeName == 'OL')){
- liparent.insertBefore(fc.ownerDocument.createTextNode('\xA0'),fc);
- var newrange = rangeapi.create(this.editor.window);
- newrange.setStart(liparent.firstChild,0);
- var selection = rangeapi.getSelection(this.editor.window, true);
- selection.removeAllRanges();
- selection.addRange(newrange);
- }
- }
- }
- this._checkListLater = false;
- }
- if(this._pressedEnterInBlock){
- // the new created is the original current P, so we have previousSibling below
- if(this._pressedEnterInBlock.previousSibling){
- this.removeTrailingBr(this._pressedEnterInBlock.previousSibling);
- }
- delete this._pressedEnterInBlock;
- }
- },
- // bogusHtmlContent: [private] String
- // HTML to stick into a new empty block
- bogusHtmlContent: ' ', //
- // blockNodes: [private] Regex
- // Regex for testing if a given tag is a block level (display:block) tag
- blockNodes: /^(?:P|H1|H2|H3|H4|H5|H6|LI)$/,
- handleEnterKey: function(e){
- // summary:
- // Handler for enter key events when blockNodeForEnter is DIV or P.
- // description:
- // Manually handle enter key event to make the behavior consistent across
- // all supported browsers. See class description for details.
- // tags:
- // private
- var selection, range, newrange, startNode, endNode, brNode, doc=this.editor.document,br,rs,txt;
- if(e.shiftKey){ // shift+enter always generates <br>
- var parent = win.withGlobal(this.editor.window, "getParentElement", selectionapi);
- var header = rangeapi.getAncestor(parent,this.blockNodes);
- if(header){
- if(header.tagName == 'LI'){
- return true; // let browser handle
- }
- selection = rangeapi.getSelection(this.editor.window);
- range = selection.getRangeAt(0);
- if(!range.collapsed){
- range.deleteContents();
- selection = rangeapi.getSelection(this.editor.window);
- range = selection.getRangeAt(0);
- }
- if(rangeapi.atBeginningOfContainer(header, range.startContainer, range.startOffset)){
- br=doc.createElement('br');
- newrange = rangeapi.create(this.editor.window);
- header.insertBefore(br,header.firstChild);
- newrange.setStartAfter(br);
- selection.removeAllRanges();
- selection.addRange(newrange);
- }else if(rangeapi.atEndOfContainer(header, range.startContainer, range.startOffset)){
- newrange = rangeapi.create(this.editor.window);
- br=doc.createElement('br');
- header.appendChild(br);
- header.appendChild(doc.createTextNode('\xA0'));
- newrange.setStart(header.lastChild,0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- }else{
- rs = range.startContainer;
- if(rs && rs.nodeType == 3){
- // Text node, we have to split it.
- txt = rs.nodeValue;
- win.withGlobal(this.editor.window, function(){
- startNode = doc.createTextNode(txt.substring(0, range.startOffset));
- endNode = doc.createTextNode(txt.substring(range.startOffset));
- brNode = doc.createElement("br");
- if(endNode.nodeValue == "" && has("webkit")){
- endNode = doc.createTextNode('\xA0')
- }
- domConstruct.place(startNode, rs, "after");
- domConstruct.place(brNode, startNode, "after");
- domConstruct.place(endNode, brNode, "after");
- domConstruct.destroy(rs);
- newrange = rangeapi.create();
- newrange.setStart(endNode,0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- });
- return false;
- }
- return true; // let browser handle
- }
- }else{
- selection = rangeapi.getSelection(this.editor.window);
- if(selection.rangeCount){
- range = selection.getRangeAt(0);
- if(range && range.startContainer){
- if(!range.collapsed){
- range.deleteContents();
- selection = rangeapi.getSelection(this.editor.window);
- range = selection.getRangeAt(0);
- }
- rs = range.startContainer;
- if(rs && rs.nodeType == 3){
- // Text node, we have to split it.
- win.withGlobal(this.editor.window, lang.hitch(this, function(){
- var endEmpty = false;
- var offset = range.startOffset;
- if(rs.length < offset){
- //We are not splitting the right node, try to locate the correct one
- ret = this._adjustNodeAndOffset(rs, offset);
- rs = ret.node;
- offset = ret.offset;
- }
- txt = rs.nodeValue;
- startNode = doc.createTextNode(txt.substring(0, offset));
- endNode = doc.createTextNode(txt.substring(offset));
- brNode = doc.createElement("br");
- if(!endNode.length){
- endNode = doc.createTextNode('\xA0');
- endEmpty = true;
- }
- if(startNode.length){
- domConstruct.place(startNode, rs, "after");
- }else{
- startNode = rs;
- }
- domConstruct.place(brNode, startNode, "after");
- domConstruct.place(endNode, brNode, "after");
- domConstruct.destroy(rs);
- newrange = rangeapi.create();
- newrange.setStart(endNode,0);
- newrange.setEnd(endNode, endNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- if(endEmpty && !has("webkit")){
- selectionapi.remove();
- }else{
- selectionapi.collapse(true);
- }
- }));
- }else{
- var targetNode;
- if(range.startOffset >= 0){
- targetNode = rs.childNodes[range.startOffset];
- }
- win.withGlobal(this.editor.window, lang.hitch(this, function(){
- var brNode = doc.createElement("br");
- var endNode = doc.createTextNode('\xA0');
- if(!targetNode){
- rs.appendChild(brNode);
- rs.appendChild(endNode);
- }else{
- domConstruct.place(brNode, targetNode, "before");
- domConstruct.place(endNode, brNode, "after");
- }
- newrange = rangeapi.create(win.global);
- newrange.setStart(endNode,0);
- newrange.setEnd(endNode, endNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- selectionapi.collapse(true);
- }));
- }
- }
- }else{
- // don't change this: do not call this.execCommand, as that may have other logic in subclass
- RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>');
- }
- }
- return false;
- }
- var _letBrowserHandle = true;
- // first remove selection
- selection = rangeapi.getSelection(this.editor.window);
- range = selection.getRangeAt(0);
- if(!range.collapsed){
- range.deleteContents();
- selection = rangeapi.getSelection(this.editor.window);
- range = selection.getRangeAt(0);
- }
- var block = rangeapi.getBlockAncestor(range.endContainer, null, this.editor.editNode);
- var blockNode = block.blockNode;
- // if this is under a LI or the parent of the blockNode is LI, just let browser to handle it
- if((this._checkListLater = (blockNode && (blockNode.nodeName == 'LI' || blockNode.parentNode.nodeName == 'LI')))){
- if(has("mozilla")){
- // press enter in middle of P may leave a trailing <br/>, let's remove it later
- this._pressedEnterInBlock = blockNode;
- }
- // if this li only contains spaces, set the content to empty so the browser will outdent this item
- if(/^(\s| | |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| | |\xA0)<\/span>)?(<br>)?$/.test(blockNode.innerHTML)){
- // empty LI node
- blockNode.innerHTML = '';
- if(has("webkit")){ // WebKit tosses the range when innerHTML is reset
- newrange = rangeapi.create(this.editor.window);
- newrange.setStart(blockNode, 0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- }
- this._checkListLater = false; // nothing to check since the browser handles outdent
- }
- return true;
- }
- // text node directly under body, let's wrap them in a node
- if(!block.blockNode || block.blockNode===this.editor.editNode){
- try{
- RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter);
- }catch(e2){ /*squelch FF3 exception bug when editor content is a single BR*/ }
- // get the newly created block node
- // FIXME
- block = {blockNode:win.withGlobal(this.editor.window, "getAncestorElement", selectionapi, [this.blockNodeForEnter]),
- blockContainer: this.editor.editNode};
- if(block.blockNode){
- if(block.blockNode != this.editor.editNode &&
- (!(block.blockNode.textContent || block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length)){
- this.removeTrailingBr(block.blockNode);
- return false;
- }
- }else{ // we shouldn't be here if formatblock worked
- block.blockNode = this.editor.editNode;
- }
- selection = rangeapi.getSelection(this.editor.window);
- range = selection.getRangeAt(0);
- }
- var newblock = doc.createElement(this.blockNodeForEnter);
- newblock.innerHTML=this.bogusHtmlContent;
- this.removeTrailingBr(block.blockNode);
- var endOffset = range.endOffset;
- var node = range.endContainer;
- if(node.length < endOffset){
- //We are not checking the right node, try to locate the correct one
- var ret = this._adjustNodeAndOffset(node, endOffset);
- node = ret.node;
- endOffset = ret.offset;
- }
- if(rangeapi.atEndOfContainer(block.blockNode, node, endOffset)){
- if(block.blockNode === block.blockContainer){
- block.blockNode.appendChild(newblock);
- }else{
- domConstruct.place(newblock, block.blockNode, "after");
- }
- _letBrowserHandle = false;
- // lets move caret to the newly created block
- newrange = rangeapi.create(this.editor.window);
- newrange.setStart(newblock, 0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- if(this.editor.height){
- winUtils.scrollIntoView(newblock);
- }
- }else if(rangeapi.atBeginningOfContainer(block.blockNode,
- range.startContainer, range.startOffset)){
- domConstruct.place(newblock, block.blockNode, block.blockNode === block.blockContainer ? "first" : "before");
- if(newblock.nextSibling && this.editor.height){
- // position input caret - mostly WebKit needs this
- newrange = rangeapi.create(this.editor.window);
- newrange.setStart(newblock.nextSibling, 0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- // browser does not scroll the caret position into view, do it manually
- winUtils.scrollIntoView(newblock.nextSibling);
- }
- _letBrowserHandle = false;
- }else{ //press enter in the middle of P/DIV/Whatever/
- if(block.blockNode === block.blockContainer){
- block.blockNode.appendChild(newblock);
- }else{
- domConstruct.place(newblock, block.blockNode, "after");
- }
- _letBrowserHandle = false;
- // Clone any block level styles.
- if(block.blockNode.style){
- if(newblock.style){
- if(block.blockNode.style.cssText){
- newblock.style.cssText = block.blockNode.style.cssText;
- }
- }
- }
- // Okay, we probably have to split.
- rs = range.startContainer;
- var firstNodeMoved;
- if(rs && rs.nodeType == 3){
- // Text node, we have to split it.
- var nodeToMove, tNode;
- endOffset = range.endOffset;
- if(rs.length < endOffset){
- //We are not splitting the right node, try to locate the correct one
- ret = this._adjustNodeAndOffset(rs, endOffset);
- rs = ret.node;
- endOffset = ret.offset;
- }
- txt = rs.nodeValue;
- startNode = doc.createTextNode(txt.substring(0, endOffset));
- endNode = doc.createTextNode(txt.substring(endOffset, txt.length));
- // Place the split, then remove original nodes.
- domConstruct.place(startNode, rs, "before");
- domConstruct.place(endNode, rs, "after");
- domConstruct.destroy(rs);
- // Okay, we split the text. Now we need to see if we're
- // parented to the block element we're splitting and if
- // not, we have to split all the way up. Ugh.
- var parentC = startNode.parentNode;
- while(parentC !== block.blockNode){
- var tg = parentC.tagName;
- var newTg = doc.createElement(tg);
- // Clone over any 'style' data.
- if(parentC.style){
- if(newTg.style){
- if(parentC.style.cssText){
- newTg.style.cssText = parentC.style.cssText;
- }
- }
- }
- // If font also need to clone over any font data.
- if(parentC.tagName === "FONT"){
- if(parentC.color){
- newTg.color = parentC.color;
- }
- if(parentC.face){
- newTg.face = parentC.face;
- }
- if(parentC.size){ // this check was necessary on IE
- newTg.size = parentC.size;
- }
- }
- nodeToMove = endNode;
- while(nodeToMove){
- tNode = nodeToMove.nextSibling;
- newTg.appendChild(nodeToMove);
- nodeToMove = tNode;
- }
- domConstruct.place(newTg, parentC, "after");
- startNode = parentC;
- endNode = newTg;
- parentC = parentC.parentNode;
- }
- // Lastly, move the split out tags to the new block.
- // as they should now be split properly.
- nodeToMove = endNode;
- if(nodeToMove.nodeType == 1 || (nodeToMove.nodeType == 3 && nodeToMove.nodeValue)){
- // Non-blank text and non-text nodes need to clear out that blank space
- // before moving the contents.
- newblock.innerHTML = "";
- }
- firstNodeMoved = nodeToMove;
- while(nodeToMove){
- tNode = nodeToMove.nextSibling;
- newblock.appendChild(nodeToMove);
- nodeToMove = tNode;
- }
- }
- //lets move caret to the newly created block
- newrange = rangeapi.create(this.editor.window);
- var nodeForCursor;
- var innerMostFirstNodeMoved = firstNodeMoved;
- if(this.blockNodeForEnter !== 'BR'){
- while(innerMostFirstNodeMoved){
- nodeForCursor = innerMostFirstNodeMoved;
- tNode = innerMostFirstNodeMoved.firstChild;
- innerMostFirstNodeMoved = tNode;
- }
- if(nodeForCursor && nodeForCursor.parentNode){
- newblock = nodeForCursor.parentNode;
- newrange.setStart(newblock, 0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- if(this.editor.height){
- winUtils.scrollIntoView(newblock);
- }
- if(has("mozilla")){
- // press enter in middle of P may leave a trailing <br/>, let's remove it later
- this._pressedEnterInBlock = block.blockNode;
- }
- }else{
- _letBrowserHandle = true;
- }
- }else{
- newrange.setStart(newblock, 0);
- selection.removeAllRanges();
- selection.addRange(newrange);
- if(this.editor.height){
- winUtils.scrollIntoView(newblock);
- }
- if(has("mozilla")){
- // press enter in middle of P may leave a trailing <br/>, let's remove it later
- this._pressedEnterInBlock = block.blockNode;
- }
- }
- }
- return _letBrowserHandle;
- },
- _adjustNodeAndOffset: function(/*DomNode*/node, /*Int*/offset){
- // summary:
- // In the case there are multiple text nodes in a row the offset may not be within the node. If the offset is larger than the node length, it will attempt to find
- // the next text sibling until it locates the text node in which the offset refers to
- // node:
- // The node to check.
- // offset:
- // The position to find within the text node
- // tags:
- // private.
- while(node.length < offset && node.nextSibling && node.nextSibling.nodeType==3){
- //Adjust the offset and node in the case of multiple text nodes in a row
- offset = offset - node.length;
- node = node.nextSibling;
- }
- return {"node": node, "offset": offset};
- },
- removeTrailingBr: function(container){
- // summary:
- // If last child of container is a <br>, then remove it.
- // tags:
- // private
- var para = /P|DIV|LI/i.test(container.tagName) ?
- container : selectionapi.getParentOfType(container,['P','DIV','LI']);
- if(!para){ return; }
- if(para.lastChild){
- if((para.childNodes.length > 1 && para.lastChild.nodeType == 3 && /^[\s\xAD]*$/.test(para.lastChild.nodeValue)) ||
- para.lastChild.tagName=='BR'){
- domConstruct.destroy(para.lastChild);
- }
- }
- if(!para.childNodes.length){
- para.innerHTML=this.bogusHtmlContent;
- }
- }
- });
- });
- },
- 'dojo/dnd/Selector':function(){
- define("dojo/dnd/Selector", ["../main", "./common", "./Container"], function(dojo) {
- // module:
- // dojo/dnd/Selector
- // summary:
- // TODOC
- /*
- Container item states:
- "" - an item is not selected
- "Selected" - an item is selected
- "Anchor" - an item is selected, and is an anchor for a "shift" selection
- */
- /*=====
- dojo.declare("dojo.dnd.__SelectorArgs", [dojo.dnd.__ContainerArgs], {
- // singular: Boolean
- // allows selection of only one element, if true
- singular: false,
- // autoSync: Boolean
- // autosynchronizes the source with its list of DnD nodes,
- autoSync: false
- });
- =====*/
- dojo.declare("dojo.dnd.Selector", dojo.dnd.Container, {
- // summary:
- // a Selector object, which knows how to select its children
- /*=====
- // selection: Set<String>
- // The set of id's that are currently selected, such that this.selection[id] == 1
- // if the node w/that id is selected. Can iterate over selected node's id's like:
- // | for(var id in this.selection)
- selection: {},
- =====*/
- constructor: function(node, params){
- // summary:
- // constructor of the Selector
- // node: Node||String
- // node or node's id to build the selector on
- // params: dojo.dnd.__SelectorArgs?
- // a dictionary of parameters
- if(!params){ params = {}; }
- this.singular = params.singular;
- this.autoSync = params.autoSync;
- // class-specific variables
- this.selection = {};
- this.anchor = null;
- this.simpleSelection = false;
- // set up events
- this.events.push(
- dojo.connect(this.node, "onmousedown", this, "onMouseDown"),
- dojo.connect(this.node, "onmouseup", this, "onMouseUp"));
- },
- // object attributes (for markup)
- singular: false, // is singular property
- // methods
- getSelectedNodes: function(){
- // summary:
- // returns a list (an array) of selected nodes
- var t = new dojo.NodeList();
- var e = dojo.dnd._empty;
- for(var i in this.selection){
- if(i in e){ continue; }
- t.push(dojo.byId(i));
- }
- return t; // NodeList
- },
- selectNone: function(){
- // summary:
- // unselects all items
- return this._removeSelection()._removeAnchor(); // self
- },
- selectAll: function(){
- // summary:
- // selects all items
- this.forInItems(function(data, id){
- this._addItemClass(dojo.byId(id), "Selected");
- this.selection[id] = 1;
- }, this);
- return this._removeAnchor(); // self
- },
- deleteSelectedNodes: function(){
- // summary:
- // deletes all selected items
- var e = dojo.dnd._empty;
- for(var i in this.selection){
- if(i in e){ continue; }
- var n = dojo.byId(i);
- this.delItem(i);
- dojo.destroy(n);
- }
- this.anchor = null;
- this.selection = {};
- return this; // self
- },
- forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
- // summary:
- // iterates over selected items;
- // see `dojo.dnd.Container.forInItems()` for details
- o = o || dojo.global;
- var s = this.selection, e = dojo.dnd._empty;
- for(var i in s){
- if(i in e){ continue; }
- f.call(o, this.getItem(i), i, this);
- }
- },
- sync: function(){
- // summary:
- // sync up the node list with the data map
- dojo.dnd.Selector.superclass.sync.call(this);
- // fix the anchor
- if(this.anchor){
- if(!this.getItem(this.anchor.id)){
- this.anchor = null;
- }
- }
- // fix the selection
- var t = [], e = dojo.dnd._empty;
- for(var i in this.selection){
- if(i in e){ continue; }
- if(!this.getItem(i)){
- t.push(i);
- }
- }
- dojo.forEach(t, function(i){
- delete this.selection[i];
- }, this);
- return this; // self
- },
- insertNodes: function(addSelected, data, before, anchor){
- // summary:
- // inserts new data items (see `dojo.dnd.Container.insertNodes()` method for details)
- // addSelected: Boolean
- // all new nodes will be added to selected items, if true, no selection change otherwise
- // data: Array
- // a list of data items, which should be processed by the creator function
- // before: Boolean
- // insert before the anchor, if true, and after the anchor otherwise
- // anchor: Node
- // the anchor node to be used as a point of insertion
- var oldCreator = this._normalizedCreator;
- this._normalizedCreator = function(item, hint){
- var t = oldCreator.call(this, item, hint);
- if(addSelected){
- if(!this.anchor){
- this.anchor = t.node;
- this._removeItemClass(t.node, "Selected");
- this._addItemClass(this.anchor, "Anchor");
- }else if(this.anchor != t.node){
- this._removeItemClass(t.node, "Anchor");
- this._addItemClass(t.node, "Selected");
- }
- this.selection[t.node.id] = 1;
- }else{
- this._removeItemClass(t.node, "Selected");
- this._removeItemClass(t.node, "Anchor");
- }
- return t;
- };
- dojo.dnd.Selector.superclass.insertNodes.call(this, data, before, anchor);
- this._normalizedCreator = oldCreator;
- return this; // self
- },
- destroy: function(){
- // summary:
- // prepares the object to be garbage-collected
- dojo.dnd.Selector.superclass.destroy.call(this);
- this.selection = this.anchor = null;
- },
- // mouse events
- onMouseDown: function(e){
- // summary:
- // event processor for onmousedown
- // e: Event
- // mouse event
- if(this.autoSync){ this.sync(); }
- if(!this.current){ return; }
- if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
- this.simpleSelection = true;
- if(e.button === dojo.mouseButtons.LEFT){
- // accept the left button and stop the event
- // for IE we don't stop event when multiple buttons are pressed
- dojo.stopEvent(e);
- }
- return;
- }
- if(!this.singular && e.shiftKey){
- if(!dojo.isCopyKey(e)){
- this._removeSelection();
- }
- var c = this.getAllNodes();
- if(c.length){
- if(!this.anchor){
- this.anchor = c[0];
- this._addItemClass(this.anchor, "Anchor");
- }
- this.selection[this.anchor.id] = 1;
- if(this.anchor != this.current){
- var i = 0;
- for(; i < c.length; ++i){
- var node = c[i];
- if(node == this.anchor || node == this.current){ break; }
- }
- for(++i; i < c.length; ++i){
- var node = c[i];
- if(node == this.anchor || node == this.current){ break; }
- this._addItemClass(node, "Selected");
- this.selection[node.id] = 1;
- }
- this._addItemClass(this.current, "Selected");
- this.selection[this.current.id] = 1;
- }
- }
- }else{
- if(this.singular){
- if(this.anchor == this.current){
- if(dojo.isCopyKey(e)){
- this.selectNone();
- }
- }else{
- this.selectNone();
- this.anchor = this.current;
- this._addItemClass(this.anchor, "Anchor");
- this.selection[this.current.id] = 1;
- }
- }else{
- if(dojo.isCopyKey(e)){
- if(this.anchor == this.current){
- delete this.selection[this.anchor.id];
- this._removeAnchor();
- }else{
- if(this.current.id in this.selection){
- this._removeItemClass(this.current, "Selected");
- delete this.selection[this.current.id];
- }else{
- if(this.anchor){
- this._removeItemClass(this.anchor, "Anchor");
- this._addItemClass(this.anchor, "Selected");
- }
- this.anchor = this.current;
- this._addItemClass(this.current, "Anchor");
- this.selection[this.current.id] = 1;
- }
- }
- }else{
- if(!(this.current.id in this.selection)){
- this.selectNone();
- this.anchor = this.current;
- this._addItemClass(this.current, "Anchor");
- this.selection[this.current.id] = 1;
- }
- }
- }
- }
- dojo.stopEvent(e);
- },
- onMouseUp: function(e){
- // summary:
- // event processor for onmouseup
- // e: Event
- // mouse event
- if(!this.simpleSelection){ return; }
- this.simpleSelection = false;
- this.selectNone();
- if(this.current){
- this.anchor = this.current;
- this._addItemClass(this.anchor, "Anchor");
- this.selection[this.current.id] = 1;
- }
- },
- onMouseMove: function(e){
- // summary:
- // event processor for onmousemove
- // e: Event
- // mouse event
- this.simpleSelection = false;
- },
- // utilities
- onOverEvent: function(){
- // summary:
- // this function is called once, when mouse is over our container
- this.onmousemoveEvent = dojo.connect(this.node, "onmousemove", this, "onMouseMove");
- },
- onOutEvent: function(){
- // summary:
- // this function is called once, when mouse is out of our container
- dojo.disconnect(this.onmousemoveEvent);
- delete this.onmousemoveEvent;
- },
- _removeSelection: function(){
- // summary:
- // unselects all items
- var e = dojo.dnd._empty;
- for(var i in this.selection){
- if(i in e){ continue; }
- var node = dojo.byId(i);
- if(node){ this._removeItemClass(node, "Selected"); }
- }
- this.selection = {};
- return this; // self
- },
- _removeAnchor: function(){
- if(this.anchor){
- this._removeItemClass(this.anchor, "Anchor");
- this.anchor = null;
- }
- return this; // self
- }
- });
- return dojo.dnd.Selector;
- });
- },
- 'dijit/focus':function(){
- define("dijit/focus", [
- "dojo/aspect",
- "dojo/_base/declare", // declare
- "dojo/dom", // domAttr.get dom.isDescendant
- "dojo/dom-attr", // domAttr.get dom.isDescendant
- "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy
- "dojo/Evented",
- "dojo/_base/lang", // lang.hitch
- "dojo/on",
- "dojo/ready",
- "dojo/_base/sniff", // has("ie")
- "dojo/Stateful",
- "dojo/_base/unload", // unload.addOnWindowUnload
- "dojo/_base/window", // win.body
- "dojo/window", // winUtils.get
- "./a11y", // a11y.isTabNavigable
- "./registry", // registry.byId
- "." // to set dijit.focus
- ], function(aspect, declare, dom, domAttr, domConstruct, Evented, lang, on, ready, has, Stateful, unload, win, winUtils,
- a11y, registry, dijit){
- // module:
- // dijit/focus
- // summary:
- // Returns a singleton that tracks the currently focused node, and which widgets are currently "active".
- /*=====
- dijit.focus = {
- // summary:
- // Tracks the currently focused node, and which widgets are currently "active".
- // Access via require(["dijit/focus"], function(focus){ ... }).
- //
- // A widget is considered active if it or a descendant widget has focus,
- // or if a non-focusable node of this widget or a descendant was recently clicked.
- //
- // Call focus.watch("curNode", callback) to track the current focused DOMNode,
- // or focus.watch("activeStack", callback) to track the currently focused stack of widgets.
- //
- // Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when
- // when widgets become active/inactive
- //
- // Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist.
- // curNode: DomNode
- // Currently focused item on screen
- curNode: null,
- // activeStack: dijit._Widget[]
- // List of currently active widgets (focused widget and it's ancestors)
- activeStack: [],
- registerIframe: function(iframe){
- // summary:
- // Registers listeners on the specified iframe so that any click
- // or focus event on that iframe (or anything in it) is reported
- // as a focus/click event on the <iframe> itself.
- // description:
- // Currently only used by editor.
- // returns:
- // Handle with remove() method to deregister.
- },
- registerWin: function(targetWindow, effectiveNode){
- // summary:
- // Registers listeners on the specified window (either the main
- // window or an iframe's window) to detect when the user has clicked somewhere
- // or focused somewhere.
- // description:
- // Users should call registerIframe() instead of this method.
- // targetWindow: Window?
- // If specified this is the window associated with the iframe,
- // i.e. iframe.contentWindow.
- // effectiveNode: DOMNode?
- // If specified, report any focus events inside targetWindow as
- // an event on effectiveNode, rather than on evt.target.
- // returns:
- // Handle with remove() method to deregister.
- }
- };
- =====*/
- var FocusManager = declare([Stateful, Evented], {
- // curNode: DomNode
- // Currently focused item on screen
- curNode: null,
- // activeStack: dijit._Widget[]
- // List of currently active widgets (focused widget and it's ancestors)
- activeStack: [],
- constructor: function(){
- // Don't leave curNode/prevNode pointing to bogus elements
- var check = lang.hitch(this, function(node){
- if(dom.isDescendant(this.curNode, node)){
- this.set("curNode", null);
- }
- if(dom.isDescendant(this.prevNode, node)){
- this.set("prevNode", null);
- }
- });
- aspect.before(domConstruct, "empty", check);
- aspect.before(domConstruct, "destroy", check);
- },
- registerIframe: function(/*DomNode*/ iframe){
- // summary:
- // Registers listeners on the specified iframe so that any click
- // or focus event on that iframe (or anything in it) is reported
- // as a focus/click event on the <iframe> itself.
- // description:
- // Currently only used by editor.
- // returns:
- // Handle with remove() method to deregister.
- return this.registerWin(iframe.contentWindow, iframe);
- },
- registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
- // summary:
- // Registers listeners on the specified window (either the main
- // window or an iframe's window) to detect when the user has clicked somewhere
- // or focused somewhere.
- // description:
- // Users should call registerIframe() instead of this method.
- // targetWindow:
- // If specified this is the window associated with the iframe,
- // i.e. iframe.contentWindow.
- // effectiveNode:
- // If specified, report any focus events inside targetWindow as
- // an event on effectiveNode, rather than on evt.target.
- // returns:
- // Handle with remove() method to deregister.
- // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
- var _this = this;
- var mousedownListener = function(evt){
- _this._justMouseDowned = true;
- setTimeout(function(){ _this._justMouseDowned = false; }, 0);
- // workaround weird IE bug where the click is on an orphaned node
- // (first time clicking a Select/DropDownButton inside a TooltipDialog)
- if(has("ie") && evt && evt.srcElement && evt.srcElement.parentNode == null){
- return;
- }
- _this._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
- };
- // Listen for blur and focus events on targetWindow's document.
- // IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble
- // through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers
- // fire.
- // Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
- // (at least for FF) the focus event doesn't fire on <html> or <body>.
- var doc = has("ie") ? targetWindow.document.documentElement : targetWindow.document;
- if(doc){
- if(has("ie")){
- targetWindow.document.body.attachEvent('onmousedown', mousedownListener);
- var activateListener = function(evt){
- // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
- // ignore those events
- var tag = evt.srcElement.tagName.toLowerCase();
- if(tag == "#document" || tag == "body"){ return; }
- // Previous code called _onTouchNode() for any activate event on a non-focusable node. Can
- // probably just ignore such an event as it will be handled by onmousedown handler above, but
- // leaving the code for now.
- if(a11y.isTabNavigable(evt.srcElement)){
- _this._onFocusNode(effectiveNode || evt.srcElement);
- }else{
- _this._onTouchNode(effectiveNode || evt.srcElement);
- }
- };
- doc.attachEvent('onactivate', activateListener);
- var deactivateListener = function(evt){
- _this._onBlurNode(effectiveNode || evt.srcElement);
- };
- doc.attachEvent('ondeactivate', deactivateListener);
- return {
- remove: function(){
- targetWindow.document.detachEvent('onmousedown', mousedownListener);
- doc.detachEvent('onactivate', activateListener);
- doc.detachEvent('ondeactivate', deactivateListener);
- doc = null; // prevent memory leak (apparent circular reference via closure)
- }
- };
- }else{
- doc.body.addEventListener('mousedown', mousedownListener, true);
- doc.body.addEventListener('touchstart', mousedownListener, true);
- var focusListener = function(evt){
- _this._onFocusNode(effectiveNode || evt.target);
- };
- doc.addEventListener('focus', focusListener, true);
- var blurListener = function(evt){
- _this._onBlurNode(effectiveNode || evt.target);
- };
- doc.addEventListener('blur', blurListener, true);
- return {
- remove: function(){
- doc.body.removeEventListener('mousedown', mousedownListener, true);
- doc.body.removeEventListener('touchstart', mousedownListener, true);
- doc.removeEventListener('focus', focusListener, true);
- doc.removeEventListener('blur', blurListener, true);
- doc = null; // prevent memory leak (apparent circular reference via closure)
- }
- };
- }
- }
- },
- _onBlurNode: function(/*DomNode*/ /*===== node =====*/){
- // summary:
- // Called when focus leaves a node.
- // Usually ignored, _unless_ it *isn't* followed by touching another node,
- // which indicates that we tabbed off the last field on the page,
- // in which case every widget is marked inactive
- this.set("prevNode", this.curNode);
- this.set("curNode", null);
- if(this._justMouseDowned){
- // the mouse down caused a new widget to be marked as active; this blur event
- // is coming late, so ignore it.
- return;
- }
- // if the blur event isn't followed by a focus event then mark all widgets as inactive.
- if(this._clearActiveWidgetsTimer){
- clearTimeout(this._clearActiveWidgetsTimer);
- }
- this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){
- delete this._clearActiveWidgetsTimer;
- this._setStack([]);
- this.prevNode = null;
- }), 100);
- },
- _onTouchNode: function(/*DomNode*/ node, /*String*/ by){
- // summary:
- // Callback when node is focused or mouse-downed
- // node:
- // The node that was touched.
- // by:
- // "mouse" if the focus/touch was caused by a mouse down event
- // ignore the recent blurNode event
- if(this._clearActiveWidgetsTimer){
- clearTimeout(this._clearActiveWidgetsTimer);
- delete this._clearActiveWidgetsTimer;
- }
- // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
- var newStack=[];
- try{
- while(node){
- var popupParent = domAttr.get(node, "dijitPopupParent");
- if(popupParent){
- node=registry.byId(popupParent).domNode;
- }else if(node.tagName && node.tagName.toLowerCase() == "body"){
- // is this the root of the document or just the root of an iframe?
- if(node === win.body()){
- // node is the root of the main document
- break;
- }
- // otherwise, find the iframe this node refers to (can't access it via parentNode,
- // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
- node=winUtils.get(node.ownerDocument).frameElement;
- }else{
- // if this node is the root node of a widget, then add widget id to stack,
- // except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
- // to support MenuItem)
- var id = node.getAttribute && node.getAttribute("widgetId"),
- widget = id && registry.byId(id);
- if(widget && !(by == "mouse" && widget.get("disabled"))){
- newStack.unshift(id);
- }
- node=node.parentNode;
- }
- }
- }catch(e){ /* squelch */ }
- this._setStack(newStack, by);
- },
- _onFocusNode: function(/*DomNode*/ node){
- // summary:
- // Callback when node is focused
- if(!node){
- return;
- }
- if(node.nodeType == 9){
- // Ignore focus events on the document itself. This is here so that
- // (for example) clicking the up/down arrows of a spinner
- // (which don't get focus) won't cause that widget to blur. (FF issue)
- return;
- }
- this._onTouchNode(node);
- if(node == this.curNode){ return; }
- this.set("curNode", node);
- },
- _setStack: function(/*String[]*/ newStack, /*String*/ by){
- // summary:
- // The stack of active widgets has changed. Send out appropriate events and records new stack.
- // newStack:
- // array of widget id's, starting from the top (outermost) widget
- // by:
- // "mouse" if the focus/touch was caused by a mouse down event
- var oldStack = this.activeStack;
- this.set("activeStack", newStack);
- // compare old stack to new stack to see how many elements they have in common
- for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
- if(oldStack[nCommon] != newStack[nCommon]){
- break;
- }
- }
- var widget;
- // for all elements that have gone out of focus, set focused=false
- for(var i=oldStack.length-1; i>=nCommon; i--){
- widget = registry.byId(oldStack[i]);
- if(widget){
- widget._hasBeenBlurred = true; // TODO: used by form widgets, should be moved there
- widget.set("focused", false);
- if(widget._focusManager == this){
- widget._onBlur(by);
- }
- this.emit("widget-blur", widget, by);
- }
- }
- // for all element that have come into focus, set focused=true
- for(i=nCommon; i<newStack.length; i++){
- widget = registry.byId(newStack[i]);
- if(widget){
- widget.set("focused", true);
- if(widget._focusManager == this){
- widget._onFocus(by);
- }
- this.emit("widget-focus", widget, by);
- }
- }
- },
- focus: function(node){
- // summary:
- // Focus the specified node, suppressing errors if they occur
- if(node){
- try{ node.focus(); }catch(e){/*quiet*/}
- }
- }
- });
- var singleton = new FocusManager();
- // register top window and all the iframes it contains
- ready(function(){
- var handle = singleton.registerWin(win.doc.parentWindow || win.doc.defaultView);
- if(has("ie")){
- unload.addOnWindowUnload(function(){
- handle.remove();
- handle = null;
- })
- }
- });
- // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility)
- // as a function to set focus.
- dijit.focus = function(node){
- singleton.focus(node); // indirection here allows dijit/_base/focus.js to override behavior
- };
- for(var attr in singleton){
- if(!/^_/.test(attr)){
- dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr];
- }
- }
- singleton.watch(function(attr, oldVal, newVal){
- dijit.focus[attr] = newVal;
- });
- return singleton;
- });
- },
- 'dojo/i18n':function(){
- define("dojo/i18n", ["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json"],
- function(dojo, require, has, array, config, lang, xhr, json) {
- // module:
- // dojo/i18n
- // summary:
- // This module implements the !dojo/i18n plugin and the v1.6- i18n API
- // description:
- // We choose to include our own plugin to leverage functionality already contained in dojo
- // and thereby reduce the size of the plugin compared to various loader implementations. Also, this
- // allows foreign AMD loaders to be used without their plugins.
- has.add("dojo-preload-i18n-Api",
- // if true, define the preload localizations machinery
- 1
- );
- true || has.add("dojo-v1x-i18n-Api",
- // if true, define the v1.x i18n functions
- 1
- );
- var
- thisModule= dojo.i18n=
- // the dojo.i18n module
- {},
- nlsRe=
- // regexp for reconstructing the master bundle name from parts of the regexp match
- // nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives:
- // ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
- // nlsRe.exec("foo/bar/baz/nls/foo") gives:
- // ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
- // so, if match[5] is blank, it means this is the top bundle definition.
- // courtesy of http://requirejs.org
- /(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,
- getAvailableLocales= function(
- root,
- locale,
- bundlePath,
- bundleName
- ){
- // return a vector of module ids containing all available locales with respect to the target locale
- // For example, assuming:
- // * the root bundle indicates specific bundles for "fr" and "fr-ca",
- // * bundlePath is "myPackage/nls"
- // * bundleName is "myBundle"
- // Then a locale argument of "fr-ca" would return
- // ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"]
- // Notice that bundles are returned least-specific to most-specific, starting with the root.
- //
- // If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales;
- // therefore, assume everything is available and get 404 errors that indicate a particular localization is not available
- //
- for(var result= [bundlePath + bundleName], localeParts= locale.split("-"), current= "", i= 0; i<localeParts.length; i++){
- current+= (current ? "-" : "") + localeParts[i];
- if(!root || root[current]){
- result.push(bundlePath + current + "/" + bundleName);
- }
- }
- return result;
- },
- cache= {},
- getL10nName= dojo.getL10nName = function(moduleName, bundleName, locale){
- locale = locale ? locale.toLowerCase() : dojo.locale;
- moduleName = "dojo/i18n!" + moduleName.replace(/\./g, "/");
- bundleName = bundleName.replace(/\./g, "/");
- return (/root/i.test(locale)) ?
- (moduleName + "/nls/" + bundleName) :
- (moduleName + "/nls/" + locale + "/" + bundleName);
- },
- doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){
- // get the root bundle which instructs which other bundles are required to construct the localized bundle
- require([bundlePathAndName], function(root){
- var current= lang.clone(root.root),
- availableLocales= getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName);
- require(availableLocales, function(){
- for (var i= 1; i<availableLocales.length; i++){
- current= lang.mixin(lang.clone(current), arguments[i]);
- }
- // target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested)
- var target= bundlePathAndName + "/" + locale;
- cache[target]= current;
- load();
- });
- });
- },
- normalize = function(id, toAbsMid){
- // id may be relative
- // preload has form *preload*<path>/nls/<module>*<flattened locales> and
- // therefore never looks like a relative
- return /^\./.test(id) ? toAbsMid(id) : id;
- },
- getLocalesToLoad = function(targetLocale){
- var list = config.extraLocale || [];
- list = lang.isArray(list) ? list : [list];
- list.push(targetLocale);
- return list;
- },
- load = function(id, require, load){
- //
- // id is in one of the following formats
- //
- // 1. <path>/nls/<bundle>
- // => load the bundle, localized to config.locale; load all bundles localized to
- // config.extraLocale (if any); return the loaded bundle localized to config.locale.
- //
- // 2. <path>/nls/<locale>/<bundle>
- // => load then return the bundle localized to <locale>
- //
- // 3. *preload*<path>/nls/<module>*<JSON array of available locales>
- // => for config.locale and all config.extraLocale, load all bundles found
- // in the best-matching bundle rollup. A value of 1 is returned, which
- // is meaningless other than to say the plugin is executing the requested
- // preloads
- //
- // In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see
- // normalize. In case 3, it <path> is assumed to be absolue; this is arranged by the builder.
- //
- // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle
- // value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key
- //
- // <path>/nls/<bundle>/<locale>
- //
- // will hold the value. Similarly, then plugin will publish this value to the loader by
- //
- // define("<path>/nls/<bundle>/<locale>", <bundle-value>);
- //
- // Given this algorithm, other machinery can provide fast load paths be preplacing
- // values in the plugin's cache, which is public. When a load is demanded the
- // cache is inspected before starting any loading. Explicitly placing values in the plugin
- // cache is an advanced/experimental feature that should not be needed; use at your own risk.
- //
- // For the normal AMD algorithm, the root bundle is loaded first, which instructs the
- // plugin what additional localized bundles are required for a particular locale. These
- // additional locales are loaded and a mix of the root and each progressively-specific
- // locale is returned. For example:
- //
- // 1. The client demands "dojo/i18n!some/path/nls/someBundle
- //
- // 2. The loader demands load(some/path/nls/someBundle)
- //
- // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
- //
- // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations
- // are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin
- // requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle"
- //
- // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle
- // ab-cd-ef as...
- //
- // mixin(mixin(mixin({}, require("some/path/nls/someBundle"),
- // require("some/path/nls/ab/someBundle")),
- // require("some/path/nls/ab-cd-ef/someBundle"));
- //
- // This value is inserted into the cache and published to the loader at the
- // key/module-id some/path/nls/someBundle/ab-cd-ef.
- //
- // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests
- // (further preload requests will be serviced) until all ongoing preloading has completed.
- //
- // The preload signature instructs the plugin that a special rollup module is available that contains
- // one or more flattened, localized bundles. The JSON array of available locales indicates which locales
- // are available. Here is an example:
- //
- // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
- //
- // This indicates the following rollup modules are available:
- //
- // some/path/nls/someModule_ROOT
- // some/path/nls/someModule_ab
- // some/path/nls/someModule_ab-cd-ef
- //
- // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash.
- // For example, assume someModule contained the bundles some/bundle/path/someBundle and
- // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as folllows:
- //
- // define({
- // some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>,
- // some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>,
- // });
- //
- // E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
- //
- // require(["some/path/nls/someModule_ab"], function(rollup){
- // for(var p in rollup){
- // var id = p + "/ab",
- // cache[id] = rollup[p];
- // define(id, rollup[p]);
- // }
- // });
- //
- // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
- // load accordingly.
- //
- // The builder will write such rollups for every layer if a non-empty localeList profile property is
- // provided. Further, the builder will include the following cache entry in the cache associated with
- // any layer.
- //
- // "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);}
- //
- // The *now special cache module instructs the loader to apply the provided function to context-require
- // with respect to the particular layer being defined. This causes the plugin to hold all normal service
- // requests until all preloading is complete.
- //
- // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case
- // where the target locale has a single segment and a layer depends on a single bundle:
- //
- // Without Preloads:
- //
- // 1. Layer loads root bundle.
- // 2. bundle is demanded; plugin loads single localized bundle.
- //
- // With Preloads:
- //
- // 1. Layer causes preloading of target bundle.
- // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
- //
- // In each case a single transaction is required to load the target bundle. In cases where multiple bundles
- // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas
- // the normal path requires an additional transaction for each additional bundle/locale-segment. However all
- // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading
- // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false.
- //
- if(has("dojo-preload-i18n-Api")){
- var split = id.split("*"),
- preloadDemand = split[1]=="preload";
- if(preloadDemand){
- if(!cache[id]){
- // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but
- // who knows what over-aggressive human optimizers may attempt
- cache[id] = 1;
- preloadL10n(split[2], json.parse(split[3]), 1);
- }
- // don't stall the loader!
- load(1);
- }
- if(preloadDemand || waitForPreloads(id, require, load)){
- return;
- }
- }
- var match= nlsRe.exec(id),
- bundlePath= match[1] + "/",
- bundleName= match[5] || match[4],
- bundlePathAndName= bundlePath + bundleName,
- localeSpecified = (match[5] && match[4]),
- targetLocale= localeSpecified || dojo.locale,
- loadTarget= bundlePathAndName + "/" + targetLocale,
- loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale),
- remaining = loadList.length,
- finish = function(){
- if(!--remaining){
- load(lang.delegate(cache[loadTarget]));
- }
- };
- array.forEach(loadList, function(locale){
- var target = bundlePathAndName + "/" + locale;
- if(has("dojo-preload-i18n-Api")){
- checkForLegacyModules(target);
- }
- if(!cache[target]){
- doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish);
- }else{
- finish();
- }
- });
- };
- if(has("dojo-unit-tests")){
- var unitTests = thisModule.unitTests = [];
- }
- if(has("dojo-preload-i18n-Api") || 1){
- var normalizeLocale = thisModule.normalizeLocale= function(locale){
- var result = locale ? locale.toLowerCase() : dojo.locale;
- return result == "root" ? "ROOT" : result;
- },
- isXd = function(mid){
- return (1 && 1) ?
- require.isXdUrl(require.toUrl(mid + ".js")) :
- true;
- },
- preloading = 0,
- preloadWaitQueue = [],
- preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean*/ guaranteedAmdFormat){
- // summary:
- // Load available flattened resource bundles associated with a particular module for dojo.locale and all dojo.config.extraLocale (if any)
- //
- // descirption:
- // Only called by built layer files. The entire locale hierarchy is loaded. For example,
- // if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6-
- // in that the v1.6- would lonly load ab-cd...which was *always* flattened.
- //
- // If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm
- // and the extra possible extra transaction.
- //
- function forEachLocale(locale, func){
- // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy
- var parts = locale.split("-");
- while(parts.length){
- if(func(parts.join("-"))){
- return true;
- }
- parts.pop();
- }
- return func("ROOT");
- }
- function preload(locale){
- locale = normalizeLocale(locale);
- forEachLocale(locale, function(loc){
- if(array.indexOf(localesGenerated, loc)>=0){
- var mid = bundlePrefix.replace(/\./g, "/")+"_"+loc;
- preloading++;
- (isXd(mid) || guaranteedAmdFormat ? require : syncRequire)([mid], function(rollup){
- for(var p in rollup){
- cache[p + "/" + loc] = rollup[p];
- }
- --preloading;
- while(!preloading && preloadWaitQueue.length){
- load.apply(null, preloadWaitQueue.shift());
- }
- });
- return true;
- }
- return false;
- });
- }
- preload();
- array.forEach(dojo.config.extraLocale, preload);
- },
- waitForPreloads = function(id, require, load){
- if(preloading){
- preloadWaitQueue.push([id, require, load]);
- }
- return preloading;
- };
- }
- if(1){
- // this code path assumes the dojo loader and won't work with a standard AMD loader
- var evalBundle=
- // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
- new Function(
- "__bundle", // the bundle to evalutate
- "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space
- "__mid", // the mid that __bundle is intended to define
- // returns one of:
- // 1 => the bundle was an AMD bundle
- // a legacy bundle object that is the value of __mid
- // instance of Error => could not figure out how to evaluate bundle
- // used to detect when __bundle calls define
- "var define = function(){define.called = 1;},"
- + " require = function(){define.called = 1;};"
- + "try{"
- + "define.called = 0;"
- + "eval(__bundle);"
- + "if(define.called==1)"
- // bundle called define; therefore signal it's an AMD bundle
- + "return 1;"
- + "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"
- // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space
- + "return __checkForLegacyModules;"
- + "}catch(e){}"
- // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
- // either way, re-eval *after* surrounding with parentheses
- + "try{"
- + "return eval('('+__bundle+')');"
- + "}catch(e){"
- + "return e;"
- + "}"
- ),
- syncRequire= function(deps, callback){
- var results= [];
- array.forEach(deps, function(mid){
- var url= require.toUrl(mid + ".js");
- function load(text){
- var result = evalBundle(text, checkForLegacyModules, mid);
- if(result===1){
- // the bundle was an AMD module; re-inject it through the normal AMD path
- // we gotta do this since it could be an anonymous module and simply evaluating
- // the text here won't provide the loader with the context to know what
- // module is being defined()'d. With browser caching, this should be free; further
- // this entire code path can be circumvented by using the AMD format to begin with
- require([mid], function(bundle){
- results.push(cache[url]= bundle);
- });
- }else{
- if(result instanceof Error){
- console.error("failed to evaluate i18n bundle; url=" + url, result);
- result = {};
- }
- // nls/<locale>/<bundle-name> indicates not the root.
- results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1}));
- }
- }
- if(cache[url]){
- results.push(cache[url]);
- }else{
- var bundle= require.syncLoadNls(mid);
- // don't need to check for legacy since syncLoadNls returns a module if the module
- // (1) was already loaded, or (2) was in the cache. In case 1, if syncRequire is called
- // from getLocalization --> load, then load will have called checkForLegacyModules() before
- // calling syncRequire; if syncRequire is called from preloadLocalizations, then we
- // don't care about checkForLegacyModules() because that will be done when a particular
- // bundle is actually demanded. In case 2, checkForLegacyModules() is never relevant
- // because cached modules are always v1.7+ built modules.
- if(bundle){
- results.push(bundle);
- }else{
- if(!xhr){
- try{
- require.getText(url, true, load);
- }catch(e){
- results.push(cache[url]= {});
- }
- }else{
- xhr.get({
- url:url,
- sync:true,
- load:load,
- error:function(){
- results.push(cache[url]= {});
- }
- });
- }
- }
- }
- });
- callback && callback.apply(null, results);
- },
- checkForLegacyModules = function(target){
- // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache
- for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){}
- if(object){
- result = object[names[i]];
- if(!result){
- // fallback for incorrect bundle build of 1.6
- result = object[names[i].replace(/-/g,"_")];
- }
- if(result){
- cache[target] = result;
- }
- }
- return result;
- };
- thisModule.getLocalization= function(moduleName, bundleName, locale){
- var result,
- l10nName= getL10nName(moduleName, bundleName, locale).substring(10);
- load(l10nName, (!isXd(l10nName) ? syncRequire : require), function(result_){ result= result_; });
- return result;
- };
- if(has("dojo-unit-tests")){
- unitTests.push(function(doh){
- doh.register("tests.i18n.unit", function(t){
- var check;
- check = evalBundle("{prop:1}");
- t.is({prop:1}, check); t.is(undefined, check[1]);
- check = evalBundle("({prop:1})");
- t.is({prop:1}, check); t.is(undefined, check[1]);
- check = evalBundle("{'prop-x':1}");
- t.is({'prop-x':1}, check); t.is(undefined, check[1]);
- check = evalBundle("({'prop-x':1})");
- t.is({'prop-x':1}, check); t.is(undefined, check[1]);
- check = evalBundle("define({'prop-x':1})");
- t.is(1, check);
- check = evalBundle("this is total nonsense and should throw an error");
- t.is(check instanceof Error, true);
- });
- });
- }
- }
- return lang.mixin(thisModule, {
- dynamic:true,
- normalize:normalize,
- load:load,
- cache:cache
- });
- });
- },
- 'dijit/hccss':function(){
- define("dijit/hccss", [
- "require", // require.toUrl
- "dojo/_base/config", // config.blankGif
- "dojo/dom-class", // domClass.add domConstruct.create domStyle.getComputedStyle
- "dojo/dom-construct", // domClass.add domConstruct.create domStyle.getComputedStyle
- "dojo/dom-style", // domClass.add domConstruct.create domStyle.getComputedStyle
- "dojo/ready", // ready
- "dojo/_base/sniff", // has("ie") has("mozilla")
- "dojo/_base/window" // win.body
- ], function(require, config, domClass, domConstruct, domStyle, ready, has, win){
- // module:
- // dijit/hccss
- // summary:
- // Test if computer is in high contrast mode, and sets dijit_a11y flag on <body> if it is.
- if(has("ie") || has("mozilla")){ // NOTE: checking in Safari messes things up
- // priority is 90 to run ahead of parser priority of 100
- ready(90, function(){
- // summary:
- // Detects if we are in high-contrast mode or not
- // create div for testing if high contrast mode is on or images are turned off
- var div = domConstruct.create("div",{
- id: "a11yTestNode",
- style:{
- cssText:'border: 1px solid;'
- + 'border-color:red green;'
- + 'position: absolute;'
- + 'height: 5px;'
- + 'top: -999px;'
- + 'background-image: url("' + (config.blankGif || require.toUrl("dojo/resources/blank.gif")) + '");'
- }
- }, win.body());
- // test it
- var cs = domStyle.getComputedStyle(div);
- if(cs){
- var bkImg = cs.backgroundImage;
- var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
- if(needsA11y){
- domClass.add(win.body(), "dijit_a11y");
- }
- if(has("ie")){
- div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014
- }else{
- win.body().removeChild(div);
- }
- }
- });
- }
- });
- },
- 'dojox/html/metrics':function(){
- define("dojox/html/metrics", ["dojo/_base/kernel","dojo/_base/lang", "dojo/_base/sniff", "dojo/ready", "dojo/_base/unload",
- "dojo/_base/window", "dojo/dom-geometry"],
- function(kernel,lang,has,ready,UnloadUtil,Window,DOMGeom){
- var dhm = lang.getObject("dojox.html.metrics",true);
- var dojox = lang.getObject("dojox");
- // derived from Morris John's emResized measurer
- dhm.getFontMeasurements = function(){
- // summary
- // Returns an object that has pixel equivilents of standard font size values.
- var heights = {
- '1em':0, '1ex':0, '100%':0, '12pt':0, '16px':0, 'xx-small':0, 'x-small':0,
- 'small':0, 'medium':0, 'large':0, 'x-large':0, 'xx-large':0
- };
-
- if(has("ie")){
- // we do a font-size fix if and only if one isn't applied already.
- // NOTE: If someone set the fontSize on the HTML Element, this will kill it.
- Window.doc.documentElement.style.fontSize="100%";
- }
-
- // set up the measuring node.
- var div=Window.doc.createElement("div");
- var ds = div.style;
- ds.position="absolute";
- ds.left="-100px";
- ds.top="0";
- ds.width="30px";
- ds.height="1000em";
- ds.borderWidth="0";
- ds.margin="0";
- ds.padding="0";
- ds.outline="0";
- ds.lineHeight="1";
- ds.overflow="hidden";
- Window.body().appendChild(div);
-
- // do the measurements.
- for(var p in heights){
- ds.fontSize = p;
- heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
- }
-
- Window.body().removeChild(div);
- div = null;
- return heights; // object
- };
- var fontMeasurements = null;
-
- dhm.getCachedFontMeasurements = function(recalculate){
- if(recalculate || !fontMeasurements){
- fontMeasurements = dhm.getFontMeasurements();
- }
- return fontMeasurements;
- };
- var measuringNode = null, empty = {};
- dhm.getTextBox = function(/* String */ text, /* Object */ style, /* String? */ className){
- var m, s;
- if(!measuringNode){
- m = measuringNode = Window.doc.createElement("div");
- // Container that we can set contraints on so that it doesn't
- // trigger a scrollbar.
- var c = Window.doc.createElement("div");
- c.appendChild(m);
- s = c.style;
- s.overflow='scroll';
- s.position = "absolute";
- s.left = "0px";
- s.top = "-10000px";
- s.width = "1px";
- s.height = "1px";
- s.visibility = "hidden";
- s.borderWidth = "0";
- s.margin = "0";
- s.padding = "0";
- s.outline = "0";
- Window.body().appendChild(c);
- }else{
- m = measuringNode;
- }
- // reset styles
- m.className = "";
- s = m.style;
- s.borderWidth = "0";
- s.margin = "0";
- s.padding = "0";
- s.outline = "0";
- // set new style
- if(arguments.length > 1 && style){
- for(var i in style){
- if(i in empty){ continue; }
- s[i] = style[i];
- }
- }
- // set classes
- if(arguments.length > 2 && className){
- m.className = className;
- }
- // take a measure
- m.innerHTML = text;
- var box = DOMGeom.position(m);
- // position doesn't report right (reports 1, since parent is 1)
- // So we have to look at the scrollWidth to get the real width
- // Height is right.
- box.w = m.parentNode.scrollWidth;
- return box;
- };
- // determine the scrollbar sizes on load.
- var scroll={ w:16, h:16 };
- dhm.getScrollbar=function(){ return { w:scroll.w, h:scroll.h }; };
- dhm._fontResizeNode = null;
- dhm.initOnFontResize = function(interval){
- var f = dhm._fontResizeNode = Window.doc.createElement("iframe");
- var fs = f.style;
- fs.position = "absolute";
- fs.width = "5em";
- fs.height = "10em";
- fs.top = "-10000px";
- if(has("ie")){
- f.onreadystatechange = function(){
- if(f.contentWindow.document.readyState == "complete"){
- f.onresize = f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
- }
- };
- }else{
- f.onload = function(){
- f.contentWindow.onresize = f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
- };
- }
- //The script tag is to work around a known firebug race condition. See comments in bug #9046
- f.setAttribute("src", "javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'");
- Window.body().appendChild(f);
- dhm.initOnFontResize = function(){};
- };
- dhm.onFontResize = function(){};
- dhm._fontresize = function(){
- dhm.onFontResize();
- }
- UnloadUtil.addOnUnload(function(){
- // destroy our font resize iframe if we have one
- var f = dhm._fontResizeNode;
- if(f){
- if(has("ie") && f.onresize){
- f.onresize = null;
- }else if(f.contentWindow && f.contentWindow.onresize){
- f.contentWindow.onresize = null;
- }
- dhm._fontResizeNode = null;
- }
- });
- ready(function(){
- // getScrollbar metrics node
- try{
- var n=Window.doc.createElement("div");
- n.style.cssText = "top:0;left:0;width:100px;height:100px;overflow:scroll;position:absolute;visibility:hidden;";
- Window.body().appendChild(n);
- scroll.w = n.offsetWidth - n.clientWidth;
- scroll.h = n.offsetHeight - n.clientHeight;
- Window.body().removeChild(n);
- //console.log("Scroll bar dimensions: ", scroll);
- delete n;
- }catch(e){}
- // text size poll setup
- if("fontSizeWatch" in kernel.config && !!kernel.config.fontSizeWatch){
- dhm.initOnFontResize();
- }
- });
- return dhm;
- });
- },
- 'dijit/TitlePane':function(){
- require({cache:{
- 'url:dijit/templates/TitlePane.html':"<div>\r\n\t<div data-dojo-attach-event=\"onclick:_onTitleClick, onkeypress:_onTitleKey\"\r\n\t\t\tclass=\"dijitTitlePaneTitle\" data-dojo-attach-point=\"titleBarNode\">\r\n\t\t<div class=\"dijitTitlePaneTitleFocus\" data-dojo-attach-point=\"focusNode\">\r\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"arrowNode\" class=\"dijitArrowNode\" role=\"presentation\"\r\n\t\t\t/><span data-dojo-attach-point=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span\r\n\t\t\t><span data-dojo-attach-point=\"titleNode\" class=\"dijitTitlePaneTextNode\"></span>\r\n\t\t</div>\r\n\t</div>\r\n\t<div class=\"dijitTitlePaneContentOuter\" data-dojo-attach-point=\"hideNode\" role=\"presentation\">\r\n\t\t<div class=\"dijitReset\" data-dojo-attach-point=\"wipeNode\" role=\"presentation\">\r\n\t\t\t<div class=\"dijitTitlePaneContentInner\" data-dojo-attach-point=\"containerNode\" role=\"region\" id=\"${id}_pane\">\r\n\t\t\t\t<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc. Put padding on inner div. -->\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t</div>\r\n</div>\r\n"}});
- define("dijit/TitlePane", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.setSelectable
- "dojo/dom-attr", // domAttr.set or get domAttr.remove
- "dojo/dom-class", // domClass.replace
- "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.getMarginBox
- "dojo/_base/event", // event.stop
- "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/keys", // keys.DOWN_ARROW keys.ENTER
- "./_CssStateMixin",
- "./_TemplatedMixin",
- "./layout/ContentPane",
- "dojo/text!./templates/TitlePane.html",
- "./_base/manager" // defaultDuration
- ], function(array, declare, dom, domAttr, domClass, domGeometry, event, fxUtils, kernel, keys,
- _CssStateMixin, _TemplatedMixin, ContentPane, template, manager){
- /*=====
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var _CssStateMixin = dijit._CssStateMixin;
- var ContentPane = dijit.layout.ContentPane;
- =====*/
- // module:
- // dijit/TitlePane
- // summary:
- // A pane with a title on top, that can be expanded or collapsed.
- return declare("dijit.TitlePane", [ContentPane, _TemplatedMixin, _CssStateMixin], {
- // summary:
- // A pane with a title on top, that can be expanded or collapsed.
- //
- // description:
- // An accessible container with a title Heading, and a content
- // section that slides open and closed. TitlePane is an extension to
- // `dijit.layout.ContentPane`, providing all the useful content-control aspects from it.
- //
- // example:
- // | // load a TitlePane from remote file:
- // | var foo = new dijit.TitlePane({ href: "foobar.html", title:"Title" });
- // | foo.startup();
- //
- // example:
- // | <!-- markup href example: -->
- // | <div data-dojo-type="dijit.TitlePane" data-dojo-props="href: 'foobar.html', title: 'Title'"></div>
- //
- // example:
- // | <!-- markup with inline data -->
- // | <div data-dojo-type="dijit.TitlePane" title="Title">
- // | <p>I am content</p>
- // | </div>
- // title: String
- // Title of the pane
- title: "",
- _setTitleAttr: { node: "titleNode", type: "innerHTML" }, // override default where title becomes a hover tooltip
- // open: Boolean
- // Whether pane is opened or closed.
- open: true,
- // toggleable: Boolean
- // Whether pane can be opened or closed by clicking the title bar.
- toggleable: true,
- // tabIndex: String
- // Tabindex setting for the title (so users can tab to the title then
- // use space/enter to open/close the title pane)
- tabIndex: "0",
- // duration: Integer
- // Time in milliseconds to fade in/fade out
- duration: manager.defaultDuration,
- // baseClass: [protected] String
- // The root className to be placed on this widget's domNode.
- baseClass: "dijitTitlePane",
- templateString: template,
- // doLayout: [protected] Boolean
- // Don't change this parameter from the default value.
- // This ContentPane parameter doesn't make sense for TitlePane, since TitlePane
- // is never a child of a layout container, nor should TitlePane try to control
- // the size of an inner widget.
- doLayout: false,
- // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here
- _setTooltipAttr: {node: "focusNode", type: "attribute", attribute: "title"}, // focusNode spans the entire width, titleNode doesn't
- buildRendering: function(){
- this.inherited(arguments);
- dom.setSelectable(this.titleNode, false);
- },
- postCreate: function(){
- this.inherited(arguments);
- // Hover and focus effect on title bar, except for non-toggleable TitlePanes
- // This should really be controlled from _setToggleableAttr() but _CssStateMixin
- // doesn't provide a way to disconnect a previous _trackMouseState() call
- if(this.toggleable){
- this._trackMouseState(this.titleBarNode, "dijitTitlePaneTitle");
- }
- // setup open/close animations
- var hideNode = this.hideNode, wipeNode = this.wipeNode;
- this._wipeIn = fxUtils.wipeIn({
- node: wipeNode,
- duration: this.duration,
- beforeBegin: function(){
- hideNode.style.display="";
- }
- });
- this._wipeOut = fxUtils.wipeOut({
- node: wipeNode,
- duration: this.duration,
- onEnd: function(){
- hideNode.style.display="none";
- }
- });
- },
- _setOpenAttr: function(/*Boolean*/ open, /*Boolean*/ animate){
- // summary:
- // Hook to make set("open", boolean) control the open/closed state of the pane.
- // open: Boolean
- // True if you want to open the pane, false if you want to close it.
- array.forEach([this._wipeIn, this._wipeOut], function(animation){
- if(animation && animation.status() == "playing"){
- animation.stop();
- }
- });
- if(animate){
- var anim = this[open ? "_wipeIn" : "_wipeOut"];
- anim.play();
- }else{
- this.hideNode.style.display = this.wipeNode.style.display = open ? "" : "none";
- }
- // load content (if this is the first time we are opening the TitlePane
- // and content is specified as an href, or href was set when hidden)
- if(this._started){
- if(open){
- this._onShow();
- }else{
- this.onHide();
- }
- }
- this.arrowNodeInner.innerHTML = open ? "-" : "+";
- this.containerNode.setAttribute("aria-hidden", open ? "false" : "true");
- this.focusNode.setAttribute("aria-pressed", open ? "true" : "false");
- this._set("open", open);
- this._setCss();
- },
- _setToggleableAttr: function(/*Boolean*/ canToggle){
- // summary:
- // Hook to make set("toggleable", boolean) work.
- // canToggle: Boolean
- // True to allow user to open/close pane by clicking title bar.
- this.focusNode.setAttribute("role", canToggle ? "button" : "heading");
- if(canToggle){
- // TODO: if canToggle is switched from true to false shouldn't we remove this setting?
- this.focusNode.setAttribute("aria-controls", this.id+"_pane");
- domAttr.set(this.focusNode, "tabIndex", this.tabIndex);
- }else{
- domAttr.remove(this.focusNode, "tabIndex");
- }
- this._set("toggleable", canToggle);
- this._setCss();
- },
- _setContentAttr: function(/*String|DomNode|Nodelist*/ content){
- // summary:
- // Hook to make set("content", ...) work.
- // Typically called when an href is loaded. Our job is to make the animation smooth.
- if(!this.open || !this._wipeOut || this._wipeOut.status() == "playing"){
- // we are currently *closing* the pane (or the pane is closed), so just let that continue
- this.inherited(arguments);
- }else{
- if(this._wipeIn && this._wipeIn.status() == "playing"){
- this._wipeIn.stop();
- }
- // freeze container at current height so that adding new content doesn't make it jump
- domGeometry.setMarginBox(this.wipeNode, { h: domGeometry.getMarginBox(this.wipeNode).h });
- // add the new content (erasing the old content, if any)
- this.inherited(arguments);
- // call _wipeIn.play() to animate from current height to new height
- if(this._wipeIn){
- this._wipeIn.play();
- }else{
- this.hideNode.style.display = "";
- }
- }
- },
- toggle: function(){
- // summary:
- // Switches between opened and closed state
- // tags:
- // private
- this._setOpenAttr(!this.open, true);
- },
- _setCss: function(){
- // summary:
- // Set the open/close css state for the TitlePane
- // tags:
- // private
- var node = this.titleBarNode || this.focusNode;
- var oldCls = this._titleBarClass;
- this._titleBarClass = "dijit" + (this.toggleable ? "" : "Fixed") + (this.open ? "Open" : "Closed");
- domClass.replace(node, this._titleBarClass, oldCls || "");
- this.arrowNodeInner.innerHTML = this.open ? "-" : "+";
- },
- _onTitleKey: function(/*Event*/ e){
- // summary:
- // Handler for when user hits a key
- // tags:
- // private
- if(e.charOrCode == keys.ENTER || e.charOrCode == ' '){
- if(this.toggleable){
- this.toggle();
- }
- event.stop(e);
- }else if(e.charOrCode == keys.DOWN_ARROW && this.open){
- this.containerNode.focus();
- e.preventDefault();
- }
- },
- _onTitleClick: function(){
- // summary:
- // Handler when user clicks the title bar
- // tags:
- // private
- if(this.toggleable){
- this.toggle();
- }
- },
- setTitle: function(/*String*/ title){
- // summary:
- // Deprecated. Use set('title', ...) instead.
- // tags:
- // deprecated
- kernel.deprecated("dijit.TitlePane.setTitle() is deprecated. Use set('title', ...) instead.", "", "2.0");
- this.set("title", title);
- }
- });
- });
- },
- 'dijit/form/_ComboBoxMenuMixin':function(){
- define("dijit/form/_ComboBoxMenuMixin", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.set
- "dojo/i18n", // i18n.getLocalization
- "dojo/_base/window", // win.doc.createTextNode
- "dojo/i18n!./nls/ComboBox"
- ], function(array, declare, domAttr, i18n, win){
- // module:
- // dijit/form/_ComboBoxMenuMixin
- // summary:
- // Focus-less menu for internal use in `dijit.form.ComboBox`
- return declare( "dijit.form._ComboBoxMenuMixin", null, {
- // summary:
- // Focus-less menu for internal use in `dijit.form.ComboBox`
- // tags:
- // private
- // _messages: Object
- // Holds "next" and "previous" text for paging buttons on drop down
- _messages: null,
- postMixInProperties: function(){
- this.inherited(arguments);
- this._messages = i18n.getLocalization("dijit.form", "ComboBox", this.lang);
- },
- buildRendering: function(){
- this.inherited(arguments);
- // fill in template with i18n messages
- this.previousButton.innerHTML = this._messages["previousMessage"];
- this.nextButton.innerHTML = this._messages["nextMessage"];
- },
- _setValueAttr: function(/*Object*/ value){
- this.value = value;
- this.onChange(value);
- },
- onClick: function(/*DomNode*/ node){
- if(node == this.previousButton){
- this._setSelectedAttr(null);
- this.onPage(-1);
- }else if(node == this.nextButton){
- this._setSelectedAttr(null);
- this.onPage(1);
- }else{
- this.onChange(node);
- }
- },
- // stubs
- onChange: function(/*Number*/ /*===== direction =====*/){
- // summary:
- // Notifies ComboBox/FilteringSelect that user selected an option.
- // tags:
- // callback
- },
- onPage: function(/*Number*/ /*===== direction =====*/){
- // summary:
- // Notifies ComboBox/FilteringSelect that user clicked to advance to next/previous page.
- // tags:
- // callback
- },
- onClose: function(){
- // summary:
- // Callback from dijit.popup code to this widget, notifying it that it closed
- // tags:
- // private
- this._setSelectedAttr(null);
- },
- _createOption: function(/*Object*/ item, labelFunc){
- // summary:
- // Creates an option to appear on the popup menu subclassed by
- // `dijit.form.FilteringSelect`.
- var menuitem = this._createMenuItem();
- var labelObject = labelFunc(item);
- if(labelObject.html){
- menuitem.innerHTML = labelObject.label;
- }else{
- menuitem.appendChild(
- win.doc.createTextNode(labelObject.label)
- );
- }
- // #3250: in blank options, assign a normal height
- if(menuitem.innerHTML == ""){
- menuitem.innerHTML = " "; //
- }
- // update menuitem.dir if BidiSupport was required
- this.applyTextDir(menuitem, (menuitem.innerText || menuitem.textContent || ""));
- menuitem.item=item;
- return menuitem;
- },
- createOptions: function(results, options, labelFunc){
- // summary:
- // Fills in the items in the drop down list
- // results:
- // Array of items
- // options:
- // The options to the query function of the store
- //
- // labelFunc:
- // Function to produce a label in the drop down list from a dojo.data item
- this.items = results;
- // display "Previous . . ." button
- this.previousButton.style.display = (options.start == 0) ? "none" : "";
- domAttr.set(this.previousButton, "id", this.id + "_prev");
- // create options using _createOption function defined by parent
- // ComboBox (or FilteringSelect) class
- // #2309:
- // iterate over cache nondestructively
- array.forEach(results, function(item, i){
- var menuitem = this._createOption(item, labelFunc);
- menuitem.setAttribute("item", i); // index to this.items; use indirection to avoid mem leak
- domAttr.set(menuitem, "id", this.id + i);
- this.nextButton.parentNode.insertBefore(menuitem, this.nextButton);
- }, this);
- // display "Next . . ." button
- var displayMore = false;
- // Try to determine if we should show 'more'...
- if(results.total && !results.total.then && results.total != -1){
- if((options.start + options.count) < results.total){
- displayMore = true;
- }else if((options.start + options.count) > results.total && options.count == results.length){
- // Weird return from a data store, where a start + count > maxOptions
- // implies maxOptions isn't really valid and we have to go into faking it.
- // And more or less assume more if count == results.length
- displayMore = true;
- }
- }else if(options.count == results.length){
- //Don't know the size, so we do the best we can based off count alone.
- //So, if we have an exact match to count, assume more.
- displayMore = true;
- }
- this.nextButton.style.display = displayMore ? "" : "none";
- domAttr.set(this.nextButton,"id", this.id + "_next");
- },
- clearResultList: function(){
- // summary:
- // Clears the entries in the drop down list, but of course keeps the previous and next buttons.
- var container = this.containerNode;
- while(container.childNodes.length > 2){
- container.removeChild(container.childNodes[container.childNodes.length-2]);
- }
- this._setSelectedAttr(null);
- },
- highlightFirstOption: function(){
- // summary:
- // Highlight the first real item in the list (not Previous Choices).
- this.selectFirstNode();
- },
- highlightLastOption: function(){
- // summary:
- // Highlight the last real item in the list (not More Choices).
- this.selectLastNode();
- },
- selectFirstNode: function(){
- this.inherited(arguments);
- if(this.getHighlightedOption() == this.previousButton){
- this.selectNextNode();
- }
- },
- selectLastNode: function(){
- this.inherited(arguments);
- if(this.getHighlightedOption() == this.nextButton){
- this.selectPreviousNode();
- }
- },
- getHighlightedOption: function(){
- return this._getSelectedAttr();
- }
- });
- });
- },
- 'dojox/grid/_RowSelector':function(){
- define("dojox/grid/_RowSelector", [
- "dojo/_base/declare",
- "./_View"
- ], function(declare, _View){
- return declare('dojox.grid._RowSelector', _View, {
- // summary:
- // Custom grid view. If used in a grid structure, provides a small selectable region for grid rows.
- defaultWidth: "2em",
- noscroll: true,
- padBorderWidth: 2,
- buildRendering: function(){
- this.inherited('buildRendering', arguments);
- this.scrollboxNode.style.overflow = "hidden";
- this.headerNode.style.visibility = "hidden";
- },
- getWidth: function(){
- return this.viewWidth || this.defaultWidth;
- },
- buildRowContent: function(inRowIndex, inRowNode){
- var w = this.contentWidth || 0;
- inRowNode.innerHTML = '<table class="dojoxGridRowbarTable" style="width:' + w + 'px;height:1px;" border="0" cellspacing="0" cellpadding="0" role="presentation"><tr><td class="dojoxGridRowbarInner"> </td></tr></table>';
- },
- renderHeader: function(){
- },
- updateRow: function(){
- },
- resize: function(){
- this.adaptHeight();
- },
- adaptWidth: function(){
- // Only calculate this here - rather than every call to buildRowContent
- if(!("contentWidth" in this) && this.contentNode){
- this.contentWidth = this.contentNode.offsetWidth - this.padBorderWidth;
- }
- },
- // styling
- doStyleRowNode: function(inRowIndex, inRowNode){
- var n = [ "dojoxGridRowbar dojoxGridNonNormalizedCell" ];
- if(this.grid.rows.isOver(inRowIndex)){
- n.push("dojoxGridRowbarOver");
- }
- if(this.grid.selection.isSelected(inRowIndex)){
- n.push("dojoxGridRowbarSelected");
- }
- inRowNode.className = n.join(" ");
- },
- // event handlers
- domouseover: function(e){
- this.grid.onMouseOverRow(e);
- },
- domouseout: function(e){
- if(!this.isIntraRowEvent(e)){
- this.grid.onMouseOutRow(e);
- }
- }
- });
- });
- },
- 'dojo/parser':function(){
- define(
- "dojo/parser", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/config", "./_base/html", "./_base/window", "./_base/url",
- "./_base/json", "./aspect", "./date/stamp", "./has", "./query", "./on", "./ready"],
- function(dojo, dlang, darray, config, dhtml, dwindow, _Url, djson, aspect, dates, has, query, don, ready){
- // module:
- // dojo/parser
- // summary:
- // The Dom/Widget parsing package
- new Date("X"); // workaround for #11279, new Date("") == NaN
- if (1) {
- var form = document.createElement("form");
- // Test if DOMNode.attributes only lists the attributes the user specified, not attributes w/default values.
- has.add("dom-attributes-explicit", form.attributes.length == 0);
- // IE8 will erroneously list a few attributes that weren't specified,
- // but we know to skip them because they have a specified flag which is false
- has.add("dom-attributes-specified-flag", form.attributes.length < 40);
- // Otherwise, it's IE6-7 form.attributes will list hundreds of values, need to do outerHTML instead.
- }
- dojo.parser = new function(){
- // summary:
- // The Dom/Widget parsing package
- var _nameMap = {
- // Map from widget name (ex: "dijit.form.Button") to structure mapping
- // lowercase version of attribute names to the version in the widget ex:
- // {
- // label: "label",
- // onclick: "onClick"
- // }
- };
- function getNameMap(proto){
- // summary:
- // Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"}
- var map = {};
- for(var name in proto){
- if(name.charAt(0)=="_"){ continue; } // skip internal properties
- map[name.toLowerCase()] = name;
- }
- return map;
- }
- // Widgets like BorderContainer add properties to _Widget via dojo.extend().
- // If BorderContainer is loaded after _Widget's parameter list has been cached,
- // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
- aspect.after(dlang, "extend", function(){
- _nameMap = {};
- }, true);
- // Map from widget name (ex: "dijit.form.Button") to a map of { "list-of-mixins": ctor }
- // if "list-of-mixins" is "__type" this is the raw type without mixins
- var _ctorMap = {};
- function getCtor(type){
- var map = _ctorMap[type] || (_ctorMap[type] = {});
- return map["__type"] || (map["__type"] = (dlang.getObject(type) || require(type)));
- }
- this._functionFromScript = function(script, attrData){
- // summary:
- // Convert a <script type="dojo/method" args="a, b, c"> ... </script>
- // into a function
- // script: DOMNode
- // The <script> DOMNode
- // attrData: String
- // For HTML5 compliance, searches for attrData + "args" (typically
- // "data-dojo-args") instead of "args"
- var preamble = "";
- var suffix = "";
- var argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args"));
- if(argsStr){
- darray.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
- preamble += "var "+part+" = arguments["+idx+"]; ";
- });
- }
- var withStr = script.getAttribute("with");
- if(withStr && withStr.length){
- darray.forEach(withStr.split(/\s*,\s*/), function(part){
- preamble += "with("+part+"){";
- suffix += "}";
- });
- }
- return new Function(preamble+script.innerHTML+suffix);
- };
- this.instantiate = /*====== dojo.parser.instantiate= ======*/ function(nodes, mixin, options) {
- // summary:
- // Takes array of nodes, and turns them into class instances and
- // potentially calls a startup method to allow them to connect with
- // any children.
- // nodes: Array
- // Array of DOM nodes
- // mixin: Object?
- // An object that will be mixed in with each node in the array.
- // Values in the mixin will override values in the node, if they
- // exist.
- // options: Object?
- // An object used to hold kwArgs for instantiation.
- // See parse.options argument for details.
- mixin = mixin || {};
- options = options || {};
- var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
- attrData = "data-" + (options.scope || dojo._scopeName) + "-",// typically "data-dojo-"
- dataDojoType = attrData + "type"; // typically "data-dojo-type"
- var list = [];
- darray.forEach(nodes, function(node){
- var type = dojoType in mixin ? mixin[dojoType] : node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
- if(type){
- list.push({
- node: node,
- "type": type
- });
- }
- });
- // Instantiate the nodes and return the objects
- return this._instantiate(list, mixin, options);
- };
- this._instantiate = /*====== dojo.parser.instantiate= ======*/ function(nodes, mixin, options){
- // summary:
- // Takes array of objects representing nodes, and turns them into class instances and
- // potentially calls a startup method to allow them to connect with
- // any children.
- // nodes: Array
- // Array of objects like
- // | {
- // | type: "dijit.form.Button",
- // | node: DOMNode,
- // | scripts: [ ... ], // array of <script type="dojo/..."> children of node
- // | inherited: { ... } // settings inherited from ancestors like dir, theme, etc.
- // | }
- // mixin: Object
- // An object that will be mixed in with each node in the array.
- // Values in the mixin will override values in the node, if they
- // exist.
- // options: Object
- // An options object used to hold kwArgs for instantiation.
- // See parse.options argument for details.
- var thelist = [];
- // Precompute names of special attributes we are looking for
- // TODO: for 2.0 default to data-dojo- regardless of scopeName (or maybe scopeName won't exist in 2.0)
- var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
- attrData = "data-" + (options.scope || dojo._scopeName) + "-",// typically "data-dojo-"
- dataDojoType = attrData + "type", // typically "data-dojo-type"
- dataDojoProps = attrData + "props", // typically "data-dojo-props"
- dataDojoAttachPoint = attrData + "attach-point",
- dataDojoAttachEvent = attrData + "attach-event",
- dataDojoId = attrData + "id",
- dataDojoMixins = attrData + "mixins";
- // And make hash to quickly check if a given attribute is special, and to map the name to something friendly
- var specialAttrs = {};
- darray.forEach([dataDojoProps, dataDojoType, dojoType, dataDojoId, "jsId", dataDojoAttachPoint,
- dataDojoAttachEvent, "dojoAttachPoint", "dojoAttachEvent", "class", "style", dataDojoMixins], function(name){
- specialAttrs[name.toLowerCase()] = name.replace(options.scope, "dojo");
- });
- function extend(type, mixins){
- return type.createSubclass && type.createSubclass(mixins) || type.extend.apply(type, mixins);
- }
- darray.forEach(nodes, function(obj){
- if(!obj){ return; }
- var node = obj.node,
- type = obj.type,
- mixins = node.getAttribute(dataDojoMixins), ctor;
- if(mixins){
- var map = _ctorMap[type];
- // remove whitespaces
- mixins = mixins.replace(/ /g, "");
- ctor = map && map[mixins];
- if(!ctor){
- // first get ctor for raw type (& create _ctorMap[type] if needed (should not be))
- ctor = getCtor(type);
- // then do the mixin
- ctor = _ctorMap[type][mixins] = extend(ctor, darray.map(mixins.split(","), getCtor));
- }
- }else{
- ctor = getCtor(type);
- }
- var proto = ctor && ctor.prototype;
- // Setup hash to hold parameter settings for this widget. Start with the parameter
- // settings inherited from ancestors ("dir" and "lang").
- // Inherited setting may later be overridden by explicit settings on node itself.
- var params = {};
- if(options.defaults){
- // settings for the document itself (or whatever subtree is being parsed)
- dlang.mixin(params, options.defaults);
- }
- if(obj.inherited){
- // settings from dir=rtl or lang=... on a node above this node
- dlang.mixin(params, obj.inherited);
- }
- // Get list of attributes explicitly listed in the markup
- var attributes;
- if(has("dom-attributes-explicit")){
- // Standard path to get list of user specified attributes
- attributes = node.attributes;
- }else if(has("dom-attributes-specified-flag")){
- // Special processing needed for IE8, to skip a few faux values in attributes[]
- attributes = darray.filter(node.attributes, function(a){ return a.specified;});
- }else{
- // Special path for IE6-7, avoid (sometimes >100) bogus entries in node.attributes
- var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false),
- attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*\s*/, "").replace(/\s*>.*$/, "");
- attributes = darray.map(attrs.split(/\s+/), function(name){
- var lcName = name.toLowerCase();
- return {
- name: name,
- // getAttribute() doesn't work for button.value, returns innerHTML of button.
- // but getAttributeNode().value doesn't work for the form.encType or li.value
- value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ?
- node.getAttribute(lcName) : node.getAttributeNode(lcName).value
- };
- });
- }
- // Read in attributes and process them, including data-dojo-props, data-dojo-type,
- // dojoAttachPoint, etc., as well as normal foo=bar attributes.
- var i=0, item;
- while(item = attributes[i++]){
- var name = item.name,
- lcName = name.toLowerCase(),
- value = item.value;
- if(lcName in specialAttrs){
- switch(specialAttrs[lcName]){
- // Data-dojo-props. Save for later to make sure it overrides direct foo=bar settings
- case "data-dojo-props":
- var extra = value;
- break;
- // data-dojo-id or jsId. TODO: drop jsId in 2.0
- case "data-dojo-id":
- case "jsId":
- var jsname = value;
- break;
- // For the benefit of _Templated
- case "data-dojo-attach-point":
- case "dojoAttachPoint":
- params.dojoAttachPoint = value;
- break;
- case "data-dojo-attach-event":
- case "dojoAttachEvent":
- params.dojoAttachEvent = value;
- break;
- // Special parameter handling needed for IE
- case "class":
- params["class"] = node.className;
- break;
- case "style":
- params["style"] = node.style && node.style.cssText;
- break;
- }
- }else{
- // Normal attribute, ex: value="123"
- // Find attribute in widget corresponding to specified name.
- // May involve case conversion, ex: onclick --> onClick
- if(!(name in proto)){
- var map = (_nameMap[type] || (_nameMap[type] = getNameMap(proto)));
- name = map[lcName] || name;
- }
- // Set params[name] to value, doing type conversion
- if(name in proto){
- switch(typeof proto[name]){
- case "string":
- params[name] = value;
- break;
- case "number":
- params[name] = value.length ? Number(value) : NaN;
- break;
- case "boolean":
- // for checked/disabled value might be "" or "checked". interpret as true.
- params[name] = value.toLowerCase() != "false";
- break;
- case "function":
- if(value === "" || value.search(/[^\w\.]+/i) != -1){
- // The user has specified some text for a function like "return x+5"
- params[name] = new Function(value);
- }else{
- // The user has specified the name of a function like "myOnClick"
- // or a single word function "return"
- params[name] = dlang.getObject(value, false) || new Function(value);
- }
- break;
- default:
- var pVal = proto[name];
- params[name] =
- (pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) : // array
- (pVal instanceof Date) ?
- (value == "" ? new Date("") : // the NaN of dates
- value == "now" ? new Date() : // current date
- dates.fromISOString(value)) :
- (pVal instanceof dojo._Url) ? (dojo.baseUrl + value) :
- djson.fromJson(value);
- }
- }else{
- params[name] = value;
- }
- }
- }
- // Mix things found in data-dojo-props into the params, overriding any direct settings
- if(extra){
- try{
- extra = djson.fromJson.call(options.propsThis, "{" + extra + "}");
- dlang.mixin(params, extra);
- }catch(e){
- // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
- throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
- }
- }
- // Any parameters specified in "mixin" override everything else.
- dlang.mixin(params, mixin);
- var scripts = obj.scripts || (ctor && (ctor._noScript || proto._noScript) ? [] :
- query("> script[type^='dojo/']", node));
- // Process <script type="dojo/*"> script tags
- // <script type="dojo/method" event="foo"> tags are added to params, and passed to
- // the widget on instantiation.
- // <script type="dojo/method"> tags (with no event) are executed after instantiation
- // <script type="dojo/connect" data-dojo-event="foo"> tags are dojo.connected after instantiation
- // <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation
- // <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation
- // note: dojo/* script tags cannot exist in self closing widgets, like <input />
- var connects = [], // functions to connect after instantiation
- calls = [], // functions to call after instantiation
- watch = [], //functions to watch after instantiation
- on = []; //functions to on after instantiation
- if(scripts){
- for(i=0; i<scripts.length; i++){
- var script = scripts[i];
- node.removeChild(script);
- // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead
- var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")),
- prop = script.getAttribute(attrData + "prop"),
- scriptType = script.getAttribute("type"),
- nf = this._functionFromScript(script, attrData);
- if(event){
- if(scriptType == "dojo/connect"){
- connects.push({event: event, func: nf});
- }else if(scriptType == "dojo/on"){
- on.push({event: event, func: nf});
- }else{
- params[event] = nf;
- }
- }else if(scriptType == "dojo/watch"){
- watch.push({prop: prop, func: nf});
- }else{
- calls.push(nf);
- }
- }
- }
- // create the instance
- var markupFactory = ctor.markupFactory || proto.markupFactory;
- var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node);
- thelist.push(instance);
- // map it to the JS namespace if that makes sense
- if(jsname){
- dlang.setObject(jsname, instance);
- }
- // process connections and startup functions
- for(i=0; i<connects.length; i++){
- aspect.after(instance, connects[i].event, dojo.hitch(instance, connects[i].func), true);
- }
- for(i=0; i<calls.length; i++){
- calls[i].call(instance);
- }
- for(i=0; i<watch.length; i++){
- instance.watch(watch[i].prop, watch[i].func);
- }
- for(i=0; i<on.length; i++){
- don(instance, on[i].event, on[i].func);
- }
- }, this);
- // Call startup on each top level instance if it makes sense (as for
- // widgets). Parent widgets will recursively call startup on their
- // (non-top level) children
- if(!mixin._started){
- darray.forEach(thelist, function(instance){
- if( !options.noStart && instance &&
- dlang.isFunction(instance.startup) &&
- !instance._started
- ){
- instance.startup();
- }
- });
- }
- return thelist;
- };
- this.scan = /*====== dojo.parser.scan= ======*/ function(root, options){
- // summary:
- // Scan a DOM tree and return an array of objects representing the DOMNodes
- // that need to be turned into widgets.
- // description:
- // Search specified node (or document root node) recursively for class instances
- // and return an array of objects that represent potential widgets to be
- // instantiated. Searches for either data-dojo-type="MID" or dojoType="MID" where
- // "MID" is a module ID like "dijit/form/Button" or a fully qualified Class name
- // like "dijit.form.Button".
- //
- // See parser.parse() for details of markup.
- // root: DomNode?
- // A default starting root node from which to start the parsing. Can be
- // omitted, defaulting to the entire document. If omitted, the `options`
- // object can be passed in this place. If the `options` object has a
- // `rootNode` member, that is used.
- // options: Object
- // a kwArgs options object, see parse() for details
- // Output list
- var list = [];
- var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
- attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-"
- dataDojoType = attrData + "type", // typically "data-dojo-type"
- dataDojoTextDir = attrData + "textdir"; // typically "data-dojo-textdir"
- // Info on DOMNode currently being processed
- var node = root.firstChild;
- // Info on parent of DOMNode currently being processed
- // - inherited: dir, lang, and textDir setting of parent, or inherited by parent
- // - parent: pointer to identical structure for my parent (or null if no parent)
- // - scripts: if specified, collects <script type="dojo/..."> type nodes from children
- var inherited = options.inherited;
- if(!inherited){
- function findAncestorAttr(node, attr){
- return (node.getAttribute && node.getAttribute(attr)) ||
- (node !== dwindow.doc && node !== dwindow.doc.documentElement && node.parentNode ? findAncestorAttr(node.parentNode, attr) : null);
- }
- inherited = {
- dir: findAncestorAttr(root, "dir"),
- lang: findAncestorAttr(root, "lang"),
- textDir: findAncestorAttr(root, dataDojoTextDir)
- };
- for(var key in inherited){
- if(!inherited[key]){ delete inherited[key]; }
- }
- }
- var parent = {
- inherited: inherited
- };
- // For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect)
- var scripts;
- // when true, only look for <script type="dojo/..."> tags, and don't recurse to children
- var scriptsOnly;
- function getEffective(parent){
- // summary:
- // Get effective dir, lang, textDir settings for specified obj
- // (matching "parent" object structure above), and do caching.
- // Take care not to return null entries.
- if(!parent.inherited){
- parent.inherited = {};
- var node = parent.node,
- grandparent = getEffective(parent.parent);
- var inherited = {
- dir: node.getAttribute("dir") || grandparent.dir,
- lang: node.getAttribute("lang") || grandparent.lang,
- textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir
- };
- for(var key in inherited){
- if(inherited[key]){
- parent.inherited[key] = inherited[key];
- }
- }
- }
- return parent.inherited;
- }
- // DFS on DOM tree, collecting nodes with data-dojo-type specified.
- while(true){
- if(!node){
- // Finished this level, continue to parent's next sibling
- if(!parent || !parent.node){
- break;
- }
- node = parent.node.nextSibling;
- scripts = parent.scripts;
- scriptsOnly = false;
- parent = parent.parent;
- continue;
- }
- if(node.nodeType != 1){
- // Text or comment node, skip to next sibling
- node = node.nextSibling;
- continue;
- }
- if(scripts && node.nodeName.toLowerCase() == "script"){
- // Save <script type="dojo/..."> for parent, then continue to next sibling
- type = node.getAttribute("type");
- if(type && /^dojo\/\w/i.test(type)){
- scripts.push(node);
- }
- node = node.nextSibling;
- continue;
- }
- if(scriptsOnly){
- node = node.nextSibling;
- continue;
- }
- // Check for data-dojo-type attribute, fallback to backward compatible dojoType
- var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
- // Short circuit for leaf nodes containing nothing [but text]
- var firstChild = node.firstChild;
- if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){
- node = node.nextSibling;
- continue;
- }
- // Setup data structure to save info on current node for when we return from processing descendant nodes
- var current = {
- node: node,
- scripts: scripts,
- parent: parent
- };
- // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate
- // Note: won't find classes declared via dojo.Declaration, so use try/catch to avoid throw from require()
- // We don't care yet about mixins ctors, we check script stop only on main class
- var ctor;
- try{
- ctor = type && getCtor(type);
- }catch(e){
- }
- var childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children
- if(type){
- list.push({
- "type": type,
- node: node,
- scripts: childScripts,
- inherited: getEffective(current) // dir & lang settings for current node, explicit or inherited
- });
- }
- // Recurse, collecting <script type="dojo/..."> children, and also looking for
- // descendant nodes with dojoType specified (unless the widget has the stopParser flag).
- // When finished with children, go to my next sibling.
- node = firstChild;
- scripts = childScripts;
- scriptsOnly = ctor && ctor.prototype.stopParser && !(options.template);
- parent = current;
- }
- return list;
- };
- this.parse = /*====== dojo.parser.parse= ======*/ function(rootNode, options){
- // summary:
- // Scan the DOM for class instances, and instantiate them.
- //
- // description:
- // Search specified node (or root node) recursively for class instances,
- // and instantiate them. Searches for either data-dojo-type="Class" or
- // dojoType="Class" where "Class" is a a fully qualified class name,
- // like `dijit.form.Button`
- //
- // Using `data-dojo-type`:
- // Attributes using can be mixed into the parameters used to instantiate the
- // Class by using a `data-dojo-props` attribute on the node being converted.
- // `data-dojo-props` should be a string attribute to be converted from JSON.
- //
- // Using `dojoType`:
- // Attributes are read from the original domNode and converted to appropriate
- // types by looking up the Class prototype values. This is the default behavior
- // from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will
- // go away in Dojo 2.0.
- //
- // rootNode: DomNode?
- // A default starting root node from which to start the parsing. Can be
- // omitted, defaulting to the entire document. If omitted, the `options`
- // object can be passed in this place. If the `options` object has a
- // `rootNode` member, that is used.
- //
- // options: Object?
- // A hash of options.
- //
- // * noStart: Boolean?
- // when set will prevent the parser from calling .startup()
- // when locating the nodes.
- // * rootNode: DomNode?
- // identical to the function's `rootNode` argument, though
- // allowed to be passed in via this `options object.
- // * template: Boolean
- // If true, ignores ContentPane's stopParser flag and parses contents inside of
- // a ContentPane inside of a template. This allows dojoAttachPoint on widgets/nodes
- // nested inside the ContentPane to work.
- // * inherited: Object
- // Hash possibly containing dir and lang settings to be applied to
- // parsed widgets, unless there's another setting on a sub-node that overrides
- // * scope: String
- // Root for attribute names to search for. If scopeName is dojo,
- // will search for data-dojo-type (or dojoType). For backwards compatibility
- // reasons defaults to dojo._scopeName (which is "dojo" except when
- // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
- // * propsThis: Object
- // If specified, "this" referenced from data-dojo-props will refer to propsThis.
- // Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin`
- //
- // example:
- // Parse all widgets on a page:
- // | dojo.parser.parse();
- //
- // example:
- // Parse all classes within the node with id="foo"
- // | dojo.parser.parse(dojo.byId('foo'));
- //
- // example:
- // Parse all classes in a page, but do not call .startup() on any
- // child
- // | dojo.parser.parse({ noStart: true })
- //
- // example:
- // Parse all classes in a node, but do not call .startup()
- // | dojo.parser.parse(someNode, { noStart:true });
- // | // or
- // | dojo.parser.parse({ noStart:true, rootNode: someNode });
- // determine the root node and options based on the passed arguments.
- var root;
- if(!options && rootNode && rootNode.rootNode){
- options = rootNode;
- root = options.rootNode;
- }else if(rootNode && dlang.isObject(rootNode) && !("nodeType" in rootNode)){
- options = rootNode;
- }else{
- root = rootNode;
- }
- root = root ? dhtml.byId(root) : dwindow.body();
- options = options || {};
- // List of all nodes on page w/dojoType specified
- var list = this.scan(root, options);
- // go build the object instances
- var mixin = options.template ? {template: true} : {};
- return this._instantiate(list, mixin, options); // Array
- };
- }();
- //Register the parser callback. It should be the first callback
- //after the a11y test.
- if(config.parseOnLoad){
- ready(100, dojo.parser, "parse");
- }
- return dojo.parser;
- });
- },
- 'dojox/form/Uploader':function(){
- require({cache:{
- 'url:dojox/form/resources/Uploader.html':"<span class=\"dijit dijitReset dijitInline\"\r\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\r\n\t\tdojoAttachEvent=\"ondijitclick:_onClick\"\r\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\r\n\t\t\tdojoAttachPoint=\"titleNode,focusNode\"\r\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\r\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" dojoAttachPoint=\"iconNode\"></span\r\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\r\n\t\t\t\tid=\"${id}_label\"\r\n\t\t\t\tdojoAttachPoint=\"containerNode\"\r\n\t\t\t></span\r\n\t\t></span\r\n\t></span\r\n\t><!--no need to have this for Uploader \r\n\t<input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\r\n\t\tdojoAttachPoint=\"valueNode\"\r\n/--></span>\r\n"}});
- define("dojox/form/Uploader", [
- "dojo/_base/kernel",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/array",
- "dojo/_base/connect",
- "dojo/_base/window",
- "dojo/dom-style",
- "dojo/dom-geometry",
- "dojo/dom-attr",
- "dojo/dom-construct",
- "dojo/dom-form",
- "dijit",
- "dijit/form/Button",
- "dojox/form/uploader/Base",
- "dojo/i18n!./nls/Uploader",
- "dojo/text!./resources/Uploader.html"
- ],function(kernel, declare, lang, array, connect, win, domStyle, domGeometry, domAttr, domConstruct, domForm, dijit, Button, uploader, res, template){
- kernel.experimental("dojox.form.Uploader");
- //
- // TODO:
- // i18n
- // label via innerHTML
- // Doc and or test what can be extended.
- // Doc custom file events
- // Use new FileReader() for thumbnails
- // flashFieldName should default to Flash
- // get('value'); and set warning
- // Make it so URL can change (current set to Flash on build)
- //
- /*=====
- uploader = dojox.form.uploader.Base;
- WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
- =====*/
- declare("dojox.form.Uploader", [uploader, Button], {
- //
- // Version: 1.6
- //
- // summary:
- // A widget that creates a stylable file-input button, with optional multi-file selection,
- // using only HTML elements. Non-HTML5 browsers have fallback options of Flash or an iframe.
- //
- // description:
- // A bare-bones, stylable file-input button, with optional multi-file selection. The list
- // of files is not displayed, that is for you to handle by connecting to the onChange
- // event, or use the dojox.form.uploader.FileList.
- //
- // Uploader without plugins does not have any ability to upload - it is for use in forms
- // where you handle the upload either by a standard POST or with Ajax using an iFrame. This
- // class is for convenience of multiple files only. No progress events are available.
- //
- // If the browser supports a file-input with the "multiple" attribute, that will be used.
- // If the browser does not support "multiple" (ergo, IE) multiple inputs are used,
- // one for each selection.
- //
- //
- // uploadOnSelect: Boolean
- // If true, uploads imediately after a file has been selected. If false,
- // waits for upload() to be called.
- uploadOnSelect:false,
- // tabIndex: Number|String
- // The tab order in the DOM.
- tabIndex:0,
- // multiple: Boolean
- // If true and flash mode, multiple files may be selected from the dialog.
- multiple:false,
- //
- // label: String
- // The text used in the button that when clicked, opens a system Browse Dialog.
- label:res.label,
- //
- // url: String
- // The url targeted for upload. An absolute URL is preferred. Relative URLs are
- // changed to absolute.
- url:"",
- //
- // name: String
- // The name attribute needs to end with square brackets: [] as this is the standard way
- // of handling an attribute "array". This requires a slightly different technique on the
- // server.
- name:"uploadedfile",
- //
- // flashFieldName: String
- // If set, this will be the name of the field of the flash uploaded files that the server
- // is expecting. If not set, "Flash" is appended to the "name" property.
- flashFieldName:"",
- //
- // uploadType: String [readonly]
- // The type of uploader being used. As an alternative to determining the upload type on the
- // server based on the fieldName, this property could be sent to the server to help
- // determine what type of parsing should be used.
- uploadType:"form",
- //
- // showInput: String [const]
- // Position to show an input which shows selected filename(s). Possible
- // values are "before", "after", which specifies where the input should
- // be placed with reference to the containerNode which contains the
- // label). By default, this is empty string (no such input will be
- // shown). Specify showInput="before" to mimic the look&feel of a
- // native file input element.
- showInput: "",
- _nameIndex:0,
- templateString: template,
- baseClass: 'dijitUploader '+Button.prototype.baseClass,
- postMixInProperties: function(){
- this._inputs = [];
- this._cons = [];
- this.inherited(arguments);
- },
- buildRendering: function(){
- console.warn("buildRendering", this.id)
- this.inherited(arguments);
- domStyle.set(this.domNode, {
- overflow:"hidden",
- position:"relative"
- });
- this._buildDisplay();
- //change the button node not occupy tabIndex: the real file input
- //will have tabIndex set
- domAttr.set(this.titleNode, 'tabIndex', -1);
- },
- _buildDisplay: function(){
- if(this.showInput){
- this.displayInput = dojo.create('input', {
- 'class':'dijitUploadDisplayInput',
- 'tabIndex':-1, 'autocomplete':'off'},
- this.containerNode, this.showInput);
- //schedule the attachpoint to be cleaned up on destroy
- this._attachPoints.push('displayInput');
- this.connect(this,'onChange', function(files){
- var i=0,l=files.length, f, r=[];
- while((f=files[i++])){
- if(f && f.name){
- r.push(f.name);
- }
- }
- this.displayInput.value = r.join(', ');
- });
- this.connect(this,'reset', function(){
- this.displayInput.value = '';
- });
- }
- },
- startup: function(){
- if(this._buildInitialized){
- return;
- }
- this._buildInitialized = true;
- this._getButtonStyle(this.domNode);
- this._setButtonStyle();
- this.inherited(arguments);
- },
- /*************************
- * Public Events *
- *************************/
- onChange: function(/* Array */fileArray){
- // summary:
- // stub to connect
- // Fires when files are selected
- // Event is an array of last files selected
- },
- onBegin: function(/* Array */dataArray){
- // summary:
- // Fires when upload begins
- },
- onProgress: function(/* Object */customEvent){
- // summary:
- // Stub to connect
- // Fires on upload progress. Event is a normalized object of common properties
- // from HTML5 uploaders and the Flash uploader. Will not fire for IFrame.
- // customEvent:
- // bytesLoaded: Number
- // Amount of bytes uploaded so far of entire payload (all files)
- // bytesTotal: Number
- // Amount of bytes of entire payload (all files)
- // type: String
- // Type of event (progress or load)
- // timeStamp: Number
- // Timestamp of when event occurred
- },
- onComplete: function(/* Object */customEvent){
- // summary:
- // stub to connect
- // Fires when all files have uploaded
- // Event is an array of all files
- this.reset();
- },
- onCancel: function(){
- // summary:
- // Stub to connect
- // Fires when dialog box has been closed
- // without a file selection
- },
- onAbort: function(){
- // summary:
- // Stub to connect
- // Fires when upload in progress was canceled
- },
- onError: function(/* Object or String */evtObject){
- // summary:
- // Fires on errors
- //
- //FIXME: Unsure of a standard form of error events
- },
- /*************************
- * Public Methods *
- *************************/
- upload: function(/*Object ? */formData){
- // summary:
- // When called, begins file upload. Only supported with plugins.
- },
- submit: function(/* form Node ? */form){
- // summary:
- // If Uploader is in a form, and other data should be sent along with the files, use
- // this instead of form submit.
- form = !!form ? form.tagName ? form : this.getForm() : this.getForm();
- var data = domForm.toObject(form);
- this.upload(data);
- },
- reset: function(){
- // summary
- // Resets entire input, clearing all files.
- // NOTE:
- // Removing individual files is not yet supported, because the HTML5 uploaders can't
- // be edited.
- // TODO:
- // Add this ability by effectively, not uploading them
- //
- delete this._files;
- this._disconnectButton();
- array.forEach(this._inputs, domConstruct.destroy, dojo);
- this._inputs = [];
- this._nameIndex = 0;
- this._createInput();
- },
- getFileList: function(){
- // summary:
- // Returns a list of selected files.
- //
- var fileArray = [];
- if(this.supports("multiple")){
- array.forEach(this._files, function(f, i){
- fileArray.push({
- index:i,
- name:f.name,
- size:f.size,
- type:f.type
- });
- }, this);
- }else{
- array.forEach(this._inputs, function(n, i){
- if(n.value){
- fileArray.push({
- index:i,
- name:n.value.substring(n.value.lastIndexOf("\\")+1),
- size:0,
- type:n.value.substring(n.value.lastIndexOf(".")+1)
- });
- }
- }, this);
- }
- return fileArray; // Array
- },
- /*********************************************
- * Private Property. Get off my lawn. *
- *********************************************/
- _getValueAttr: function(){
- // summary:
- // Internal. To get disabled use: uploader.get("disabled");
- return this.getFileList();
- },
- _setValueAttr: function(disabled){
- console.error("Uploader value is read only");
- },
- _setDisabledAttr: function(disabled){
- // summary:
- // Internal. To set disabled use: uploader.set("disabled", true);
- if(this._disabled == disabled){ return; }
- this.inherited(arguments);
- domStyle.set(this.inputNode, "display", disabled ? "none" : "");
- },
- _getButtonStyle: function(node){
- this.btnSize = {w:domStyle.get(node,'width'), h:domStyle.get(node,'height')};
- },
- _setButtonStyle: function(){
- this.inputNodeFontSize = Math.max(2, Math.max(Math.ceil(this.btnSize.w / 60), Math.ceil(this.btnSize.h / 15)));
- this._createInput();
- },
- _createInput: function(){
- if(this._inputs.length){
- domStyle.set(this.inputNode, {
- top:"500px"
- });
- this._disconnectButton();
- this._nameIndex++;
- }
- var name;
- if(this.supports("multiple")){
- // FF3.5+, WebKit
- name = this.name+"s[]";
- }else{
- // <=IE8
- name = this.name + (this.multiple ? this._nameIndex : "");
- }
- // reset focusNode to the inputNode, so when the button is clicked,
- // the focus is properly moved to the input element
- this.focusNode = this.inputNode = domConstruct.create("input", {type:"file", name:name}, this.domNode, "first");
- if(this.supports("multiple") && this.multiple){
- domAttr.set(this.inputNode, "multiple", true);
- }
- this._inputs.push(this.inputNode);
- domStyle.set(this.inputNode, {
- position:"absolute",
- fontSize:this.inputNodeFontSize+"em",
- top:"-3px",
- right:"-3px",
- opacity:0
- });
- this._connectButton();
- },
- _connectButton: function(){
- this._cons.push(connect.connect(this.inputNode, "change", this, function(evt){
- this._files = this.inputNode.files;
- this.onChange(this.getFileList(evt));
- if(!this.supports("multiple") && this.multiple) this._createInput();
- }));
- if(this.tabIndex > -1){
- this.inputNode.tabIndex = this.tabIndex;
- this._cons.push(connect.connect(this.inputNode, "focus", this, function(){
- this.titleNode.style.outline= "1px dashed #ccc";
- }));
- this._cons.push(connect.connect(this.inputNode, "blur", this, function(){
- this.titleNode.style.outline = "";
- }));
- }
- },
- _disconnectButton: function(){
- array.forEach(this._cons, connect.disconnect);
- this._cons.splice(0,this._cons.length);
- }
- });
- dojox.form.UploaderOrg = dojox.form.Uploader;
- var extensions = [dojox.form.UploaderOrg];
- dojox.form.addUploaderPlugin = function(plug){
- // summary:
- // Handle Uploader plugins. When the dojox.form.addUploaderPlugin() function is called,
- // the dojox.form.Uploader is recreated using the new plugin (mixin).
- //
- extensions.push(plug);
- declare("dojox.form.Uploader", extensions, {});
- }
- return dojox.form.Uploader;
- });
- },
- 'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\r\n\t><span class='dijitReset dijitInline dijitButtonNode'\r\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\r\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\r\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\r\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\r\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\r\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\r\n\t\t\t></span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\r\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\r\n\t\t\t\tid=\"${id}_label\"\r\n\t\t\t></span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">▼</span\r\n\t\t></span\r\n\t></span\r\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\r\n\t\tdata-dojo-attach-point=\"valueNode\"\r\n/></span>\r\n",
- 'dojo/dnd/Manager':function(){
- define("dojo/dnd/Manager", ["../main", "../Evented", "./common", "./autoscroll", "./Avatar"], function(dojo, Evented) {
- // module:
- // dojo/dnd/Manager
- // summary:
- // TODOC
- var Manager = dojo.declare("dojo.dnd.Manager", [Evented], {
- // summary:
- // the manager of DnD operations (usually a singleton)
- constructor: function(){
- this.avatar = null;
- this.source = null;
- this.nodes = [];
- this.copy = true;
- this.target = null;
- this.canDropFlag = false;
- this.events = [];
- },
- // avatar's offset from the mouse
- OFFSET_X: 16,
- OFFSET_Y: 16,
- // methods
- overSource: function(source){
- // summary:
- // called when a source detected a mouse-over condition
- // source: Object
- // the reporter
- if(this.avatar){
- this.target = (source && source.targetState != "Disabled") ? source : null;
- this.canDropFlag = Boolean(this.target);
- this.avatar.update();
- }
- dojo.publish("/dnd/source/over", [source]);
- },
- outSource: function(source){
- // summary:
- // called when a source detected a mouse-out condition
- // source: Object
- // the reporter
- if(this.avatar){
- if(this.target == source){
- this.target = null;
- this.canDropFlag = false;
- this.avatar.update();
- dojo.publish("/dnd/source/over", [null]);
- }
- }else{
- dojo.publish("/dnd/source/over", [null]);
- }
- },
- startDrag: function(source, nodes, copy){
- // summary:
- // called to initiate the DnD operation
- // source: Object
- // the source which provides items
- // nodes: Array
- // the list of transferred items
- // copy: Boolean
- // copy items, if true, move items otherwise
- this.source = source;
- this.nodes = nodes;
- this.copy = Boolean(copy); // normalizing to true boolean
- this.avatar = this.makeAvatar();
- dojo.body().appendChild(this.avatar.node);
- dojo.publish("/dnd/start", [source, nodes, this.copy]);
- this.events = [
- dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
- dojo.connect(dojo.doc, "onmouseup", this, "onMouseUp"),
- dojo.connect(dojo.doc, "onkeydown", this, "onKeyDown"),
- dojo.connect(dojo.doc, "onkeyup", this, "onKeyUp"),
- // cancel text selection and text dragging
- dojo.connect(dojo.doc, "ondragstart", dojo.stopEvent),
- dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent)
- ];
- var c = "dojoDnd" + (copy ? "Copy" : "Move");
- dojo.addClass(dojo.body(), c);
- },
- canDrop: function(flag){
- // summary:
- // called to notify if the current target can accept items
- var canDropFlag = Boolean(this.target && flag);
- if(this.canDropFlag != canDropFlag){
- this.canDropFlag = canDropFlag;
- this.avatar.update();
- }
- },
- stopDrag: function(){
- // summary:
- // stop the DnD in progress
- dojo.removeClass(dojo.body(), ["dojoDndCopy", "dojoDndMove"]);
- dojo.forEach(this.events, dojo.disconnect);
- this.events = [];
- this.avatar.destroy();
- this.avatar = null;
- this.source = this.target = null;
- this.nodes = [];
- },
- makeAvatar: function(){
- // summary:
- // makes the avatar; it is separate to be overwritten dynamically, if needed
- return new dojo.dnd.Avatar(this);
- },
- updateAvatar: function(){
- // summary:
- // updates the avatar; it is separate to be overwritten dynamically, if needed
- this.avatar.update();
- },
- // mouse event processors
- onMouseMove: function(e){
- // summary:
- // event processor for onmousemove
- // e: Event
- // mouse event
- var a = this.avatar;
- if(a){
- dojo.dnd.autoScrollNodes(e);
- //dojo.dnd.autoScroll(e);
- var s = a.node.style;
- s.left = (e.pageX + this.OFFSET_X) + "px";
- s.top = (e.pageY + this.OFFSET_Y) + "px";
- var copy = Boolean(this.source.copyState(dojo.isCopyKey(e)));
- if(this.copy != copy){
- this._setCopyStatus(copy);
- }
- }
- },
- onMouseUp: function(e){
- // summary:
- // event processor for onmouseup
- // e: Event
- // mouse event
- if(this.avatar){
- if(this.target && this.canDropFlag){
- var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))),
- params = [this.source, this.nodes, copy, this.target, e];
- dojo.publish("/dnd/drop/before", params);
- dojo.publish("/dnd/drop", params);
- }else{
- dojo.publish("/dnd/cancel");
- }
- this.stopDrag();
- }
- },
- // keyboard event processors
- onKeyDown: function(e){
- // summary:
- // event processor for onkeydown:
- // watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
- // e: Event
- // keyboard event
- if(this.avatar){
- switch(e.keyCode){
- case dojo.keys.CTRL:
- var copy = Boolean(this.source.copyState(true));
- if(this.copy != copy){
- this._setCopyStatus(copy);
- }
- break;
- case dojo.keys.ESCAPE:
- dojo.publish("/dnd/cancel");
- this.stopDrag();
- break;
- }
- }
- },
- onKeyUp: function(e){
- // summary:
- // event processor for onkeyup, watching for CTRL for copy/move status
- // e: Event
- // keyboard event
- if(this.avatar && e.keyCode == dojo.keys.CTRL){
- var copy = Boolean(this.source.copyState(false));
- if(this.copy != copy){
- this._setCopyStatus(copy);
- }
- }
- },
- // utilities
- _setCopyStatus: function(copy){
- // summary:
- // changes the copy status
- // copy: Boolean
- // the copy status
- this.copy = copy;
- this.source._markDndStatus(this.copy);
- this.updateAvatar();
- dojo.replaceClass(dojo.body(),
- "dojoDnd" + (this.copy ? "Copy" : "Move"),
- "dojoDnd" + (this.copy ? "Move" : "Copy"));
- }
- });
- // dojo.dnd._manager:
- // The manager singleton variable. Can be overwritten if needed.
- dojo.dnd._manager = null;
- Manager.manager = dojo.dnd.manager = function(){
- // summary:
- // Returns the current DnD manager. Creates one if it is not created yet.
- if(!dojo.dnd._manager){
- dojo.dnd._manager = new dojo.dnd.Manager();
- }
- return dojo.dnd._manager; // Object
- };
- return Manager;
- });
- },
- 'dijit/form/ToggleButton':function(){
- define("dijit/form/ToggleButton", [
- "dojo/_base/declare", // declare
- "dojo/_base/kernel", // kernel.deprecated
- "./Button",
- "./_ToggleButtonMixin"
- ], function(declare, kernel, Button, _ToggleButtonMixin){
- /*=====
- var Button = dijit.form.Button;
- var _ToggleButtonMixin = dijit.form._ToggleButtonMixin;
- =====*/
- // module:
- // dijit/form/ToggleButton
- // summary:
- // A templated button widget that can be in two states (checked or not).
- return declare("dijit.form.ToggleButton", [Button, _ToggleButtonMixin], {
- // summary:
- // A templated button widget that can be in two states (checked or not).
- // Can be base class for things like tabs or checkbox or radio buttons
- baseClass: "dijitToggleButton",
- setChecked: function(/*Boolean*/ checked){
- // summary:
- // Deprecated. Use set('checked', true/false) instead.
- kernel.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0");
- this.set('checked', checked);
- }
- });
- });
- },
- 'dojo/date/stamp':function(){
- define("dojo/date/stamp", ["../_base/kernel", "../_base/lang", "../_base/array"], function(dojo, lang, array) {
- // module:
- // dojo/date/stamp
- // summary:
- // TODOC
- lang.getObject("date.stamp", true, dojo);
- // Methods to convert dates to or from a wire (string) format using well-known conventions
- dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
- // summary:
- // Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
- //
- // description:
- // Accepts a string formatted according to a profile of ISO8601 as defined by
- // [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
- // Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
- // The following combinations are valid:
- //
- // * dates only
- // | * yyyy
- // | * yyyy-MM
- // | * yyyy-MM-dd
- // * times only, with an optional time zone appended
- // | * THH:mm
- // | * THH:mm:ss
- // | * THH:mm:ss.SSS
- // * and "datetimes" which could be any combination of the above
- //
- // timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
- // Assumes the local time zone if not specified. Does not validate. Improperly formatted
- // input may return null. Arguments which are out of bounds will be handled
- // by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
- // Only years between 100 and 9999 are supported.
- //
- // formattedString:
- // A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
- //
- // defaultTime:
- // Used for defaults for fields omitted in the formattedString.
- // Uses 1970-01-01T00:00:00.0Z by default.
- if(!dojo.date.stamp._isoRegExp){
- dojo.date.stamp._isoRegExp =
- //TODO: could be more restrictive and check for 00-59, etc.
- /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
- }
- var match = dojo.date.stamp._isoRegExp.exec(formattedString),
- result = null;
- if(match){
- match.shift();
- if(match[1]){match[1]--;} // Javascript Date months are 0-based
- if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
- if(defaultTime){
- // mix in defaultTime. Relatively expensive, so use || operators for the fast path of defaultTime === 0
- defaultTime = new Date(defaultTime);
- array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
- return defaultTime["get" + prop]();
- }), function(value, index){
- match[index] = match[index] || value;
- });
- }
- 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
- if(match[0] < 100){
- result.setFullYear(match[0] || 1970);
- }
- var offset = 0,
- zoneSign = match[7] && match[7].charAt(0);
- if(zoneSign != 'Z'){
- offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
- if(zoneSign != '-'){ offset *= -1; }
- }
- if(zoneSign){
- offset -= result.getTimezoneOffset();
- }
- if(offset){
- result.setTime(result.getTime() + offset * 60000);
- }
- }
- return result; // Date or null
- };
- /*=====
- dojo.date.stamp.__Options = function(){
- // selector: String
- // "date" or "time" for partial formatting of the Date object.
- // Both date and time will be formatted by default.
- // zulu: Boolean
- // if true, UTC/GMT is used for a timezone
- // milliseconds: Boolean
- // if true, output milliseconds
- this.selector = selector;
- this.zulu = zulu;
- this.milliseconds = milliseconds;
- }
- =====*/
- dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
- // summary:
- // Format a Date object as a string according a subset of the ISO-8601 standard
- //
- // description:
- // When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
- // The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
- // Does not check bounds. Only years between 100 and 9999 are supported.
- //
- // dateObject:
- // A Date object
- var _ = function(n){ return (n < 10) ? "0" + n : n; };
- options = options || {};
- var formattedDate = [],
- getter = options.zulu ? "getUTC" : "get",
- date = "";
- if(options.selector != "time"){
- var year = dateObject[getter+"FullYear"]();
- date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
- }
- formattedDate.push(date);
- if(options.selector != "date"){
- var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
- var millis = dateObject[getter+"Milliseconds"]();
- if(options.milliseconds){
- time += "."+ (millis < 100 ? "0" : "") + _(millis);
- }
- if(options.zulu){
- time += "Z";
- }else if(options.selector != "time"){
- var timezoneOffset = dateObject.getTimezoneOffset();
- var absOffset = Math.abs(timezoneOffset);
- time += (timezoneOffset > 0 ? "-" : "+") +
- _(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
- }
- formattedDate.push(time);
- }
- return formattedDate.join('T'); // String
- };
- return dojo.date.stamp;
- });
- },
- 'dijit/form/NumberSpinner':function(){
- define("dijit/form/NumberSpinner", [
- "dojo/_base/declare", // declare
- "dojo/_base/event", // event.stop
- "dojo/keys", // keys.END keys.HOME
- "./_Spinner",
- "./NumberTextBox"
- ], function(declare, event, keys, _Spinner, NumberTextBox){
- /*=====
- var _Spinner = dijit.form._Spinner;
- var NumberTextBox = dijit.form.NumberTextBox;
- =====*/
- // module:
- // dijit/form/NumberSpinner
- // summary:
- // Extends NumberTextBox to add up/down arrows and pageup/pagedown for incremental change to the value
- return declare("dijit.form.NumberSpinner", [_Spinner, NumberTextBox.Mixin], {
- // summary:
- // Extends NumberTextBox to add up/down arrows and pageup/pagedown for incremental change to the value
- //
- // description:
- // A `dijit.form.NumberTextBox` extension to provide keyboard accessible value selection
- // as well as icons for spinning direction. When using the keyboard, the typematic rules
- // apply, meaning holding the key will gradually increase or decrease the value and
- // accelerate.
- //
- // example:
- // | new dijit.form.NumberSpinner({ constraints:{ max:300, min:100 }}, "someInput");
- adjust: function(/*Object*/ val, /*Number*/ delta){
- // summary:
- // Change Number val by the given amount
- // tags:
- // protected
- var tc = this.constraints,
- v = isNaN(val),
- gotMax = !isNaN(tc.max),
- gotMin = !isNaN(tc.min)
- ;
- if(v && delta != 0){ // blank or invalid value and they want to spin, so create defaults
- val = (delta > 0) ?
- gotMin ? tc.min : gotMax ? tc.max : 0 :
- gotMax ? this.constraints.max : gotMin ? tc.min : 0
- ;
- }
- var newval = val + delta;
- if(v || isNaN(newval)){ return val; }
- if(gotMax && (newval > tc.max)){
- newval = tc.max;
- }
- if(gotMin && (newval < tc.min)){
- newval = tc.min;
- }
- return newval;
- },
- _onKeyPress: function(e){
- if((e.charOrCode == keys.HOME || e.charOrCode == keys.END) && !(e.ctrlKey || e.altKey || e.metaKey)
- && typeof this.get('value') != 'undefined' /* gibberish, so HOME and END are default editing keys*/){
- var value = this.constraints[(e.charOrCode == keys.HOME ? "min" : "max")];
- if(typeof value == "number"){
- this._setValueAttr(value, false);
- }
- // eat home or end key whether we change the value or not
- event.stop(e);
- }
- }
- });
- });
- },
- 'dojo/Stateful':function(){
- define("dojo/Stateful", ["./_base/declare", "./_base/lang", "./_base/array"], function(declare, lang, array) {
- // module:
- // dojo/Stateful
- // summary:
- // TODOC
- return declare("dojo.Stateful", null, {
- // summary:
- // Base class for objects that provide named properties with optional getter/setter
- // control and the ability to watch for property changes
- // example:
- // | var obj = new dojo.Stateful();
- // | obj.watch("foo", function(){
- // | console.log("foo changed to " + this.get("foo"));
- // | });
- // | obj.set("foo","bar");
- postscript: function(mixin){
- if(mixin){
- lang.mixin(this, mixin);
- }
- },
- get: function(/*String*/name){
- // summary:
- // Get a property on a Stateful instance.
- // name:
- // The property to get.
- // returns:
- // The property value on this Stateful instance.
- // description:
- // Get a named property on a Stateful object. The property may
- // potentially be retrieved via a getter method in subclasses. In the base class
- // this just retrieves the object's property.
- // For example:
- // | stateful = new dojo.Stateful({foo: 3});
- // | stateful.get("foo") // returns 3
- // | stateful.foo // returns 3
- return this[name]; //Any
- },
- set: function(/*String*/name, /*Object*/value){
- // summary:
- // Set a property on a Stateful instance
- // name:
- // The property to set.
- // value:
- // The value to set in the property.
- // returns:
- // The function returns this dojo.Stateful instance.
- // description:
- // Sets named properties on a stateful object and notifies any watchers of
- // the property. A programmatic setter may be defined in subclasses.
- // For example:
- // | stateful = new dojo.Stateful();
- // | stateful.watch(function(name, oldValue, value){
- // | // this will be called on the set below
- // | }
- // | stateful.set(foo, 5);
- //
- // set() may also be called with a hash of name/value pairs, ex:
- // | myObj.set({
- // | foo: "Howdy",
- // | bar: 3
- // | })
- // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
- if(typeof name === "object"){
- for(var x in name){
- if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
- this.set(x, name[x]);
- }
- }
- return this;
- }
- var oldValue = this[name];
- this[name] = value;
- if(this._watchCallbacks){
- this._watchCallbacks(name, oldValue, value);
- }
- return this; //dojo.Stateful
- },
- watch: function(/*String?*/name, /*Function*/callback){
- // summary:
- // Watches a property for changes
- // name:
- // Indicates the property to watch. This is optional (the callback may be the
- // only parameter), and if omitted, all the properties will be watched
- // returns:
- // An object handle for the watch. The unwatch method of this object
- // can be used to discontinue watching this property:
- // | var watchHandle = obj.watch("foo", callback);
- // | watchHandle.unwatch(); // callback won't be called now
- // callback:
- // The function to execute when the property changes. This will be called after
- // the property has been changed. The callback will be called with the |this|
- // set to the instance, the first argument as the name of the property, the
- // second argument as the old value and the third argument as the new value.
- var callbacks = this._watchCallbacks;
- if(!callbacks){
- var self = this;
- callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
- var notify = function(propertyCallbacks){
- if(propertyCallbacks){
- propertyCallbacks = propertyCallbacks.slice();
- for(var i = 0, l = propertyCallbacks.length; i < l; i++){
- propertyCallbacks[i].call(self, name, oldValue, value);
- }
- }
- };
- notify(callbacks['_' + name]);
- if(!ignoreCatchall){
- notify(callbacks["*"]); // the catch-all
- }
- }; // we use a function instead of an object so it will be ignored by JSON conversion
- }
- if(!callback && typeof name === "function"){
- callback = name;
- name = "*";
- }else{
- // prepend with dash to prevent name conflicts with function (like "name" property)
- name = '_' + name;
- }
- var propertyCallbacks = callbacks[name];
- if(typeof propertyCallbacks !== "object"){
- propertyCallbacks = callbacks[name] = [];
- }
- propertyCallbacks.push(callback);
- return {
- unwatch: function(){
- propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
- }
- }; //Object
- }
- });
- });
- },
- 'dijit/form/DateTextBox':function(){
- define("dijit/form/DateTextBox", [
- "dojo/_base/declare", // declare
- "../Calendar",
- "./_DateTimeTextBox"
- ], function(declare, Calendar, _DateTimeTextBox){
- /*=====
- var Calendar = dijit.Calendar;
- var _DateTimeTextBox = dijit.form._DateTimeTextBox;
- =====*/
- // module:
- // dijit/form/DateTextBox
- // summary:
- // A validating, serializable, range-bound date text box with a drop down calendar
- return declare("dijit.form.DateTextBox", _DateTimeTextBox, {
- // summary:
- // A validating, serializable, range-bound date text box with a drop down calendar
- //
- // Example:
- // | new dijit.form.DateTextBox({value: new Date(2009, 0, 20)})
- //
- // Example:
- // | <input data-dojo-type='dijit.form.DateTextBox' value='2009-01-20'>
- baseClass: "dijitTextBox dijitComboBox dijitDateTextBox",
- popupClass: Calendar,
- _selector: "date",
- // value: Date
- // The value of this widget as a JavaScript Date object, with only year/month/day specified.
- // If specified in markup, use the format specified in `stamp.fromISOString`.
- // set("value", ...) accepts either a Date object or a string.
- value: new Date("") // value.toString()="NaN"
- });
- });
- },
- 'dojox/xml/parser':function(){
- define("dojox/xml/parser", ['dojo/_base/kernel', 'dojo/_base/lang', 'dojo/_base/array', 'dojo/_base/window', 'dojo/_base/sniff'], function(dojo){
- dojo.getObject("xml.parser", true, dojox);
- //DOM type to int value for reference.
- //Ints make for more compact code than full constant names.
- //ELEMENT_NODE = 1;
- //ATTRIBUTE_NODE = 2;
- //TEXT_NODE = 3;
- //CDATA_SECTION_NODE = 4;
- //ENTITY_REFERENCE_NODE = 5;
- //ENTITY_NODE = 6;
- //PROCESSING_INSTRUCTION_NODE = 7;
- //COMMENT_NODE = 8;
- //DOCUMENT_NODE = 9;
- //DOCUMENT_TYPE_NODE = 10;
- //DOCUMENT_FRAGMENT_NODE = 11;
- //NOTATION_NODE = 12;
- dojox.xml.parser.parse = function(/*String?*/ str, /*String?*/ mimetype){
- // summary:
- // cross-browser implementation of creating an XML document object from null, empty string, and XML text..
- //
- // str:
- // Optional text to create the document from. If not provided, an empty XML document will be created.
- // If str is empty string "", then a new empty document will be created.
- // mimetype:
- // Optional mimetype of the text. Typically, this is text/xml. Will be defaulted to text/xml if not provided.
- var _document = dojo.doc;
- var doc;
- mimetype = mimetype || "text/xml";
- if(str && dojo.trim(str) && "DOMParser" in dojo.global){
- //Handle parsing the text on Mozilla based browsers etc..
- var parser = new DOMParser();
- doc = parser.parseFromString(str, mimetype);
- var de = doc.documentElement;
- var errorNS = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
- if(de.nodeName == "parsererror" && de.namespaceURI == errorNS){
- var sourceText = de.getElementsByTagNameNS(errorNS, 'sourcetext')[0];
- if(sourceText){
- sourceText = sourceText.firstChild.data;
- }
- throw new Error("Error parsing text " + de.firstChild.data + " \n" + sourceText);
- }
- return doc;
- }else if("ActiveXObject" in dojo.global){
- //Handle IE.
- var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
- var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
- dojo.some(dp, function(p){
- try{
- doc = new ActiveXObject(p);
- }catch(e){ return false; }
- return true;
- });
- if(str && doc){
- doc.async = false;
- doc.loadXML(str);
- var pe = doc.parseError;
- if(pe.errorCode !== 0){
- throw new Error("Line: " + pe.line + "\n" +
- "Col: " + pe.linepos + "\n" +
- "Reason: " + pe.reason + "\n" +
- "Error Code: " + pe.errorCode + "\n" +
- "Source: " + pe.srcText);
- }
- }
- if(doc){
- return doc; //DOMDocument
- }
- }else if(_document.implementation && _document.implementation.createDocument){
- if(str && dojo.trim(str) && _document.createElement){
- //Everyone else that we couldn't get to work. Fallback case.
- // FIXME: this may change all tags to uppercase!
- var tmp = _document.createElement("xml");
- tmp.innerHTML = str;
- var xmlDoc = _document.implementation.createDocument("foo", "", null);
- dojo.forEach(tmp.childNodes, function(child){
- xmlDoc.importNode(child, true);
- });
- return xmlDoc; // DOMDocument
- }else{
- return _document.implementation.createDocument("", "", null); // DOMDocument
- }
- }
- return null; // null
- };
- dojox.xml.parser.textContent = function(/*Node*/node, /*String?*/text){
- // summary:
- // Implementation of the DOM Level 3 attribute; scan node for text
- // description:
- // Implementation of the DOM Level 3 attribute; scan node for text
- // This function can also update the text of a node by replacing all child
- // content of the node.
- // node:
- // The node to get the text off of or set the text on.
- // text:
- // Optional argument of the text to apply to the node.
- if(arguments.length>1){
- var _document = node.ownerDocument || dojo.doc; //Preference is to get the node owning doc first or it may fail
- dojox.xml.parser.replaceChildren(node, _document.createTextNode(text));
- return text; // String
- }else{
- if(node.textContent !== undefined){ //FF 1.5 -- remove?
- return node.textContent; // String
- }
- var _result = "";
- if(node){
- dojo.forEach(node.childNodes, function(child){
- switch(child.nodeType){
- case 1: // ELEMENT_NODE
- case 5: // ENTITY_REFERENCE_NODE
- _result += dojox.xml.parser.textContent(child);
- break;
- case 3: // TEXT_NODE
- case 2: // ATTRIBUTE_NODE
- case 4: // CDATA_SECTION_NODE
- _result += child.nodeValue;
- }
- });
- }
- return _result; // String
- }
- };
- dojox.xml.parser.replaceChildren = function(/*Element*/node, /*Node || Array*/ newChildren){
- // summary:
- // Removes all children of node and appends newChild. All the existing
- // children will be destroyed.
- // description:
- // Removes all children of node and appends newChild. All the existing
- // children will be destroyed.
- // node:
- // The node to modify the children on
- // newChildren:
- // The children to add to the node. It can either be a single Node or an
- // array of Nodes.
- var nodes = [];
- if(dojo.isIE){
- dojo.forEach(node.childNodes, function(child){
- nodes.push(child);
- });
- }
- dojox.xml.parser.removeChildren(node);
- dojo.forEach(nodes, dojo.destroy);
- if(!dojo.isArray(newChildren)){
- node.appendChild(newChildren);
- }else{
- dojo.forEach(newChildren, function(child){
- node.appendChild(child);
- });
- }
- };
- dojox.xml.parser.removeChildren = function(/*Element*/node){
- // summary:
- // removes all children from node and returns the count of children removed.
- // The children nodes are not destroyed. Be sure to call dojo.destroy on them
- // after they are not used anymore.
- // node:
- // The node to remove all the children from.
- var count = node.childNodes.length;
- while(node.hasChildNodes()){
- node.removeChild(node.firstChild);
- }
- return count; // int
- };
- dojox.xml.parser.innerXML = function(/*Node*/node){
- // summary:
- // Implementation of MS's innerXML function.
- // node:
- // The node from which to generate the XML text representation.
- if(node.innerXML){
- return node.innerXML; // String
- }else if(node.xml){
- return node.xml; // String
- }else if(typeof XMLSerializer != "undefined"){
- return (new XMLSerializer()).serializeToString(node); // String
- }
- return null;
- };
- return dojox.xml.parser;
- });
- },
- 'url:dijit/templates/Calendar.html':"<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\" role=\"grid\" aria-labelledby=\"${id}_mddb ${id}_year\">\r\n\t<thead>\r\n\t\t<tr class=\"dijitReset dijitCalendarMonthContainer\" valign=\"top\">\r\n\t\t\t<th class='dijitReset dijitCalendarArrow' data-dojo-attach-point=\"decrementMonth\">\r\n\t\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitCalendarIncrementControl dijitCalendarDecrease\" role=\"presentation\"/>\r\n\t\t\t\t<span data-dojo-attach-point=\"decreaseArrowNode\" class=\"dijitA11ySideArrow\">-</span>\r\n\t\t\t</th>\r\n\t\t\t<th class='dijitReset' colspan=\"5\">\r\n\t\t\t\t<div data-dojo-attach-point=\"monthNode\">\r\n\t\t\t\t</div>\r\n\t\t\t</th>\r\n\t\t\t<th class='dijitReset dijitCalendarArrow' data-dojo-attach-point=\"incrementMonth\">\r\n\t\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitCalendarIncrementControl dijitCalendarIncrease\" role=\"presentation\"/>\r\n\t\t\t\t<span data-dojo-attach-point=\"increaseArrowNode\" class=\"dijitA11ySideArrow\">+</span>\r\n\t\t\t</th>\r\n\t\t</tr>\r\n\t\t<tr>\r\n\t\t\t${!dayCellsHtml}\r\n\t\t</tr>\r\n\t</thead>\r\n\t<tbody data-dojo-attach-point=\"dateRowsNode\" data-dojo-attach-event=\"onclick: _onDayClick\" class=\"dijitReset dijitCalendarBodyContainer\">\r\n\t\t\t${!dateRowsHtml}\r\n\t</tbody>\r\n\t<tfoot class=\"dijitReset dijitCalendarYearContainer\">\r\n\t\t<tr>\r\n\t\t\t<td class='dijitReset' valign=\"top\" colspan=\"7\" role=\"presentation\">\r\n\t\t\t\t<div class=\"dijitCalendarYearLabel\">\r\n\t\t\t\t\t<span data-dojo-attach-point=\"previousYearLabelNode\" class=\"dijitInline dijitCalendarPreviousYear\" role=\"button\"></span>\r\n\t\t\t\t\t<span data-dojo-attach-point=\"currentYearLabelNode\" class=\"dijitInline dijitCalendarSelectedYear\" role=\"button\" id=\"${id}_year\"></span>\r\n\t\t\t\t\t<span data-dojo-attach-point=\"nextYearLabelNode\" class=\"dijitInline dijitCalendarNextYear\" role=\"button\"></span>\r\n\t\t\t\t</div>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t</tfoot>\r\n</table>\r\n",
- 'dijit/form/_AutoCompleterMixin':function(){
- define("dijit/form/_AutoCompleterMixin", [
- "dojo/_base/connect", // keys keys.SHIFT
- "dojo/data/util/filter", // patternToRegExp
- "dojo/_base/declare", // declare
- "dojo/_base/Deferred", // Deferred.when
- "dojo/dom-attr", // domAttr.get
- "dojo/_base/event", // event.stop
- "dojo/keys",
- "dojo/_base/lang", // lang.clone lang.hitch
- "dojo/query", // query
- "dojo/regexp", // regexp.escapeString
- "dojo/_base/sniff", // has("ie")
- "dojo/string", // string.substitute
- "dojo/_base/window", // win.doc.selection.createRange
- "./DataList",
- "../registry", // registry.byId
- "./_TextBoxMixin" // defines _TextBoxMixin.selectInputText
- ], function(connect, filter, declare, Deferred, domAttr, event, keys, lang, query, regexp, has, string, win,
- DataList, registry, _TextBoxMixin){
- // module:
- // dijit/form/_AutoCompleterMixin
- // summary:
- // A mixin that implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect`
- return declare("dijit.form._AutoCompleterMixin", null, {
- // summary:
- // A mixin that implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect`
- // description:
- // All widgets that mix in dijit.form._AutoCompleterMixin must extend `dijit.form._FormValueWidget`.
- // tags:
- // protected
- // item: Object
- // This is the item returned by the dojo.data.store implementation that
- // provides the data for this ComboBox, it's the currently selected item.
- item: null,
- // pageSize: Integer
- // Argument to data provider.
- // Specifies number of search results per page (before hitting "next" button)
- pageSize: Infinity,
- // store: [const] dojo.store.api.Store
- // Reference to data provider object used by this ComboBox
- store: null,
- // fetchProperties: Object
- // Mixin to the store's fetch.
- // For example, to set the sort order of the ComboBox menu, pass:
- // | { sort: [{attribute:"name",descending: true}] }
- // To override the default queryOptions so that deep=false, do:
- // | { queryOptions: {ignoreCase: true, deep: false} }
- fetchProperties:{},
- // query: Object
- // A query that can be passed to 'store' to initially filter the items,
- // before doing further filtering based on `searchAttr` and the key.
- // Any reference to the `searchAttr` is ignored.
- query: {},
- // autoComplete: Boolean
- // If user types in a partial string, and then tab out of the `<input>` box,
- // automatically copy the first entry displayed in the drop down list to
- // the `<input>` field
- autoComplete: true,
- // highlightMatch: String
- // One of: "first", "all" or "none".
- //
- // If the ComboBox/FilteringSelect opens with the search results and the searched
- // string can be found, it will be highlighted. If set to "all"
- // then will probably want to change `queryExpr` parameter to '*${0}*'
- //
- // Highlighting is only performed when `labelType` is "text", so as to not
- // interfere with any HTML markup an HTML label might contain.
- highlightMatch: "first",
- // searchDelay: Integer
- // Delay in milliseconds between when user types something and we start
- // searching based on that value
- searchDelay: 100,
- // searchAttr: String
- // Search for items in the data store where this attribute (in the item)
- // matches what the user typed
- searchAttr: "name",
- // labelAttr: String?
- // The entries in the drop down list come from this attribute in the
- // dojo.data items.
- // If not specified, the searchAttr attribute is used instead.
- labelAttr: "",
- // labelType: String
- // Specifies how to interpret the labelAttr in the data store items.
- // Can be "html" or "text".
- labelType: "text",
- // queryExpr: String
- // This specifies what query ComboBox/FilteringSelect sends to the data store,
- // based on what the user has typed. Changing this expression will modify
- // whether the drop down shows only exact matches, a "starting with" match,
- // etc. Use it in conjunction with highlightMatch.
- // dojo.data query expression pattern.
- // `${0}` will be substituted for the user text.
- // `*` is used for wildcards.
- // `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is"
- queryExpr: "${0}*",
- // ignoreCase: Boolean
- // Set true if the ComboBox/FilteringSelect should ignore case when matching possible items
- ignoreCase: true,
- // Flags to _HasDropDown to limit height of drop down to make it fit in viewport
- maxHeight: -1,
- // For backwards compatibility let onClick events propagate, even clicks on the down arrow button
- _stopClickEvents: false,
- _getCaretPos: function(/*DomNode*/ element){
- // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
- var pos = 0;
- if(typeof(element.selectionStart) == "number"){
- // FIXME: this is totally borked on Moz < 1.3. Any recourse?
- pos = element.selectionStart;
- }else if(has("ie")){
- // in the case of a mouse click in a popup being handled,
- // then the win.doc.selection is not the textarea, but the popup
- // var r = win.doc.selection.createRange();
- // hack to get IE 6 to play nice. What a POS browser.
- var tr = win.doc.selection.createRange().duplicate();
- var ntr = element.createTextRange();
- tr.move("character",0);
- ntr.move("character",0);
- try{
- // If control doesn't have focus, you get an exception.
- // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
- // There appears to be no workaround for this - googled for quite a while.
- ntr.setEndPoint("EndToEnd", tr);
- pos = String(ntr.text).replace(/\r/g,"").length;
- }catch(e){
- // If focus has shifted, 0 is fine for caret pos.
- }
- }
- return pos;
- },
- _setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
- location = parseInt(location);
- _TextBoxMixin.selectInputText(element, location, location);
- },
- _setDisabledAttr: function(/*Boolean*/ value){
- // Additional code to set disabled state of ComboBox node.
- // Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr().
- this.inherited(arguments);
- this.domNode.setAttribute("aria-disabled", value);
- },
- _abortQuery: function(){
- // stop in-progress query
- if(this.searchTimer){
- clearTimeout(this.searchTimer);
- this.searchTimer = null;
- }
- if(this._fetchHandle){
- if(this._fetchHandle.cancel){
- this._cancelingQuery = true;
- this._fetchHandle.cancel();
- this._cancelingQuery = false;
- }
- this._fetchHandle = null;
- }
- },
- _onInput: function(/*Event*/ evt){
- // summary:
- // Handles paste events
- this.inherited(arguments);
- if(evt.charOrCode == 229){ // IME or cut/paste event
- this._onKey(evt);
- }
- },
- _onKey: function(/*Event*/ evt){
- // summary:
- // Handles keyboard events
- if(this.disabled || this.readOnly){ return; }
- var key = evt.charOrCode;
- // except for cutting/pasting case - ctrl + x/v
- if(evt.altKey || ((evt.ctrlKey || evt.metaKey) && (key != 'x' && key != 'v')) || key == keys.SHIFT){
- return; // throw out weird key combinations and spurious events
- }
- var doSearch = false;
- var pw = this.dropDown;
- var highlighted = null;
- this._prev_key_backspace = false;
- this._abortQuery();
- // _HasDropDown will do some of the work:
- // 1. when drop down is not yet shown:
- // - if user presses the down arrow key, call loadDropDown()
- // 2. when drop down is already displayed:
- // - on ESC key, call closeDropDown()
- // - otherwise, call dropDown.handleKey() to process the keystroke
- this.inherited(arguments);
- if(this._opened){
- highlighted = pw.getHighlightedOption();
- }
- switch(key){
- case keys.PAGE_DOWN:
- case keys.DOWN_ARROW:
- case keys.PAGE_UP:
- case keys.UP_ARROW:
- // Keystroke caused ComboBox_menu to move to a different item.
- // Copy new item to <input> box.
- if(this._opened){
- this._announceOption(highlighted);
- }
- event.stop(evt);
- break;
- case keys.ENTER:
- // prevent submitting form if user presses enter. Also
- // prevent accepting the value if either Next or Previous
- // are selected
- if(highlighted){
- // only stop event on prev/next
- if(highlighted == pw.nextButton){
- this._nextSearch(1);
- event.stop(evt);
- break;
- }else if(highlighted == pw.previousButton){
- this._nextSearch(-1);
- event.stop(evt);
- break;
- }
- }else{
- // Update 'value' (ex: KY) according to currently displayed text
- this._setBlurValue(); // set value if needed
- this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting
- }
- // default case:
- // if enter pressed while drop down is open, or for FilteringSelect,
- // if we are in the middle of a query to convert a directly typed in value to an item,
- // prevent submit
- if(this._opened || this._fetchHandle){
- event.stop(evt);
- }
- // fall through
- case keys.TAB:
- var newvalue = this.get('displayedValue');
- // if the user had More Choices selected fall into the
- // _onBlur handler
- if(pw && (
- newvalue == pw._messages["previousMessage"] ||
- newvalue == pw._messages["nextMessage"])
- ){
- break;
- }
- if(highlighted){
- this._selectOption(highlighted);
- }
- // fall through
- case keys.ESCAPE:
- if(this._opened){
- this._lastQuery = null; // in case results come back later
- this.closeDropDown();
- }
- break;
- case ' ':
- if(highlighted){
- // user is effectively clicking a choice in the drop down menu
- event.stop(evt);
- this._selectOption(highlighted);
- this.closeDropDown();
- }else{
- // user typed a space into the input box, treat as normal character
- doSearch = true;
- }
- break;
- case keys.DELETE:
- case keys.BACKSPACE:
- this._prev_key_backspace = true;
- doSearch = true;
- break;
- default:
- // Non char keys (F1-F12 etc..) shouldn't open list.
- // Ascii characters and IME input (Chinese, Japanese etc.) should.
- //IME input produces keycode == 229.
- doSearch = typeof key == 'string' || key == 229;
- }
- if(doSearch){
- // need to wait a tad before start search so that the event
- // bubbles through DOM and we have value visible
- this.item = undefined; // undefined means item needs to be set
- this.searchTimer = setTimeout(lang.hitch(this, "_startSearchFromInput"),1);
- }
- },
- _autoCompleteText: function(/*String*/ text){
- // summary:
- // Fill in the textbox with the first item from the drop down
- // list, and highlight the characters that were
- // auto-completed. For example, if user typed "CA" and the
- // drop down list appeared, the textbox would be changed to
- // "California" and "ifornia" would be highlighted.
- var fn = this.focusNode;
- // IE7: clear selection so next highlight works all the time
- _TextBoxMixin.selectInputText(fn, fn.value.length);
- // does text autoComplete the value in the textbox?
- var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr';
- if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){
- var cpos = this.autoComplete ? this._getCaretPos(fn) : fn.value.length;
- // only try to extend if we added the last character at the end of the input
- if((cpos+1) > fn.value.length){
- // only add to input node as we would overwrite Capitalisation of chars
- // actually, that is ok
- fn.value = text;//.substr(cpos);
- // visually highlight the autocompleted characters
- _TextBoxMixin.selectInputText(fn, cpos);
- }
- }else{
- // text does not autoComplete; replace the whole value and highlight
- fn.value = text;
- _TextBoxMixin.selectInputText(fn);
- }
- },
- _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){
- // summary:
- // Callback when a search completes.
- // description:
- // 1. generates drop-down list and calls _showResultList() to display it
- // 2. if this result list is from user pressing "more choices"/"previous choices"
- // then tell screen reader to announce new option
- this._fetchHandle = null;
- if( this.disabled ||
- this.readOnly ||
- (query[this.searchAttr] !== this._lastQuery) // TODO: better way to avoid getting unwanted notify
- ){
- return;
- }
- var wasSelected = this.dropDown.getHighlightedOption();
- this.dropDown.clearResultList();
- if(!results.length && options.start == 0){ // if no results and not just the previous choices button
- this.closeDropDown();
- return;
- }
- // Fill in the textbox with the first item from the drop down list,
- // and highlight the characters that were auto-completed. For
- // example, if user typed "CA" and the drop down list appeared, the
- // textbox would be changed to "California" and "ifornia" would be
- // highlighted.
- this.dropDown.createOptions(
- results,
- options,
- lang.hitch(this, "_getMenuLabelFromItem")
- );
- // show our list (only if we have content, else nothing)
- this._showResultList();
- // #4091:
- // tell the screen reader that the paging callback finished by
- // shouting the next choice
- if(options.direction){
- if(1 == options.direction){
- this.dropDown.highlightFirstOption();
- }else if(-1 == options.direction){
- this.dropDown.highlightLastOption();
- }
- if(wasSelected){
- this._announceOption(this.dropDown.getHighlightedOption());
- }
- }else if(this.autoComplete && !this._prev_key_backspace
- // when the user clicks the arrow button to show the full list,
- // startSearch looks for "*".
- // it does not make sense to autocomplete
- // if they are just previewing the options available.
- && !/^[*]+$/.test(query[this.searchAttr].toString())){
- this._announceOption(this.dropDown.containerNode.firstChild.nextSibling); // 1st real item
- }
- },
- _showResultList: function(){
- // summary:
- // Display the drop down if not already displayed, or if it is displayed, then
- // reposition it if necessary (reposition may be necessary if drop down's height changed).
- this.closeDropDown(true);
- this.openDropDown();
- this.domNode.setAttribute("aria-expanded", "true");
- },
- loadDropDown: function(/*Function*/ /*===== callback =====*/){
- // Overrides _HasDropDown.loadDropDown().
- // This is called when user has pressed button icon or pressed the down arrow key
- // to open the drop down.
- this._startSearchAll();
- },
- isLoaded: function(){
- // signal to _HasDropDown that it needs to call loadDropDown() to load the
- // drop down asynchronously before displaying it
- return false;
- },
- closeDropDown: function(){
- // Overrides _HasDropDown.closeDropDown(). Closes the drop down (assuming that it's open).
- // This method is the callback when the user types ESC or clicking
- // the button icon while the drop down is open. It's also called by other code.
- this._abortQuery();
- if(this._opened){
- this.inherited(arguments);
- this.domNode.setAttribute("aria-expanded", "false");
- this.focusNode.removeAttribute("aria-activedescendant");
- }
- },
- _setBlurValue: function(){
- // if the user clicks away from the textbox OR tabs away, set the
- // value to the textbox value
- // #4617:
- // if value is now more choices or previous choices, revert
- // the value
- var newvalue = this.get('displayedValue');
- var pw = this.dropDown;
- if(pw && (
- newvalue == pw._messages["previousMessage"] ||
- newvalue == pw._messages["nextMessage"]
- )
- ){
- this._setValueAttr(this._lastValueReported, true);
- }else if(typeof this.item == "undefined"){
- // Update 'value' (ex: KY) according to currently displayed text
- this.item = null;
- this.set('displayedValue', newvalue);
- }else{
- if(this.value != this._lastValueReported){
- this._handleOnChange(this.value, true);
- }
- this._refreshState();
- }
- },
- _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
- // summary:
- // Set the displayed valued in the input box, and the hidden value
- // that gets submitted, based on a dojo.data store item.
- // description:
- // Users shouldn't call this function; they should be calling
- // set('item', value)
- // tags:
- // private
- var value = '';
- if(item){
- if(!displayedValue){
- displayedValue = this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API)
- this.store.getValue(item, this.searchAttr) : item[this.searchAttr];
- }
- value = this._getValueField() != this.searchAttr ? this.store.getIdentity(item) : displayedValue;
- }
- this.set('value', value, priorityChange, displayedValue, item);
- },
- _announceOption: function(/*Node*/ node){
- // summary:
- // a11y code that puts the highlighted option in the textbox.
- // This way screen readers will know what is happening in the
- // menu.
- if(!node){
- return;
- }
- // pull the text value from the item attached to the DOM node
- var newValue;
- if(node == this.dropDown.nextButton ||
- node == this.dropDown.previousButton){
- newValue = node.innerHTML;
- this.item = undefined;
- this.value = '';
- }else{
- var item = this.dropDown.items[node.getAttribute("item")];
- newValue = (this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API)
- this.store.getValue(item, this.searchAttr) : item[this.searchAttr]).toString();
- this.set('item', item, false, newValue);
- }
- // get the text that the user manually entered (cut off autocompleted text)
- this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
- // set up ARIA activedescendant
- this.focusNode.setAttribute("aria-activedescendant", domAttr.get(node, "id"));
- // autocomplete the rest of the option to announce change
- this._autoCompleteText(newValue);
- },
- _selectOption: function(/*DomNode*/ target){
- // summary:
- // Menu callback function, called when an item in the menu is selected.
- this.closeDropDown();
- if(target){
- this._announceOption(target);
- }
- this._setCaretPos(this.focusNode, this.focusNode.value.length);
- this._handleOnChange(this.value, true);
- },
- _startSearchAll: function(){
- this._startSearch('');
- },
- _startSearchFromInput: function(){
- this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1"));
- },
- _getQueryString: function(/*String*/ text){
- return string.substitute(this.queryExpr, [text]);
- },
- _startSearch: function(/*String*/ key){
- // summary:
- // Starts a search for elements matching key (key=="" means to return all items),
- // and calls _openResultList() when the search completes, to display the results.
- if(!this.dropDown){
- var popupId = this.id + "_popup",
- dropDownConstructor = lang.isString(this.dropDownClass) ?
- lang.getObject(this.dropDownClass, false) : this.dropDownClass;
- this.dropDown = new dropDownConstructor({
- onChange: lang.hitch(this, this._selectOption),
- id: popupId,
- dir: this.dir,
- textDir: this.textDir
- });
- this.focusNode.removeAttribute("aria-activedescendant");
- this.textbox.setAttribute("aria-owns",popupId); // associate popup with textbox
- }
- this._lastInput = key; // Store exactly what was entered by the user.
- // Setup parameters to be passed to store.query().
- // Create a new query to prevent accidentally querying for a hidden
- // value from FilteringSelect's keyField
- var query = lang.clone(this.query); // #5970
- var options = {
- start: 0,
- count: this.pageSize,
- queryOptions: { // remove for 2.0
- ignoreCase: this.ignoreCase,
- deep: true
- }
- };
- lang.mixin(options, this.fetchProperties);
- // Generate query
- var qs = this._getQueryString(key), q;
- if(this.store._oldAPI){
- // remove this branch for 2.0
- q = qs;
- }else{
- // Query on searchAttr is a regex for benefit of dojo.store.Memory,
- // but with a toString() method to help dojo.store.JsonRest.
- // Search string like "Co*" converted to regex like /^Co.*$/i.
- q = filter.patternToRegExp(qs, this.ignoreCase);
- q.toString = function(){ return qs; };
- }
- this._lastQuery = query[this.searchAttr] = q;
- // Function to run the query, wait for the results, and then call _openResultList()
- var _this = this,
- startQuery = function(){
- var resPromise = _this._fetchHandle = _this.store.query(query, options);
- Deferred.when(resPromise, function(res){
- _this._fetchHandle = null;
- res.total = resPromise.total;
- _this._openResultList(res, query, options);
- }, function(err){
- _this._fetchHandle = null;
- if(!_this._cancelingQuery){ // don't treat canceled query as an error
- console.error(_this.declaredClass + ' ' + err.toString());
- _this.closeDropDown();
- }
- });
- };
- // #5970: set _lastQuery, *then* start the timeout
- // otherwise, if the user types and the last query returns before the timeout,
- // _lastQuery won't be set and their input gets rewritten
- this.searchTimer = setTimeout(lang.hitch(this, function(query, _this){
- this.searchTimer = null;
- startQuery();
- // Setup method to handle clicking next/previous buttons to page through results
- this._nextSearch = this.dropDown.onPage = function(direction){
- options.start += options.count * direction;
- // tell callback the direction of the paging so the screen
- // reader knows which menu option to shout
- options.direction = direction;
- startQuery();
- _this.focus();
- };
- }, query, this), this.searchDelay);
- },
- _getValueField: function(){
- // summary:
- // Helper for postMixInProperties() to set this.value based on data inlined into the markup.
- // Returns the attribute name in the item (in dijit.form._ComboBoxDataStore) to use as the value.
- return this.searchAttr;
- },
- //////////// INITIALIZATION METHODS ///////////////////////////////////////
- constructor: function(){
- this.query={};
- this.fetchProperties={};
- },
- postMixInProperties: function(){
- if(!this.store){
- var srcNodeRef = this.srcNodeRef;
- var list = this.list;
- if(list){
- this.store = registry.byId(list);
- }else{
- // if user didn't specify store, then assume there are option tags
- this.store = new DataList({}, srcNodeRef);
- }
- // if there is no value set and there is an option list, set
- // the value to the first value to be consistent with native Select
- // Firefox and Safari set value
- // IE6 and Opera set selectedIndex, which is automatically set
- // by the selected attribute of an option tag
- // IE6 does not set value, Opera sets value = selectedIndex
- if(!("value" in this.params)){
- var item = (this.item = this.store.fetchSelectedItem());
- if(item){
- var valueField = this._getValueField();
- // remove getValue() for 2.0 (old dojo.data API)
- this.value = this.store._oldAPI ? this.store.getValue(item, valueField) : item[valueField];
- }
- }
- }
- this.inherited(arguments);
- },
- postCreate: function(){
- // summary:
- // Subclasses must call this method from their postCreate() methods
- // tags:
- // protected
- // find any associated label element and add to ComboBox node.
- var label=query('label[for="'+this.id+'"]');
- if(label.length){
- label[0].id = (this.id+"_label");
- this.domNode.setAttribute("aria-labelledby", label[0].id);
- }
- this.inherited(arguments);
- },
- _getMenuLabelFromItem: function(/*Item*/ item){
- var label = this.labelFunc(item, this.store),
- labelType = this.labelType;
- // If labelType is not "text" we don't want to screw any markup ot whatever.
- if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){
- label = this.doHighlight(label, this._escapeHtml(this._lastInput));
- labelType = "html";
- }
- return {html: labelType == "html", label: label};
- },
- doHighlight: function(/*String*/ label, /*String*/ find){
- // summary:
- // Highlights the string entered by the user in the menu. By default this
- // highlights the first occurrence found. Override this method
- // to implement your custom highlighting.
- // tags:
- // protected
- var
- // Add (g)lobal modifier when this.highlightMatch == "all" and (i)gnorecase when this.ignoreCase == true
- modifiers = (this.ignoreCase ? "i" : "") + (this.highlightMatch == "all" ? "g" : ""),
- i = this.queryExpr.indexOf("${0}");
- find = regexp.escapeString(find); // escape regexp special chars
- return this._escapeHtml(label).replace(
- // prepend ^ when this.queryExpr == "${0}*" and append $ when this.queryExpr == "*${0}"
- new RegExp((i == 0 ? "^" : "") + "("+ find +")" + (i == (this.queryExpr.length - 4) ? "$" : ""), modifiers),
- '<span class="dijitComboBoxHighlightMatch">$1</span>'
- ); // returns String, (almost) valid HTML (entities encoded)
- },
- _escapeHtml: function(/*String*/ str){
- // TODO Should become dojo.html.entities(), when exists use instead
- // summary:
- // Adds escape sequences for special characters in XML: &<>"'
- str = String(str).replace(/&/gm, "&").replace(/</gm, "<")
- .replace(/>/gm, ">").replace(/"/gm, """); //balance"
- return str; // string
- },
- reset: function(){
- // Overrides the _FormWidget.reset().
- // Additionally reset the .item (to clean up).
- this.item = null;
- this.inherited(arguments);
- },
- labelFunc: function(/*item*/ item, /*dojo.store.api.Store*/ store){
- // summary:
- // Computes the label to display based on the dojo.data store item.
- // returns:
- // The label that the ComboBox should display
- // tags:
- // private
- // Use toString() because XMLStore returns an XMLItem whereas this
- // method is expected to return a String (#9354).
- // Remove getValue() for 2.0 (old dojo.data API)
- return (store._oldAPI ? store.getValue(item, this.labelAttr || this.searchAttr) :
- item[this.labelAttr || this.searchAttr]).toString(); // String
- },
- _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){
- // summary:
- // Hook so set('value', value) works.
- // description:
- // Sets the value of the select.
- this._set("item", item||null); // value not looked up in store
- if(!value){ value = ''; } // null translates to blank
- this.inherited(arguments);
- },
- _setTextDirAttr: function(/*String*/ textDir){
- // summary:
- // Setter for textDir, needed for the dropDown's textDir update.
- // description:
- // Users shouldn't call this function; they should be calling
- // set('textDir', value)
- // tags:
- // private
- this.inherited(arguments);
- // update the drop down also (_ComboBoxMenuMixin)
- if(this.dropDown){
- this.dropDown._set("textDir", textDir);
- }
- }
- });
- });
- },
- 'dojox/grid/Selection':function(){
- define("dojox/grid/Selection", [
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/dom-attr"
- ], function(declare, array, lang, domAttr){
- return declare("dojox.grid.Selection", null, {
- // summary:
- // Manages row selection for grid. Owned by grid and used internally
- // for selection. Override to implement custom selection.
- constructor: function(inGrid){
- this.grid = inGrid;
- this.selected = [];
- this.setMode(inGrid.selectionMode);
- },
- mode: 'extended',
- selected: null,
- updating: 0,
- selectedIndex: -1,
- setMode: function(mode){
- if(this.selected.length){
- this.deselectAll();
- }
- if(mode != 'extended' && mode != 'multiple' && mode != 'single' && mode != 'none'){
- this.mode = 'extended';
- }else{
- this.mode = mode;
- }
- },
- onCanSelect: function(inIndex){
- return this.grid.onCanSelect(inIndex);
- },
- onCanDeselect: function(inIndex){
- return this.grid.onCanDeselect(inIndex);
- },
- onSelected: function(inIndex){
- },
- onDeselected: function(inIndex){
- },
- //onSetSelected: function(inIndex, inSelect) { };
- onChanging: function(){
- },
- onChanged: function(){
- },
- isSelected: function(inIndex){
- if(this.mode == 'none'){
- return false;
- }
- return this.selected[inIndex];
- },
- getFirstSelected: function(){
- if(!this.selected.length||this.mode == 'none'){ return -1; }
- for(var i=0, l=this.selected.length; i<l; i++){
- if(this.selected[i]){
- return i;
- }
- }
- return -1;
- },
- getNextSelected: function(inPrev){
- if(this.mode == 'none'){ return -1; }
- for(var i=inPrev+1, l=this.selected.length; i<l; i++){
- if(this.selected[i]){
- return i;
- }
- }
- return -1;
- },
- getSelected: function(){
- var result = [];
- for(var i=0, l=this.selected.length; i<l; i++){
- if(this.selected[i]){
- result.push(i);
- }
- }
- return result;
- },
- getSelectedCount: function(){
- var c = 0;
- for(var i=0; i<this.selected.length; i++){
- if(this.selected[i]){
- c++;
- }
- }
- return c;
- },
- _beginUpdate: function(){
- if(this.updating === 0){
- this.onChanging();
- }
- this.updating++;
- },
- _endUpdate: function(){
- this.updating--;
- if(this.updating === 0){
- this.onChanged();
- }
- },
- select: function(inIndex){
- if(this.mode == 'none'){ return; }
- if(this.mode != 'multiple'){
- this.deselectAll(inIndex);
- this.addToSelection(inIndex);
- }else{
- this.toggleSelect(inIndex);
- }
- },
- addToSelection: function(inIndex){
- if(this.mode == 'none'){ return; }
- if(lang.isArray(inIndex)){
- array.forEach(inIndex, this.addToSelection, this);
- return;
- }
- inIndex = Number(inIndex);
- if(this.selected[inIndex]){
- this.selectedIndex = inIndex;
- }else{
- if(this.onCanSelect(inIndex) !== false){
- this.selectedIndex = inIndex;
- var rowNode = this.grid.getRowNode(inIndex);
- if(rowNode){
- domAttr.set(rowNode, "aria-selected", "true");
- }
- this._beginUpdate();
- this.selected[inIndex] = true;
- //this.grid.onSelected(inIndex);
- this.onSelected(inIndex);
- //this.onSetSelected(inIndex, true);
- this._endUpdate();
- }
- }
- },
- deselect: function(inIndex){
- if(this.mode == 'none'){ return; }
- if(lang.isArray(inIndex)){
- array.forEach(inIndex, this.deselect, this);
- return;
- }
- inIndex = Number(inIndex);
- if(this.selectedIndex == inIndex){
- this.selectedIndex = -1;
- }
- if(this.selected[inIndex]){
- if(this.onCanDeselect(inIndex) === false){
- return;
- }
- var rowNode = this.grid.getRowNode(inIndex);
- if(rowNode){
- domAttr.set(rowNode, "aria-selected", "false");
- }
- this._beginUpdate();
- delete this.selected[inIndex];
- //this.grid.onDeselected(inIndex);
- this.onDeselected(inIndex);
- //this.onSetSelected(inIndex, false);
- this._endUpdate();
- }
- },
- setSelected: function(inIndex, inSelect){
- this[(inSelect ? 'addToSelection' : 'deselect')](inIndex);
- },
- toggleSelect: function(inIndex){
- if(lang.isArray(inIndex)){
- array.forEach(inIndex, this.toggleSelect, this);
- return;
- }
- this.setSelected(inIndex, !this.selected[inIndex]);
- },
- _range: function(inFrom, inTo, func){
- var s = (inFrom >= 0 ? inFrom : inTo), e = inTo;
- if(s > e){
- e = s;
- s = inTo;
- }
- for(var i=s; i<=e; i++){
- func(i);
- }
- },
- selectRange: function(inFrom, inTo){
- this._range(inFrom, inTo, lang.hitch(this, "addToSelection"));
- },
- deselectRange: function(inFrom, inTo){
- this._range(inFrom, inTo, lang.hitch(this, "deselect"));
- },
- insert: function(inIndex){
- this.selected.splice(inIndex, 0, false);
- if(this.selectedIndex >= inIndex){
- this.selectedIndex++;
- }
- },
- remove: function(inIndex){
- this.selected.splice(inIndex, 1);
- if(this.selectedIndex >= inIndex){
- this.selectedIndex--;
- }
- },
- deselectAll: function(inExcept){
- for(var i in this.selected){
- if((i!=inExcept)&&(this.selected[i]===true)){
- this.deselect(i);
- }
- }
- },
- clickSelect: function(inIndex, inCtrlKey, inShiftKey){
- if(this.mode == 'none'){ return; }
- this._beginUpdate();
- if(this.mode != 'extended'){
- this.select(inIndex);
- }else{
- var lastSelected = this.selectedIndex;
- if(!inCtrlKey){
- this.deselectAll(inIndex);
- }
- if(inShiftKey){
- this.selectRange(lastSelected, inIndex);
- }else if(inCtrlKey){
- this.toggleSelect(inIndex);
- }else{
- this.addToSelection(inIndex);
- }
- }
- this._endUpdate();
- },
- clickSelectEvent: function(e){
- this.clickSelect(e.rowIndex, dojo.isCopyKey(e), e.shiftKey);
- },
- clear: function(){
- this._beginUpdate();
- this.deselectAll();
- this._endUpdate();
- }
- });
- });
- },
- 'dijit/form/MappedTextBox':function(){
- define("dijit/form/MappedTextBox", [
- "dojo/_base/declare", // declare
- "dojo/dom-construct", // domConstruct.place
- "./ValidationTextBox"
- ], function(declare, domConstruct, ValidationTextBox){
- /*=====
- var ValidationTextBox = dijit.form.ValidationTextBox;
- =====*/
- // module:
- // dijit/form/MappedTextBox
- // summary:
- // A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have
- // a visible formatted display value, and a serializable
- // value in a hidden input field which is actually sent to the server.
- return declare("dijit.form.MappedTextBox", ValidationTextBox, {
- // summary:
- // A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have
- // a visible formatted display value, and a serializable
- // value in a hidden input field which is actually sent to the server.
- // description:
- // The visible display may
- // be locale-dependent and interactive. The value sent to the server is stored in a hidden
- // input field which uses the `name` attribute declared by the original widget. That value sent
- // to the server is defined by the dijit.form.MappedTextBox.serialize method and is typically
- // locale-neutral.
- // tags:
- // protected
- postMixInProperties: function(){
- this.inherited(arguments);
- // we want the name attribute to go to the hidden <input>, not the displayed <input>,
- // so override _FormWidget.postMixInProperties() setting of nameAttrSetting
- this.nameAttrSetting = "";
- },
- // Override default behavior to assign name to focusNode
- _setNameAttr: null,
- serialize: function(val /*=====, options =====*/){
- // summary:
- // Overridable function used to convert the get('value') result to a canonical
- // (non-localized) string. For example, will print dates in ISO format, and
- // numbers the same way as they are represented in javascript.
- // val: anything
- // options: Object?
- // tags:
- // protected extension
- return val.toString ? val.toString() : ""; // String
- },
- toString: function(){
- // summary:
- // Returns widget as a printable string using the widget's value
- // tags:
- // protected
- var val = this.filter(this.get('value')); // call filter in case value is nonstring and filter has been customized
- return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String
- },
- validate: function(){
- // Overrides `dijit.form.TextBox.validate`
- this.valueNode.value = this.toString();
- return this.inherited(arguments);
- },
- buildRendering: function(){
- // Overrides `dijit._TemplatedMixin.buildRendering`
- this.inherited(arguments);
- // Create a hidden <input> node with the serialized value used for submit
- // (as opposed to the displayed value).
- // Passing in name as markup rather than calling domConstruct.create() with an attrs argument
- // to make query(input[name=...]) work on IE. (see #8660)
- this.valueNode = domConstruct.place("<input type='hidden'" + (this.name ? " name='" + this.name.replace(/'/g, """) + "'" : "") + "/>", this.textbox, "after");
- },
- reset: function(){
- // Overrides `dijit.form.ValidationTextBox.reset` to
- // reset the hidden textbox value to ''
- this.valueNode.value = '';
- this.inherited(arguments);
- }
- });
- });
- },
- 'dijit/form/ComboBoxMixin':function(){
- require({cache:{
- 'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\"\r\n\trole=\"combobox\"\r\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\r\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\r\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t${_buttonInputDisabled}\r\n\t/></div\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\r\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\r\n\t/></div\r\n></div>\r\n"}});
- define("dijit/form/ComboBoxMixin", [
- "dojo/_base/declare", // declare
- "dojo/_base/Deferred",
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/lang", // lang.mixin
- "dojo/store/util/QueryResults", // dojo.store.util.QueryResults
- "./_AutoCompleterMixin",
- "./_ComboBoxMenu",
- "../_HasDropDown",
- "dojo/text!./templates/DropDownBox.html"
- ], function(declare, Deferred, kernel, lang, QueryResults, _AutoCompleterMixin, _ComboBoxMenu, _HasDropDown, template){
- /*=====
- var _AutoCompleterMixin = dijit.form._AutoCompleterMixin;
- var _ComboBoxMenu = dijit.form._ComboBoxMenu;
- var _HasDropDown = dijit._HasDropDown;
- =====*/
- // module:
- // dijit/form/ComboBoxMixin
- // summary:
- // Provides main functionality of ComboBox widget
- return declare("dijit.form.ComboBoxMixin", [_HasDropDown, _AutoCompleterMixin], {
- // summary:
- // Provides main functionality of ComboBox widget
- // dropDownClass: [protected extension] Function String
- // Dropdown widget class used to select a date/time.
- // Subclasses should specify this.
- dropDownClass: _ComboBoxMenu,
- // hasDownArrow: Boolean
- // Set this textbox to have a down arrow button, to display the drop down list.
- // Defaults to true.
- hasDownArrow: true,
- templateString: template,
- baseClass: "dijitTextBox dijitComboBox",
- /*=====
- // store: [const] dojo.store.api.Store || dojo.data.api.Read
- // Reference to data provider object used by this ComboBox.
- //
- // Should be dojo.store.api.Store, but dojo.data.api.Read supported
- // for backwards compatibility.
- store: null,
- =====*/
- // Set classes like dijitDownArrowButtonHover depending on
- // mouse action over button node
- cssStateNodes: {
- "_buttonNode": "dijitDownArrowButton"
- },
- _setHasDownArrowAttr: function(/*Boolean*/ val){
- this._set("hasDownArrow", val);
- this._buttonNode.style.display = val ? "" : "none";
- },
- _showResultList: function(){
- // hide the tooltip
- this.displayMessage("");
- this.inherited(arguments);
- },
- _setStoreAttr: function(store){
- // For backwards-compatibility, accept dojo.data store in addition to dojo.store.store. Remove in 2.0.
- if(!store.get){
- lang.mixin(store, {
- _oldAPI: true,
- get: function(id){
- // summary:
- // Retrieves an object by it's identity. This will trigger a fetchItemByIdentity.
- // Like dojo.store.DataStore.get() except returns native item.
- var deferred = new Deferred();
- this.fetchItemByIdentity({
- identity: id,
- onItem: function(object){
- deferred.resolve(object);
- },
- onError: function(error){
- deferred.reject(error);
- }
- });
- return deferred.promise;
- },
- query: function(query, options){
- // summary:
- // Queries the store for objects. Like dojo.store.DataStore.query()
- // except returned Deferred contains array of native items.
- var deferred = new Deferred(function(){ fetchHandle.abort && fetchHandle.abort(); });
- var fetchHandle = this.fetch(lang.mixin({
- query: query,
- onBegin: function(count){
- deferred.total = count;
- },
- onComplete: function(results){
- deferred.resolve(results);
- },
- onError: function(error){
- deferred.reject(error);
- }
- }, options));
- return QueryResults(deferred);
- }
- });
- }
- this._set("store", store);
- },
- postMixInProperties: function(){
- // Since _setValueAttr() depends on this.store, _setStoreAttr() needs to execute first.
- // Unfortunately, without special code, it ends up executing second.
- if(this.params.store){
- this._setStoreAttr(this.params.store);
- }
- this.inherited(arguments);
- // User may try to access this.store.getValue() etc. in a custom labelFunc() function.
- // It's not available with the new data store for handling inline <option> tags, so add it.
- if(!this.params.store){
- var clazz = this.declaredClass;
- lang.mixin(this.store, {
- getValue: function(item, attr){
- kernel.deprecated(clazz + ".store.getValue(item, attr) is deprecated for builtin store. Use item.attr directly", "", "2.0");
- return item[attr];
- },
- getLabel: function(item){
- kernel.deprecated(clazz + ".store.getLabel(item) is deprecated for builtin store. Use item.label directly", "", "2.0");
- return item.name;
- },
- fetch: function(args){
- kernel.deprecated(clazz + ".store.fetch() is deprecated for builtin store.", "Use store.query()", "2.0");
- var shim = ["dojo/data/ObjectStore"]; // indirection so it doesn't get rolled into a build
- require(shim, lang.hitch(this, function(ObjectStore){
- new ObjectStore({objectStore: this}).fetch(args);
- }));
- }
- });
- }
- }
- });
- });
- },
- 'dijit/form/_TextBoxMixin':function(){
- define("dijit/form/_TextBoxMixin", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.byId
- "dojo/_base/event", // event.stop
- "dojo/keys", // keys.ALT keys.CAPS_LOCK keys.CTRL keys.META keys.SHIFT
- "dojo/_base/lang", // lang.mixin
- ".." // for exporting dijit._setSelectionRange, dijit.selectInputText
- ], function(array, declare, dom, event, keys, lang, dijit){
- // module:
- // dijit/form/_TextBoxMixin
- // summary:
- // A mixin for textbox form input widgets
- var _TextBoxMixin = declare("dijit.form._TextBoxMixin", null, {
- // summary:
- // A mixin for textbox form input widgets
- // trim: Boolean
- // Removes leading and trailing whitespace if true. Default is false.
- trim: false,
- // uppercase: Boolean
- // Converts all characters to uppercase if true. Default is false.
- uppercase: false,
- // lowercase: Boolean
- // Converts all characters to lowercase if true. Default is false.
- lowercase: false,
- // propercase: Boolean
- // Converts the first character of each word to uppercase if true.
- propercase: false,
- // maxLength: String
- // HTML INPUT tag maxLength declaration.
- maxLength: "",
- // selectOnClick: [const] Boolean
- // If true, all text will be selected when focused with mouse
- selectOnClick: false,
- // placeHolder: String
- // Defines a hint to help users fill out the input field (as defined in HTML 5).
- // This should only contain plain text (no html markup).
- placeHolder: "",
- _getValueAttr: function(){
- // summary:
- // Hook so get('value') works as we like.
- // description:
- // For `dijit.form.TextBox` this basically returns the value of the <input>.
- //
- // For `dijit.form.MappedTextBox` subclasses, which have both
- // a "displayed value" and a separate "submit value",
- // This treats the "displayed value" as the master value, computing the
- // submit value from it via this.parse().
- return this.parse(this.get('displayedValue'), this.constraints);
- },
- _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
- // summary:
- // Hook so set('value', ...) works.
- //
- // description:
- // Sets the value of the widget to "value" which can be of
- // any type as determined by the widget.
- //
- // value:
- // The visual element value is also set to a corresponding,
- // but not necessarily the same, value.
- //
- // formattedValue:
- // If specified, used to set the visual element value,
- // otherwise a computed visual value is used.
- //
- // priorityChange:
- // If true, an onChange event is fired immediately instead of
- // waiting for the next blur event.
- var filteredValue;
- if(value !== undefined){
- // TODO: this is calling filter() on both the display value and the actual value.
- // I added a comment to the filter() definition about this, but it should be changed.
- filteredValue = this.filter(value);
- if(typeof formattedValue != "string"){
- if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){
- formattedValue = this.filter(this.format(filteredValue, this.constraints));
- }else{ formattedValue = ''; }
- }
- }
- if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){
- this.textbox.value = formattedValue;
- this._set("displayedValue", this.get("displayedValue"));
- }
- if(this.textDir == "auto"){
- this.applyTextDir(this.focusNode, formattedValue);
- }
- this.inherited(arguments, [filteredValue, priorityChange]);
- },
- // displayedValue: String
- // For subclasses like ComboBox where the displayed value
- // (ex: Kentucky) and the serialized value (ex: KY) are different,
- // this represents the displayed value.
- //
- // Setting 'displayedValue' through set('displayedValue', ...)
- // updates 'value', and vice-versa. Otherwise 'value' is updated
- // from 'displayedValue' periodically, like onBlur etc.
- //
- // TODO: move declaration to MappedTextBox?
- // Problem is that ComboBox references displayedValue,
- // for benefit of FilteringSelect.
- displayedValue: "",
- _getDisplayedValueAttr: function(){
- // summary:
- // Hook so get('displayedValue') works.
- // description:
- // Returns the displayed value (what the user sees on the screen),
- // after filtering (ie, trimming spaces etc.).
- //
- // For some subclasses of TextBox (like ComboBox), the displayed value
- // is different from the serialized value that's actually
- // sent to the server (see dijit.form.ValidationTextBox.serialize)
- // TODO: maybe we should update this.displayedValue on every keystroke so that we don't need
- // this method
- // TODO: this isn't really the displayed value when the user is typing
- return this.filter(this.textbox.value);
- },
- _setDisplayedValueAttr: function(/*String*/ value){
- // summary:
- // Hook so set('displayedValue', ...) works.
- // description:
- // Sets the value of the visual element to the string "value".
- // The widget value is also set to a corresponding,
- // but not necessarily the same, value.
- if(value === null || value === undefined){ value = '' }
- else if(typeof value != "string"){ value = String(value) }
- this.textbox.value = value;
- // sets the serialized value to something corresponding to specified displayedValue
- // (if possible), and also updates the textbox.value, for example converting "123"
- // to "123.00"
- this._setValueAttr(this.get('value'), undefined);
- this._set("displayedValue", this.get('displayedValue'));
- // textDir support
- if(this.textDir == "auto"){
- this.applyTextDir(this.focusNode, value);
- }
- },
- format: function(value /*=====, constraints =====*/){
- // summary:
- // Replaceable function to convert a value to a properly formatted string.
- // value: String
- // constraints: Object
- // tags:
- // protected extension
- return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
- },
- parse: function(value /*=====, constraints =====*/){
- // summary:
- // Replaceable function to convert a formatted string to a value
- // value: String
- // constraints: Object
- // tags:
- // protected extension
- return value; // String
- },
- _refreshState: function(){
- // summary:
- // After the user types some characters, etc., this method is
- // called to check the field for validity etc. The base method
- // in `dijit.form.TextBox` does nothing, but subclasses override.
- // tags:
- // protected
- },
- /*=====
- onInput: function(event){
- // summary:
- // Connect to this function to receive notifications of various user data-input events.
- // Return false to cancel the event and prevent it from being processed.
- // event:
- // keydown | keypress | cut | paste | input
- // tags:
- // callback
- },
- =====*/
- onInput: function(){},
- __skipInputEvent: false,
- _onInput: function(){
- // summary:
- // Called AFTER the input event has happened
- // set text direction according to textDir that was defined in creation
- if(this.textDir == "auto"){
- this.applyTextDir(this.focusNode, this.focusNode.value);
- }
- this._refreshState();
- // In case someone is watch()'ing for changes to displayedValue
- this._set("displayedValue", this.get("displayedValue"));
- },
- postCreate: function(){
- // setting the value here is needed since value="" in the template causes "undefined"
- // and setting in the DOM (instead of the JS object) helps with form reset actions
- this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values should be the same
- this.inherited(arguments);
- // normalize input events to reduce spurious event processing
- // onkeydown: do not forward modifier keys
- // set charOrCode to numeric keycode
- // onkeypress: do not forward numeric charOrCode keys (already sent through onkeydown)
- // onpaste & oncut: set charOrCode to 229 (IME)
- // oninput: if primary event not already processed, set charOrCode to 229 (IME), else do not forward
- var handleEvent = function(e){
- var charCode = e.charOrCode || e.keyCode || 229;
- if(e.type == "keydown"){
- switch(charCode){ // ignore "state" keys
- case keys.SHIFT:
- case keys.ALT:
- case keys.CTRL:
- case keys.META:
- case keys.CAPS_LOCK:
- return;
- default:
- if(charCode >= 65 && charCode <= 90){ return; } // keydown for A-Z can be processed with keypress
- }
- }
- if(e.type == "keypress" && typeof charCode != "string"){ return; }
- if(e.type == "input"){
- if(this.__skipInputEvent){ // duplicate event
- this.__skipInputEvent = false;
- return;
- }
- }else{
- this.__skipInputEvent = true;
- }
- // create fake event to set charOrCode and to know if preventDefault() was called
- var faux = lang.mixin({}, e, {
- charOrCode: charCode,
- wasConsumed: false,
- preventDefault: function(){
- faux.wasConsumed = true;
- e.preventDefault();
- },
- stopPropagation: function(){ e.stopPropagation(); }
- });
- // give web page author a chance to consume the event
- if(this.onInput(faux) === false){
- event.stop(faux); // return false means stop
- }
- if(faux.wasConsumed){ return; } // if preventDefault was called
- setTimeout(lang.hitch(this, "_onInput", faux), 0); // widget notification after key has posted
- };
- array.forEach([ "onkeydown", "onkeypress", "onpaste", "oncut", "oninput", "oncompositionend" ], function(event){
- this.connect(this.textbox, event, handleEvent);
- }, this);
- },
- _blankValue: '', // if the textbox is blank, what value should be reported
- filter: function(val){
- // summary:
- // Auto-corrections (such as trimming) that are applied to textbox
- // value on blur or form submit.
- // description:
- // For MappedTextBox subclasses, this is called twice
- // - once with the display value
- // - once the value as set/returned by set('value', ...)
- // and get('value'), ex: a Number for NumberTextBox.
- //
- // In the latter case it does corrections like converting null to NaN. In
- // the former case the NumberTextBox.filter() method calls this.inherited()
- // to execute standard trimming code in TextBox.filter().
- //
- // TODO: break this into two methods in 2.0
- //
- // tags:
- // protected extension
- if(val === null){ return this._blankValue; }
- if(typeof val != "string"){ return val; }
- if(this.trim){
- val = lang.trim(val);
- }
- if(this.uppercase){
- val = val.toUpperCase();
- }
- if(this.lowercase){
- val = val.toLowerCase();
- }
- if(this.propercase){
- val = val.replace(/[^\s]+/g, function(word){
- return word.substring(0,1).toUpperCase() + word.substring(1);
- });
- }
- return val;
- },
- _setBlurValue: function(){
- this._setValueAttr(this.get('value'), true);
- },
- _onBlur: function(e){
- if(this.disabled){ return; }
- this._setBlurValue();
- this.inherited(arguments);
- if(this._selectOnClickHandle){
- this.disconnect(this._selectOnClickHandle);
- }
- },
- _isTextSelected: function(){
- return this.textbox.selectionStart == this.textbox.selectionEnd;
- },
- _onFocus: function(/*String*/ by){
- if(this.disabled || this.readOnly){ return; }
- // Select all text on focus via click if nothing already selected.
- // Since mouse-up will clear the selection need to defer selection until after mouse-up.
- // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event.
- if(this.selectOnClick && by == "mouse"){
- this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
- // Only select all text on first click; otherwise users would have no way to clear
- // the selection.
- this.disconnect(this._selectOnClickHandle);
- // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
- // and if not, then select all the text
- if(this._isTextSelected()){
- _TextBoxMixin.selectInputText(this.textbox);
- }
- });
- }
- // call this.inherited() before refreshState(), since this.inherited() will possibly scroll the viewport
- // (to scroll the TextBox into view), which will affect how _refreshState() positions the tooltip
- this.inherited(arguments);
- this._refreshState();
- },
- reset: function(){
- // Overrides dijit._FormWidget.reset().
- // Additionally resets the displayed textbox value to ''
- this.textbox.value = '';
- this.inherited(arguments);
- },
- _setTextDirAttr: function(/*String*/ textDir){
- // summary:
- // Setter for textDir.
- // description:
- // Users shouldn't call this function; they should be calling
- // set('textDir', value)
- // tags:
- // private
- // only if new textDir is different from the old one
- // and on widgets creation.
- if(!this._created
- || this.textDir != textDir){
- this._set("textDir", textDir);
- // so the change of the textDir will take place immediately.
- this.applyTextDir(this.focusNode, this.focusNode.value);
- }
- }
- });
- _TextBoxMixin._setSelectionRange = dijit._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
- if(element.setSelectionRange){
- element.setSelectionRange(start, stop);
- }
- };
- _TextBoxMixin.selectInputText = dijit.selectInputText = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
- // summary:
- // Select text in the input element argument, from start (default 0), to stop (default end).
- // TODO: use functions in _editor/selection.js?
- element = dom.byId(element);
- if(isNaN(start)){ start = 0; }
- if(isNaN(stop)){ stop = element.value ? element.value.length : 0; }
- try{
- element.focus();
- _TextBoxMixin._setSelectionRange(element, start, stop);
- }catch(e){ /* squelch random errors (esp. on IE) from unexpected focus changes or DOM nodes being hidden */ }
- };
- return _TextBoxMixin;
- });
- },
- 'dijit/_TimePicker':function(){
- require({cache:{
- 'url:dijit/templates/TimePicker.html':"<div id=\"widget_${id}\" class=\"dijitMenu\"\r\n ><div data-dojo-attach-point=\"upArrow\" class=\"dijitButtonNode dijitUpArrowButton\" data-dojo-attach-event=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\r\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" role=\"presentation\"> </div\r\n\t\t><div class=\"dijitArrowButtonChar\">▲</div></div\r\n ><div data-dojo-attach-point=\"timeMenu,focusNode\" data-dojo-attach-event=\"onclick:_onOptionSelected,onmouseover,onmouseout\"></div\r\n ><div data-dojo-attach-point=\"downArrow\" class=\"dijitButtonNode dijitDownArrowButton\" data-dojo-attach-event=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\r\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" role=\"presentation\"> </div\r\n\t\t><div class=\"dijitArrowButtonChar\">▼</div></div\r\n></div>\r\n"}});
- define("dijit/_TimePicker", [
- "dojo/_base/array", // array.forEach
- "dojo/date", // date.compare
- "dojo/date/locale", // locale.format
- "dojo/date/stamp", // stamp.fromISOString stamp.toISOString
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.add domClass.contains domClass.toggle
- "dojo/dom-construct", // domConstruct.create
- "dojo/_base/event", // event.stop
- "dojo/_base/kernel", // deprecated
- "dojo/keys", // keys
- "dojo/_base/lang", // lang.mixin
- "dojo/_base/sniff", // has(...)
- "dojo/query", // query
- "./typematic",
- "./_Widget",
- "./_TemplatedMixin",
- "./form/_FormValueWidget",
- "dojo/text!./templates/TimePicker.html"
- ], function(array, ddate, locale, stamp, declare, domClass, domConstruct, event, kernel, keys, lang, has, query,
- typematic, _Widget, _TemplatedMixin, _FormValueWidget, template){
- /*=====
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var _FormValueWidget = dijit.form._FormValueWidget;
- =====*/
- // module:
- // dijit/_TimePicker
- // summary:
- // A graphical time picker.
- /*=====
- declare(
- "dijit._TimePicker.__Constraints",
- locale.__FormatOptions,
- {
- // clickableIncrement: String
- // See `dijit._TimePicker.clickableIncrement`
- clickableIncrement: "T00:15:00",
- // visibleIncrement: String
- // See `dijit._TimePicker.visibleIncrement`
- visibleIncrement: "T01:00:00",
- // visibleRange: String
- // See `dijit._TimePicker.visibleRange`
- visibleRange: "T05:00:00"
- }
- );
- =====*/
- return declare("dijit._TimePicker", [_Widget, _TemplatedMixin], {
- // summary:
- // A graphical time picker.
- // This widget is used internally by other widgets and is not available
- // as a standalone widget due to lack of accessibility support.
- templateString: template,
- // baseClass: [protected] String
- // The root className to use for the various states of this widget
- baseClass: "dijitTimePicker",
- // clickableIncrement: String
- // ISO-8601 string representing the amount by which
- // every clickable element in the time picker increases.
- // Set in local time, without a time zone.
- // Example: `T00:15:00` creates 15 minute increments
- // Must divide dijit._TimePicker.visibleIncrement evenly
- clickableIncrement: "T00:15:00",
- // visibleIncrement: String
- // ISO-8601 string representing the amount by which
- // every element with a visible time in the time picker increases.
- // Set in local time, without a time zone.
- // Example: `T01:00:00` creates text in every 1 hour increment
- visibleIncrement: "T01:00:00",
- // visibleRange: String
- // ISO-8601 string representing the range of this TimePicker.
- // The TimePicker will only display times in this range.
- // Example: `T05:00:00` displays 5 hours of options
- visibleRange: "T05:00:00",
- // value: String
- // Date to display.
- // Defaults to current time and date.
- // Can be a Date object or an ISO-8601 string.
- // If you specify the GMT time zone (`-01:00`),
- // the time will be converted to the local time in the local time zone.
- // Otherwise, the time is considered to be in the local time zone.
- // If you specify the date and isDate is true, the date is used.
- // Example: if your local time zone is `GMT -05:00`,
- // `T10:00:00` becomes `T10:00:00-05:00` (considered to be local time),
- // `T10:00:00-01:00` becomes `T06:00:00-05:00` (4 hour difference),
- // `T10:00:00Z` becomes `T05:00:00-05:00` (5 hour difference between Zulu and local time)
- // `yyyy-mm-ddThh:mm:ss` is the format to set the date and time
- // Example: `2007-06-01T09:00:00`
- value: new Date(),
- _visibleIncrement:2,
- _clickableIncrement:1,
- _totalIncrements:10,
- // constraints: dijit._TimePicker.__Constraints
- // Specifies valid range of times (start time, end time)
- constraints:{},
- /*=====
- serialize: function(val, options){
- // summary:
- // User overridable function used to convert the attr('value') result to a String
- // val: Date
- // The current value
- // options: Object?
- // tags:
- // protected
- },
- =====*/
- serialize: stamp.toISOString,
- /*=====
- // filterString: string
- // The string to filter by
- filterString: "",
- =====*/
- setValue: function(/*Date*/ value){
- // summary:
- // Deprecated. Used set('value') instead.
- // tags:
- // deprecated
- kernel.deprecated("dijit._TimePicker:setValue() is deprecated. Use set('value', ...) instead.", "", "2.0");
- this.set('value', value);
- },
- _setValueAttr: function(/*Date*/ date){
- // summary:
- // Hook so set('value', ...) works.
- // description:
- // Set the value of the TimePicker.
- // Redraws the TimePicker around the new date.
- // tags:
- // protected
- this._set("value", date);
- this._showText();
- },
- _setFilterStringAttr: function(val){
- // summary:
- // Called by TimeTextBox to filter the values shown in my list
- this._set("filterString", val);
- this._showText();
- },
- isDisabledDate: function(/*===== dateObject, locale =====*/){
- // summary:
- // May be overridden to disable certain dates in the TimePicker e.g. `isDisabledDate=locale.isWeekend`
- // dateObject: Date
- // locale: String?
- // type:
- // extension
- return false; // Boolean
- },
- _getFilteredNodes: function(/*number*/ start, /*number*/ maxNum, /*Boolean*/ before, /*DOMnode*/ lastNode){
- // summary:
- // Returns an array of nodes with the filter applied. At most maxNum nodes
- // will be returned - but fewer may be returned as well. If the
- // before parameter is set to true, then it will return the elements
- // before the given index
- // tags:
- // private
- var
- nodes = [],
- lastValue = lastNode ? lastNode.date : this._refDate,
- n,
- i = start,
- max = this._maxIncrement + Math.abs(i),
- chk = before ? -1 : 1,
- dec = before ? 1 : 0,
- inc = 1 - dec;
- do{
- i -= dec;
- n = this._createOption(i);
- if(n){
- if((before && n.date > lastValue) || (!before && n.date < lastValue)){
- break; // don't wrap
- }
- nodes[before ? "unshift" : "push"](n);
- lastValue = n.date;
- }
- i += inc;
- }while(nodes.length < maxNum && (i*chk) < max);
- return nodes;
- },
- _showText: function(){
- // summary:
- // Displays the relevant choices in the drop down list
- // tags:
- // private
- var fromIso = stamp.fromISOString;
- this.timeMenu.innerHTML = "";
- this._clickableIncrementDate=fromIso(this.clickableIncrement);
- this._visibleIncrementDate=fromIso(this.visibleIncrement);
- this._visibleRangeDate=fromIso(this.visibleRange);
- // get the value of the increments and the range in seconds (since 00:00:00) to find out how many divs to create
- var
- sinceMidnight = function(/*Date*/ date){
- return date.getHours() * 60 * 60 + date.getMinutes() * 60 + date.getSeconds();
- },
- clickableIncrementSeconds = sinceMidnight(this._clickableIncrementDate),
- visibleIncrementSeconds = sinceMidnight(this._visibleIncrementDate),
- visibleRangeSeconds = sinceMidnight(this._visibleRangeDate),
- // round reference date to previous visible increment
- time = (this.value || this.currentFocus).getTime();
- this._refDate = new Date(time - time % (clickableIncrementSeconds*1000));
- this._refDate.setFullYear(1970,0,1); // match parse defaults
- // assume clickable increment is the smallest unit
- this._clickableIncrement = 1;
- // divide the visible range by the clickable increment to get the number of divs to create
- // example: 10:00:00/00:15:00 -> display 40 divs
- this._totalIncrements = visibleRangeSeconds / clickableIncrementSeconds;
- // divide the visible increments by the clickable increments to get how often to display the time inline
- // example: 01:00:00/00:15:00 -> display the time every 4 divs
- this._visibleIncrement = visibleIncrementSeconds / clickableIncrementSeconds;
- // divide the number of seconds in a day by the clickable increment in seconds to get the
- // absolute max number of increments.
- this._maxIncrement = (60 * 60 * 24) / clickableIncrementSeconds;
- var
- // Find the nodes we should display based on our filter.
- // Limit to 10 nodes displayed as a half-hearted attempt to stop drop down from overlapping <input>.
- count = Math.min(this._totalIncrements, 10),
- after = this._getFilteredNodes(0, (count >> 1) + 1, false),
- moreAfter = [],
- estBeforeLength = count - after.length,
- before = this._getFilteredNodes(0, estBeforeLength, true, after[0]);
- if(before.length < estBeforeLength && after.length > 0){
- moreAfter = this._getFilteredNodes(after.length, estBeforeLength - before.length, false, after[after.length-1]);
- }
- array.forEach(before.concat(after, moreAfter), function(n){ this.timeMenu.appendChild(n); }, this);
- },
- constructor: function(){
- this.constraints = {}; // create instance object
- },
- postMixInProperties: function(){
- this.inherited(arguments);
- this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls
- },
- _setConstraintsAttr: function(/* Object */ constraints){
- // brings in visibleRange, increments, etc.
- lang.mixin(this, constraints);
- // locale needs the lang in the constraints as locale
- if(!constraints.locale){
- constraints.locale = this.lang;
- }
- },
- postCreate: function(){
- // assign typematic mouse listeners to the arrow buttons
- this.connect(this.timeMenu, has("mozilla") ? 'DOMMouseScroll' : "onmousewheel", "_mouseWheeled");
- this._connects.push(typematic.addMouseListener(this.upArrow, this, "_onArrowUp", 33, 250));
- this._connects.push(typematic.addMouseListener(this.downArrow, this, "_onArrowDown", 33, 250));
- this.inherited(arguments);
- },
- _buttonMouse: function(/*Event*/ e){
- // summary:
- // Handler for hover (and unhover) on up/down arrows
- // tags:
- // private
- // in non-IE browser the "mouseenter" event will become "mouseover",
- // but in IE it's still "mouseenter"
- domClass.toggle(e.currentTarget, e.currentTarget == this.upArrow ? "dijitUpArrowHover" : "dijitDownArrowHover",
- e.type == "mouseenter" || e.type == "mouseover");
- },
- _createOption: function(/*Number*/ index){
- // summary:
- // Creates a clickable time option
- // tags:
- // private
- var date = new Date(this._refDate);
- var incrementDate = this._clickableIncrementDate;
- date.setTime(date.getTime()
- + incrementDate.getHours() * index * 3600000
- + incrementDate.getMinutes() * index * 60000
- + incrementDate.getSeconds() * index * 1000);
- if(this.constraints.selector == "time"){
- date.setFullYear(1970,0,1); // make sure each time is for the same date
- }
- var dateString = locale.format(date, this.constraints);
- if(this.filterString && dateString.toLowerCase().indexOf(this.filterString) !== 0){
- // Doesn't match the filter - return null
- return null;
- }
- var div = domConstruct.create("div", {"class": this.baseClass+"Item"});
- div.date = date;
- div.idx = index;
- domConstruct.create('div',{
- "class": this.baseClass + "ItemInner",
- innerHTML: dateString
- }, div);
- if(index%this._visibleIncrement<1 && index%this._visibleIncrement>-1){
- domClass.add(div, this.baseClass+"Marker");
- }else if(!(index%this._clickableIncrement)){
- domClass.add(div, this.baseClass+"Tick");
- }
- if(this.isDisabledDate(date)){
- // set disabled
- domClass.add(div, this.baseClass+"ItemDisabled");
- }
- if(this.value && !ddate.compare(this.value, date, this.constraints.selector)){
- div.selected = true;
- domClass.add(div, this.baseClass+"ItemSelected");
- if(domClass.contains(div, this.baseClass+"Marker")){
- domClass.add(div, this.baseClass+"MarkerSelected");
- }else{
- domClass.add(div, this.baseClass+"TickSelected");
- }
- // Initially highlight the current value. User can change highlight by up/down arrow keys
- // or mouse movement.
- this._highlightOption(div, true);
- }
- return div;
- },
- _onOptionSelected: function(/*Object*/ tgt){
- // summary:
- // Called when user clicks an option in the drop down list
- // tags:
- // private
- var tdate = tgt.target.date || tgt.target.parentNode.date;
- if(!tdate || this.isDisabledDate(tdate)){ return; }
- this._highlighted_option = null;
- this.set('value', tdate);
- this.onChange(tdate);
- },
- onChange: function(/*Date*/ /*===== time =====*/){
- // summary:
- // Notification that a time was selected. It may be the same as the previous value.
- // tags:
- // public
- },
- _highlightOption: function(/*node*/ node, /*Boolean*/ highlight){
- // summary:
- // Turns on/off highlight effect on a node based on mouse out/over event
- // tags:
- // private
- if(!node){return;}
- if(highlight){
- if(this._highlighted_option){
- this._highlightOption(this._highlighted_option, false);
- }
- this._highlighted_option = node;
- }else if(this._highlighted_option !== node){
- return;
- }else{
- this._highlighted_option = null;
- }
- domClass.toggle(node, this.baseClass+"ItemHover", highlight);
- if(domClass.contains(node, this.baseClass+"Marker")){
- domClass.toggle(node, this.baseClass+"MarkerHover", highlight);
- }else{
- domClass.toggle(node, this.baseClass+"TickHover", highlight);
- }
- },
- onmouseover: function(/*Event*/ e){
- // summary:
- // Handler for onmouseover event
- // tags:
- // private
- this._keyboardSelected = null;
- var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;
- // if we aren't targeting an item, then we return
- if(!domClass.contains(tgr, this.baseClass+"Item")){return;}
- this._highlightOption(tgr, true);
- },
- onmouseout: function(/*Event*/ e){
- // summary:
- // Handler for onmouseout event
- // tags:
- // private
- this._keyboardSelected = null;
- var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;
- this._highlightOption(tgr, false);
- },
- _mouseWheeled: function(/*Event*/ e){
- // summary:
- // Handle the mouse wheel events
- // tags:
- // private
- this._keyboardSelected = null;
- event.stop(e);
- // we're not _measuring_ the scroll amount, just direction
- var scrollAmount = has("mozilla") ? -e.detail : e.wheelDelta;
- this[(scrollAmount>0 ? "_onArrowUp" : "_onArrowDown")](); // yes, we're making a new dom node every time you mousewheel, or click
- },
- _onArrowUp: function(count){
- // summary:
- // Handler for up arrow key.
- // description:
- // Removes the bottom time and add one to the top
- // tags:
- // private
- if(count === -1){
- domClass.remove(this.upArrow, "dijitUpArrowActive");
- return;
- }else if(count === 0){
- domClass.add(this.upArrow, "dijitUpArrowActive");
- } // typematic end
- if(!this.timeMenu.childNodes.length){ return; }
- var index = this.timeMenu.childNodes[0].idx;
- var divs = this._getFilteredNodes(index, 1, true, this.timeMenu.childNodes[0]);
- if(divs.length){
- this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]);
- this.timeMenu.insertBefore(divs[0], this.timeMenu.childNodes[0]);
- }
- },
- _onArrowDown: function(count){
- // summary:
- // Handler for up arrow key.
- // description:
- // Remove the top time and add one to the bottom
- // tags:
- // private
- if(count === -1){
- domClass.remove(this.downArrow, "dijitDownArrowActive");
- return;
- }else if(count === 0){
- domClass.add(this.downArrow, "dijitDownArrowActive");
- } // typematic end
- if(!this.timeMenu.childNodes.length){ return; }
- var index = this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1].idx + 1;
- var divs = this._getFilteredNodes(index, 1, false, this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]);
- if(divs.length){
- this.timeMenu.removeChild(this.timeMenu.childNodes[0]);
- this.timeMenu.appendChild(divs[0]);
- }
- },
- handleKey: function(/*Event*/ e){
- // summary:
- // Called from `dijit.form._DateTimeTextBox` to pass a keypress event
- // from the `dijit.form.TimeTextBox` to be handled in this widget
- // tags:
- // protected
- if(e.charOrCode == keys.DOWN_ARROW || e.charOrCode == keys.UP_ARROW){
- event.stop(e);
- // Figure out which option to highlight now and then highlight it
- if(this._highlighted_option && !this._highlighted_option.parentNode){
- this._highlighted_option = null;
- }
- var timeMenu = this.timeMenu,
- tgt = this._highlighted_option || query("." + this.baseClass + "ItemSelected", timeMenu)[0];
- if(!tgt){
- tgt = timeMenu.childNodes[0];
- }else if(timeMenu.childNodes.length){
- if(e.charOrCode == keys.DOWN_ARROW && !tgt.nextSibling){
- this._onArrowDown();
- }else if(e.charOrCode == keys.UP_ARROW && !tgt.previousSibling){
- this._onArrowUp();
- }
- if(e.charOrCode == keys.DOWN_ARROW){
- tgt = tgt.nextSibling;
- }else{
- tgt = tgt.previousSibling;
- }
- }
- this._highlightOption(tgt, true);
- this._keyboardSelected = tgt;
- return false;
- }else if(e.charOrCode == keys.ENTER || e.charOrCode === keys.TAB){
- // mouse hover followed by TAB is NO selection
- if(!this._keyboardSelected && e.charOrCode === keys.TAB){
- return true; // true means don't call stopEvent()
- }
- // Accept the currently-highlighted option as the value
- if(this._highlighted_option){
- this._onOptionSelected({target: this._highlighted_option});
- }
- // Call stopEvent() for ENTER key so that form doesn't submit,
- // but not for TAB, so that TAB does switch focus
- return e.charOrCode === keys.TAB;
- }
- return undefined;
- }
- });
- });
- },
- 'url:dijit/form/templates/HorizontalSlider.html':"<table class=\"dijit dijitReset dijitSlider dijitSliderH\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" data-dojo-attach-event=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\r\n\trole=\"presentation\"\r\n\t><tr class=\"dijitReset\"\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t\t><td data-dojo-attach-point=\"topDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationT dijitSliderDecorationH\"></td\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t></tr\r\n\t><tr class=\"dijitReset\"\r\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\r\n\t\t\t><div class=\"dijitSliderDecrementIconH\" style=\"display:none\" data-dojo-attach-point=\"decrementButton\"><span class=\"dijitSliderButtonInner\">-</span></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset\"\r\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper\" data-dojo-attach-event=\"press:_onClkDecBumper\"></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset\"\r\n\t\t\t><input data-dojo-attach-point=\"valueNode\" type=\"hidden\" ${!nameAttrSetting}\r\n\t\t\t/><div class=\"dijitReset dijitSliderBarContainerH\" role=\"presentation\" data-dojo-attach-point=\"sliderBarContainer\"\r\n\t\t\t\t><div role=\"presentation\" data-dojo-attach-point=\"progressBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH\" data-dojo-attach-event=\"press:_onBarClick\"\r\n\t\t\t\t\t><div class=\"dijitSliderMoveable dijitSliderMoveableH\"\r\n\t\t\t\t\t\t><div data-dojo-attach-point=\"sliderHandle,focusNode\" class=\"dijitSliderImageHandle dijitSliderImageHandleH\" data-dojo-attach-event=\"press:_onHandleClick\" role=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"></div\r\n\t\t\t\t\t></div\r\n\t\t\t\t></div\r\n\t\t\t\t><div role=\"presentation\" data-dojo-attach-point=\"remainingBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH\" data-dojo-attach-event=\"press:_onBarClick\"></div\r\n\t\t\t></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset\"\r\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper\" data-dojo-attach-event=\"press:_onClkIncBumper\"></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\r\n\t\t\t><div class=\"dijitSliderIncrementIconH\" style=\"display:none\" data-dojo-attach-point=\"incrementButton\"><span class=\"dijitSliderButtonInner\">+</span></div\r\n\t\t></td\r\n\t></tr\r\n\t><tr class=\"dijitReset\"\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t\t><td data-dojo-attach-point=\"containerNode,bottomDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationB dijitSliderDecorationH\"></td\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t></tr\r\n></table>\r\n",
- 'url:dijit/templates/TimePicker.html':"<div id=\"widget_${id}\" class=\"dijitMenu\"\r\n ><div data-dojo-attach-point=\"upArrow\" class=\"dijitButtonNode dijitUpArrowButton\" data-dojo-attach-event=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\r\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" role=\"presentation\"> </div\r\n\t\t><div class=\"dijitArrowButtonChar\">▲</div></div\r\n ><div data-dojo-attach-point=\"timeMenu,focusNode\" data-dojo-attach-event=\"onclick:_onOptionSelected,onmouseover,onmouseout\"></div\r\n ><div data-dojo-attach-point=\"downArrow\" class=\"dijitButtonNode dijitDownArrowButton\" data-dojo-attach-event=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\r\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" role=\"presentation\"> </div\r\n\t\t><div class=\"dijitArrowButtonChar\">▼</div></div\r\n></div>\r\n",
- 'dijit/main':function(){
- define("dijit/main", [
- "dojo/_base/kernel"
- ], function(dojo){
- // module:
- // dijit
- // summary:
- // The dijit package main module
- return dojo.dijit;
- });
- },
- 'dojox/grid/enhanced/_PluginManager':function(){
- define("dojox/grid/enhanced/_PluginManager", [
- "dojo/_base/kernel",
- "dojo/_base/lang",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/connect",
- "./_Events",
- "./_FocusManager",
- "../util"
- ], function(dojo, lang, declare, array, connect, _Events, _FocusManager, util){
- var _PluginManager = declare("dojox.grid.enhanced._PluginManager", null, {
- // summary:
- // Singleton plugin manager
- //
- // description:
- // Plugin manager is responsible for
- // 1. Loading required plugins
- // 2. Handling collaborat ion and dependencies among plugins
- //
- // Some plugin dependencies:
- // - "columnReordering" attribute won't work when either DnD or Indirect Selections plugin is on.
-
- //_options: Object
- // Normalized plugin options
- _options: null,
- //_plugins: Array
- // Plugin list
- _plugins: null,
- //_connects: Array
- // Connection list
- _connects: null,
- constructor: function(inGrid){
- this.grid = inGrid;
- this._store = inGrid.store;
- this._options = {};
- this._plugins = [];
- this._connects = [];
- this._parseProps(this.grid.plugins);
-
- inGrid.connect(inGrid, "_setStore", lang.hitch(this, function(store){
- if(this._store !== store){
- this.forEach('onSetStore', [store, this._store]);
- this._store = store;
- }
- }));
- },
- startup: function(){
- this.forEach('onStartUp');
- },
- preInit: function(){
- // summary:
- // Load appropriate plugins before DataGrid.postCreate().
- // See EnhancedGrid.postCreate()
- this.grid.focus.destroy();
- this.grid.focus = new _FocusManager(this.grid);
- new _Events(this.grid);//overwrite some default events of DataGrid
- this._init(true);
- this.forEach('onPreInit');
- },
- postInit: function(){
- // summary:
- // Load plugins after DataGrid.postCreate() - the default phase when plugins are created
- // See EnhancedGrid.postCreate()
- this._init(false);
-
- array.forEach(this.grid.views.views, this._initView, this);
- this._connects.push(connect.connect(this.grid.views, 'addView', lang.hitch(this, this._initView)));
-
- if(this._plugins.length > 0){
- var edit = this.grid.edit;
- if(edit){ edit.styleRow = function(inRow){}; }
- }
- this.forEach('onPostInit');
- },
- forEach: function(func, args){
- array.forEach(this._plugins, function(p){
- if(!p || !p[func]){ return; }
- p[func].apply(p, args ? args : []);
- });
- },
- _parseProps: function(plugins){
- // summary:
- // Parse plugins properties
- // plugins: Object
- // Plugin properties defined by user
- if(!plugins){ return; }
-
- var p, loading = {}, options = this._options, grid = this.grid;
- var registry = _PluginManager.registry;//global plugin registry
- for(p in plugins){
- if(plugins[p]){//filter out boolean false e.g. {p:false}
- this._normalize(p, plugins, registry, loading);
- }
- }
- //"columnReordering" attribute won't work when either DnD or Indirect Selections plugin is used.
- if(options.dnd || options.indirectSelection){
- options.columnReordering = false;
- }
-
- //mixin all plugin properties into Grid
- lang.mixin(grid, options);
- },
- _normalize: function(p, plugins, registry, loading){
- // summary:
- // Normalize plugin properties especially the dependency chain
- // p: String
- // Plugin name
- // plugins: Object
- // Plugin properties set by user
- // registry: Object
- // The global plugin registry
- // loading: Object
- // Map for checking process state
- if(!registry[p]){ throw new Error('Plugin ' + p + ' is required.');}
-
- if(loading[p]){ throw new Error('Recursive cycle dependency is not supported.'); }
-
- var options = this._options;
- if(options[p]){ return options[p]; }
-
- loading[p] = true;
- //TBD - more strict conditions?
- options[p] = lang.mixin({}, registry[p], lang.isObject(plugins[p]) ? plugins[p] : {});
-
- var dependencies = options[p]['dependency'];
- if(dependencies){
- if(!lang.isArray(dependencies)){
- dependencies = options[p]['dependency'] = [dependencies];
- }
- array.forEach(dependencies, function(dependency){
- if(!this._normalize(dependency, plugins, registry, loading)){
- throw new Error('Plugin ' + dependency + ' is required.');
- }
- }, this);
- }
- delete loading[p];
- return options[p];
- },
- _init: function(pre){
- // summary:
- // Find appropriate plugins and load them
- // pre: Boolean
- // True - preInit | False - postInit(by default)
- var p, preInit, options = this._options;
- for(p in options){
- preInit = options[p]['preInit'];
- if((pre ? preInit : !preInit) && options[p]['class'] && !this.pluginExisted(p)){
- this.loadPlugin(p);
- }
- }
- },
- loadPlugin: function(name){
- // summary:
- // Load required plugin("name")
- // name: String
- // Plugin name
- // return: Object
- // The newly loaded plugin
- var option = this._options[name];
- if(!option){ return null; } //return if no plugin option
-
- var plugin = this.getPlugin(name);
- if(plugin){ return plugin; } //return if plugin("name") already existed
-
- var dependencies = option['dependency'];
- array.forEach(dependencies, function(dependency){
- if(!this.loadPlugin(dependency)){
- throw new Error('Plugin ' + dependency + ' is required.');
- }
- }, this);
- var cls = option['class'];
- delete option['class'];//remove it for safety
- plugin = new this.getPluginClazz(cls)(this.grid, option);
- this._plugins.push(plugin);
- return plugin;
- },
- _initView: function(view){
- // summary:
- // Overwrite several default behavior for each views(including _RowSelector view)
- if(!view){ return; }
- //add more events handler - _View
- util.funnelEvents(view.contentNode, view, "doContentEvent", ['mouseup', 'mousemove']);
- util.funnelEvents(view.headerNode, view, "doHeaderEvent", ['mouseup']);
- },
- pluginExisted: function(name){
- // summary:
- // Check if plugin("name") existed
- // name: String
- // Plugin name
- // return: Boolean
- // True - existed | False - not existed
- return !!this.getPlugin(name);
- },
- getPlugin: function(name){
- // summary:
- // Get plugin("name")
- // name: String
- // Plugin name
- // return: Object
- // Plugin instance
- var plugins = this._plugins;
- name = name.toLowerCase();
- for(var i = 0, len = plugins.length; i < len; i++){
- if(name == plugins[i]['name'].toLowerCase()){
- return plugins[i];
- }
- }
- return null;
- },
- getPluginClazz: function(clazz){
- // summary:
- // Load target plugin which must be already required (require(..))
- // clazz: class | String
- // Plugin class
- if(lang.isFunction(clazz)){
- return clazz;//return if it's already a clazz
- }
- var errorMsg = 'Please make sure Plugin "' + clazz + '" is existed.';
- try{
- var cls = lang.getObject(clazz);
- if(!cls){ throw new Error(errorMsg); }
- return cls;
- }catch(e){
- throw new Error(errorMsg);
- }
- },
- isFixedCell: function(cell){
- // summary:
- // See if target cell(column) is fixed or not.
- // cell: Object
- // Target cell(column)
- // return: Boolean
- // True - fixed| False - not fixed
- //target cell can use Boolean attributes named "isRowSelector" or "fixedPos" to mark it's a fixed cell(column)
- return cell && (cell.isRowSelector || cell.fixedPos);
- },
- destroy: function(){
- // summary:
- // Destroy all resources
- array.forEach(this._connects, connect.disconnect);
- this.forEach('destroy');
- if(this.grid.unwrap){
- this.grid.unwrap();
- }
- delete this._connects;
- delete this._plugins;
- delete this._options;
- }
- });
- _PluginManager.registerPlugin = function(clazz, props){
- // summary:
- // Register plugins - TODO, a better way rather than global registry?
- // clazz: String
- // Full class name, e.g. "dojox.grid.enhanced.plugins.DnD"
- // props: Object - Optional
- // Plugin properties e.g. {"dependency": ["nestedSorting"], ...}
- if(!clazz){
- console.warn("Failed to register plugin, class missed!");
- return;
- }
- var cls = _PluginManager;
- cls.registry = cls.registry || {};
- cls.registry[clazz.prototype.name]/*plugin name*/ = lang.mixin({"class": clazz}, (props ? props : {}));
- };
- return _PluginManager;
- });
- },
- 'dijit/_OnDijitClickMixin':function(){
- define("dijit/_OnDijitClickMixin", [
- "dojo/on",
- "dojo/_base/array", // array.forEach
- "dojo/keys", // keys.ENTER keys.SPACE
- "dojo/_base/declare", // declare
- "dojo/_base/sniff", // has("ie")
- "dojo/_base/unload", // unload.addOnWindowUnload
- "dojo/_base/window" // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent
- ], function(on, array, keys, declare, has, unload, win){
- // module:
- // dijit/_OnDijitClickMixin
- // summary:
- // Mixin so you can pass "ondijitclick" to this.connect() method,
- // as a way to handle clicks by mouse, or by keyboard (SPACE/ENTER key)
- // Keep track of where the last keydown event was, to help avoid generating
- // spurious ondijitclick events when:
- // 1. focus is on a <button> or <a>
- // 2. user presses then releases the ENTER key
- // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
- // 4. onkeyup event fires, causing the ondijitclick handler to fire
- var lastKeyDownNode = null;
- if(has("ie")){
- (function(){
- var keydownCallback = function(evt){
- lastKeyDownNode = evt.srcElement;
- };
- win.doc.attachEvent('onkeydown', keydownCallback);
- unload.addOnWindowUnload(function(){
- win.doc.detachEvent('onkeydown', keydownCallback);
- });
- })();
- }else{
- win.doc.addEventListener('keydown', function(evt){
- lastKeyDownNode = evt.target;
- }, true);
- }
- // Custom a11yclick (a.k.a. ondijitclick) event
- var a11yclick = function(node, listener){
- if(/input|button/i.test(node.nodeName)){
- // pass through, the browser already generates click event on SPACE/ENTER key
- return on(node, "click", listener);
- }else{
- // Don't fire the click event unless both the keydown and keyup occur on this node.
- // Avoids problems where focus shifted to this node or away from the node on keydown,
- // either causing this node to process a stray keyup event, or causing another node
- // to get a stray keyup event.
- function clickKey(/*Event*/ e){
- return (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE) &&
- !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey;
- }
- var handles = [
- on(node, "keypress", function(e){
- //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
- if(clickKey(e)){
- // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
- lastKeyDownNode = e.target;
- // Prevent viewport scrolling on space key in IE<9.
- // (Reproducible on test_Button.html on any of the first dijit.form.Button examples)
- // Do this onkeypress rather than onkeydown because onkeydown.preventDefault() will
- // suppress the onkeypress event, breaking _HasDropDown
- e.preventDefault();
- }
- }),
- on(node, "keyup", function(e){
- //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
- if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey
- //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
- lastKeyDownNode = null;
- listener.call(this, e);
- }
- }),
- on(node, "click", function(e){
- // and connect for mouse clicks too (or touch-clicks on mobile)
- listener.call(this, e);
- })
- ];
- return {
- remove: function(){
- array.forEach(handles, function(h){ h.remove(); });
- }
- };
- }
- };
- return declare("dijit._OnDijitClickMixin", null, {
- connect: function(
- /*Object|null*/ obj,
- /*String|Function*/ event,
- /*String|Function*/ method){
- // summary:
- // Connects specified obj/event to specified method of this object
- // and registers for disconnect() on widget destroy.
- // description:
- // Provide widget-specific analog to connect.connect, except with the
- // implicit use of this widget as the target object.
- // This version of connect also provides a special "ondijitclick"
- // event which triggers on a click or space or enter keyup.
- // Events connected with `this.connect` are disconnected upon
- // destruction.
- // returns:
- // A handle that can be passed to `disconnect` in order to disconnect before
- // the widget is destroyed.
- // example:
- // | var btn = new dijit.form.Button();
- // | // when foo.bar() is called, call the listener we're going to
- // | // provide in the scope of btn
- // | btn.connect(foo, "bar", function(){
- // | console.debug(this.toString());
- // | });
- // tags:
- // protected
- return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]);
- }
- });
- });
- },
- 'dojo/dnd/autoscroll':function(){
- define("dojo/dnd/autoscroll", ["../main", "../window"], function(dojo) {
- // module:
- // dojo/dnd/autoscroll
- // summary:
- // TODOC
- dojo.getObject("dnd", true, dojo);
- dojo.dnd.getViewport = dojo.window.getBox;
- dojo.dnd.V_TRIGGER_AUTOSCROLL = 32;
- dojo.dnd.H_TRIGGER_AUTOSCROLL = 32;
- dojo.dnd.V_AUTOSCROLL_VALUE = 16;
- dojo.dnd.H_AUTOSCROLL_VALUE = 16;
- dojo.dnd.autoScroll = function(e){
- // summary:
- // a handler for onmousemove event, which scrolls the window, if
- // necesary
- // e: Event
- // onmousemove event
- // FIXME: needs more docs!
- var v = dojo.window.getBox(), dx = 0, dy = 0;
- if(e.clientX < dojo.dnd.H_TRIGGER_AUTOSCROLL){
- dx = -dojo.dnd.H_AUTOSCROLL_VALUE;
- }else if(e.clientX > v.w - dojo.dnd.H_TRIGGER_AUTOSCROLL){
- dx = dojo.dnd.H_AUTOSCROLL_VALUE;
- }
- if(e.clientY < dojo.dnd.V_TRIGGER_AUTOSCROLL){
- dy = -dojo.dnd.V_AUTOSCROLL_VALUE;
- }else if(e.clientY > v.h - dojo.dnd.V_TRIGGER_AUTOSCROLL){
- dy = dojo.dnd.V_AUTOSCROLL_VALUE;
- }
- window.scrollBy(dx, dy);
- };
- dojo.dnd._validNodes = {"div": 1, "p": 1, "td": 1};
- dojo.dnd._validOverflow = {"auto": 1, "scroll": 1};
- dojo.dnd.autoScrollNodes = function(e){
- // summary:
- // a handler for onmousemove event, which scrolls the first avaialble
- // Dom element, it falls back to dojo.dnd.autoScroll()
- // e: Event
- // onmousemove event
- // FIXME: needs more docs!
- var b, t, w, h, rx, ry, dx = 0, dy = 0, oldLeft, oldTop;
- for(var n = e.target; n;){
- if(n.nodeType == 1 && (n.tagName.toLowerCase() in dojo.dnd._validNodes)){
- var s = dojo.getComputedStyle(n),
- overflow = (s.overflow.toLowerCase() in dojo.dnd._validOverflow),
- overflowX = (s.overflowX.toLowerCase() in dojo.dnd._validOverflow),
- overflowY = (s.overflowY.toLowerCase() in dojo.dnd._validOverflow);
- if(overflow || overflowX || overflowY){
- b = dojo._getContentBox(n, s);
- t = dojo.position(n, true);
- }
- // overflow-x
- if(overflow || overflowX){
- w = Math.min(dojo.dnd.H_TRIGGER_AUTOSCROLL, b.w / 2);
- rx = e.pageX - t.x;
- if(dojo.isWebKit || dojo.isOpera){
- // FIXME: this code should not be here, it should be taken into account
- // either by the event fixing code, or the dojo.position()
- // FIXME: this code doesn't work on Opera 9.5 Beta
- rx += dojo.body().scrollLeft;
- }
- dx = 0;
- if(rx > 0 && rx < b.w){
- if(rx < w){
- dx = -w;
- }else if(rx > b.w - w){
- dx = w;
- }
- oldLeft = n.scrollLeft;
- n.scrollLeft = n.scrollLeft + dx;
- }
- }
- // overflow-y
- if(overflow || overflowY){
- //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
- h = Math.min(dojo.dnd.V_TRIGGER_AUTOSCROLL, b.h / 2);
- ry = e.pageY - t.y;
- if(dojo.isWebKit || dojo.isOpera){
- // FIXME: this code should not be here, it should be taken into account
- // either by the event fixing code, or the dojo.position()
- // FIXME: this code doesn't work on Opera 9.5 Beta
- ry += dojo.body().scrollTop;
- }
- dy = 0;
- if(ry > 0 && ry < b.h){
- if(ry < h){
- dy = -h;
- }else if(ry > b.h - h){
- dy = h;
- }
- oldTop = n.scrollTop;
- n.scrollTop = n.scrollTop + dy;
- }
- }
- if(dx || dy){ return; }
- }
- try{
- n = n.parentNode;
- }catch(x){
- n = null;
- }
- }
- dojo.dnd.autoScroll(e);
- };
- return dojo.dnd;
- });
- },
- 'dojo/data/ObjectStore':function(){
- define("dojo/data/ObjectStore", ["../_base/lang", "../Evented", "../_base/declare", "../_base/Deferred", "../_base/array",
- "../_base/connect", "../regexp"
- ], function(lang, Evented, declare, Deferred, array, connect, regexp) {
- // module:
- // dojo/data/ObjectStore
- // summary:
- // TODOC
- return declare("dojo.data.ObjectStore", [Evented],{
- objectStore: null,
- constructor: function(options){
- // summary:
- // A Dojo Data implementation that wraps Dojo object stores for backwards
- // compatibility.
- // options:
- // The configuration information to pass into the data store.
- // options.objectStore:
- // The object store to use as the source provider for this data store
- lang.mixin(this, options);
- },
- labelProperty: "label",
- getValue: function(/*Object*/ item, /*String*/property, /*value?*/defaultValue){
- // summary:
- // Gets the value of an item's 'property'
- //
- // item:
- // The item to get the value from
- // property:
- // property to look up value for
- // defaultValue:
- // the default value
- return typeof item.get === "function" ? item.get(property) :
- property in item ?
- item[property] : defaultValue;
- },
- getValues: function(item, property){
- // summary:
- // Gets the value of an item's 'property' and returns
- // it. If this value is an array it is just returned,
- // if not, the value is added to an array and that is returned.
- //
- // item: /* object */
- // property: /* string */
- // property to look up value for
- var val = this.getValue(item,property);
- return val instanceof Array ? val : val === undefined ? [] : [val];
- },
- getAttributes: function(item){
- // summary:
- // Gets the available attributes of an item's 'property' and returns
- // it as an array.
- //
- // item: /* object */
- var res = [];
- for(var i in item){
- if(item.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_')){
- res.push(i);
- }
- }
- return res;
- },
- hasAttribute: function(item,attribute){
- // summary:
- // Checks to see if item has attribute
- //
- // item: /* object */
- // attribute: /* string */
- return attribute in item;
- },
- containsValue: function(item, attribute, value){
- // summary:
- // Checks to see if 'item' has 'value' at 'attribute'
- //
- // item: /* object */
- // attribute: /* string */
- // value: /* anything */
- return array.indexOf(this.getValues(item,attribute),value) > -1;
- },
- isItem: function(item){
- // summary:
- // Checks to see if the argument is an item
- //
- // item: /* object */
- // attribute: /* string */
- // we have no way of determining if it belongs, we just have object returned from
- // service queries
- return (typeof item == 'object') && item && !(item instanceof Date);
- },
- isItemLoaded: function(item){
- // summary:
- // Checks to see if the item is loaded.
- //
- // item: /* object */
- return item && typeof item.load !== "function";
- },
- loadItem: function(args){
- // summary:
- // Loads an item and calls the callback handler. Note, that this will call the callback
- // handler even if the item is loaded. Consequently, you can use loadItem to ensure
- // that an item is loaded is situations when the item may or may not be loaded yet.
- // If you access a value directly through property access, you can use this to load
- // a lazy value as well (doesn't need to be an item).
- //
- // example:
- // store.loadItem({
- // item: item, // this item may or may not be loaded
- // onItem: function(item){
- // // do something with the item
- // }
- // });
- var item;
- if(typeof args.item.load === "function"){
- Deferred.when(args.item.load(), function(result){
- item = result; // in synchronous mode this can allow loadItem to return the value
- var func = result instanceof Error ? args.onError : args.onItem;
- if(func){
- func.call(args.scope, result);
- }
- });
- }else if(args.onItem){
- // even if it is already loaded, we will use call the callback, this makes it easier to
- // use when it is not known if the item is loaded (you can always safely call loadItem).
- args.onItem.call(args.scope, args.item);
- }
- return item;
- },
- close: function(request){
- return request && request.abort && request.abort();
- },
- fetch: function(args){
- // summary:
- // See dojo.data.api.Read.fetch
- //
- args = lang.delegate(args, args && args.queryOptions);
- var self = this;
- var scope = args.scope || self;
- var query = args.query;
- if(typeof query == "object"){ // can be null, but that is ignore by for-in
- query = lang.delegate(query); // don't modify the original
- for(var i in query){
- // find any strings and convert them to regular expressions for wildcard support
- var required = query[i];
- if(typeof required == "string"){
- query[i] = RegExp("^" + regexp.escapeString(required, "*?").replace(/\*/g, '.*').replace(/\?/g, '.') + "$", args.ignoreCase ? "mi" : "m");
- query[i].toString = (function(original){
- return function(){
- return original;
- }
- })(required);
- }
- }
- }
- var results = this.objectStore.query(query, args);
- Deferred.when(results.total, function(totalCount){
- Deferred.when(results, function(results){
- if(args.onBegin){
- args.onBegin.call(scope, totalCount || results.length, args);
- }
- if(args.onItem){
- for(var i=0; i<results.length;i++){
- args.onItem.call(scope, results[i], args);
- }
- }
- if(args.onComplete){
- args.onComplete.call(scope, args.onItem ? null : results, args);
- }
- return results;
- }, errorHandler);
- }, errorHandler);
- function errorHandler(error){
- if(args.onError){
- args.onError.call(scope, error, args);
- }
- }
- args.abort = function(){
- // abort the request
- if(results.cancel){
- results.cancel();
- }
- };
- if(results.observe){
- if(this.observing){
- // if we were previously observing, cancel the last time to avoid multiple notifications. Just the best we can do for the impedance mismatch between APIs
- this.observing.cancel();
- }
- this.observing = results.observe(function(object, removedFrom, insertedInto){
- if(array.indexOf(self._dirtyObjects, object) == -1){
- if(removedFrom == -1){
- self.onNew(object);
- }
- else if(insertedInto == -1){
- self.onDelete(object);
- }
- else{
- for(var i in object){
- if(i != self.objectStore.idProperty){
- self.onSet(object, i, null, object[i]);
- }
- }
- }
- }
- }, true);
- }
- this.onFetch(results);
- args.store = this;
- return args;
- },
- getFeatures: function(){
- // summary:
- // return the store feature set
- return {
- "dojo.data.api.Read": !!this.objectStore.get,
- "dojo.data.api.Identity": true,
- "dojo.data.api.Write": !!this.objectStore.put,
- "dojo.data.api.Notification": true
- };
- },
- getLabel: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getLabel()
- if(this.isItem(item)){
- return this.getValue(item,this.labelProperty); //String
- }
- return undefined; //undefined
- },
- getLabelAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getLabelAttributes()
- return [this.labelProperty]; //array
- },
- //Identity API Support
- getIdentity: function(item){
- return this.objectStore.getIdentity ? this.objectStore.getIdentity(item) : item[this.objectStore.idProperty || "id"];
- },
- getIdentityAttributes: function(item){
- // summary:
- // returns the attributes which are used to make up the
- // identity of an item. Basically returns this.objectStore.idProperty
- return [this.objectStore.idProperty];
- },
- fetchItemByIdentity: function(args){
- // summary:
- // fetch an item by its identity, by looking in our index of what we have loaded
- var item;
- Deferred.when(this.objectStore.get(args.identity),
- function(result){
- item = result;
- args.onItem.call(args.scope, result);
- },
- function(error){
- args.onError.call(args.scope, error);
- }
- );
- return item;
- },
- newItem: function(data, parentInfo){
- // summary:
- // adds a new item to the store at the specified point.
- // Takes two parameters, data, and options.
- //
- // data: Object
- // The data to be added in as an item.
-
- // TODOC: parentInfo
- if(parentInfo){
- // get the previous value or any empty array
- var values = this.getValue(parentInfo.parent,parentInfo.attribute,[]);
- // set the new value
- values = values.concat([data]);
- data.__parent = values;
- this.setValue(parentInfo.parent, parentInfo.attribute, values);
- }
- this._dirtyObjects.push({object:data, save: true});
- this.onNew(data);
- return data;
- },
- deleteItem: function(item){
- // summary:
- // deletes item and any references to that item from the store.
- //
- // item:
- // item to delete
- //
- // If the desire is to delete only one reference, unsetAttribute or
- // setValue is the way to go.
- this.changing(item, true);
- this.onDelete(item);
- },
- setValue: function(item, attribute, value){
- // summary:
- // sets 'attribute' on 'item' to 'value'
- var old = item[attribute];
- this.changing(item);
- item[attribute]=value;
- this.onSet(item,attribute,old,value);
- },
- setValues: function(item, attribute, values){
- // summary:
- // sets 'attribute' on 'item' to 'value' value
- // must be an array.
- if(!lang.isArray(values)){
- throw new Error("setValues expects to be passed an Array object as its value");
- }
- this.setValue(item,attribute,values);
- },
- unsetAttribute: function(item, attribute){
- // summary:
- // unsets 'attribute' on 'item'
- this.changing(item);
- var old = item[attribute];
- delete item[attribute];
- this.onSet(item,attribute,old,undefined);
- },
- _dirtyObjects: [],
- changing: function(object,_deleting){
- // summary:
- // adds an object to the list of dirty objects. This object
- // contains a reference to the object itself as well as a
- // cloned and trimmed version of old object for use with
- // revert.
- object.__isDirty = true;
- //if an object is already in the list of dirty objects, don't add it again
- //or it will overwrite the premodification data set.
- for(var i=0; i<this._dirtyObjects.length; i++){
- var dirty = this._dirtyObjects[i];
- if(object==dirty.object){
- if(_deleting){
- // we are deleting, no object is an indicator of deletiong
- dirty.object = false;
- if(!this._saveNotNeeded){
- dirty.save = true;
- }
- }
- return;
- }
- }
- var old = object instanceof Array ? [] : {};
- for(i in object){
- if(object.hasOwnProperty(i)){
- old[i] = object[i];
- }
- }
- this._dirtyObjects.push({object: !_deleting && object, old: old, save: !this._saveNotNeeded});
- },
- save: function(kwArgs){
- // summary:
- // Saves the dirty data using object store provider. See dojo.data.api.Write for API.
- //
- // kwArgs.global:
- // This will cause the save to commit the dirty data for all
- // ObjectStores as a single transaction.
- //
- // kwArgs.revertOnError
- // This will cause the changes to be reverted if there is an
- // error on the save. By default a revert is executed unless
- // a value of false is provide for this parameter.
- // TODOC: kwArgs pseudo
- kwArgs = kwArgs || {};
- var result, actions = [];
- var savingObjects = [];
- var self = this;
- var dirtyObjects = this._dirtyObjects;
- var left = dirtyObjects.length;// this is how many changes are remaining to be received from the server
- try{
- connect.connect(kwArgs,"onError",function(){
- if(kwArgs.revertOnError !== false){
- var postCommitDirtyObjects = dirtyObjects;
- dirtyObjects = savingObjects;
- self.revert(); // revert if there was an error
- self._dirtyObjects = postCommitDirtyObjects;
- }
- else{
- self._dirtyObjects = dirtyObjects.concat(savingObjects);
- }
- });
- if(this.objectStore.transaction){
- var transaction = this.objectStore.transaction();
- }
- for(var i = 0; i < dirtyObjects.length; i++){
- var dirty = dirtyObjects[i];
- var object = dirty.object;
- var old = dirty.old;
- delete object.__isDirty;
- if(object){
- result = this.objectStore.put(object, {overwrite: !!old});
- }
- else if(typeof old != "undefined"){
- result = this.objectStore.remove(this.getIdentity(old));
- }
- savingObjects.push(dirty);
- dirtyObjects.splice(i--,1);
- Deferred.when(result, function(value){
- if(!(--left)){
- if(kwArgs.onComplete){
- kwArgs.onComplete.call(kwArgs.scope, actions);
- }
- }
- },function(value){
- // on an error we want to revert, first we want to separate any changes that were made since the commit
- left = -1; // first make sure that success isn't called
- kwArgs.onError.call(kwArgs.scope, value);
- });
- }
- if(transaction){
- transaction.commit();
- }
- }catch(e){
- kwArgs.onError.call(kwArgs.scope, value);
- }
- },
- revert: function(kwArgs){
- // summary:
- // returns any modified data to its original state prior to a save();
- //
- var dirtyObjects = this._dirtyObjects;
- for(var i = dirtyObjects.length; i > 0;){
- i--;
- var dirty = dirtyObjects[i];
- var object = dirty.object;
- var old = dirty.old;
- if(object && old){
- // changed
- for(var j in old){
- if(old.hasOwnProperty(j) && object[j] !== old[j]){
- this.onSet(object, j, object[j], old[j]);
- object[j] = old[j];
- }
- }
- for(j in object){
- if(!old.hasOwnProperty(j)){
- this.onSet(object, j, object[j]);
- delete object[j];
- }
- }
- }else if(!old){
- // was an addition, remove it
- this.onDelete(object);
- }else{
- // was a deletion, we will add it back
- this.onNew(old);
- }
- delete (object || old).__isDirty;
- dirtyObjects.splice(i, 1);
- }
- },
- isDirty: function(item){
- // summary:
- // returns true if the item is marked as dirty or true if there are any dirty items
- if(!item){
- return !!this._dirtyObjects.length;
- }
- return item.__isDirty;
- },
- //Notifcation Support
- onSet: function(){},
- onNew: function(){},
- onDelete: function(){},
- // an extra to get result sets
- onFetch: function(results){}
- }
- );
- });
- },
- 'dojox/grid/enhanced/_Events':function(){
- define("dojox/grid/enhanced/_Events", [
- "dojo/_base/kernel",
- "dojo/_base/declare",
- "dojo/keys",
- "dojo/_base/html",
- "dojo/_base/event",
- "dojox/grid/_Events"
- ], function(dojo, declare, keys, html, event, _Events){
- return declare("dojox.grid.enhanced._Events", null, {
- // summary:
- // Overwrite some default events of DataGrid
- //
- // description:
- // Methods are copied or replaced for overwriting, this might be refined once
- // an overall plugin architecture is set up for DataGrid.
- //_events: Object
- // Method map cached from dojox.grid._Events().
- _events: null,
- // headerCellActiveClass: String
- // css class to apply to grid header cells when activated(mouse down)
- headerCellActiveClass: 'dojoxGridHeaderActive',
-
- // cellActiveClass: String
- // css class to apply to grid content cells when activated(mouse down)
- cellActiveClass: 'dojoxGridCellActive',
-
- // rowActiveClass: String
- // css class to apply to grid rows when activated(mouse down)
- rowActiveClass: 'dojoxGridRowActive',
- constructor: function(inGrid){
- //TODO - extend dojox.grid._Events rather than mixin for 1.8
- this._events = new _Events();
- //mixin "this" to Grid
- inGrid.mixin(inGrid, this);
- },
- dokeyup: function(e){
- // summary:
- // Grid key up event handler.
- // e: Event
- // Un-decorated event object
- this.focus.currentArea().keyup(e);
- },
- onKeyDown: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onKeyDown();
- if(e.altKey || e.metaKey){ return; }
- var focus = this.focus;
- var editing = this.edit.isEditing();
- switch(e.keyCode){
- case keys.TAB:
- if(e.ctrlKey){ return; }
- focus.tab(e.shiftKey ? -1:1,e);
- break;
- case keys.UP_ARROW:
- case keys.DOWN_ARROW:
- if(editing){ return; }
- focus.currentArea().move(e.keyCode == keys.UP_ARROW ? -1 : 1, 0, e);
- break;
- case keys.LEFT_ARROW:
- case keys.RIGHT_ARROW:
- if(editing){ return; }
- var offset = (e.keyCode == keys.LEFT_ARROW) ? 1 : -1;
- if(html._isBodyLtr()){ offset *= -1; }
- focus.currentArea().move(0, offset, e);
- break;
- case keys.F10:
- if(this.menus && e.shiftKey){
- this.onRowContextMenu(e);
- }
- break;
- default:
- focus.currentArea().keydown(e);
- break;
- }
- },
- //TODO - make the following events more reasonalble - e.g. more accurate conditions
- //events for row selectors
- domouseup: function(e){
- if(e.cellNode){
- this.onMouseUp(e);
- }else{
- this.onRowSelectorMouseUp(e);
- }
- },
- domousedown: function(e){
- if(!e.cellNode){
- this.onRowSelectorMouseDown(e);
- }
- },
- onMouseUp: function(e){
- // summary:
- // New - Event fired when mouse is up inside grid.
- // e: Event
- // Decorated event object that contains reference to grid, cell, and rowIndex
- this[e.rowIndex == -1 ? "onHeaderCellMouseUp" : "onCellMouseUp"](e);
- },
- onCellMouseDown: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onCellMouseDown()
- html.addClass(e.cellNode, this.cellActiveClass);
- html.addClass(e.rowNode, this.rowActiveClass);
- },
- onCellMouseUp: function(e){
- // summary:
- // New - Event fired when mouse is up inside content cell.
- // e: Event
- // Decorated event object that contains reference to grid, cell, and rowIndex
- html.removeClass(e.cellNode, this.cellActiveClass);
- html.removeClass(e.rowNode, this.rowActiveClass);
- },
- onCellClick: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onCellClick()
- //invoke dojox.grid._Events.onCellClick()
- this._events.onCellClick.call(this, e);
- //move mouse events to the focus manager.
- this.focus.contentMouseEvent(e);//TODO
- },
- onCellDblClick: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onCellDblClick()
- if(this.pluginMgr.isFixedCell(e.cell)){ return; }
- if(this._click.length > 1 && (!this._click[0] || !this._click[1])){
- this._click[0] = this._click[1] = e;
- }
- //invoke dojox.grid._Events.onCellDblClick()
- this._events.onCellDblClick.call(this, e);
- },
- onRowClick: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onRowClick()
- this.edit.rowClick(e);
- if(!e.cell || !this.plugin('indirectSelection')){
- this.selection.clickSelectEvent(e);
- }
- },
- onRowContextMenu: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onRowContextMenu()
- if(!this.edit.isEditing() && this.menus){
- this.showMenu(e);
- }
- },
- onSelectedRegionContextMenu: function(e){
- // summary:
- // New - Event fired when a selected region context menu is accessed via mouse right click.
- // e: Event
- // Decorated event object which contains reference to grid and info of selected
- // regions(selection type - row|column, selected index - [...])
- if(this.selectedRegionMenu){
- this.selectedRegionMenu._openMyself({
- target: e.target,
- coords: e.keyCode !== keys.F10 && "pageX" in e ? {
- x: e.pageX,
- y: e.pageY
- } : null
- });
- event.stop(e);
- }
- },
- onHeaderCellMouseOut: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onHeaderCellMouseOut()
- if(e.cellNode){
- html.removeClass(e.cellNode, this.cellOverClass);
- html.removeClass(e.cellNode, this.headerCellActiveClass);
- }
- },
- onHeaderCellMouseDown: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onHeaderCellMouseDown()
- if(e.cellNode){//TBD - apply to selection region for nested sorting?
- html.addClass(e.cellNode, this.headerCellActiveClass);
- }
- },
- onHeaderCellMouseUp: function(e){
- // summary:
- // New event
- if(e.cellNode){
- html.removeClass(e.cellNode, this.headerCellActiveClass);
- }
- },
- onHeaderCellClick: function(e){
- // summary:
- // Overwritten, see dojox.grid._Events.onHeaderCellClick()
- //move focus to header.
- this.focus.currentArea("header");
- //invoke dojox.grid._Events.onHeaderCellClick()
- if(!e.cell.isRowSelector){
- this._events.onHeaderCellClick.call(this, e);
- }
- //move mouse events to the focus manager.
- this.focus.headerMouseEvent(e);
- },
- onRowSelectorMouseDown: function(e){
- this.focus.focusArea("rowHeader", e);
- },
-
- onRowSelectorMouseUp: function(e){},
-
- //triggered in _View, see Selector plugin
- onMouseUpRow: function(e){
- if(e.rowIndex != -1){
- this.onRowMouseUp(e);
- }
- },
- onRowMouseUp: function(e){}
- });
- });
- },
- 'dijit/form/_ListMouseMixin':function(){
- define("dijit/form/_ListMouseMixin", [
- "dojo/_base/declare", // declare
- "dojo/_base/event", // event.stop
- "dojo/touch",
- "./_ListBase"
- ], function(declare, event, touch, _ListBase){
- /*=====
- var _ListBase = dijit.form._ListBase;
- =====*/
- // module:
- // dijit/form/_ListMouseMixin
- // summary:
- // a mixin to handle mouse or touch events for a focus-less menu
- return declare( "dijit.form._ListMouseMixin", _ListBase, {
- // summary:
- // a Mixin to handle mouse or touch events for a focus-less menu
- // Abstract methods that must be defined externally:
- // onClick: item was chosen (mousedown somewhere on the menu and mouseup somewhere on the menu)
- // tags:
- // private
- postCreate: function(){
- this.inherited(arguments);
- this.connect(this.domNode, touch.press, "_onMouseDown");
- this.connect(this.domNode, touch.release, "_onMouseUp");
- this.connect(this.domNode, "onmouseover", "_onMouseOver");
- this.connect(this.domNode, "onmouseout", "_onMouseOut");
- },
- _onMouseDown: function(/*Event*/ evt){
- event.stop(evt);
- if(this._hoveredNode){
- this.onUnhover(this._hoveredNode);
- this._hoveredNode = null;
- }
- this._isDragging = true;
- this._setSelectedAttr(this._getTarget(evt));
- },
- _onMouseUp: function(/*Event*/ evt){
- event.stop(evt);
- this._isDragging = false;
- var selectedNode = this._getSelectedAttr();
- var target = this._getTarget(evt);
- var hoveredNode = this._hoveredNode;
- if(selectedNode && target == selectedNode){
- this.onClick(selectedNode);
- }else if(hoveredNode && target == hoveredNode){ // drag to select
- this._setSelectedAttr(hoveredNode);
- this.onClick(hoveredNode);
- }
- },
- _onMouseOut: function(/*Event*/ /*===== evt ====*/){
- if(this._hoveredNode){
- this.onUnhover(this._hoveredNode);
- if(this._getSelectedAttr() == this._hoveredNode){
- this.onSelect(this._hoveredNode);
- }
- this._hoveredNode = null;
- }
- if(this._isDragging){
- this._cancelDrag = (new Date()).getTime() + 1000; // cancel in 1 second if no _onMouseOver fires
- }
- },
- _onMouseOver: function(/*Event*/ evt){
- if(this._cancelDrag){
- var time = (new Date()).getTime();
- if(time > this._cancelDrag){
- this._isDragging = false;
- }
- this._cancelDrag = null;
- }
- var node = this._getTarget(evt);
- if(!node){ return; }
- if(this._hoveredNode != node){
- if(this._hoveredNode){
- this._onMouseOut({ target: this._hoveredNode });
- }
- if(node && node.parentNode == this.containerNode){
- if(this._isDragging){
- this._setSelectedAttr(node);
- }else{
- this._hoveredNode = node;
- this.onHover(node);
- }
- }
- }
- }
- });
- });
- },
- 'dojo/cldr/monetary':function(){
- define("dojo/cldr/monetary", ["../main"], function(dojo) {
- // module:
- // dojo/cldr/monetary
- // summary:
- // TODOC
- dojo.getObject("cldr.monetary", true, dojo);
- dojo.cldr.monetary.getData = function(/*String*/code){
- // summary: A mapping of currency code to currency-specific formatting information. Returns a unique object with properties: places, round.
- // code: an [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code
- // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/currencyData/fractions
- var placesData = {
- ADP:0,AFN:0,ALL:0,AMD:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,
- COP:0,CRC:0,DJF:0,ESP:0,GNF:0,GYD:0,HUF:0,IDR:0,IQD:0,
- IRR:3,ISK:0,ITL:0,JOD:3,JPY:0,KMF:0,KPW:0,KRW:0,KWD:3,
- LAK:0,LBP:0,LUF:0,LYD:3,MGA:0,MGF:0,MMK:0,MNT:0,MRO:0,
- MUR:0,OMR:3,PKR:0,PYG:0,RSD:0,RWF:0,SLL:0,SOS:0,STD:0,
- SYP:0,TMM:0,TND:3,TRL:0,TZS:0,UGX:0,UZS:0,VND:0,VUV:0,
- XAF:0,XOF:0,XPF:0,YER:0,ZMK:0,ZWD:0
- };
- var roundingData = {CHF:5};
- var places = placesData[code], round = roundingData[code];
- if(typeof places == "undefined"){ places = 2; }
- if(typeof round == "undefined"){ round = 0; }
- return {places: places, round: round}; // Object
- };
- return dojo.cldr.monetary;
- });
- },
- 'dojo/cookie':function(){
- define("dojo/cookie", ["./_base/kernel", "./regexp"], function(dojo, regexp) {
- // module:
- // dojo/cookie
- // summary:
- // TODOC
- /*=====
- dojo.__cookieProps = function(){
- // expires: Date|String|Number?
- // If a number, the number of days from today at which the cookie
- // will expire. If a date, the date past which the cookie will expire.
- // If expires is in the past, the cookie will be deleted.
- // If expires is omitted or is 0, the cookie will expire when the browser closes.
- // path: String?
- // The path to use for the cookie.
- // domain: String?
- // The domain to use for the cookie.
- // secure: Boolean?
- // Whether to only send the cookie on secure connections
- this.expires = expires;
- this.path = path;
- this.domain = domain;
- this.secure = secure;
- }
- =====*/
- dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){
- // summary:
- // Get or set a cookie.
- // description:
- // If one argument is passed, returns the value of the cookie
- // For two or more arguments, acts as a setter.
- // name:
- // Name of the cookie
- // value:
- // Value for the cookie
- // props:
- // Properties for the cookie
- // example:
- // set a cookie with the JSON-serialized contents of an object which
- // will expire 5 days from now:
- // | dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });
- //
- // example:
- // de-serialize a cookie back into a JavaScript object:
- // | var config = dojo.fromJson(dojo.cookie("configObj"));
- //
- // example:
- // delete a cookie:
- // | dojo.cookie("configObj", null, {expires: -1});
- var c = document.cookie, ret;
- if(arguments.length == 1){
- var matches = c.match(new RegExp("(?:^|; )" + regexp.escapeString(name) + "=([^;]*)"));
- ret = matches ? decodeURIComponent(matches[1]) : undefined;
- }else{
- props = props || {};
- // FIXME: expires=0 seems to disappear right away, not on close? (FF3) Change docs?
- var exp = props.expires;
- if(typeof exp == "number"){
- var d = new Date();
- d.setTime(d.getTime() + exp*24*60*60*1000);
- exp = props.expires = d;
- }
- if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); }
- value = encodeURIComponent(value);
- var updatedCookie = name + "=" + value, propName;
- for(propName in props){
- updatedCookie += "; " + propName;
- var propValue = props[propName];
- if(propValue !== true){ updatedCookie += "=" + propValue; }
- }
- document.cookie = updatedCookie;
- }
- return ret; // String|undefined
- };
- dojo.cookie.isSupported = function(){
- // summary:
- // Use to determine if the current browser supports cookies or not.
- //
- // Returns true if user allows cookies.
- // Returns false if user doesn't allow cookies.
- if(!("cookieEnabled" in navigator)){
- this("__djCookieTest__", "CookiesAllowed");
- navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed";
- if(navigator.cookieEnabled){
- this("__djCookieTest__", "", {expires: -1});
- }
- }
- return navigator.cookieEnabled;
- };
- return dojo.cookie;
- });
- },
- 'dojo/cache':function(){
- define("dojo/cache", ["./_base/kernel", "./text"], function(dojo, text){
- // module:
- // dojo/cache
- // summary:
- // The module defines dojo.cache by loading dojo/text.
- //dojo.cache is defined in dojo/text
- return dojo.cache;
- });
- },
- 'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\"\r\n\trole=\"combobox\"\r\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\r\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\r\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t${_buttonInputDisabled}\r\n\t/></div\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\r\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\r\n\t/></div\r\n></div>\r\n",
- 'dijit/ProgressBar':function(){
- require({cache:{
- 'url:dijit/templates/ProgressBar.html':"<div class=\"dijitProgressBar dijitProgressBarEmpty\" role=\"progressbar\"\r\n\t><div data-dojo-attach-point=\"internalProgress\" class=\"dijitProgressBarFull\"\r\n\t\t><div class=\"dijitProgressBarTile\" role=\"presentation\"></div\r\n\t\t><span style=\"visibility:hidden\"> </span\r\n\t></div\r\n\t><div data-dojo-attach-point=\"labelNode\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"></div\r\n\t><img data-dojo-attach-point=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\r\n/></div>\r\n"}});
- define("dijit/ProgressBar", [
- "require", // require.toUrl
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.toggle
- "dojo/_base/lang", // lang.mixin
- "dojo/number", // number.format
- "./_Widget",
- "./_TemplatedMixin",
- "dojo/text!./templates/ProgressBar.html"
- ], function(require, declare, domClass, lang, number, _Widget, _TemplatedMixin, template){
- /*=====
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- =====*/
- // module:
- // dijit/ProgressBar
- // summary:
- // A progress indication widget, showing the amount completed
- // (often the percentage completed) of a task.
- return declare("dijit.ProgressBar", [_Widget, _TemplatedMixin], {
- // summary:
- // A progress indication widget, showing the amount completed
- // (often the percentage completed) of a task.
- //
- // example:
- // | <div data-dojo-type="ProgressBar"
- // | places="0"
- // | value="..." maximum="...">
- // | </div>
- // progress: [const] String (Percentage or Number)
- // Number or percentage indicating amount of task completed.
- // Deprecated. Use "value" instead.
- progress: "0",
- // value: String (Percentage or Number)
- // Number or percentage indicating amount of task completed.
- // With "%": percentage value, 0% <= progress <= 100%, or
- // without "%": absolute value, 0 <= progress <= maximum.
- // Infinity means that the progress bar is indeterminate.
- value: "",
- // maximum: [const] Float
- // Max sample number
- maximum: 100,
- // places: [const] Number
- // Number of places to show in values; 0 by default
- places: 0,
- // indeterminate: [const] Boolean
- // If false: show progress value (number or percentage).
- // If true: show that a process is underway but that the amount completed is unknown.
- // Deprecated. Use "value" instead.
- indeterminate: false,
- // label: String?
- // Label on progress bar. Defaults to percentage for determinate progress bar and
- // blank for indeterminate progress bar.
- label:"",
- // name: String
- // this is the field name (for a form) if set. This needs to be set if you want to use
- // this widget in a dijit.form.Form widget (such as dijit.Dialog)
- name: '',
- templateString: template,
- // _indeterminateHighContrastImagePath: [private] URL
- // URL to image to use for indeterminate progress bar when display is in high contrast mode
- _indeterminateHighContrastImagePath:
- require.toUrl("./themes/a11y/indeterminate_progress.gif"),
- postMixInProperties: function(){
- this.inherited(arguments);
- if(!("value" in this.params)){
- this.value = this.indeterminate ? Infinity : this.progress;
- }
- },
- buildRendering: function(){
- this.inherited(arguments);
- this.indeterminateHighContrastImage.setAttribute("src",
- this._indeterminateHighContrastImagePath.toString());
- this.update();
- },
- update: function(/*Object?*/attributes){
- // summary:
- // Internal method to change attributes of ProgressBar, similar to set(hash). Users should call
- // set("value", ...) rather than calling this method directly.
- // attributes:
- // May provide progress and/or maximum properties on this parameter;
- // see attribute specs for details.
- // example:
- // | myProgressBar.update({'indeterminate': true});
- // | myProgressBar.update({'progress': 80});
- // | myProgressBar.update({'indeterminate': true, label:"Loading ..." })
- // tags:
- // private
- // TODO: deprecate this method and use set() instead
- lang.mixin(this, attributes || {});
- var tip = this.internalProgress, ap = this.domNode;
- var percent = 1;
- if(this.indeterminate){
- ap.removeAttribute("aria-valuenow");
- ap.removeAttribute("aria-valuemin");
- ap.removeAttribute("aria-valuemax");
- }else{
- if(String(this.progress).indexOf("%") != -1){
- percent = Math.min(parseFloat(this.progress)/100, 1);
- this.progress = percent * this.maximum;
- }else{
- this.progress = Math.min(this.progress, this.maximum);
- percent = this.maximum ? this.progress / this.maximum : 0;
- }
- ap.setAttribute("aria-describedby", this.labelNode.id);
- ap.setAttribute("aria-valuenow", this.progress);
- ap.setAttribute("aria-valuemin", 0);
- ap.setAttribute("aria-valuemax", this.maximum);
- }
- this.labelNode.innerHTML = this.report(percent);
- domClass.toggle(this.domNode, "dijitProgressBarIndeterminate", this.indeterminate);
- tip.style.width = (percent * 100) + "%";
- this.onChange();
- },
- _setValueAttr: function(v){
- this._set("value", v);
- if(v == Infinity){
- this.update({indeterminate:true});
- }else{
- this.update({indeterminate:false, progress:v});
- }
- },
- _setLabelAttr: function(label){
- this._set("label", label);
- this.update();
- },
- _setIndeterminateAttr: function(indeterminate){
- // Deprecated, use set("value", ...) instead
- this.indeterminate = indeterminate;
- this.update();
- },
- report: function(/*float*/percent){
- // summary:
- // Generates message to show inside progress bar (normally indicating amount of task completed).
- // May be overridden.
- // tags:
- // extension
- return this.label ? this.label :
- (this.indeterminate ? " " : number.format(percent, { type: "percent", places: this.places, locale: this.lang }));
- },
- onChange: function(){
- // summary:
- // Callback fired when progress updates.
- // tags:
- // extension
- }
- });
- });
- },
- 'dojox/grid/_ViewManager':function(){
- define("dojox/grid/_ViewManager", [
- "dojo/_base/declare",
- "dojo/_base/sniff",
- "dojo/dom-class"
- ], function(declare, has, domClass){
- return declare('dojox.grid._ViewManager', null, {
- // summary:
- // A collection of grid views. Owned by grid and used internally for managing grid views.
- // description:
- // Grid creates views automatically based on grid's layout structure.
- // Users should typically not need to access individual views or the views collection directly.
- constructor: function(inGrid){
- this.grid = inGrid;
- },
- defaultWidth: 200,
- views: [],
- // operations
- resize: function(){
- this.onEach("resize");
- },
- render: function(){
- this.onEach("render");
- },
- // views
- addView: function(inView){
- inView.idx = this.views.length;
- this.views.push(inView);
- },
- destroyViews: function(){
- for(var i=0, v; v=this.views[i]; i++){
- v.destroy();
- }
- this.views = [];
- },
- getContentNodes: function(){
- var nodes = [];
- for(var i=0, v; v=this.views[i]; i++){
- nodes.push(v.contentNode);
- }
- return nodes;
- },
- forEach: function(inCallback){
- for(var i=0, v; v=this.views[i]; i++){
- inCallback(v, i);
- }
- },
- onEach: function(inMethod, inArgs){
- inArgs = inArgs || [];
- for(var i=0, v; v=this.views[i]; i++){
- if(inMethod in v){
- v[inMethod].apply(v, inArgs);
- }
- }
- },
- // layout
- normalizeHeaderNodeHeight: function(){
- var rowNodes = [];
- for(var i=0, v; (v=this.views[i]); i++){
- if(v.headerContentNode.firstChild){
- rowNodes.push(v.headerContentNode);
- }
- }
- this.normalizeRowNodeHeights(rowNodes);
- },
- normalizeRowNodeHeights: function(inRowNodes){
- var h = 0;
- var currHeights = [];
- if(this.grid.rowHeight){
- h = this.grid.rowHeight;
- }else{
- if(inRowNodes.length <= 1){
- // no need to normalize if we are the only one...
- return;
- }
- for(var i=0, n; (n=inRowNodes[i]); i++){
- // We only care about the height - so don't use marginBox. This
- // depends on the container not having any margin (which it shouldn't)
- // Also - we only look up the height if the cell doesn't have the
- // dojoxGridNonNormalizedCell class (like for row selectors)
- if(!domClass.contains(n, "dojoxGridNonNormalizedCell")){
- currHeights[i] = n.firstChild.offsetHeight;
- h = Math.max(h, currHeights[i]);
- }
- }
- h = (h >= 0 ? h : 0);
-
- //Work around odd FF3 rendering bug: #8864.
- //A one px increase fixes FireFox 3's rounding bug for fractional font sizes.
- if((has("mozilla") || has("ie") > 8 ) && h){h++;}
- }
- for(i=0; (n=inRowNodes[i]); i++){
- if(currHeights[i] != h){
- n.firstChild.style.height = h + "px";
- }
- }
- },
-
- resetHeaderNodeHeight: function(){
- for(var i=0, v, n; (v=this.views[i]); i++){
- n = v.headerContentNode.firstChild;
- if(n){
- n.style.height = "";
- }
- }
- },
- renormalizeRow: function(inRowIndex){
- var rowNodes = [];
- for(var i=0, v, n; (v=this.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
- n.firstChild.style.height = '';
- rowNodes.push(n);
- }
- this.normalizeRowNodeHeights(rowNodes);
- },
- getViewWidth: function(inIndex){
- return this.views[inIndex].getWidth() || this.defaultWidth;
- },
- // must be called after view widths are properly set or height can be miscalculated
- // if there are flex columns
- measureHeader: function(){
- // need to reset view header heights so they are properly measured.
- this.resetHeaderNodeHeight();
- this.forEach(function(inView){
- inView.headerContentNode.style.height = '';
- });
- var h = 0;
- // calculate maximum view header height
- this.forEach(function(inView){
- h = Math.max(inView.headerNode.offsetHeight, h);
- });
- return h;
- },
- measureContent: function(){
- var h = 0;
- this.forEach(function(inView){
- h = Math.max(inView.domNode.offsetHeight, h);
- });
- return h;
- },
- findClient: function(inAutoWidth){
- // try to use user defined client
- var c = this.grid.elasticView || -1;
- // attempt to find implicit client
- if(c < 0){
- for(var i=1, v; (v=this.views[i]); i++){
- if(v.viewWidth){
- for(i=1; (v=this.views[i]); i++){
- if(!v.viewWidth){
- c = i;
- break;
- }
- }
- break;
- }
- }
- }
- // client is in the middle by default
- if(c < 0){
- c = Math.floor(this.views.length / 2);
- }
- return c;
- },
- arrange: function(l, w){
- var i, v, vw, len = this.views.length, self = this;
- // find the client
- var c = (w <= 0 ? len : this.findClient());
- // layout views
- var setPosition = function(v, l){
- var ds = v.domNode.style;
- var hs = v.headerNode.style;
- if(!self.grid.isLeftToRight()){
- ds.right = l + 'px';
- // fixed rtl, the scrollbar is on the right side in FF < 4
- if (has("ff") < 4){
- hs.right = l + v.getScrollbarWidth() + 'px';
- }else{
- hs.right = l + 'px';
- }
- if(!has("webkit")){
- hs.width = parseInt(hs.width, 10) - v.getScrollbarWidth() + 'px';
- }
- }else{
- ds.left = l + 'px';
- hs.left = l + 'px';
- }
- ds.top = 0 + 'px';
- hs.top = 0;
- };
- // for views left of the client
- //BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with
- //leading and tailing concept.
- for(i=0; (v=this.views[i])&&(i<c); i++){
- // get width
- vw = this.getViewWidth(i);
- // process boxes
- v.setSize(vw, 0);
- setPosition(v, l);
- if(v.headerContentNode && v.headerContentNode.firstChild){
- vw = v.getColumnsWidth()+v.getScrollbarWidth();
- }else{
- vw = v.domNode.offsetWidth;
- }
- // update position
- l += vw;
- }
- // next view (is the client, i++ == c)
- i++;
- // start from the right edge
- var r = w;
- // for views right of the client (iterated from the right)
- for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
- // get width
- vw = this.getViewWidth(j);
- // set size
- v.setSize(vw, 0);
- // measure in pixels
- vw = v.domNode.offsetWidth;
- // update position
- r -= vw;
- // set position
- setPosition(v, r);
- }
- if(c<len){
- v = this.views[c];
- // position the client box between left and right boxes
- vw = Math.max(1, r-l);
- // set size
- v.setSize(vw + 'px', 0);
- setPosition(v, l);
- }
- return l;
- },
- // rendering
- renderRow: function(inRowIndex, inNodes, skipRenorm){
- var rowNodes = [];
- for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
- rowNode = v.renderRow(inRowIndex);
- n.appendChild(rowNode);
- rowNodes.push(rowNode);
- }
- if(!skipRenorm){
- this.normalizeRowNodeHeights(rowNodes);
- }
- },
-
- rowRemoved: function(inRowIndex){
- this.onEach("rowRemoved", [ inRowIndex ]);
- },
-
- // updating
- updateRow: function(inRowIndex, skipRenorm){
- for(var i=0, v; v=this.views[i]; i++){
- v.updateRow(inRowIndex);
- }
- if(!skipRenorm){
- this.renormalizeRow(inRowIndex);
- }
- },
-
- updateRowStyles: function(inRowIndex){
- this.onEach("updateRowStyles", [ inRowIndex ]);
- },
-
- // scrolling
- setScrollTop: function(inTop){
- var top = inTop;
- for(var i=0, v; v=this.views[i]; i++){
- top = v.setScrollTop(inTop);
- // Work around IE not firing scroll events that cause header offset
- // issues to occur.
- if(has("ie") && v.headerNode && v.scrollboxNode){
- v.headerNode.scrollLeft = v.scrollboxNode.scrollLeft;
- }
- }
- return top;
- //this.onEach("setScrollTop", [ inTop ]);
- },
-
- getFirstScrollingView: function(){
- // summary: Returns the first grid view with a scroll bar
- for(var i=0, v; (v=this.views[i]); i++){
- if(v.hasHScrollbar() || v.hasVScrollbar()){
- return v;
- }
- }
- return null;
- }
- });
- });
- },
- 'dijit/form/NumberTextBox':function(){
- define("dijit/form/NumberTextBox", [
- "dojo/_base/declare", // declare
- "dojo/_base/lang", // lang.hitch lang.mixin
- "dojo/number", // number._realNumberRegexp number.format number.parse number.regexp
- "./RangeBoundTextBox"
- ], function(declare, lang, number, RangeBoundTextBox){
- /*=====
- var RangeBoundTextBox = dijit.form.RangeBoundTextBox;
- =====*/
- // module:
- // dijit/form/NumberTextBox
- // summary:
- // A TextBox for entering numbers, with formatting and range checking
- /*=====
- declare(
- "dijit.form.NumberTextBox.__Constraints",
- [dijit.form.RangeBoundTextBox.__Constraints, number.__FormatOptions, number.__ParseOptions], {
- // summary:
- // Specifies both the rules on valid/invalid values (minimum, maximum,
- // number of required decimal places), and also formatting options for
- // displaying the value when the field is not focused.
- // example:
- // Minimum/maximum:
- // To specify a field between 0 and 120:
- // | {min:0,max:120}
- // To specify a field that must be an integer:
- // | {fractional:false}
- // To specify a field where 0 to 3 decimal places are allowed on input:
- // | {places:'0,3'}
- });
- =====*/
- var NumberTextBoxMixin = declare("dijit.form.NumberTextBoxMixin", null, {
- // summary:
- // A mixin for all number textboxes
- // tags:
- // protected
- // Override ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
- // than a straight regexp to deal with locale (plus formatting options too?)
- regExpGen: number.regexp,
- /*=====
- // constraints: dijit.form.NumberTextBox.__Constraints
- // Despite the name, this parameter specifies both constraints on the input
- // (including minimum/maximum allowed values) as well as
- // formatting options like places (the number of digits to display after
- // the decimal point). See `dijit.form.NumberTextBox.__Constraints` for details.
- constraints: {},
- ======*/
- // value: Number
- // The value of this NumberTextBox as a Javascript Number (i.e., not a String).
- // If the displayed value is blank, the value is NaN, and if the user types in
- // an gibberish value (like "hello world"), the value is undefined
- // (i.e. get('value') returns undefined).
- //
- // Symmetrically, set('value', NaN) will clear the displayed value,
- // whereas set('value', undefined) will have no effect.
- value: NaN,
- // editOptions: [protected] Object
- // Properties to mix into constraints when the value is being edited.
- // This is here because we edit the number in the format "12345", which is
- // different than the display value (ex: "12,345")
- editOptions: { pattern: '#.######' },
- /*=====
- _formatter: function(value, options){
- // summary:
- // _formatter() is called by format(). It's the base routine for formatting a number,
- // as a string, for example converting 12345 into "12,345".
- // value: Number
- // The number to be converted into a string.
- // options: dojo.number.__FormatOptions?
- // Formatting options
- // tags:
- // protected extension
- return "12345"; // String
- },
- =====*/
- _formatter: number.format,
- postMixInProperties: function(){
- this.inherited(arguments);
- this._set("type", "text"); // in case type="number" was specified which messes up parse/format
- },
- _setConstraintsAttr: function(/*Object*/ constraints){
- var places = typeof constraints.places == "number"? constraints.places : 0;
- if(places){ places++; } // decimal rounding errors take away another digit of precision
- if(typeof constraints.max != "number"){
- constraints.max = 9 * Math.pow(10, 15-places);
- }
- if(typeof constraints.min != "number"){
- constraints.min = -9 * Math.pow(10, 15-places);
- }
- this.inherited(arguments, [ constraints ]);
- if(this.focusNode && this.focusNode.value && !isNaN(this.value)){
- this.set('value', this.value);
- }
- },
- _onFocus: function(){
- if(this.disabled){ return; }
- var val = this.get('value');
- if(typeof val == "number" && !isNaN(val)){
- var formattedValue = this.format(val, this.constraints);
- if(formattedValue !== undefined){
- this.textbox.value = formattedValue;
- }
- }
- this.inherited(arguments);
- },
- format: function(/*Number*/ value, /*dojo.number.__FormatOptions*/ constraints){
- // summary:
- // Formats the value as a Number, according to constraints.
- // tags:
- // protected
- var formattedValue = String(value);
- if(typeof value != "number"){ return formattedValue; }
- if(isNaN(value)){ return ""; }
- // check for exponential notation that dojo.number.format chokes on
- if(!("rangeCheck" in this && this.rangeCheck(value, constraints)) && constraints.exponent !== false && /\de[-+]?\d/i.test(formattedValue)){
- return formattedValue;
- }
- if(this.editOptions && this.focused){
- constraints = lang.mixin({}, constraints, this.editOptions);
- }
- return this._formatter(value, constraints);
- },
- /*=====
- _parser: function(value, constraints){
- // summary:
- // Parses the string value as a Number, according to constraints.
- // value: String
- // String representing a number
- // constraints: dojo.number.__ParseOptions
- // Formatting options
- // tags:
- // protected
- return 123.45; // Number
- },
- =====*/
- _parser: number.parse,
- parse: function(/*String*/ value, /*number.__FormatOptions*/ constraints){
- // summary:
- // Replaceable function to convert a formatted string to a number value
- // tags:
- // protected extension
- var v = this._parser(value, lang.mixin({}, constraints, (this.editOptions && this.focused) ? this.editOptions : {}));
- if(this.editOptions && this.focused && isNaN(v)){
- v = this._parser(value, constraints); // parse w/o editOptions: not technically needed but is nice for the user
- }
- return v;
- },
- _getDisplayedValueAttr: function(){
- var v = this.inherited(arguments);
- return isNaN(v) ? this.textbox.value : v;
- },
- filter: function(/*Number*/ value){
- // summary:
- // This is called with both the display value (string), and the actual value (a number).
- // When called with the actual value it does corrections so that '' etc. are represented as NaN.
- // Otherwise it dispatches to the superclass's filter() method.
- //
- // See `dijit.form.TextBox.filter` for more details.
- return (value === null || value === '' || value === undefined) ? NaN : this.inherited(arguments); // set('value', null||''||undefined) should fire onChange(NaN)
- },
- serialize: function(/*Number*/ value, /*Object?*/ options){
- // summary:
- // Convert value (a Number) into a canonical string (ie, how the number literal is written in javascript/java/C/etc.)
- // tags:
- // protected
- return (typeof value != "number" || isNaN(value)) ? '' : this.inherited(arguments);
- },
- _setBlurValue: function(){
- var val = lang.hitch(lang.mixin({}, this, { focused: true }), "get")('value'); // parse with editOptions
- this._setValueAttr(val, true);
- },
- _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
- // summary:
- // Hook so set('value', ...) works.
- if(value !== undefined && formattedValue === undefined){
- formattedValue = String(value);
- if(typeof value == "number"){
- if(isNaN(value)){ formattedValue = '' }
- // check for exponential notation that number.format chokes on
- else if(("rangeCheck" in this && this.rangeCheck(value, this.constraints)) || this.constraints.exponent === false || !/\de[-+]?\d/i.test(formattedValue)){
- formattedValue = undefined; // lets format compute a real string value
- }
- }else if(!value){ // 0 processed in if branch above, ''|null|undefined flows through here
- formattedValue = '';
- value = NaN;
- }else{ // non-numeric values
- value = undefined;
- }
- }
- this.inherited(arguments, [value, priorityChange, formattedValue]);
- },
- _getValueAttr: function(){
- // summary:
- // Hook so get('value') works.
- // Returns Number, NaN for '', or undefined for unparseable text
- var v = this.inherited(arguments); // returns Number for all values accepted by parse() or NaN for all other displayed values
- // If the displayed value of the textbox is gibberish (ex: "hello world"), this.inherited() above
- // returns NaN; this if() branch converts the return value to undefined.
- // Returning undefined prevents user text from being overwritten when doing _setValueAttr(_getValueAttr()).
- // A blank displayed value is still returned as NaN.
- if(isNaN(v) && this.textbox.value !== ''){
- if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value) && (new RegExp("^"+number._realNumberRegexp(lang.mixin({}, this.constraints))+"$").test(this.textbox.value))){ // check for exponential notation that parse() rejected (erroneously?)
- var n = Number(this.textbox.value);
- return isNaN(n) ? undefined : n; // return exponential Number or undefined for random text (may not be possible to do with the above RegExp check)
- }else{
- return undefined; // gibberish
- }
- }else{
- return v; // Number or NaN for ''
- }
- },
- isValid: function(/*Boolean*/ isFocused){
- // Overrides dijit.form.RangeBoundTextBox.isValid to check that the editing-mode value is valid since
- // it may not be formatted according to the regExp validation rules
- if(!this.focused || this._isEmpty(this.textbox.value)){
- return this.inherited(arguments);
- }else{
- var v = this.get('value');
- if(!isNaN(v) && this.rangeCheck(v, this.constraints)){
- if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value)){ // exponential, parse doesn't like it
- return true; // valid exponential number in range
- }else{
- return this.inherited(arguments);
- }
- }else{
- return false;
- }
- }
- }
- });
- /*=====
- NumberTextBoxMixin = dijit.form.NumberTextBoxMixin;
- =====*/
- var NumberTextBox = declare("dijit.form.NumberTextBox", [RangeBoundTextBox,NumberTextBoxMixin], {
- // summary:
- // A TextBox for entering numbers, with formatting and range checking
- // description:
- // NumberTextBox is a textbox for entering and displaying numbers, supporting
- // the following main features:
- //
- // 1. Enforce minimum/maximum allowed values (as well as enforcing that the user types
- // a number rather than a random string)
- // 2. NLS support (altering roles of comma and dot as "thousands-separator" and "decimal-point"
- // depending on locale).
- // 3. Separate modes for editing the value and displaying it, specifically that
- // the thousands separator character (typically comma) disappears when editing
- // but reappears after the field is blurred.
- // 4. Formatting and constraints regarding the number of places (digits after the decimal point)
- // allowed on input, and number of places displayed when blurred (see `constraints` parameter).
- baseClass: "dijitTextBox dijitNumberTextBox"
- });
- NumberTextBox.Mixin = NumberTextBoxMixin; // for monkey patching
- return NumberTextBox;
- });
- },
- 'dijit/form/TimeTextBox':function(){
- define("dijit/form/TimeTextBox", [
- "dojo/_base/declare", // declare
- "dojo/keys", // keys.DOWN_ARROW keys.ENTER keys.ESCAPE keys.TAB keys.UP_ARROW
- "dojo/_base/lang", // lang.hitch
- "../_TimePicker",
- "./_DateTimeTextBox"
- ], function(declare, keys, lang, _TimePicker, _DateTimeTextBox){
- /*=====
- var _TimePicker = dijit._TimePicker;
- var _DateTimeTextBox = dijit.form._DateTimeTextBox;
- =====*/
- // module:
- // dijit/form/TimeTextBox
- // summary:
- // A validating, serializable, range-bound time text box with a drop down time picker
- /*=====
- declare(
- "dijit.form.TimeTextBox.__Constraints",
- [dijit.form._DateTimeTextBox.__Constraints, dijit._TimePicker.__Constraints]
- );
- =====*/
- return declare("dijit.form.TimeTextBox", _DateTimeTextBox, {
- // summary:
- // A validating, serializable, range-bound time text box with a drop down time picker
- baseClass: "dijitTextBox dijitComboBox dijitTimeTextBox",
- popupClass: _TimePicker,
- _selector: "time",
- /*=====
- // constraints: dijit.form.TimeTextBox.__Constraints
- constraints:{},
- =====*/
- // value: Date
- // The value of this widget as a JavaScript Date object. Note that the date portion implies time zone and daylight savings rules.
- //
- // Example:
- // | new dijit.form.TimeTextBox({value: stamp.fromISOString("T12:59:59", new Date())})
- //
- // When passed to the parser in markup, must be specified according to locale-independent
- // `stamp.fromISOString` format.
- //
- // Example:
- // | <input data-dojo-type='dijit.form.TimeTextBox' value='T12:34:00'>
- value: new Date(""), // value.toString()="NaN"
- //FIXME: in markup, you have no control over daylight savings
- _onKey: function(evt){
- if(this.disabled || this.readOnly){ return; }
- this.inherited(arguments);
- // If the user has backspaced or typed some numbers, then filter the result list
- // by what they typed. Maybe there's a better way to detect this, like _handleOnChange()?
- switch(evt.keyCode){
- case keys.ENTER:
- case keys.TAB:
- case keys.ESCAPE:
- case keys.DOWN_ARROW:
- case keys.UP_ARROW:
- // these keys have special meaning
- break;
- default:
- // setTimeout() because the keystroke hasn't yet appeared in the <input>,
- // so the get('displayedValue') call below won't give the result we want.
- setTimeout(lang.hitch(this, function(){
- // set this.filterString to the filter to apply to the drop down list;
- // it will be used in openDropDown()
- var val = this.get('displayedValue');
- this.filterString = (val && !this.parse(val, this.constraints)) ? val.toLowerCase() : "";
- // close the drop down and reopen it, in order to filter the items shown in the list
- // and also since the drop down may need to be repositioned if the number of list items has changed
- // and it's being displayed above the <input>
- if(this._opened){
- this.closeDropDown();
- }
- this.openDropDown();
- }), 0);
- }
- }
- });
- });
- },
- 'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\r\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\r\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\r\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\r\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\r\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\r\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\r\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\r\n\t\t\t\tid=\"${id}_label\"\r\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\r\n\t\t\t></span\r\n\t\t></span\r\n\t></span\r\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\r\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\r\n/></span>\r\n",
- 'dijit/form/CurrencyTextBox':function(){
- define("dijit/form/CurrencyTextBox", [
- "dojo/currency", // currency._mixInDefaults currency.format currency.parse currency.regexp
- "dojo/_base/declare", // declare
- "dojo/_base/lang", // lang.hitch
- "./NumberTextBox"
- ], function(currency, declare, lang, NumberTextBox){
- /*=====
- var NumberTextBox = dijit.form.NumberTextBox;
- =====*/
- // module:
- // dijit/form/CurrencyTextBox
- // summary:
- // A validating currency textbox
- /*=====
- declare(
- "dijit.form.CurrencyTextBox.__Constraints",
- [dijit.form.NumberTextBox.__Constraints, currency.__FormatOptions, currency.__ParseOptions], {
- // summary:
- // Specifies both the rules on valid/invalid values (minimum, maximum,
- // number of required decimal places), and also formatting options for
- // displaying the value when the field is not focused (currency symbol,
- // etc.)
- // description:
- // Follows the pattern of `dijit.form.NumberTextBox.constraints`.
- // In general developers won't need to set this parameter
- // example:
- // To ensure that the user types in the cents (for example, 1.00 instead of just 1):
- // | {fractional:true}
- });
- =====*/
- return declare("dijit.form.CurrencyTextBox", NumberTextBox, {
- // summary:
- // A validating currency textbox
- // description:
- // CurrencyTextBox is similar to `dijit.form.NumberTextBox` but has a few
- // extra features related to currency:
- //
- // 1. After specifying the currency type (american dollars, euros, etc.) it automatically
- // sets parse/format options such as how many decimal places to show.
- // 2. The currency mark (dollar sign, euro mark, etc.) is displayed when the field is blurred
- // but erased during editing, so that the user can just enter a plain number.
- // currency: [const] String
- // the [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD"
- currency: "",
- /*=====
- // constraints: dijit.form.CurrencyTextBox.__Constraints
- // Despite the name, this parameter specifies both constraints on the input
- // (including minimum/maximum allowed values) as well as
- // formatting options. See `dijit.form.CurrencyTextBox.__Constraints` for details.
- constraints: {},
- ======*/
- baseClass: "dijitTextBox dijitCurrencyTextBox",
- // Override regExpGen ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
- // than a straight regexp to deal with locale (plus formatting options too?)
- regExpGen: function(constraints){
- // if focused, accept either currency data or NumberTextBox format
- return '(' + (this.focused ? this.inherited(arguments, [ lang.mixin({}, constraints, this.editOptions) ]) + '|' : '')
- + currency.regexp(constraints) + ')';
- },
- // Override NumberTextBox._formatter to deal with currencies, ex: converts "123.45" to "$123.45"
- _formatter: currency.format,
- _parser: currency.parse,
- parse: function(/*String*/ value, /*Object*/ constraints){
- // summary:
- // Parses string value as a Currency, according to the constraints object
- // tags:
- // protected extension
- var v = this.inherited(arguments);
- if(isNaN(v) && /\d+/.test(value)){ // currency parse failed, but it could be because they are using NumberTextBox format so try its parse
- v = lang.hitch(lang.mixin({}, this, { _parser: NumberTextBox.prototype._parser }), "inherited")(arguments);
- }
- return v;
- },
- _setConstraintsAttr: function(/*Object*/ constraints){
- if(!constraints.currency && this.currency){
- constraints.currency = this.currency;
- }
- this.inherited(arguments, [ currency._mixInDefaults(lang.mixin(constraints, { exponent: false })) ]); // get places
- }
- });
- });
- },
- 'dojo/_base/url':function(){
- define("dojo/_base/url", ["./kernel"], function(dojo) {
- // module:
- // dojo/url
- // summary:
- // This module contains dojo._Url
- var
- ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
- ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),
- _Url = function(){
- var n = null,
- _a = arguments,
- uri = [_a[0]];
- // resolve uri components relative to each other
- for(var i = 1; i<_a.length; i++){
- if(!_a[i]){ continue; }
- // Safari doesn't support this.constructor so we have to be explicit
- // FIXME: Tracked (and fixed) in Webkit bug 3537.
- // http://bugs.webkit.org/show_bug.cgi?id=3537
- var relobj = new _Url(_a[i]+""),
- uriobj = new _Url(uri[0]+"");
- if(
- relobj.path == "" &&
- !relobj.scheme &&
- !relobj.authority &&
- !relobj.query
- ){
- if(relobj.fragment != n){
- uriobj.fragment = relobj.fragment;
- }
- relobj = uriobj;
- }else if(!relobj.scheme){
- relobj.scheme = uriobj.scheme;
- if(!relobj.authority){
- relobj.authority = uriobj.authority;
- if(relobj.path.charAt(0) != "/"){
- var path = uriobj.path.substring(0,
- uriobj.path.lastIndexOf("/") + 1) + relobj.path;
- var segs = path.split("/");
- for(var j = 0; j < segs.length; j++){
- if(segs[j] == "."){
- // flatten "./" references
- if(j == segs.length - 1){
- segs[j] = "";
- }else{
- segs.splice(j, 1);
- j--;
- }
- }else if(j > 0 && !(j == 1 && segs[0] == "") &&
- segs[j] == ".." && segs[j-1] != ".."){
- // flatten "../" references
- if(j == (segs.length - 1)){
- segs.splice(j, 1);
- segs[j - 1] = "";
- }else{
- segs.splice(j - 1, 2);
- j -= 2;
- }
- }
- }
- relobj.path = segs.join("/");
- }
- }
- }
- uri = [];
- if(relobj.scheme){
- uri.push(relobj.scheme, ":");
- }
- if(relobj.authority){
- uri.push("//", relobj.authority);
- }
- uri.push(relobj.path);
- if(relobj.query){
- uri.push("?", relobj.query);
- }
- if(relobj.fragment){
- uri.push("#", relobj.fragment);
- }
- }
- this.uri = uri.join("");
- // break the uri into its main components
- var r = this.uri.match(ore);
- this.scheme = r[2] || (r[1] ? "" : n);
- this.authority = r[4] || (r[3] ? "" : n);
- this.path = r[5]; // can never be undefined
- this.query = r[7] || (r[6] ? "" : n);
- this.fragment = r[9] || (r[8] ? "" : n);
- if(this.authority != n){
- // server based naming authority
- r = this.authority.match(ire);
- this.user = r[3] || n;
- this.password = r[4] || n;
- this.host = r[6] || r[7]; // ipv6 || ipv4
- this.port = r[9] || n;
- }
- };
- _Url.prototype.toString = function(){ return this.uri; };
- return dojo._Url = _Url;
- });
- },
- 'dojox/main':function(){
- define("dojox/main", ["dojo/_base/kernel"], function(dojo) {
- // module:
- // dojox/main
- // summary:
- // The dojox package main module; dojox package is somewhat unusual in that the main module currently just provides an empty object.
- return dojo.dojox;
- });
- },
- 'dojo/text':function(){
- define("dojo/text", ["./_base/kernel", "require", "./has", "./_base/xhr"], function(dojo, require, has, xhr){
- // module:
- // dojo/text
- // summary:
- // This module implements the !dojo/text plugin and the dojo.cache API.
- // description:
- // We choose to include our own plugin to leverage functionality already contained in dojo
- // and thereby reduce the size of the plugin compared to various foreign loader implementations.
- // Also, this allows foreign AMD loaders to be used without their plugins.
- //
- // CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous
- // loader. This feature is outside the scope of the CommonJS plugins specification.
- var getText;
- if(1){
- getText= function(url, sync, load){
- xhr("GET", {url:url, sync:!!sync, load:load});
- };
- }else{
- // TODOC: only works for dojo AMD loader
- if(require.getText){
- getText= require.getText;
- }else{
- console.error("dojo/text plugin failed to load because loader does not support getText");
- }
- }
- var
- theCache= {},
- strip= function(text){
- //Strips <?xml ...?> declarations so that external SVG and XML
- //documents can be added to a document without worry. Also, if the string
- //is an HTML document, only the part inside the body tag is returned.
- if(text){
- text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
- var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
- if(matches){
- text= matches[1];
- }
- }else{
- text = "";
- }
- return text;
- },
- notFound = {},
- pending = {},
- result= {
- dynamic:
- // the dojo/text caches it's own resources because of dojo.cache
- true,
- normalize:function(id, toAbsMid){
- // id is something like (path may be relative):
- //
- // "path/to/text.html"
- // "path/to/text.html!strip"
- var parts= id.split("!"),
- url= parts[0];
- return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : "");
- },
- load:function(id, require, load){
- // id is something like (path is always absolute):
- //
- // "path/to/text.html"
- // "path/to/text.html!strip"
- var
- parts= id.split("!"),
- stripFlag= parts.length>1,
- absMid= parts[0],
- url = require.toUrl(parts[0]),
- text = notFound,
- finish = function(text){
- load(stripFlag ? strip(text) : text);
- };
- if(absMid in theCache){
- text = theCache[absMid];
- }else if(url in require.cache){
- text = require.cache[url];
- }else if(url in theCache){
- text = theCache[url];
- }
- if(text===notFound){
- if(pending[url]){
- pending[url].push(finish);
- }else{
- var pendingList = pending[url] = [finish];
- getText(url, !require.async, function(text){
- theCache[absMid]= theCache[url]= text;
- for(var i = 0; i<pendingList.length;){
- pendingList[i++](text);
- }
- delete pending[url];
- });
- }
- }else{
- finish(text);
- }
- }
- };
- dojo.cache= function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
- // * (string string [value]) => (module, url, value)
- // * (object [value]) => (module, value), url defaults to ""
- //
- // * if module is an object, then it must be convertable to a string
- // * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl
- // * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize"
- var key;
- if(typeof module=="string"){
- if(/\//.test(module)){
- // module is a version 1.7+ resolved path
- key = module;
- value = url;
- }else{
- // module is a version 1.6- argument to dojo.moduleUrl
- key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : ""));
- }
- }else{
- key = module + "";
- value = url;
- }
- var
- val = (value != undefined && typeof value != "string") ? value.value : value,
- sanitize = value && value.sanitize;
- if(typeof val == "string"){
- //We have a string, set cache value
- theCache[key] = val;
- return sanitize ? strip(val) : val;
- }else if(val === null){
- //Remove cached value
- delete theCache[key];
- return null;
- }else{
- //Allow cache values to be empty strings. If key property does
- //not exist, fetch it.
- if(!(key in theCache)){
- getText(key, true, function(text){
- theCache[key]= text;
- });
- }
- return sanitize ? strip(theCache[key]) : theCache[key];
- }
- };
- return result;
- /*=====
- dojo.cache = function(module, url, value){
- // summary:
- // A getter and setter for storing the string content associated with the
- // module and url arguments.
- // description:
- // If module is a string that contains slashes, then it is interpretted as a fully
- // resolved path (typically a result returned by require.toUrl), and url should not be
- // provided. This is the preferred signature. If module is a string that does not
- // contain slashes, then url must also be provided and module and url are used to
- // call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated.
- // If value is specified, the cache value for the moduleUrl will be set to
- // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
- // in its internal cache and return that cached value for the URL. To clear
- // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
- // the URL contents, only modules on the same domain of the page can use this capability.
- // The build system can inline the cache values though, to allow for xdomain hosting.
- // module: String||Object
- // If a String with slashes, a fully resolved path; if a String without slashes, the
- // module name to use for the base part of the URL, similar to module argument
- // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
- // generates a valid path for the cache item. For example, a dojo._Url object.
- // url: String
- // The rest of the path to append to the path derived from the module argument. If
- // module is an object, then this second argument should be the "value" argument instead.
- // value: String||Object?
- // If a String, the value to use in the cache for the module/url combination.
- // If an Object, it can have two properties: value and sanitize. The value property
- // should be the value to use in the cache, and sanitize can be set to true or false,
- // to indicate if XML declarations should be removed from the value and if the HTML
- // inside a body tag in the value should be extracted as the real value. The value argument
- // or the value property on the value argument are usually only used by the build system
- // as it inlines cache content.
- // example:
- // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
- // of call is used to avoid an issue with the build system erroneously trying to intern
- // this example. To get the build system to intern your dojo.cache calls, use the
- // "dojo.cache" style of call):
- // | //If template.html contains "<h1>Hello</h1>" that will be
- // | //the value for the text variable.
- // | var text = dojo["cache"]("my.module", "template.html");
- // example:
- // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
- // (the dojo["cache"] style of call is used to avoid an issue with the build system
- // erroneously trying to intern this example. To get the build system to intern your
- // dojo.cache calls, use the "dojo.cache" style of call):
- // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
- // | //text variable will contain just "<h1>Hello</h1>".
- // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
- // example:
- // Same example as previous, but demostrates how an object can be passed in as
- // the first argument, then the value argument can then be the second argument.
- // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
- // | //text variable will contain just "<h1>Hello</h1>".
- // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
- return val; //String
- };
- =====*/
- });
- },
- 'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\"\r\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\r\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\r\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\r\n\t</td>\r\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\r\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\r\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\r\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\r\n\t\t</div>\r\n\t</td>\r\n</tr>\r\n",
- 'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\r\n\t><input\r\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\r\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\r\n\t\tdata-dojo-attach-point=\"focusNode\"\r\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\r\n/></div>\r\n",
- 'dojo/uacss':function(){
- define("dojo/uacss", ["./dom-geometry", "./_base/lang", "./ready", "./_base/sniff", "./_base/window"],
- function(geometry, lang, ready, has, baseWindow){
- // module:
- // dojo/uacss
- // summary:
- // Applies pre-set CSS classes to the top-level HTML node, based on:
- // - browser (ex: dj_ie)
- // - browser version (ex: dj_ie6)
- // - box model (ex: dj_contentBox)
- // - text direction (ex: dijitRtl)
- //
- // In addition, browser, browser version, and box model are
- // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl.
- var
- html = baseWindow.doc.documentElement,
- ie = has("ie"),
- opera = has("opera"),
- maj = Math.floor,
- ff = has("ff"),
- boxModel = geometry.boxModel.replace(/-/,''),
- classes = {
- "dj_ie": ie,
- "dj_ie6": maj(ie) == 6,
- "dj_ie7": maj(ie) == 7,
- "dj_ie8": maj(ie) == 8,
- "dj_ie9": maj(ie) == 9,
- "dj_quirks": has("quirks"),
- "dj_iequirks": ie && has("quirks"),
- // NOTE: Opera not supported by dijit
- "dj_opera": opera,
- "dj_khtml": has("khtml"),
- "dj_webkit": has("webkit"),
- "dj_safari": has("safari"),
- "dj_chrome": has("chrome"),
- "dj_gecko": has("mozilla"),
- "dj_ff3": maj(ff) == 3
- }; // no dojo unsupported browsers
- classes["dj_" + boxModel] = true;
- // apply browser, browser version, and box model class names
- var classStr = "";
- for(var clz in classes){
- if(classes[clz]){
- classStr += clz + " ";
- }
- }
- html.className = lang.trim(html.className + " " + classStr);
- // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
- // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).
- // priority is 90 to run ahead of parser priority of 100
- ready(90, function(){
- if(!geometry.isBodyLtr()){
- var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ");
- html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "));
- }
- });
- return has;
- });
- },
- 'dijit/Tooltip':function(){
- require({cache:{
- 'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\r\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\r\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\r\n></div>\r\n"}});
- define("dijit/Tooltip", [
- "dojo/_base/array", // array.forEach array.indexOf array.map
- "dojo/_base/declare", // declare
- "dojo/_base/fx", // fx.fadeIn fx.fadeOut
- "dojo/dom", // dom.byId
- "dojo/dom-class", // domClass.add
- "dojo/dom-geometry", // domGeometry.getMarginBox domGeometry.position
- "dojo/dom-style", // domStyle.set, domStyle.get
- "dojo/_base/lang", // lang.hitch lang.isArrayLike
- "dojo/_base/sniff", // has("ie")
- "dojo/_base/window", // win.body
- "./_base/manager", // manager.defaultDuration
- "./place",
- "./_Widget",
- "./_TemplatedMixin",
- "./BackgroundIframe",
- "dojo/text!./templates/Tooltip.html",
- "." // sets dijit.showTooltip etc. for back-compat
- ], function(array, declare, fx, dom, domClass, domGeometry, domStyle, lang, has, win,
- manager, place, _Widget, _TemplatedMixin, BackgroundIframe, template, dijit){
- /*=====
- var _Widget = dijit._Widget;
- var BackgroundIframe = dijit.BackgroundIframe;
- var _TemplatedMixin = dijit._TemplatedMixin;
- =====*/
- // module:
- // dijit/Tooltip
- // summary:
- // Defines dijit.Tooltip widget (to display a tooltip), showTooltip()/hideTooltip(), and _MasterTooltip
- var MasterTooltip = declare("dijit._MasterTooltip", [_Widget, _TemplatedMixin], {
- // summary:
- // Internal widget that holds the actual tooltip markup,
- // which occurs once per page.
- // Called by Tooltip widgets which are just containers to hold
- // the markup
- // tags:
- // protected
- // duration: Integer
- // Milliseconds to fade in/fade out
- duration: manager.defaultDuration,
- templateString: template,
- postCreate: function(){
- win.body().appendChild(this.domNode);
- this.bgIframe = new BackgroundIframe(this.domNode);
- // Setup fade-in and fade-out functions.
- this.fadeIn = fx.fadeIn({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onShow") });
- this.fadeOut = fx.fadeOut({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onHide") });
- },
- show: function(innerHTML, aroundNode, position, rtl, textDir){
- // summary:
- // Display tooltip w/specified contents to right of specified node
- // (To left if there's no space on the right, or if rtl == true)
- // innerHTML: String
- // Contents of the tooltip
- // aroundNode: DomNode || dijit.__Rectangle
- // Specifies that tooltip should be next to this node / area
- // position: String[]?
- // List of positions to try to position tooltip (ex: ["right", "above"])
- // rtl: Boolean?
- // Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true
- // means "rtl"; specifies GUI direction, not text direction.
- // textDir: String?
- // Corresponds to `WidgetBase.textdir` attribute; specifies direction of text.
- if(this.aroundNode && this.aroundNode === aroundNode && this.containerNode.innerHTML == innerHTML){
- return;
- }
- // reset width; it may have been set by orient() on a previous tooltip show()
- this.domNode.width = "auto";
- if(this.fadeOut.status() == "playing"){
- // previous tooltip is being hidden; wait until the hide completes then show new one
- this._onDeck=arguments;
- return;
- }
- this.containerNode.innerHTML=innerHTML;
-
- this.set("textDir", textDir);
- this.containerNode.align = rtl? "right" : "left"; //fix the text alignment
- var pos = place.around(this.domNode, aroundNode,
- position && position.length ? position : Tooltip.defaultPosition, !rtl, lang.hitch(this, "orient"));
- // Position the tooltip connector for middle alignment.
- // This could not have been done in orient() since the tooltip wasn't positioned at that time.
- var aroundNodeCoords = pos.aroundNodePos;
- if(pos.corner.charAt(0) == 'M' && pos.aroundCorner.charAt(0) == 'M'){
- this.connectorNode.style.top = aroundNodeCoords.y + ((aroundNodeCoords.h - this.connectorNode.offsetHeight) >> 1) - pos.y + "px";
- this.connectorNode.style.left = "";
- }else if(pos.corner.charAt(1) == 'M' && pos.aroundCorner.charAt(1) == 'M'){
- this.connectorNode.style.left = aroundNodeCoords.x + ((aroundNodeCoords.w - this.connectorNode.offsetWidth) >> 1) - pos.x + "px";
- }
- // show it
- domStyle.set(this.domNode, "opacity", 0);
- this.fadeIn.play();
- this.isShowingNow = true;
- this.aroundNode = aroundNode;
- },
- orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ tooltipCorner, /*Object*/ spaceAvailable, /*Object*/ aroundNodeCoords){
- // summary:
- // Private function to set CSS for tooltip node based on which position it's in.
- // This is called by the dijit popup code. It will also reduce the tooltip's
- // width to whatever width is available
- // tags:
- // protected
- this.connectorNode.style.top = ""; //reset to default
- //Adjust the spaceAvailable width, without changing the spaceAvailable object
- var tooltipSpaceAvaliableWidth = spaceAvailable.w - this.connectorNode.offsetWidth;
- node.className = "dijitTooltip " +
- {
- "MR-ML": "dijitTooltipRight",
- "ML-MR": "dijitTooltipLeft",
- "TM-BM": "dijitTooltipAbove",
- "BM-TM": "dijitTooltipBelow",
- "BL-TL": "dijitTooltipBelow dijitTooltipABLeft",
- "TL-BL": "dijitTooltipAbove dijitTooltipABLeft",
- "BR-TR": "dijitTooltipBelow dijitTooltipABRight",
- "TR-BR": "dijitTooltipAbove dijitTooltipABRight",
- "BR-BL": "dijitTooltipRight",
- "BL-BR": "dijitTooltipLeft"
- }[aroundCorner + "-" + tooltipCorner];
- // reduce tooltip's width to the amount of width available, so that it doesn't overflow screen
- this.domNode.style.width = "auto";
- var size = domGeometry.getContentBox(this.domNode);
- var width = Math.min((Math.max(tooltipSpaceAvaliableWidth,1)), size.w);
- var widthWasReduced = width < size.w;
- this.domNode.style.width = width+"px";
- //Adjust width for tooltips that have a really long word or a nowrap setting
- if(widthWasReduced){
- this.containerNode.style.overflow = "auto"; //temp change to overflow to detect if our tooltip needs to be wider to support the content
- var scrollWidth = this.containerNode.scrollWidth;
- this.containerNode.style.overflow = "visible"; //change it back
- if(scrollWidth > width){
- scrollWidth = scrollWidth + domStyle.get(this.domNode,"paddingLeft") + domStyle.get(this.domNode,"paddingRight");
- this.domNode.style.width = scrollWidth + "px";
- }
- }
- // Reposition the tooltip connector.
- if(tooltipCorner.charAt(0) == 'B' && aroundCorner.charAt(0) == 'B'){
- var mb = domGeometry.getMarginBox(node);
- var tooltipConnectorHeight = this.connectorNode.offsetHeight;
- if(mb.h > spaceAvailable.h){
- // The tooltip starts at the top of the page and will extend past the aroundNode
- var aroundNodePlacement = spaceAvailable.h - ((aroundNodeCoords.h + tooltipConnectorHeight) >> 1);
- this.connectorNode.style.top = aroundNodePlacement + "px";
- this.connectorNode.style.bottom = "";
- }else{
- // Align center of connector with center of aroundNode, except don't let bottom
- // of connector extend below bottom of tooltip content, or top of connector
- // extend past top of tooltip content
- this.connectorNode.style.bottom = Math.min(
- Math.max(aroundNodeCoords.h/2 - tooltipConnectorHeight/2, 0),
- mb.h - tooltipConnectorHeight) + "px";
- this.connectorNode.style.top = "";
- }
- }else{
- // reset the tooltip back to the defaults
- this.connectorNode.style.top = "";
- this.connectorNode.style.bottom = "";
- }
- return Math.max(0, size.w - tooltipSpaceAvaliableWidth);
- },
- _onShow: function(){
- // summary:
- // Called at end of fade-in operation
- // tags:
- // protected
- if(has("ie")){
- // the arrow won't show up on a node w/an opacity filter
- this.domNode.style.filter="";
- }
- },
- hide: function(aroundNode){
- // summary:
- // Hide the tooltip
- if(this._onDeck && this._onDeck[1] == aroundNode){
- // this hide request is for a show() that hasn't even started yet;
- // just cancel the pending show()
- this._onDeck=null;
- }else if(this.aroundNode === aroundNode){
- // this hide request is for the currently displayed tooltip
- this.fadeIn.stop();
- this.isShowingNow = false;
- this.aroundNode = null;
- this.fadeOut.play();
- }else{
- // just ignore the call, it's for a tooltip that has already been erased
- }
- },
- _onHide: function(){
- // summary:
- // Called at end of fade-out operation
- // tags:
- // protected
- this.domNode.style.cssText=""; // to position offscreen again
- this.containerNode.innerHTML="";
- if(this._onDeck){
- // a show request has been queued up; do it now
- this.show.apply(this, this._onDeck);
- this._onDeck=null;
- }
- },
-
- _setAutoTextDir: function(/*Object*/node){
- // summary:
- // Resolve "auto" text direction for children nodes
- // tags:
- // private
- this.applyTextDir(node, has("ie") ? node.outerText : node.textContent);
- array.forEach(node.children, function(child){this._setAutoTextDir(child); }, this);
- },
-
- _setTextDirAttr: function(/*String*/ textDir){
- // summary:
- // Setter for textDir.
- // description:
- // Users shouldn't call this function; they should be calling
- // set('textDir', value)
- // tags:
- // private
-
- this._set("textDir", typeof textDir != 'undefined'? textDir : "");
- if (textDir == "auto"){
- this._setAutoTextDir(this.containerNode);
- }else{
- this.containerNode.dir = this.textDir;
- }
- }
- });
- dijit.showTooltip = function(innerHTML, aroundNode, position, rtl, textDir){
- // summary:
- // Static method to display tooltip w/specified contents in specified position.
- // See description of dijit.Tooltip.defaultPosition for details on position parameter.
- // If position is not specified then dijit.Tooltip.defaultPosition is used.
- // innerHTML: String
- // Contents of the tooltip
- // aroundNode: dijit.__Rectangle
- // Specifies that tooltip should be next to this node / area
- // position: String[]?
- // List of positions to try to position tooltip (ex: ["right", "above"])
- // rtl: Boolean?
- // Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true
- // means "rtl"; specifies GUI direction, not text direction.
- // textDir: String?
- // Corresponds to `WidgetBase.textdir` attribute; specifies direction of text.
- // after/before don't work, but they used to, so for back-compat convert them to after-centered, before-centered
- if(position){
- position = array.map(position, function(val){
- return {after: "after-centered", before: "before-centered"}[val] || val;
- });
- }
- if(!Tooltip._masterTT){ dijit._masterTT = Tooltip._masterTT = new MasterTooltip(); }
- return Tooltip._masterTT.show(innerHTML, aroundNode, position, rtl, textDir);
- };
- dijit.hideTooltip = function(aroundNode){
- // summary:
- // Static method to hide the tooltip displayed via showTooltip()
- return Tooltip._masterTT && Tooltip._masterTT.hide(aroundNode);
- };
- var Tooltip = declare("dijit.Tooltip", _Widget, {
- // summary:
- // Pops up a tooltip (a help message) when you hover over a node.
- // label: String
- // Text to display in the tooltip.
- // Specified as innerHTML when creating the widget from markup.
- label: "",
- // showDelay: Integer
- // Number of milliseconds to wait after hovering over/focusing on the object, before
- // the tooltip is displayed.
- showDelay: 400,
- // connectId: String|String[]
- // Id of domNode(s) to attach the tooltip to.
- // When user hovers over specified dom node, the tooltip will appear.
- connectId: [],
- // position: String[]
- // See description of `dijit.Tooltip.defaultPosition` for details on position parameter.
- position: [],
- _setConnectIdAttr: function(/*String|String[]*/ newId){
- // summary:
- // Connect to specified node(s)
- // Remove connections to old nodes (if there are any)
- array.forEach(this._connections || [], function(nested){
- array.forEach(nested, lang.hitch(this, "disconnect"));
- }, this);
- // Make array of id's to connect to, excluding entries for nodes that don't exist yet, see startup()
- this._connectIds = array.filter(lang.isArrayLike(newId) ? newId : (newId ? [newId] : []),
- function(id){ return dom.byId(id); });
- // Make connections
- this._connections = array.map(this._connectIds, function(id){
- var node = dom.byId(id);
- return [
- this.connect(node, "onmouseenter", "_onHover"),
- this.connect(node, "onmouseleave", "_onUnHover"),
- this.connect(node, "onfocus", "_onHover"),
- this.connect(node, "onblur", "_onUnHover")
- ];
- }, this);
- this._set("connectId", newId);
- },
- addTarget: function(/*DOMNODE || String*/ node){
- // summary:
- // Attach tooltip to specified node if it's not already connected
- // TODO: remove in 2.0 and just use set("connectId", ...) interface
- var id = node.id || node;
- if(array.indexOf(this._connectIds, id) == -1){
- this.set("connectId", this._connectIds.concat(id));
- }
- },
- removeTarget: function(/*DomNode || String*/ node){
- // summary:
- // Detach tooltip from specified node
- // TODO: remove in 2.0 and just use set("connectId", ...) interface
- var id = node.id || node, // map from DOMNode back to plain id string
- idx = array.indexOf(this._connectIds, id);
- if(idx >= 0){
- // remove id (modifies original this._connectIds but that's OK in this case)
- this._connectIds.splice(idx, 1);
- this.set("connectId", this._connectIds);
- }
- },
- buildRendering: function(){
- this.inherited(arguments);
- domClass.add(this.domNode,"dijitTooltipData");
- },
- startup: function(){
- this.inherited(arguments);
- // If this tooltip was created in a template, or for some other reason the specified connectId[s]
- // didn't exist during the widget's initialization, then connect now.
- var ids = this.connectId;
- array.forEach(lang.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
- },
- _onHover: function(/*Event*/ e){
- // summary:
- // Despite the name of this method, it actually handles both hover and focus
- // events on the target node, setting a timer to show the tooltip.
- // tags:
- // private
- if(!this._showTimer){
- var target = e.target;
- this._showTimer = setTimeout(lang.hitch(this, function(){this.open(target)}), this.showDelay);
- }
- },
- _onUnHover: function(/*Event*/ /*===== e =====*/){
- // summary:
- // Despite the name of this method, it actually handles both mouseleave and blur
- // events on the target node, hiding the tooltip.
- // tags:
- // private
- // keep a tooltip open if the associated element still has focus (even though the
- // mouse moved away)
- if(this._focus){ return; }
- if(this._showTimer){
- clearTimeout(this._showTimer);
- delete this._showTimer;
- }
- this.close();
- },
- open: function(/*DomNode*/ target){
- // summary:
- // Display the tooltip; usually not called directly.
- // tags:
- // private
- if(this._showTimer){
- clearTimeout(this._showTimer);
- delete this._showTimer;
- }
- Tooltip.show(this.label || this.domNode.innerHTML, target, this.position, !this.isLeftToRight(), this.textDir);
- this._connectNode = target;
- this.onShow(target, this.position);
- },
- close: function(){
- // summary:
- // Hide the tooltip or cancel timer for show of tooltip
- // tags:
- // private
- if(this._connectNode){
- // if tooltip is currently shown
- Tooltip.hide(this._connectNode);
- delete this._connectNode;
- this.onHide();
- }
- if(this._showTimer){
- // if tooltip is scheduled to be shown (after a brief delay)
- clearTimeout(this._showTimer);
- delete this._showTimer;
- }
- },
- onShow: function(/*===== target, position =====*/){
- // summary:
- // Called when the tooltip is shown
- // tags:
- // callback
- },
- onHide: function(){
- // summary:
- // Called when the tooltip is hidden
- // tags:
- // callback
- },
- uninitialize: function(){
- this.close();
- this.inherited(arguments);
- }
- });
- Tooltip._MasterTooltip = MasterTooltip; // for monkey patching
- Tooltip.show = dijit.showTooltip; // export function through module return value
- Tooltip.hide = dijit.hideTooltip; // export function through module return value
- // dijit.Tooltip.defaultPosition: String[]
- // This variable controls the position of tooltips, if the position is not specified to
- // the Tooltip widget or *TextBox widget itself. It's an array of strings with the values
- // possible for `dijit/place::around()`. The recommended values are:
- //
- // * before-centered: centers tooltip to the left of the anchor node/widget, or to the right
- // in the case of RTL scripts like Hebrew and Arabic
- // * after-centered: centers tooltip to the right of the anchor node/widget, or to the left
- // in the case of RTL scripts like Hebrew and Arabic
- // * above-centered: tooltip is centered above anchor node
- // * below-centered: tooltip is centered above anchor node
- //
- // The list is positions is tried, in order, until a position is found where the tooltip fits
- // within the viewport.
- //
- // Be careful setting this parameter. A value of "above-centered" may work fine until the user scrolls
- // the screen so that there's no room above the target node. Nodes with drop downs, like
- // DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure
- // that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there
- // is only room below (or above) the target node, but not both.
- Tooltip.defaultPosition = ["after-centered", "before-centered"];
- return Tooltip;
- });
- },
- 'dojo/string':function(){
- define("dojo/string", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
- // module:
- // dojo/string
- // summary:
- // TODOC
- lang.getObject("string", true, dojo);
- /*=====
- dojo.string = {
- // summary: String utilities for Dojo
- };
- =====*/
- dojo.string.rep = function(/*String*/str, /*Integer*/num){
- // summary:
- // Efficiently replicate a string `n` times.
- // str:
- // the string to replicate
- // num:
- // number of times to replicate the string
- if(num <= 0 || !str){ return ""; }
- var buf = [];
- for(;;){
- if(num & 1){
- buf.push(str);
- }
- if(!(num >>= 1)){ break; }
- str += str;
- }
- return buf.join(""); // String
- };
- dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
- // summary:
- // Pad a string to guarantee that it is at least `size` length by
- // filling with the character `ch` at either the start or end of the
- // string. Pads at the start, by default.
- // text:
- // the string to pad
- // size:
- // length to provide padding
- // ch:
- // character to pad, defaults to '0'
- // end:
- // adds padding at the end if true, otherwise pads at start
- // example:
- // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++".
- // | dojo.string.pad("Dojo", 10, "+", true);
- if(!ch){
- ch = '0';
- }
- var out = String(text),
- pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
- return end ? out + pad : pad + out; // String
- };
- dojo.string.substitute = function( /*String*/ template,
- /*Object|Array*/map,
- /*Function?*/ transform,
- /*Object?*/ thisObject){
- // summary:
- // Performs parameterized substitutions on a string. Throws an
- // exception if any parameter is unmatched.
- // template:
- // a string with expressions in the form `${key}` to be replaced or
- // `${key:format}` which specifies a format function. keys are case-sensitive.
- // map:
- // hash to search for substitutions
- // transform:
- // a function to process all parameters before substitution takes
- // place, e.g. mylib.encodeXML
- // thisObject:
- // where to look for optional format function; default to the global
- // namespace
- // example:
- // Substitutes two expressions in a string from an Array or Object
- // | // returns "File 'foo.html' is not found in directory '/temp'."
- // | // by providing substitution data in an Array
- // | dojo.string.substitute(
- // | "File '${0}' is not found in directory '${1}'.",
- // | ["foo.html","/temp"]
- // | );
- // |
- // | // also returns "File 'foo.html' is not found in directory '/temp'."
- // | // but provides substitution data in an Object structure. Dotted
- // | // notation may be used to traverse the structure.
- // | dojo.string.substitute(
- // | "File '${name}' is not found in directory '${info.dir}'.",
- // | { name: "foo.html", info: { dir: "/temp" } }
- // | );
- // example:
- // Use a transform function to modify the values:
- // | // returns "file 'foo.html' is not found in directory '/temp'."
- // | dojo.string.substitute(
- // | "${0} is not found in ${1}.",
- // | ["foo.html","/temp"],
- // | function(str){
- // | // try to figure out the type
- // | var prefix = (str.charAt(0) == "/") ? "directory": "file";
- // | return prefix + " '" + str + "'";
- // | }
- // | );
- // example:
- // Use a formatter
- // | // returns "thinger -- howdy"
- // | dojo.string.substitute(
- // | "${0:postfix}", ["thinger"], null, {
- // | postfix: function(value, key){
- // | return value + " -- howdy";
- // | }
- // | }
- // | );
- thisObject = thisObject || dojo.global;
- transform = transform ?
- lang.hitch(thisObject, transform) : function(v){ return v; };
- return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
- function(match, key, format){
- var value = lang.getObject(key, false, map);
- if(format){
- value = lang.getObject(format, false, thisObject).call(thisObject, value, key);
- }
- return transform(value, key).toString();
- }); // String
- };
- /*=====
- dojo.string.trim = function(str){
- // summary:
- // Trims whitespace from both sides of the string
- // str: String
- // String to be trimmed
- // returns: String
- // Returns the trimmed string
- // description:
- // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
- // The short yet performant version of this function is dojo.trim(),
- // which is part of Dojo base. Uses String.prototype.trim instead, if available.
- return ""; // String
- }
- =====*/
- dojo.string.trim = String.prototype.trim ?
- lang.trim : // aliasing to the native function
- function(str){
- str = str.replace(/^\s+/, '');
- for(var i = str.length - 1; i >= 0; i--){
- if(/\S/.test(str.charAt(i))){
- str = str.substring(0, i + 1);
- break;
- }
- }
- return str;
- };
- return dojo.string;
- });
- },
- 'dijit/form/_FormValueMixin':function(){
- define("dijit/form/_FormValueMixin", [
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.set
- "dojo/keys", // keys.ESCAPE
- "dojo/_base/sniff", // has("ie"), has("quirks")
- "./_FormWidgetMixin"
- ], function(declare, domAttr, keys, has, _FormWidgetMixin){
- /*=====
- var _FormWidgetMixin = dijit.form._FormWidgetMixin;
- =====*/
- // module:
- // dijit/form/_FormValueMixin
- // summary:
- // Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
- return declare("dijit.form._FormValueMixin", _FormWidgetMixin, {
- // summary:
- // Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
- // description:
- // Each _FormValueMixin represents a single input value, and has a (possibly hidden) <input> element,
- // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
- // works as expected.
- // readOnly: Boolean
- // Should this widget respond to user input?
- // In markup, this is specified as "readOnly".
- // Similar to disabled except readOnly form values are submitted.
- readOnly: false,
- _setReadOnlyAttr: function(/*Boolean*/ value){
- domAttr.set(this.focusNode, 'readOnly', value);
- this.focusNode.setAttribute("aria-readonly", value);
- this._set("readOnly", value);
- },
- postCreate: function(){
- this.inherited(arguments);
- if(has("ie")){ // IE won't stop the event with keypress
- this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
- }
- // Update our reset value if it hasn't yet been set (because this.set()
- // is only called when there *is* a value)
- if(this._resetValue === undefined){
- this._lastValueReported = this._resetValue = this.value;
- }
- },
- _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
- // summary:
- // Hook so set('value', value) works.
- // description:
- // Sets the value of the widget.
- // If the value has changed, then fire onChange event, unless priorityChange
- // is specified as null (or false?)
- this._handleOnChange(newValue, priorityChange);
- },
- _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
- // summary:
- // Called when the value of the widget has changed. Saves the new value in this.value,
- // and calls onChange() if appropriate. See _FormWidget._handleOnChange() for details.
- this._set("value", newValue);
- this.inherited(arguments);
- },
- undo: function(){
- // summary:
- // Restore the value to the last value passed to onChange
- this._setValueAttr(this._lastValueReported, false);
- },
- reset: function(){
- // summary:
- // Reset the widget's value to what it was at initialization time
- this._hasBeenBlurred = false;
- this._setValueAttr(this._resetValue, true);
- },
- _onKeyDown: function(e){
- if(e.keyCode == keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){
- var te;
- if(has("ie") < 9 || (has("ie") && has("quirks"))){
- e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
- te = document.createEventObject();
- te.keyCode = keys.ESCAPE;
- te.shiftKey = e.shiftKey;
- e.srcElement.fireEvent('onkeypress', te);
- }
- }
- }
- });
- });
- },
- 'dijit/form/DropDownButton':function(){
- require({cache:{
- 'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\r\n\t><span class='dijitReset dijitInline dijitButtonNode'\r\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\r\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\r\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\r\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\r\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\r\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\r\n\t\t\t></span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\r\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\r\n\t\t\t\tid=\"${id}_label\"\r\n\t\t\t></span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">▼</span\r\n\t\t></span\r\n\t></span\r\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\r\n\t\tdata-dojo-attach-point=\"valueNode\"\r\n/></span>\r\n"}});
- define("dijit/form/DropDownButton", [
- "dojo/_base/declare", // declare
- "dojo/_base/lang", // hitch
- "dojo/query", // query
- "../registry", // registry.byNode
- "../popup", // dijit.popup2.hide
- "./Button",
- "../_Container",
- "../_HasDropDown",
- "dojo/text!./templates/DropDownButton.html"
- ], function(declare, lang, query, registry, popup, Button, _Container, _HasDropDown, template){
- /*=====
- Button = dijit.form.Button;
- _Container = dijit._Container;
- _HasDropDown = dijit._HasDropDown;
- =====*/
- // module:
- // dijit/form/DropDownButton
- // summary:
- // A button with a drop down
- return declare("dijit.form.DropDownButton", [Button, _Container, _HasDropDown], {
- // summary:
- // A button with a drop down
- //
- // example:
- // | <button data-dojo-type="dijit.form.DropDownButton">
- // | Hello world
- // | <div data-dojo-type="dijit.Menu">...</div>
- // | </button>
- //
- // example:
- // | var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
- // | win.body().appendChild(button1);
- //
- baseClass : "dijitDropDownButton",
- templateString: template,
- _fillContent: function(){
- // Overrides Button._fillContent().
- //
- // My inner HTML contains both the button contents and a drop down widget, like
- // <DropDownButton> <span>push me</span> <Menu> ... </Menu> </DropDownButton>
- // The first node is assumed to be the button content. The widget is the popup.
- if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
- //FIXME: figure out how to filter out the widget and use all remaining nodes as button
- // content, not just nodes[0]
- var nodes = query("*", this.srcNodeRef);
- this.inherited(arguments, [nodes[0]]);
- // save pointer to srcNode so we can grab the drop down widget after it's instantiated
- this.dropDownContainer = this.srcNodeRef;
- }
- },
- startup: function(){
- if(this._started){ return; }
- // the child widget from srcNodeRef is the dropdown widget. Insert it in the page DOM,
- // make it invisible, and store a reference to pass to the popup code.
- if(!this.dropDown && this.dropDownContainer){
- var dropDownNode = query("[widgetId]", this.dropDownContainer)[0];
- this.dropDown = registry.byNode(dropDownNode);
- delete this.dropDownContainer;
- }
- if(this.dropDown){
- popup.hide(this.dropDown);
- }
- this.inherited(arguments);
- },
- isLoaded: function(){
- // Returns whether or not we are loaded - if our dropdown has an href,
- // then we want to check that.
- var dropDown = this.dropDown;
- return (!!dropDown && (!dropDown.href || dropDown.isLoaded));
- },
- loadDropDown: function(/*Function*/ callback){
- // Default implementation assumes that drop down already exists,
- // but hasn't loaded it's data (ex: ContentPane w/href).
- // App must override if the drop down is lazy-created.
- var dropDown = this.dropDown;
- var handler = dropDown.on("load", lang.hitch(this, function(){
- handler.remove();
- callback();
- }));
- dropDown.refresh(); // tell it to load
- },
- isFocusable: function(){
- // Overridden so that focus is handled by the _HasDropDown mixin, not by
- // the _FormWidget mixin.
- return this.inherited(arguments) && !this._mouseDown;
- }
- });
- });
- },
- 'dijit/form/_FormWidgetMixin':function(){
- define("dijit/form/_FormWidgetMixin", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.set
- "dojo/dom-style", // domStyle.get
- "dojo/_base/lang", // lang.hitch lang.isArray
- "dojo/mouse", // mouse.isLeft
- "dojo/_base/sniff", // has("webkit")
- "dojo/_base/window", // win.body
- "dojo/window", // winUtils.scrollIntoView
- "../a11y" // a11y.hasDefaultTabStop
- ], function(array, declare, domAttr, domStyle, lang, mouse, has, win, winUtils, a11y){
- // module:
- // dijit/form/_FormWidgetMixin
- // summary:
- // Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
- // which can be children of a <form> node or a `dijit.form.Form` widget.
- return declare("dijit.form._FormWidgetMixin", null, {
- // summary:
- // Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
- // which can be children of a <form> node or a `dijit.form.Form` widget.
- //
- // description:
- // Represents a single HTML element.
- // All these widgets should have these attributes just like native HTML input elements.
- // You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
- //
- // They also share some common methods.
- // name: [const] String
- // Name used when submitting form; same as "name" attribute or plain HTML elements
- name: "",
- // alt: String
- // Corresponds to the native HTML <input> element's attribute.
- alt: "",
- // value: String
- // Corresponds to the native HTML <input> element's attribute.
- value: "",
- // type: [const] String
- // Corresponds to the native HTML <input> element's attribute.
- type: "text",
- // tabIndex: Integer
- // Order fields are traversed when user hits the tab key
- tabIndex: "0",
- _setTabIndexAttr: "focusNode", // force copy even when tabIndex default value, needed since Button is <span>
- // disabled: Boolean
- // Should this widget respond to user input?
- // In markup, this is specified as "disabled='disabled'", or just "disabled".
- disabled: false,
- // intermediateChanges: Boolean
- // Fires onChange for each value change or only on demand
- intermediateChanges: false,
- // scrollOnFocus: Boolean
- // On focus, should this widget scroll into view?
- scrollOnFocus: true,
- // Override _WidgetBase mapping id to this.domNode, needs to be on focusNode so <label> etc.
- // works with screen reader
- _setIdAttr: "focusNode",
- _setDisabledAttr: function(/*Boolean*/ value){
- this._set("disabled", value);
- domAttr.set(this.focusNode, 'disabled', value);
- if(this.valueNode){
- domAttr.set(this.valueNode, 'disabled', value);
- }
- this.focusNode.setAttribute("aria-disabled", value ? "true" : "false");
- if(value){
- // reset these, because after the domNode is disabled, we can no longer receive
- // mouse related events, see #4200
- this._set("hovering", false);
- this._set("active", false);
- // clear tab stop(s) on this widget's focusable node(s) (ComboBox has two focusable nodes)
- var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex :
- ("_setTabIndexAttr" in this) ? this._setTabIndexAttr : "focusNode";
- array.forEach(lang.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
- var node = this[attachPointName];
- // complex code because tabIndex=-1 on a <div> doesn't work on FF
- if(has("webkit") || a11y.hasDefaultTabStop(node)){ // see #11064 about webkit bug
- node.setAttribute('tabIndex', "-1");
- }else{
- node.removeAttribute('tabIndex');
- }
- }, this);
- }else{
- if(this.tabIndex != ""){
- this.set('tabIndex', this.tabIndex);
- }
- }
- },
- _onFocus: function(/*String*/ by){
- // If user clicks on the widget, even if the mouse is released outside of it,
- // this widget's focusNode should get focus (to mimic native browser hehavior).
- // Browsers often need help to make sure the focus via mouse actually gets to the focusNode.
- if(by == "mouse" && this.isFocusable()){
- // IE exhibits strange scrolling behavior when refocusing a node so only do it when !focused.
- var focusConnector = this.connect(this.focusNode, "onfocus", function(){
- this.disconnect(mouseUpConnector);
- this.disconnect(focusConnector);
- });
- // Set a global event to handle mouseup, so it fires properly
- // even if the cursor leaves this.domNode before the mouse up event.
- var mouseUpConnector = this.connect(win.body(), "onmouseup", function(){
- this.disconnect(mouseUpConnector);
- this.disconnect(focusConnector);
- // if here, then the mousedown did not focus the focusNode as the default action
- if(this.focused){
- this.focus();
- }
- });
- }
- if(this.scrollOnFocus){
- this.defer(function(){ winUtils.scrollIntoView(this.domNode); }); // without defer, the input caret position can change on mouse click
- }
- this.inherited(arguments);
- },
- isFocusable: function(){
- // summary:
- // Tells if this widget is focusable or not. Used internally by dijit.
- // tags:
- // protected
- return !this.disabled && this.focusNode && (domStyle.get(this.domNode, "display") != "none");
- },
- focus: function(){
- // summary:
- // Put focus on this widget
- if(!this.disabled && this.focusNode.focus){
- try{ this.focusNode.focus(); }catch(e){}/*squelch errors from hidden nodes*/
- }
- },
- compare: function(/*anything*/ val1, /*anything*/ val2){
- // summary:
- // Compare 2 values (as returned by get('value') for this widget).
- // tags:
- // protected
- if(typeof val1 == "number" && typeof val2 == "number"){
- return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2;
- }else if(val1 > val2){
- return 1;
- }else if(val1 < val2){
- return -1;
- }else{
- return 0;
- }
- },
- onChange: function(/*===== newValue =====*/){
- // summary:
- // Callback when this widget's value is changed.
- // tags:
- // callback
- },
- // _onChangeActive: [private] Boolean
- // Indicates that changes to the value should call onChange() callback.
- // This is false during widget initialization, to avoid calling onChange()
- // when the initial value is set.
- _onChangeActive: false,
- _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
- // summary:
- // Called when the value of the widget is set. Calls onChange() if appropriate
- // newValue:
- // the new value
- // priorityChange:
- // For a slider, for example, dragging the slider is priorityChange==false,
- // but on mouse up, it's priorityChange==true. If intermediateChanges==false,
- // onChange is only called form priorityChange=true events.
- // tags:
- // private
- if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
- // this block executes not for a change, but during initialization,
- // and is used to store away the original value (or for ToggleButton, the original checked state)
- this._resetValue = this._lastValueReported = newValue;
- }
- this._pendingOnChange = this._pendingOnChange
- || (typeof newValue != typeof this._lastValueReported)
- || (this.compare(newValue, this._lastValueReported) != 0);
- if((this.intermediateChanges || priorityChange || priorityChange === undefined) && this._pendingOnChange){
- this._lastValueReported = newValue;
- this._pendingOnChange = false;
- if(this._onChangeActive){
- if(this._onChangeHandle){
- this._onChangeHandle.remove();
- }
- // defer allows hidden value processing to run and
- // also the onChange handler can safely adjust focus, etc
- this._onChangeHandle = this.defer(
- function(){
- this._onChangeHandle = null;
- this.onChange(newValue);
- }); // try to collapse multiple onChange's fired faster than can be processed
- }
- }
- },
- create: function(){
- // Overrides _Widget.create()
- this.inherited(arguments);
- this._onChangeActive = true;
- },
- destroy: function(){
- if(this._onChangeHandle){ // destroy called before last onChange has fired
- this._onChangeHandle.remove();
- this.onChange(this._lastValueReported);
- }
- this.inherited(arguments);
- }
- });
- });
- },
- 'url:dijit/templates/ProgressBar.html':"<div class=\"dijitProgressBar dijitProgressBarEmpty\" role=\"progressbar\"\r\n\t><div data-dojo-attach-point=\"internalProgress\" class=\"dijitProgressBarFull\"\r\n\t\t><div class=\"dijitProgressBarTile\" role=\"presentation\"></div\r\n\t\t><span style=\"visibility:hidden\"> </span\r\n\t></div\r\n\t><div data-dojo-attach-point=\"labelNode\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"></div\r\n\t><img data-dojo-attach-point=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\r\n/></div>\r\n",
- 'dojox/grid/cells':function(){
- define("dojox/grid/cells", ["../main", "./cells/_base"], function(dojox){
- return dojox.grid.cells;
- });
- },
- 'dojox/grid/enhanced/_FocusManager':function(){
- define("dojox/grid/enhanced/_FocusManager", [
- "dojo/_base/kernel",
- "dojo/_base/lang",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/connect",
- "dojo/_base/event",
- "dojo/_base/sniff",
- "dojo/_base/html",
- "dojo/keys",
- "dijit/a11y",
- "dijit/focus",
- "../_FocusManager"
- ], function(dojo, lang, declare, array, connect, event, has, html, keys, dijitA11y, dijitFocus, _FocusManager){
- var _FocusArea = declare("dojox.grid.enhanced._FocusArea", null, {
- // summary:
- // This is a friend class of _FocusManager
- /*=====
- // name: string
- // Name of this area.
- name: "",
-
- // onFocus: function(event, step)
- // Called when this area logically gets focus.
- // event: Event object
- // May be unavailable, should check before use.
- // step: Integer
- // The distance in the tab sequence from last focused area to this area.
- // returns:
- // whether this area is successfully focused. If not, the next area will get focus.
- onFocus: function(event, step){return true;},
-
- // onBlur: function(event, step)
- // Called when this area logically loses focus.
- // event: Event object
- // May be unavailable, should check before use.
- // step: Integer
- // The distance in the tab sequence from this area to the area to focus.
- // returns:
- // If Boolean, means whether this area has successfully blurred. If not, the next area to focus is still this one.
- // If String, means the next area to focus is given by this returned name.
- onBlur: function(event, step){return true;},
-
- // onMove: function(rowStep, colStep, event)
- // Called when focus is moving around within this area.
- // rowStep: Integer
- // colStep: Integer
- // event: Event object
- // May be unavailable, should check before use.
- onMove: function(rowStep, colStep, event){},
-
- // onKey: function(event, isBubble)
- // Called when some key is pressed when focus is logically in this area.
- // event: Event object
- // isBubble: Boolean
- // Whether is in bubble stage (true) or catch stage (false).
- // returns:
- // If you do NOT want the event to propagate any further along the area stack, return exactly false.
- // So if you return nothing (undefined), this event is still propagating.
- onKey: function(event, isBubble){return true},
-
- // getRegions: function()
- // Define the small regions (dom nodes) in this area.
- // returns: Array of dom nodes.
- getRegions: function(){},
-
- // onRegionFocus: function(event)
- // Connected to the onfocus event of the defined regions (if any)
- onRegionFocus: function(event){},
-
- // onRegionBlur: function(event)
- // Connected to the onblur event of the defined regions (if any)
- onRegionBlur: function(event){},
- =====*/
- constructor: function(area, focusManager){
- this._fm = focusManager;
- this._evtStack = [area.name];
- var dummy = function(){return true;};
- area.onFocus = area.onFocus || dummy;
- area.onBlur = area.onBlur || dummy;
- area.onMove = area.onMove || dummy;
- area.onKeyUp = area.onKeyUp || dummy;
- area.onKeyDown = area.onKeyDown || dummy;
- lang.mixin(this, area);
- },
- move: function(rowStep, colStep, evt){
- if(this.name){
- var i, len = this._evtStack.length;
- for(i = len - 1; i >= 0; --i){
- if(this._fm._areas[this._evtStack[i]].onMove(rowStep, colStep, evt) === false){
- return false;
- }
- }
- }
- return true;
- },
- _onKeyEvent: function(evt, funcName){
- if(this.name){
- var i, len = this._evtStack.length;
- for(i = len - 1; i >= 0; --i){
- if(this._fm._areas[this._evtStack[i]][funcName](evt, false) === false){
- return false;
- }
- }
- for(i = 0; i < len; ++i){
- if(this._fm._areas[this._evtStack[i]][funcName](evt, true) === false){
- return false;
- }
- }
- }
- return true;
- },
- keydown: function(evt){
- return this._onKeyEvent(evt, "onKeyDown");
- },
- keyup: function(evt){
- return this._onKeyEvent(evt, "onKeyUp");
- },
- contentMouseEventPlanner: function(){
- return 0;
- },
- headerMouseEventPlanner: function(){
- return 0;
- }
- });
- return declare("dojox.grid.enhanced._FocusManager", _FocusManager, {
- _stopEvent: function(evt){
- try{
- if(evt && evt.preventDefault){
- event.stop(evt);
- }
- }catch(e){}
- },
-
- constructor: function(grid){
- this.grid = grid;
- this._areas = {};
- this._areaQueue = [];
- this._contentMouseEventHandlers = [];
- this._headerMouseEventHandlers = [];
- this._currentAreaIdx = -1;
- this._gridBlured = true;
- this._connects.push(connect.connect(grid, "onBlur", this, "_doBlur"));
- this._connects.push(connect.connect(grid.scroller, "renderPage", this, "_delayedCellFocus"));
-
- this.addArea({
- name: "header",
- onFocus: lang.hitch(this, this.focusHeader),
- onBlur: lang.hitch(this, this._blurHeader),
- onMove: lang.hitch(this, this._navHeader),
- getRegions: lang.hitch(this, this._findHeaderCells),
- onRegionFocus: lang.hitch(this, this.doColHeaderFocus),
- onRegionBlur: lang.hitch(this, this.doColHeaderBlur),
- onKeyDown: lang.hitch(this, this._onHeaderKeyDown)
- });
- this.addArea({
- name: "content",
- onFocus: lang.hitch(this, this._focusContent),
- onBlur: lang.hitch(this, this._blurContent),
- onMove: lang.hitch(this, this._navContent),
- onKeyDown: lang.hitch(this, this._onContentKeyDown)
- });
- this.addArea({
- name: "editableCell",
- onFocus: lang.hitch(this, this._focusEditableCell),
- onBlur: lang.hitch(this, this._blurEditableCell),
- onKeyDown: lang.hitch(this, this._onEditableCellKeyDown),
- onContentMouseEvent: lang.hitch(this, this._onEditableCellMouseEvent),
- contentMouseEventPlanner: function(evt, areas){ return -1; }
- });
- this.placeArea("header");
- this.placeArea("content");
- this.placeArea("editableCell");
- this.placeArea("editableCell","above","content");
- },
- destroy: function(){
- for(var name in this._areas){
- var area = this._areas[name];
- array.forEach(area._connects, connect.disconnect);
- area._connects = null;
- if(area.uninitialize){
- area.uninitialize();
- }
- }
- this.inherited(arguments);
- },
- addArea: function(area){
- if(area.name && lang.isString(area.name)){
- if(this._areas[area.name]){
- //Just replace the original area, instead of remove it, so the position does not change.
- array.forEach(area._connects, connect.disconnect);
- }
- this._areas[area.name] = new _FocusArea(area, this);
- if(area.onHeaderMouseEvent){
- this._headerMouseEventHandlers.push(area.name);
- }
- if(area.onContentMouseEvent){
- this._contentMouseEventHandlers.push(area.name);
- }
- }
- },
- getArea: function(areaName){
- return this._areas[areaName];
- },
- _bindAreaEvents: function(){
- var area, hdl, areas = this._areas;
- array.forEach(this._areaQueue, function(name){
- area = areas[name];
- if(!area._initialized && lang.isFunction(area.initialize)){
- area.initialize();
- area._initialized = true;
- }
- if(area.getRegions){
- area._regions = area.getRegions() || [];
- array.forEach(area._connects || [], connect.disconnect);
- area._connects = [];
- array.forEach(area._regions, function(r){
- if(area.onRegionFocus){
- hdl = connect.connect(r, "onfocus", area.onRegionFocus);
- area._connects.push(hdl);
- }
- if(area.onRegionBlur){
- hdl = connect.connect(r, "onblur", area.onRegionBlur);
- area._connects.push(hdl);
- }
- });
- }
- });
- },
- removeArea: function(areaName){
- var area = this._areas[areaName];
- if(area){
- this.ignoreArea(areaName);
- var i = array.indexOf(this._contentMouseEventHandlers, areaName);
- if(i >= 0){
- this._contentMouseEventHandlers.splice(i, 1);
- }
- i = array.indexOf(this._headerMouseEventHandlers, areaName);
- if(i >= 0){
- this._headerMouseEventHandlers.splice(i, 1);
- }
- array.forEach(area._connects, connect.disconnect);
- if(area.uninitialize){
- area.uninitialize();
- }
- delete this._areas[areaName];
- }
- },
- currentArea: function(areaName, toBlurOld){
- // summary:
- // Set current area to the one areaName refers.
- // areaName: String
- var idx, cai = this._currentAreaIdx;
- if(lang.isString(areaName) && (idx = array.indexOf(this._areaQueue, areaName)) >= 0){
- if(cai != idx){
- this.tabbingOut = false;
- if(toBlurOld && cai >= 0 && cai < this._areaQueue.length){
- this._areas[this._areaQueue[cai]].onBlur();
- }
- this._currentAreaIdx = idx;
- }
- }else{
- return (cai < 0 || cai >= this._areaQueue.length) ?
- new _FocusArea({}, this) :
- this._areas[this._areaQueue[this._currentAreaIdx]];
- }
- return null;
- },
- placeArea: function(name, pos, otherAreaName){
- // summary:
- // Place the area refered by *name* at some logical position relative to an existing area.
- // example:
- // placeArea("myarea","before"|"after",...)
- // placeArea("myarea","below"|"above",...)
- if(!this._areas[name]){ return; }
- var idx = array.indexOf(this._areaQueue,otherAreaName);
- switch(pos){
- case "after":
- if(idx >= 0){ ++idx; }
- //intentional drop through
- case "before":
- if(idx >= 0){
- this._areaQueue.splice(idx,0,name);
- break;
- }
- //intentional drop through
- default:
- this._areaQueue.push(name);
- break;
- case "above":
- var isAbove = true;
- //intentional drop through
- case "below":
- var otherArea = this._areas[otherAreaName];
- if(otherArea){
- if(isAbove){
- otherArea._evtStack.push(name);
- }else{
- otherArea._evtStack.splice(0,0,name);
- }
- }
- }
- },
- ignoreArea: function(name){
- this._areaQueue = array.filter(this._areaQueue,function(areaName){
- return areaName != name;
- });
- },
- focusArea: function(/* int|string|areaObj */areaId,evt){
- var idx;
- if(typeof areaId == "number"){
- idx = areaId < 0 ? this._areaQueue.length + areaId : areaId;
- }else{
- idx = array.indexOf(this._areaQueue,
- lang.isString(areaId) ? areaId : (areaId && areaId.name));
- }
- if(idx < 0){ idx = 0; }
- var step = idx - this._currentAreaIdx;
- this._gridBlured = false;
- if(step){
- this.tab(step, evt);
- }else{
- this.currentArea().onFocus(evt, step);
- }
- },
- tab: function(step,evt){
- //console.log("===========tab",step,"curArea",this._currentAreaIdx,"areaCnt",this._areaQueue.length);
- this._gridBlured = false;
- this.tabbingOut = false;
- if(step === 0){
- return;
- }
- var cai = this._currentAreaIdx;
- var dir = step > 0 ? 1:-1;
- if(cai < 0 || cai >= this._areaQueue.length){
- cai = (this._currentAreaIdx += step);
- }else{
- var nextArea = this._areas[this._areaQueue[cai]].onBlur(evt,step);
- if(nextArea === true){
- cai = (this._currentAreaIdx += step);
- }else if(lang.isString(nextArea) && this._areas[nextArea]){
- cai = this._currentAreaIdx = array.indexOf(this._areaQueue,nextArea);
- }
- }
- //console.log("target area:",cai);
- for(; cai >= 0 && cai < this._areaQueue.length; cai += dir){
- this._currentAreaIdx = cai;
- if(this._areaQueue[cai] && this._areas[this._areaQueue[cai]].onFocus(evt,step)){
- //console.log("final target area:",this._currentAreaIdx);
- return;
- }
- }
- //console.log("tab out");
- this.tabbingOut = true;
- if(step < 0){
- this._currentAreaIdx = -1;
- dijitFocus.focus(this.grid.domNode);
- }else{
- this._currentAreaIdx = this._areaQueue.length;
- dijitFocus.focus(this.grid.lastFocusNode);
- }
- },
- _onMouseEvent: function(type, evt){
- var lowercase = type.toLowerCase(),
- handlers = this["_" + lowercase + "MouseEventHandlers"],
- res = array.map(handlers, function(areaName){
- return {
- "area": areaName,
- "idx": this._areas[areaName][lowercase + "MouseEventPlanner"](evt, handlers)
- };
- }, this).sort(function(a, b){
- return b.idx - a.idx;
- }),
- resHandlers = array.map(res, function(handler){
- return res.area;
- }),
- i = res.length;
- while(--i >= 0){
- if(this._areas[res[i].area]["on" + type + "MouseEvent"](evt, resHandlers) === false){
- return;
- }
- }
- },
- contentMouseEvent: function(evt){
- this._onMouseEvent("Content", evt);
- },
- headerMouseEvent: function(evt){
- this._onMouseEvent("Header", evt);
- },
- initFocusView: function(){
- // summary:
- // Overwritten
- this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
- this._bindAreaEvents();
- },
- isNavHeader: function(){
- // summary:
- // Overwritten
- // Check whether currently navigating among column headers.
- // return:
- // true - focus is on a certain column header | false otherwise
- return this._areaQueue[this._currentAreaIdx] == "header";
- },
- previousKey: function(e){
- // summary:
- // Overwritten
- this.tab(-1,e);
- },
- nextKey: function(e){
- // summary:
- // Overwritten
- this.tab(1,e);
- },
- setFocusCell: function(/* Object */inCell, /* Integer */inRowIndex){
- // summary:
- // Overwritten - focuses the given grid cell
- if(inCell){
- this.currentArea(this.grid.edit.isEditing() ? "editableCell" : "content", true);
- //This is very slow when selecting cells!
- //this.focusGridView();
- this._focusifyCellNode(false);
- this.cell = inCell;
- this.rowIndex = inRowIndex;
- this._focusifyCellNode(true);
- }
- this.grid.onCellFocus(this.cell, this.rowIndex);
- },
- doFocus: function(e){
- // summary:
- // Overwritten
- // trap focus only for grid dom node
- // do not focus for scrolling if grid is about to blur
- if(e && e.target == e.currentTarget && !this.tabbingOut){
- if(this._gridBlured){
- this._gridBlured = false;
- if(this._currentAreaIdx < 0 || this._currentAreaIdx >= this._areaQueue.length){
- this.focusArea(0, e);
- }else{
- this.focusArea(this._currentAreaIdx, e);
- }
- }
- }else{
- this.tabbingOut = false;
- }
- event.stop(e);
- },
- _doBlur: function(){
- this._gridBlured = true;
- },
- doLastNodeFocus: function(e){
- // summary:
- // Overwritten
- if(this.tabbingOut){
- this.tabbingOut = false;
- }else{
- this.focusArea(-1, e);
- }
- },
- _delayedHeaderFocus: function(){
- // summary:
- // Overwritten
- if(this.isNavHeader() && !has("ie")){
- this.focusHeader();
- }
- },
- _delayedCellFocus: function(){
- // summary:
- // Overwritten
- this.currentArea("header", true);
- this.focusArea(this._currentAreaIdx);
- },
- _changeMenuBindNode: function(oldBindNode, newBindNode){
- var hm = this.grid.headerMenu;
- if(hm && this._contextMenuBindNode == oldBindNode){
- hm.unBindDomNode(oldBindNode);
- hm.bindDomNode(newBindNode);
- this._contextMenuBindNode = newBindNode;
- }
- },
- //---------------Header Area------------------------------------------
- focusHeader: function(evt, step){ //need a further look why these changes to parent's
- // summary:
- // Overwritten
- var didFocus = false;
- this.inherited(arguments);
- if(this._colHeadNode && html.style(this._colHeadNode, 'display') != "none"){
- dijitFocus.focus(this._colHeadNode);
- this._stopEvent(evt);
- didFocus = true;
- }
- return didFocus;
- },
- _blurHeader: function(evt,step){
- // summary:
- // Overwritten
- if(this._colHeadNode){
- html.removeClass(this._colHeadNode, this.focusClass);
- }
- html.removeAttr(this.grid.domNode,"aria-activedescendant");
- // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
- this._changeMenuBindNode(this.grid.domNode,this.grid.viewsHeaderNode);
- //moved here from nextKey
- this._colHeadNode = this._colHeadFocusIdx = null;
- return true;
- },
- _navHeader: function(rowStep, colStep, evt){
- var colDir = colStep < 0 ? -1 : 1,
- savedIdx = array.indexOf(this._findHeaderCells(), this._colHeadNode);
- if(savedIdx >= 0 && (evt.shiftKey && evt.ctrlKey)){
- this.colSizeAdjust(evt, savedIdx, colDir * 5);
- return;
- }
- this.move(rowStep, colStep);
- },
- _onHeaderKeyDown: function(e, isBubble){
- if(isBubble){
- var dk = keys;
- switch(e.keyCode){
- case dk.ENTER:
- case dk.SPACE:
- var colIdx = this.getHeaderIndex();
- if(colIdx >= 0 && !this.grid.pluginMgr.isFixedCell(e.cell)/*TODO*/){
- this.grid.setSortIndex(colIdx, null, e);
- event.stop(e);
- }
- break;
- }
- }
- return true;
- },
- _setActiveColHeader: function(){
- // summary:
- // Overwritten
- this.inherited(arguments);
- //EDG now will decorate event on header key events, if no focus, the cell will be wrong
- dijitFocus.focus(this._colHeadNode);
- },
- //---------------Content Area------------------------------------------
- findAndFocusGridCell: function(){
- // summary:
- // Overwritten
- this._focusContent();
- },
- _focusContent: function(evt,step){
- var didFocus = true;
- var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
- if(this.isNoFocusCell() && !isEmpty){
- //skip all the hidden cells
- for(var i = 0, cell = this.grid.getCell(0); cell && cell.hidden; cell = this.grid.getCell(++i)){}
- this.setFocusIndex(0, cell ? i : 0);
- }else if(this.cell && !isEmpty){
- if(this.focusView && !this.focusView.rowNodes[this.rowIndex]){
- // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
- // scroll to that row
- this.grid.scrollToRow(this.rowIndex);
- this.focusGrid();
- }else{
- this.setFocusIndex(this.rowIndex, this.cell.index);
- }
- }else{
- didFocus = false;
- }
- if(didFocus){ this._stopEvent(evt); }
- return didFocus;
- },
- _blurContent: function(evt,step){
- this._focusifyCellNode(false);
- return true;
- },
- _navContent: function(rowStep, colStep, evt){
- if((this.rowIndex === 0 && rowStep < 0) || (this.rowIndex === this.grid.rowCount - 1 && rowStep > 0)){
- return;
- }
- this._colHeadNode = null;
- this.move(rowStep, colStep, evt);
- if(evt){
- event.stop(evt);
- }
- },
- _onContentKeyDown: function(e, isBubble){
- if(isBubble){
- var dk = keys, s = this.grid.scroller;
- switch(e.keyCode){
- case dk.ENTER:
- case dk.SPACE:
- var g = this.grid;
- if(g.indirectSelection){ break; }
- g.selection.clickSelect(this.rowIndex, connect.isCopyKey(e), e.shiftKey);
- g.onRowClick(e);
- event.stop(e);
- break;
- case dk.PAGE_UP:
- if(this.rowIndex !== 0){
- if(this.rowIndex != s.firstVisibleRow + 1){
- this._navContent(s.firstVisibleRow - this.rowIndex, 0);
- }else{
- this.grid.setScrollTop(s.findScrollTop(this.rowIndex - 1));
- this._navContent(s.firstVisibleRow - s.lastVisibleRow + 1, 0);
- }
- event.stop(e);
- }
- break;
- case dk.PAGE_DOWN:
- if(this.rowIndex + 1 != this.grid.rowCount){
- event.stop(e);
- if(this.rowIndex != s.lastVisibleRow - 1){
- this._navContent(s.lastVisibleRow - this.rowIndex - 1, 0);
- }else{
- this.grid.setScrollTop(s.findScrollTop(this.rowIndex + 1));
- this._navContent(s.lastVisibleRow - s.firstVisibleRow - 1, 0);
- }
- event.stop(e);
- }
- break;
- }
- }
- return true;
- },
- //------------------editable content area-------------------------
- _blurFromEditableCell: false,
- _isNavigating: false,
- _navElems: null,
- _focusEditableCell: function(evt,step){
- var didFocus = false;
- if(this._isNavigating){
- didFocus = true;
- }else if(this.grid.edit.isEditing() && this.cell){
- if(this._blurFromEditableCell || !this._blurEditableCell(evt, step)){
- this.setFocusIndex(this.rowIndex,this.cell.index);
- didFocus = true;
- }
- this._stopEvent(evt);
- }
- return didFocus;
- },
- _applyEditableCell: function(){
- try{
- this.grid.edit.apply();
- }catch(e){
- console.warn("_FocusManager._applyEditableCell() error:", e);
- }
- },
- _blurEditableCell: function(evt,step){
- this._blurFromEditableCell = false;
- if(this._isNavigating){
- var toBlur = true;
- if(evt){
- var elems = this._navElems;
- var firstElem = elems.lowest || elems.first;
- var lastElem = elems.last || elems.highest || firstElem;
- var target = has("ie") ? evt.srcElement : evt.target;
- toBlur = target == (step > 0 ? lastElem : firstElem);
- }
- if(toBlur){
- this._isNavigating = false;
- html.setSelectable(this.cell.getNode(this.rowIndex), false);
- return "content";
- }
- return false;
- }else if(this.grid.edit.isEditing() && this.cell){
- if(!step || typeof step != "number"){ return false; }
- var dir = step > 0 ? 1 : -1;
- var cc = this.grid.layout.cellCount;
- for(var cell, col = this.cell.index + dir; col >= 0 && col < cc; col += dir){
- cell = this.grid.getCell(col);
- if(cell.editable){
- this.cell = cell;
- this._blurFromEditableCell = true;
- return false;
- }
- }
- if((this.rowIndex > 0 || dir == 1) && (this.rowIndex < this.grid.rowCount || dir == -1)){
- this.rowIndex += dir;
- //this.cell = this.grid.getCell(0); //There must be an editable cell, so this is not necessary.
- for(col = dir > 0 ? 0 : cc - 1; col >= 0 && col < cc; col += dir){
- cell = this.grid.getCell(col);
- if(cell.editable){
- this.cell = cell;
- break;
- }
- }
- this._applyEditableCell();
- return "content";
- }
- }
- return true;
- },
- _initNavigatableElems: function(){
- this._navElems = dijitA11y._getTabNavigable(this.cell.getNode(this.rowIndex));
- },
- _onEditableCellKeyDown: function(e, isBubble){
- var dk = keys,
- g = this.grid,
- edit = g.edit,
- editApplied = false,
- toPropagate = true;
- switch(e.keyCode){
- case dk.ENTER:
- if(isBubble && edit.isEditing()){
- this._applyEditableCell();
- editApplied = true;
- event.stop(e);
- }
- //intentional drop through
- case dk.SPACE:
- if(!isBubble && this._isNavigating){
- toPropagate = false;
- break;
- }
- if(isBubble){
- if(!this.cell.editable && this.cell.navigatable){
- this._initNavigatableElems();
- var toFocus = this._navElems.lowest || this._navElems.first;
- if(toFocus){
- this._isNavigating = true;
- html.setSelectable(this.cell.getNode(this.rowIndex), true);
- dijitFocus.focus(toFocus);
- event.stop(e);
- this.currentArea("editableCell", true);
- break;
- }
- }
- if(!editApplied && !edit.isEditing() && !g.pluginMgr.isFixedCell(this.cell)){
- edit.setEditCell(this.cell, this.rowIndex);
- }
- if(editApplied){
- this.currentArea("content", true);
- }else if(this.cell.editable && g.canEdit()){
- this.currentArea("editableCell", true);
- }
- }
- break;
- case dk.PAGE_UP:
- case dk.PAGE_DOWN:
- if(!isBubble && edit.isEditing()){
- //prevent propagating to content area
- toPropagate = false;
- }
- break;
- case dk.ESCAPE:
- if(!isBubble){
- edit.cancel();
- this.currentArea("content", true);
- }
- }
- return toPropagate;
- },
- _onEditableCellMouseEvent: function(evt){
- if(evt.type == "click"){
- var cell = this.cell || evt.cell;
- if(cell && !cell.editable && cell.navigatable){
- this._initNavigatableElems();
- if(this._navElems.lowest || this._navElems.first){
- var target = has("ie") ? evt.srcElement : evt.target;
- if(target != cell.getNode(evt.rowIndex)){
- this._isNavigating = true;
- this.focusArea("editableCell", evt);
- html.setSelectable(cell.getNode(evt.rowIndex), true);
- dijitFocus.focus(target);
- return false;
- }
- }
- }else if(this.grid.singleClickEdit){
- this.currentArea("editableCell");
- return false;
- }
- }
- return true;
- }
- });
- });
- },
- 'dojo/date':function(){
- define("dojo/date", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
- // module:
- // dojo/date
- // summary:
- // TODOC
- lang.getObject("date", true, dojo);
- /*=====
- dojo.date = {
- // summary: Date manipulation utilities
- }
- =====*/
- dojo.date.getDaysInMonth = function(/*Date*/dateObject){
- // summary:
- // Returns the number of days in the month used by dateObject
- var month = dateObject.getMonth();
- var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
- if(month == 1 && dojo.date.isLeapYear(dateObject)){ return 29; } // Number
- return days[month]; // Number
- };
- dojo.date.isLeapYear = function(/*Date*/dateObject){
- // summary:
- // Determines if the year of the dateObject is a leap year
- // description:
- // Leap years are years with an additional day YYYY-02-29, where the
- // year number is a multiple of four with the following exception: If
- // a year is a multiple of 100, then it is only a leap year if it is
- // also a multiple of 400. For example, 1900 was not a leap year, but
- // 2000 is one.
- var year = dateObject.getFullYear();
- return !(year%400) || (!(year%4) && !!(year%100)); // Boolean
- };
- // FIXME: This is not localized
- dojo.date.getTimezoneName = function(/*Date*/dateObject){
- // summary:
- // Get the user's time zone as provided by the browser
- // dateObject:
- // Needed because the timezone may vary with time (daylight savings)
- // description:
- // Try to get time zone info from toString or toLocaleString method of
- // the Date object -- UTC offset is not a time zone. See
- // http://www.twinsun.com/tz/tz-link.htm Note: results may be
- // inconsistent across browsers.
- var str = dateObject.toString(); // Start looking in toString
- var tz = ''; // The result -- return empty string if nothing found
- var match;
- // First look for something in parentheses -- fast lookup, no regex
- var pos = str.indexOf('(');
- if(pos > -1){
- tz = str.substring(++pos, str.indexOf(')'));
- }else{
- // If at first you don't succeed ...
- // If IE knows about the TZ, it appears before the year
- // Capital letters or slash before a 4-digit year
- // at the end of string
- var pat = /([A-Z\/]+) \d{4}$/;
- if((match = str.match(pat))){
- tz = match[1];
- }else{
- // Some browsers (e.g. Safari) glue the TZ on the end
- // of toLocaleString instead of putting it in toString
- str = dateObject.toLocaleString();
- // Capital letters or slash -- end of string,
- // after space
- pat = / ([A-Z\/]+)$/;
- if((match = str.match(pat))){
- tz = match[1];
- }
- }
- }
- // Make sure it doesn't somehow end up return AM or PM
- return (tz == 'AM' || tz == 'PM') ? '' : tz; // String
- };
- // Utility methods to do arithmetic calculations with Dates
- dojo.date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){
- // summary:
- // Compare two date objects by date, time, or both.
- // description:
- // Returns 0 if equal, positive if a > b, else negative.
- // date1:
- // Date object
- // date2:
- // Date object. If not specified, the current Date is used.
- // portion:
- // A string indicating the "date" or "time" portion of a Date object.
- // Compares both "date" and "time" by default. One of the following:
- // "date", "time", "datetime"
- // Extra step required in copy for IE - see #3112
- date1 = new Date(+date1);
- date2 = new Date(+(date2 || new Date()));
- if(portion == "date"){
- // Ignore times and compare dates.
- date1.setHours(0, 0, 0, 0);
- date2.setHours(0, 0, 0, 0);
- }else if(portion == "time"){
- // Ignore dates and compare times.
- date1.setFullYear(0, 0, 0);
- date2.setFullYear(0, 0, 0);
- }
- if(date1 > date2){ return 1; } // int
- if(date1 < date2){ return -1; } // int
- return 0; // int
- };
- dojo.date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){
- // summary:
- // Add to a Date in intervals of different size, from milliseconds to years
- // date: Date
- // Date object to start with
- // interval:
- // A string representing the interval. One of the following:
- // "year", "month", "day", "hour", "minute", "second",
- // "millisecond", "quarter", "week", "weekday"
- // amount:
- // How much to add to the date.
- var sum = new Date(+date); // convert to Number before copying to accomodate IE (#3112)
- var fixOvershoot = false;
- var property = "Date";
- switch(interval){
- case "day":
- break;
- case "weekday":
- //i18n FIXME: assumes Saturday/Sunday weekend, but this is not always true. see dojo.cldr.supplemental
- // Divide the increment time span into weekspans plus leftover days
- // e.g., 8 days is one 5-day weekspan / and two leftover days
- // Can't have zero leftover days, so numbers divisible by 5 get
- // a days value of 5, and the remaining days make up the number of weeks
- var days, weeks;
- var mod = amount % 5;
- if(!mod){
- days = (amount > 0) ? 5 : -5;
- weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);
- }else{
- days = mod;
- weeks = parseInt(amount/5);
- }
- // Get weekday value for orig date param
- var strt = date.getDay();
- // Orig date is Sat / positive incrementer
- // Jump over Sun
- var adj = 0;
- if(strt == 6 && amount > 0){
- adj = 1;
- }else if(strt == 0 && amount < 0){
- // Orig date is Sun / negative incrementer
- // Jump back over Sat
- adj = -1;
- }
- // Get weekday val for the new date
- var trgt = strt + days;
- // New date is on Sat or Sun
- if(trgt == 0 || trgt == 6){
- adj = (amount > 0) ? 2 : -2;
- }
- // Increment by number of weeks plus leftover days plus
- // weekend adjustments
- amount = (7 * weeks) + days + adj;
- break;
- case "year":
- property = "FullYear";
- // Keep increment/decrement from 2/29 out of March
- fixOvershoot = true;
- break;
- case "week":
- amount *= 7;
- break;
- case "quarter":
- // Naive quarter is just three months
- amount *= 3;
- // fallthrough...
- case "month":
- // Reset to last day of month if you overshoot
- fixOvershoot = true;
- property = "Month";
- break;
- // case "hour":
- // case "minute":
- // case "second":
- // case "millisecond":
- default:
- property = "UTC"+interval.charAt(0).toUpperCase() + interval.substring(1) + "s";
- }
- if(property){
- sum["set"+property](sum["get"+property]()+amount);
- }
- if(fixOvershoot && (sum.getDate() < date.getDate())){
- sum.setDate(0);
- }
- return sum; // Date
- };
- dojo.date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){
- // summary:
- // Get the difference in a specific unit of time (e.g., number of
- // months, weeks, days, etc.) between two dates, rounded to the
- // nearest integer.
- // date1:
- // Date object
- // date2:
- // Date object. If not specified, the current Date is used.
- // interval:
- // A string representing the interval. One of the following:
- // "year", "month", "day", "hour", "minute", "second",
- // "millisecond", "quarter", "week", "weekday"
- // Defaults to "day".
- date2 = date2 || new Date();
- interval = interval || "day";
- var yearDiff = date2.getFullYear() - date1.getFullYear();
- var delta = 1; // Integer return value
- switch(interval){
- case "quarter":
- var m1 = date1.getMonth();
- var m2 = date2.getMonth();
- // Figure out which quarter the months are in
- var q1 = Math.floor(m1/3) + 1;
- var q2 = Math.floor(m2/3) + 1;
- // Add quarters for any year difference between the dates
- q2 += (yearDiff * 4);
- delta = q2 - q1;
- break;
- case "weekday":
- var days = Math.round(dojo.date.difference(date1, date2, "day"));
- var weeks = parseInt(dojo.date.difference(date1, date2, "week"));
- var mod = days % 7;
- // Even number of weeks
- if(mod == 0){
- days = weeks*5;
- }else{
- // Weeks plus spare change (< 7 days)
- var adj = 0;
- var aDay = date1.getDay();
- var bDay = date2.getDay();
- weeks = parseInt(days/7);
- mod = days % 7;
- // Mark the date advanced by the number of
- // round weeks (may be zero)
- var dtMark = new Date(date1);
- dtMark.setDate(dtMark.getDate()+(weeks*7));
- var dayMark = dtMark.getDay();
- // Spare change days -- 6 or less
- if(days > 0){
- switch(true){
- // Range starts on Sat
- case aDay == 6:
- adj = -1;
- break;
- // Range starts on Sun
- case aDay == 0:
- adj = 0;
- break;
- // Range ends on Sat
- case bDay == 6:
- adj = -1;
- break;
- // Range ends on Sun
- case bDay == 0:
- adj = -2;
- break;
- // Range contains weekend
- case (dayMark + mod) > 5:
- adj = -2;
- }
- }else if(days < 0){
- switch(true){
- // Range starts on Sat
- case aDay == 6:
- adj = 0;
- break;
- // Range starts on Sun
- case aDay == 0:
- adj = 1;
- break;
- // Range ends on Sat
- case bDay == 6:
- adj = 2;
- break;
- // Range ends on Sun
- case bDay == 0:
- adj = 1;
- break;
- // Range contains weekend
- case (dayMark + mod) < 0:
- adj = 2;
- }
- }
- days += adj;
- days -= (weeks*2);
- }
- delta = days;
- break;
- case "year":
- delta = yearDiff;
- break;
- case "month":
- delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);
- break;
- case "week":
- // Truncate instead of rounding
- // Don't use Math.floor -- value may be negative
- delta = parseInt(dojo.date.difference(date1, date2, "day")/7);
- break;
- case "day":
- delta /= 24;
- // fallthrough
- case "hour":
- delta /= 60;
- // fallthrough
- case "minute":
- delta /= 60;
- // fallthrough
- case "second":
- delta /= 1000;
- // fallthrough
- case "millisecond":
- delta *= date2.getTime() - date1.getTime();
- }
- // Round for fractional values and DST leaps
- return Math.round(delta); // Number (integer)
- };
- return dojo.date;
- });
- },
- 'dojox/grid/_Layout':function(){
- define("dojox/grid/_Layout", [
- "dojo/_base/kernel",
- "../main",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/dom-geometry",
- "./cells",
- "./_RowSelector"
- ], function(dojo, dojox, declare, array, lang, domGeometry){
- return declare("dojox.grid._Layout", null, {
- // summary:
- // Controls grid cell layout. Owned by grid and used internally.
- constructor: function(inGrid){
- this.grid = inGrid;
- },
- // flat array of grid cells
- cells: [],
- // structured array of grid cells
- structure: null,
- // default cell width
- defaultWidth: '6em',
- // methods
- moveColumn: function(sourceViewIndex, destViewIndex, cellIndex, targetIndex, before){
- var source_cells = this.structure[sourceViewIndex].cells[0];
- var dest_cells = this.structure[destViewIndex].cells[0];
- var cell = null;
- var cell_ri = 0;
- var target_ri = 0;
- for(var i=0, c; c=source_cells[i]; i++){
- if(c.index == cellIndex){
- cell_ri = i;
- break;
- }
- }
- cell = source_cells.splice(cell_ri, 1)[0];
- cell.view = this.grid.views.views[destViewIndex];
- for(i=0, c=null; c=dest_cells[i]; i++){
- if(c.index == targetIndex){
- target_ri = i;
- break;
- }
- }
- if(!before){
- target_ri += 1;
- }
- dest_cells.splice(target_ri, 0, cell);
- var sortedCell = this.grid.getCell(this.grid.getSortIndex());
- if(sortedCell){
- sortedCell._currentlySorted = this.grid.getSortAsc();
- }
- this.cells = [];
- cellIndex = 0;
- var v;
- for(i=0; v=this.structure[i]; i++){
- for(var j=0, cs; cs=v.cells[j]; j++){
- for(var k=0; c=cs[k]; k++){
- c.index = cellIndex;
- this.cells.push(c);
- if("_currentlySorted" in c){
- var si = cellIndex + 1;
- si *= c._currentlySorted ? 1 : -1;
- this.grid.sortInfo = si;
- delete c._currentlySorted;
- }
- cellIndex++;
- }
- }
- }
-
- //Fix #9481 - reset idx in cell markup
- array.forEach(this.cells, function(c){
- var marks = c.markup[2].split(" ");
- var oldIdx = parseInt(marks[1].substring(5));//get old "idx"
- if(oldIdx != c.index){
- marks[1] = "idx=\"" + c.index + "\"";
- c.markup[2] = marks.join(" ");
- }
- });
-
- this.grid.setupHeaderMenu();
- //this.grid.renderOnIdle();
- },
- setColumnVisibility: function(columnIndex, visible){
- var cell = this.cells[columnIndex];
- if(cell.hidden == visible){
- cell.hidden = !visible;
- var v = cell.view, w = v.viewWidth;
- if(w && w != "auto"){
- v._togglingColumn = domGeometry.getMarginBox(cell.getHeaderNode()).w || 0;
- }
- v.update();
- return true;
- }else{
- return false;
- }
- },
-
- addCellDef: function(inRowIndex, inCellIndex, inDef){
- var self = this;
- var getCellWidth = function(inDef){
- var w = 0;
- if(inDef.colSpan > 1){
- w = 0;
- }else{
- w = inDef.width || self._defaultCellProps.width || self.defaultWidth;
- if(!isNaN(w)){
- w = w + "em";
- }
- }
- return w;
- };
- var props = {
- grid: this.grid,
- subrow: inRowIndex,
- layoutIndex: inCellIndex,
- index: this.cells.length
- };
- if(inDef && inDef instanceof dojox.grid.cells._Base){
- var new_cell = lang.clone(inDef);
- props.unitWidth = getCellWidth(new_cell._props);
- new_cell = lang.mixin(new_cell, this._defaultCellProps, inDef._props, props);
- return new_cell;
- }
- var cell_type = inDef.type || inDef.cellType || this._defaultCellProps.type || this._defaultCellProps.cellType || dojox.grid.cells.Cell;
- if(lang.isString(cell_type)){
- cell_type = lang.getObject(cell_type);
- }
- props.unitWidth = getCellWidth(inDef);
- return new cell_type(lang.mixin({}, this._defaultCellProps, inDef, props));
- },
-
- addRowDef: function(inRowIndex, inDef){
- var result = [];
- var relSum = 0, pctSum = 0, doRel = true;
- for(var i=0, def, cell; (def=inDef[i]); i++){
- cell = this.addCellDef(inRowIndex, i, def);
- result.push(cell);
- this.cells.push(cell);
- // Check and calculate the sum of all relative widths
- if(doRel && cell.relWidth){
- relSum += cell.relWidth;
- }else if(cell.width){
- var w = cell.width;
- if(typeof w == "string" && w.slice(-1) == "%"){
- pctSum += window.parseInt(w, 10);
- }else if(w == "auto"){
- // relative widths doesn't play nice with auto - since we
- // don't have a way of knowing how much space the auto is
- // supposed to take up.
- doRel = false;
- }
- }
- }
- if(relSum && doRel){
- // We have some kind of relWidths specified - so change them to %
- array.forEach(result, function(cell){
- if(cell.relWidth){
- cell.width = cell.unitWidth = ((cell.relWidth / relSum) * (100 - pctSum)) + "%";
- }
- });
- }
- return result;
-
- },
- addRowsDef: function(inDef){
- var result = [];
- if(lang.isArray(inDef)){
- if(lang.isArray(inDef[0])){
- for(var i=0, row; inDef && (row=inDef[i]); i++){
- result.push(this.addRowDef(i, row));
- }
- }else{
- result.push(this.addRowDef(0, inDef));
- }
- }
- return result;
- },
-
- addViewDef: function(inDef){
- this._defaultCellProps = inDef.defaultCell || {};
- if(inDef.width && inDef.width == "auto"){
- delete inDef.width;
- }
- return lang.mixin({}, inDef, {cells: this.addRowsDef(inDef.rows || inDef.cells)});
- },
-
- setStructure: function(inStructure){
- this.fieldIndex = 0;
- this.cells = [];
- var s = this.structure = [];
- if(this.grid.rowSelector){
- var sel = { type: dojox._scopeName + ".grid._RowSelector" };
- if(lang.isString(this.grid.rowSelector)){
- var width = this.grid.rowSelector;
- if(width == "false"){
- sel = null;
- }else if(width != "true"){
- sel['width'] = width;
- }
- }else{
- if(!this.grid.rowSelector){
- sel = null;
- }
- }
- if(sel){
- s.push(this.addViewDef(sel));
- }
- }
- var isCell = function(def){
- return ("name" in def || "field" in def || "get" in def);
- };
- var isRowDef = function(def){
- if(lang.isArray(def)){
- if(lang.isArray(def[0]) || isCell(def[0])){
- return true;
- }
- }
- return false;
- };
- var isView = function(def){
- return (def !== null && lang.isObject(def) &&
- ("cells" in def || "rows" in def || ("type" in def && !isCell(def))));
- };
- if(lang.isArray(inStructure)){
- var hasViews = false;
- for(var i=0, st; (st=inStructure[i]); i++){
- if(isView(st)){
- hasViews = true;
- break;
- }
- }
- if(!hasViews){
- s.push(this.addViewDef({ cells: inStructure }));
- }else{
- for(i=0; (st=inStructure[i]); i++){
- if(isRowDef(st)){
- s.push(this.addViewDef({ cells: st }));
- }else if(isView(st)){
- s.push(this.addViewDef(st));
- }
- }
- }
- }else if(isView(inStructure)){
- // it's a view object
- s.push(this.addViewDef(inStructure));
- }
- this.cellCount = this.cells.length;
- this.grid.setupHeaderMenu();
- }
- });
- });
- },
- 'dijit/layout/_ContentPaneResizeMixin':function(){
- define("dijit/layout/_ContentPaneResizeMixin", [
- "dojo/_base/array", // array.filter array.forEach
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.has
- "dojo/dom-class", // domClass.contains domClass.toggle
- "dojo/dom-geometry",// domGeometry.contentBox domGeometry.marginBox
- "dojo/_base/lang", // lang.mixin
- "dojo/query", // query
- "dojo/_base/sniff", // has("ie")
- "dojo/_base/window", // win.global
- "../registry", // registry.byId
- "./utils", // marginBox2contextBox
- "../_Contained"
- ], function(array, declare, domAttr, domClass, domGeometry, lang, query, has, win,
- registry, layoutUtils, _Contained){
- /*=====
- var _Contained = dijit._Contained;
- =====*/
- // module:
- // dijit/layout/_ContentPaneResizeMixin
- // summary:
- // Resize() functionality of ContentPane. If there's a single layout widget
- // child then it will call resize() with the same dimensions as the ContentPane.
- // Otherwise just calls resize on each child.
- return declare("dijit.layout._ContentPaneResizeMixin", null, {
- // summary:
- // Resize() functionality of ContentPane. If there's a single layout widget
- // child then it will call resize() with the same dimensions as the ContentPane.
- // Otherwise just calls resize on each child.
- //
- // Also implements basic startup() functionality, where starting the parent
- // will start the children
- // doLayout: Boolean
- // - false - don't adjust size of children
- // - true - if there is a single visible child widget, set it's size to
- // however big the ContentPane is
- doLayout: true,
- // isLayoutContainer: [protected] Boolean
- // Indicates that this widget will call resize() on it's child widgets
- // when they become visible.
- isLayoutContainer: true,
- startup: function(){
- // summary:
- // See `dijit.layout._LayoutWidget.startup` for description.
- // Although ContentPane doesn't extend _LayoutWidget, it does implement
- // the same API.
- if(this._started){ return; }
- var parent = this.getParent();
- this._childOfLayoutWidget = parent && parent.isLayoutContainer;
- // I need to call resize() on my child/children (when I become visible), unless
- // I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
- this._needLayout = !this._childOfLayoutWidget;
- this.inherited(arguments);
- if(this._isShown()){
- this._onShow();
- }
- if(!this._childOfLayoutWidget){
- // If my parent isn't a layout container, since my style *may be* width=height=100%
- // or something similar (either set directly or via a CSS class),
- // monitor when my size changes so that I can re-layout.
- // For browsers where I can't directly monitor when my size changes,
- // monitor when the viewport changes size, which *may* indicate a size change for me.
- this.connect(has("ie") ? this.domNode : win.global, 'onresize', function(){
- // Using function(){} closure to ensure no arguments to resize.
- this._needLayout = !this._childOfLayoutWidget;
- this.resize();
- });
- }
- },
- _checkIfSingleChild: function(){
- // summary:
- // Test if we have exactly one visible widget as a child,
- // and if so assume that we are a container for that widget,
- // and should propagate startup() and resize() calls to it.
- // Skips over things like data stores since they aren't visible.
- var childNodes = query("> *", this.containerNode).filter(function(node){
- return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
- }),
- childWidgetNodes = childNodes.filter(function(node){
- return domAttr.has(node, "data-dojo-type") || domAttr.has(node, "dojoType") || domAttr.has(node, "widgetId");
- }),
- candidateWidgets = array.filter(childWidgetNodes.map(registry.byNode), function(widget){
- return widget && widget.domNode && widget.resize;
- });
- if(
- // all child nodes are widgets
- childNodes.length == childWidgetNodes.length &&
- // all but one are invisible (like dojo.data)
- candidateWidgets.length == 1
- ){
- this._singleChild = candidateWidgets[0];
- }else{
- delete this._singleChild;
- }
- // So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
- domClass.toggle(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild);
- },
- resize: function(changeSize, resultSize){
- // summary:
- // See `dijit.layout._LayoutWidget.resize` for description.
- // Although ContentPane doesn't extend _LayoutWidget, it does implement
- // the same API.
- // For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
- // never called, so resize() is our trigger to do the initial href download (see [20099]).
- // However, don't load href for closed TitlePanes.
- if(!this._wasShown && this.open !== false){
- this._onShow();
- }
- this._resizeCalled = true;
- this._scheduleLayout(changeSize, resultSize);
- },
- _scheduleLayout: function(changeSize, resultSize){
- // summary:
- // Resize myself, and call resize() on each of my child layout widgets, either now
- // (if I'm currently visible) or when I become visible
- if(this._isShown()){
- this._layout(changeSize, resultSize);
- }else{
- this._needLayout = true;
- this._changeSize = changeSize;
- this._resultSize = resultSize;
- }
- },
- _layout: function(changeSize, resultSize){
- // summary:
- // Resize myself according to optional changeSize/resultSize parameters, like a layout widget.
- // Also, since I am a Container widget, each of my children expects me to
- // call resize() or layout() on them.
- //
- // Should be called on initialization and also whenever we get new content
- // (from an href, or from set('content', ...))... but deferred until
- // the ContentPane is visible
- // Set margin box size, unless it wasn't specified, in which case use current size.
- if(changeSize){
- domGeometry.setMarginBox(this.domNode, changeSize);
- }
- // Compute content box size of containerNode in case we [later] need to size our single child.
- var cn = this.containerNode;
- if(cn === this.domNode){
- // If changeSize or resultSize was passed to this method and this.containerNode ==
- // this.domNode then we can compute the content-box size without querying the node,
- // which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
- var mb = resultSize || {};
- lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
- if(!("h" in mb) || !("w" in mb)){
- mb = lang.mixin(domGeometry.getMarginBox(cn), mb); // just use domGeometry.setMarginBox() to fill in missing values
- }
- this._contentBox = layoutUtils.marginBox2contentBox(cn, mb);
- }else{
- this._contentBox = domGeometry.getContentBox(cn);
- }
- this._layoutChildren();
- delete this._needLayout;
- },
- _layoutChildren: function(){
- // Call _checkIfSingleChild() again in case app has manually mucked w/the content
- // of the ContentPane (rather than changing it through the set("content", ...) API.
- if(this.doLayout){
- this._checkIfSingleChild();
- }
- if(this._singleChild && this._singleChild.resize){
- var cb = this._contentBox || domGeometry.getContentBox(this.containerNode);
- // note: if widget has padding this._contentBox will have l and t set,
- // but don't pass them to resize() or it will doubly-offset the child
- this._singleChild.resize({w: cb.w, h: cb.h});
- }else{
- // All my child widgets are independently sized (rather than matching my size),
- // but I still need to call resize() on each child to make it layout.
- array.forEach(this.getChildren(), function(widget){
- if(widget.resize){
- widget.resize();
- }
- });
- }
- },
- _isShown: function(){
- // summary:
- // Returns true if the content is currently shown.
- // description:
- // If I am a child of a layout widget then it actually returns true if I've ever been visible,
- // not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
- // tree every call, and at least solves the performance problem on page load by deferring loading
- // hidden ContentPanes until they are first shown
- if(this._childOfLayoutWidget){
- // If we are TitlePane, etc - we return that only *IF* we've been resized
- if(this._resizeCalled && "open" in this){
- return this.open;
- }
- return this._resizeCalled;
- }else if("open" in this){
- return this.open; // for TitlePane, etc.
- }else{
- var node = this.domNode, parent = this.domNode.parentNode;
- return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !domClass.contains(node, "dijitHidden") &&
- parent && parent.style && (parent.style.display != 'none');
- }
- },
- _onShow: function(){
- // summary:
- // Called when the ContentPane is made visible
- // description:
- // For a plain ContentPane, this is called on initialization, from startup().
- // If the ContentPane is a hidden pane of a TabContainer etc., then it's
- // called whenever the pane is made visible.
- //
- // Does layout/resize of child widget(s)
- if(this._needLayout){
- // If a layout has been scheduled for when we become visible, do it now
- this._layout(this._changeSize, this._resultSize);
- }
- this.inherited(arguments);
- // Need to keep track of whether ContentPane has been shown (which is different than
- // whether or not it's currently visible).
- this._wasShown = true;
- }
- });
- });
- },
- 'dijit/form/RangeBoundTextBox':function(){
- define("dijit/form/RangeBoundTextBox", [
- "dojo/_base/declare", // declare
- "dojo/i18n", // i18n.getLocalization
- "./MappedTextBox"
- ], function(declare, i18n, MappedTextBox){
- /*=====
- var MappedTextBox = dijit.form.MappedTextBox;
- =====*/
- // module:
- // dijit/form/RangeBoundTextBox
- // summary:
- // Base class for textbox form widgets which defines a range of valid values.
- /*=====
- dijit.form.RangeBoundTextBox.__Constraints = function(){
- // min: Number
- // Minimum signed value. Default is -Infinity
- // max: Number
- // Maximum signed value. Default is +Infinity
- this.min = min;
- this.max = max;
- }
- =====*/
- return declare("dijit.form.RangeBoundTextBox", MappedTextBox, {
- // summary:
- // Base class for textbox form widgets which defines a range of valid values.
- // rangeMessage: String
- // The message to display if value is out-of-range
- rangeMessage: "",
- /*=====
- // constraints: dijit.form.RangeBoundTextBox.__Constraints
- constraints: {},
- ======*/
- rangeCheck: function(/*Number*/ primitive, /*dijit.form.RangeBoundTextBox.__Constraints*/ constraints){
- // summary:
- // Overridable function used to validate the range of the numeric input value.
- // tags:
- // protected
- return ("min" in constraints? (this.compare(primitive,constraints.min) >= 0) : true) &&
- ("max" in constraints? (this.compare(primitive,constraints.max) <= 0) : true); // Boolean
- },
- isInRange: function(/*Boolean*/ /*===== isFocused =====*/){
- // summary:
- // Tests if the value is in the min/max range specified in constraints
- // tags:
- // protected
- return this.rangeCheck(this.get('value'), this.constraints);
- },
- _isDefinitelyOutOfRange: function(){
- // summary:
- // Returns true if the value is out of range and will remain
- // out of range even if the user types more characters
- var val = this.get('value');
- var isTooLittle = false;
- var isTooMuch = false;
- if("min" in this.constraints){
- var min = this.constraints.min;
- min = this.compare(val, ((typeof min == "number") && min >= 0 && val !=0) ? 0 : min);
- isTooLittle = (typeof min == "number") && min < 0;
- }
- if("max" in this.constraints){
- var max = this.constraints.max;
- max = this.compare(val, ((typeof max != "number") || max > 0) ? max : 0);
- isTooMuch = (typeof max == "number") && max > 0;
- }
- return isTooLittle || isTooMuch;
- },
- _isValidSubset: function(){
- // summary:
- // Overrides `dijit.form.ValidationTextBox._isValidSubset`.
- // Returns true if the input is syntactically valid, and either within
- // range or could be made in range by more typing.
- return this.inherited(arguments) && !this._isDefinitelyOutOfRange();
- },
- isValid: function(/*Boolean*/ isFocused){
- // Overrides dijit.form.ValidationTextBox.isValid to check that the value is also in range.
- return this.inherited(arguments) &&
- ((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused)); // Boolean
- },
- getErrorMessage: function(/*Boolean*/ isFocused){
- // Overrides dijit.form.ValidationTextBox.getErrorMessage to print "out of range" message if appropriate
- var v = this.get('value');
- if(v !== null && v !== '' && v !== undefined && (typeof v != "number" || !isNaN(v)) && !this.isInRange(isFocused)){ // don't check isInRange w/o a real value
- return this.rangeMessage; // String
- }
- return this.inherited(arguments);
- },
- postMixInProperties: function(){
- this.inherited(arguments);
- if(!this.rangeMessage){
- this.messages = i18n.getLocalization("dijit.form", "validate", this.lang);
- this.rangeMessage = this.messages.rangeMessage;
- }
- },
- _setConstraintsAttr: function(/*Object*/ constraints){
- this.inherited(arguments);
- if(this.focusNode){ // not set when called from postMixInProperties
- if(this.constraints.min !== undefined){
- this.focusNode.setAttribute("aria-valuemin", this.constraints.min);
- }else{
- this.focusNode.removeAttribute("aria-valuemin");
- }
- if(this.constraints.max !== undefined){
- this.focusNode.setAttribute("aria-valuemax", this.constraints.max);
- }else{
- this.focusNode.removeAttribute("aria-valuemax");
- }
- }
- },
- _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
- // summary:
- // Hook so set('value', ...) works.
- this.focusNode.setAttribute("aria-valuenow", value);
- this.inherited(arguments);
- },
- applyTextDir: function(/*===== element, text =====*/){
- // summary:
- // The function overridden in the _BidiSupport module,
- // originally used for setting element.dir according to this.textDir.
- // In this case does nothing.
- // element: Object
- // text: String
- // tags:
- // protected.
- }
- });
- });
- },
- 'dijit/_editor/RichText':function(){
- define("dijit/_editor/RichText", [
- "dojo/_base/array", // array.forEach array.indexOf array.some
- "dojo/_base/config", // config
- "dojo/_base/declare", // declare
- "dojo/_base/Deferred", // Deferred
- "dojo/dom", // dom.byId
- "dojo/dom-attr", // domAttr.set or get
- "dojo/dom-class", // domClass.add domClass.remove
- "dojo/dom-construct", // domConstruct.create domConstruct.destroy domConstruct.place
- "dojo/dom-geometry", // domGeometry.getMarginBox domGeometry.position
- "dojo/dom-style", // domStyle.getComputedStyle domStyle.set
- "dojo/_base/event", // event.stop
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/keys", // keys.BACKSPACE keys.TAB
- "dojo/_base/lang", // lang.clone lang.hitch lang.isArray lang.isFunction lang.isString lang.trim
- "dojo/on", // on()
- "dojo/query", // query
- "dojo/ready", // ready
- "dojo/_base/sniff", // has("ie") has("mozilla") has("opera") has("safari") has("webkit")
- "dojo/topic", // topic.publish() (publish)
- "dojo/_base/unload", // unload
- "dojo/_base/url", // url
- "dojo/_base/window", // win.body win.doc.body.focus win.doc.createElement win.global.location win.withGlobal
- "../_Widget",
- "../_CssStateMixin",
- "./selection",
- "./range",
- "./html",
- "../focus",
- ".." // dijit._scopeName
- ], function(array, config, declare, Deferred, dom, domAttr, domClass, domConstruct, domGeometry, domStyle,
- event, kernel, keys, lang, on, query, ready, has, topic, unload, _Url, win,
- _Widget, _CssStateMixin, selectionapi, rangeapi, htmlapi, focus, dijit){
- /*=====
- var _Widget = dijit._Widget;
- var _CssStateMixin = dijit._CssStateMixin;
- =====*/
- // module:
- // dijit/_editor/RichText
- // summary:
- // dijit._editor.RichText is the core of dijit.Editor, which provides basic
- // WYSIWYG editing features.
- // if you want to allow for rich text saving with back/forward actions, you must add a text area to your page with
- // the id==dijit._scopeName + "._editor.RichText.value" (typically "dijit._editor.RichText.value). For example,
- // something like this will work:
- //
- // <textarea id="dijit._editor.RichText.value" style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>
- //
- var RichText = declare("dijit._editor.RichText", [_Widget, _CssStateMixin], {
- // summary:
- // dijit._editor.RichText is the core of dijit.Editor, which provides basic
- // WYSIWYG editing features.
- //
- // description:
- // dijit._editor.RichText is the core of dijit.Editor, which provides basic
- // WYSIWYG editing features. It also encapsulates the differences
- // of different js engines for various browsers. Do not use this widget
- // with an HTML <TEXTAREA> tag, since the browser unescapes XML escape characters,
- // like <. This can have unexpected behavior and lead to security issues
- // such as scripting attacks.
- //
- // tags:
- // private
- constructor: function(params){
- // contentPreFilters: Function(String)[]
- // Pre content filter function register array.
- // these filters will be executed before the actual
- // editing area gets the html content.
- this.contentPreFilters = [];
- // contentPostFilters: Function(String)[]
- // post content filter function register array.
- // These will be used on the resulting html
- // from contentDomPostFilters. The resulting
- // content is the final html (returned by getValue()).
- this.contentPostFilters = [];
- // contentDomPreFilters: Function(DomNode)[]
- // Pre content dom filter function register array.
- // These filters are applied after the result from
- // contentPreFilters are set to the editing area.
- this.contentDomPreFilters = [];
- // contentDomPostFilters: Function(DomNode)[]
- // Post content dom filter function register array.
- // These filters are executed on the editing area dom.
- // The result from these will be passed to contentPostFilters.
- this.contentDomPostFilters = [];
- // editingAreaStyleSheets: dojo._URL[]
- // array to store all the stylesheets applied to the editing area
- this.editingAreaStyleSheets = [];
- // Make a copy of this.events before we start writing into it, otherwise we
- // will modify the prototype which leads to bad things on pages w/multiple editors
- this.events = [].concat(this.events);
- this._keyHandlers = {};
- if(params && lang.isString(params.value)){
- this.value = params.value;
- }
- this.onLoadDeferred = new Deferred();
- },
- baseClass: "dijitEditor",
- // inheritWidth: Boolean
- // whether to inherit the parent's width or simply use 100%
- inheritWidth: false,
- // focusOnLoad: [deprecated] Boolean
- // Focus into this widget when the page is loaded
- focusOnLoad: false,
- // name: String?
- // Specifies the name of a (hidden) <textarea> node on the page that's used to save
- // the editor content on page leave. Used to restore editor contents after navigating
- // to a new page and then hitting the back button.
- name: "",
- // styleSheets: [const] String
- // semicolon (";") separated list of css files for the editing area
- styleSheets: "",
- // height: String
- // Set height to fix the editor at a specific height, with scrolling.
- // By default, this is 300px. If you want to have the editor always
- // resizes to accommodate the content, use AlwaysShowToolbar plugin
- // and set height="". If this editor is used within a layout widget,
- // set height="100%".
- height: "300px",
- // minHeight: String
- // The minimum height that the editor should have.
- minHeight: "1em",
- // isClosed: [private] Boolean
- isClosed: true,
- // isLoaded: [private] Boolean
- isLoaded: false,
- // _SEPARATOR: [private] String
- // Used to concat contents from multiple editors into a single string,
- // so they can be saved into a single <textarea> node. See "name" attribute.
- _SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@",
- // _NAME_CONTENT_SEP: [private] String
- // USed to separate name from content. Just a colon isn't safe.
- _NAME_CONTENT_SEP: "@@**%%:%%**@@",
- // onLoadDeferred: [readonly] dojo.Deferred
- // Deferred which is fired when the editor finishes loading.
- // Call myEditor.onLoadDeferred.then(callback) it to be informed
- // when the rich-text area initialization is finalized.
- onLoadDeferred: null,
- // isTabIndent: Boolean
- // Make tab key and shift-tab indent and outdent rather than navigating.
- // Caution: sing this makes web pages inaccessible to users unable to use a mouse.
- isTabIndent: false,
- // disableSpellCheck: [const] Boolean
- // When true, disables the browser's native spell checking, if supported.
- // Works only in Firefox.
- disableSpellCheck: false,
- postCreate: function(){
- if("textarea" === this.domNode.tagName.toLowerCase()){
- console.warn("RichText should not be used with the TEXTAREA tag. See dijit._editor.RichText docs.");
- }
- // Push in the builtin filters now, making them the first executed, but not over-riding anything
- // users passed in. See: #6062
- this.contentPreFilters = [lang.hitch(this, "_preFixUrlAttributes")].concat(this.contentPreFilters);
- if(has("mozilla")){
- this.contentPreFilters = [this._normalizeFontStyle].concat(this.contentPreFilters);
- this.contentPostFilters = [this._removeMozBogus].concat(this.contentPostFilters);
- }
- if(has("webkit")){
- // Try to clean up WebKit bogus artifacts. The inserted classes
- // made by WebKit sometimes messes things up.
- this.contentPreFilters = [this._removeWebkitBogus].concat(this.contentPreFilters);
- this.contentPostFilters = [this._removeWebkitBogus].concat(this.contentPostFilters);
- }
- if(has("ie")){
- // IE generates <strong> and <em> but we want to normalize to <b> and <i>
- this.contentPostFilters = [this._normalizeFontStyle].concat(this.contentPostFilters);
- this.contentDomPostFilters = [lang.hitch(this, this._stripBreakerNodes)].concat(this.contentDomPostFilters);
- }
- this.inherited(arguments);
- topic.publish(dijit._scopeName + "._editor.RichText::init", this);
- this.open();
- this.setupDefaultShortcuts();
- },
- setupDefaultShortcuts: function(){
- // summary:
- // Add some default key handlers
- // description:
- // Overwrite this to setup your own handlers. The default
- // implementation does not use Editor commands, but directly
- // executes the builtin commands within the underlying browser
- // support.
- // tags:
- // protected
- var exec = lang.hitch(this, function(cmd, arg){
- return function(){
- return !this.execCommand(cmd,arg);
- };
- });
- var ctrlKeyHandlers = {
- b: exec("bold"),
- i: exec("italic"),
- u: exec("underline"),
- a: exec("selectall"),
- s: function(){ this.save(true); },
- m: function(){ this.isTabIndent = !this.isTabIndent; },
- "1": exec("formatblock", "h1"),
- "2": exec("formatblock", "h2"),
- "3": exec("formatblock", "h3"),
- "4": exec("formatblock", "h4"),
- "\\": exec("insertunorderedlist")
- };
- if(!has("ie")){
- ctrlKeyHandlers.Z = exec("redo"); //FIXME: undo?
- }
- var key;
- for(key in ctrlKeyHandlers){
- this.addKeyHandler(key, true, false, ctrlKeyHandlers[key]);
- }
- },
- // events: [private] String[]
- // events which should be connected to the underlying editing area
- events: ["onKeyPress", "onKeyDown", "onKeyUp"], // onClick handled specially
- // captureEvents: [deprecated] String[]
- // Events which should be connected to the underlying editing
- // area, events in this array will be addListener with
- // capture=true.
- // TODO: looking at the code I don't see any distinction between events and captureEvents,
- // so get rid of this for 2.0 if not sooner
- captureEvents: [],
- _editorCommandsLocalized: false,
- _localizeEditorCommands: function(){
- // summary:
- // When IE is running in a non-English locale, the API actually changes,
- // so that we have to say (for example) danraku instead of p (for paragraph).
- // Handle that here.
- // tags:
- // private
- if(RichText._editorCommandsLocalized){
- // Use the already generate cache of mappings.
- this._local2NativeFormatNames = RichText._local2NativeFormatNames;
- this._native2LocalFormatNames = RichText._native2LocalFormatNames;
- return;
- }
- RichText._editorCommandsLocalized = true;
- RichText._local2NativeFormatNames = {};
- RichText._native2LocalFormatNames = {};
- this._local2NativeFormatNames = RichText._local2NativeFormatNames;
- this._native2LocalFormatNames = RichText._native2LocalFormatNames;
- //in IE, names for blockformat is locale dependent, so we cache the values here
- //put p after div, so if IE returns Normal, we show it as paragraph
- //We can distinguish p and div if IE returns Normal, however, in order to detect that,
- //we have to call this.document.selection.createRange().parentElement() or such, which
- //could slow things down. Leave it as it is for now
- var formats = ['div', 'p', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'address'];
- var localhtml = "", format, i=0;
- while((format=formats[i++])){
- //append a <br> after each element to separate the elements more reliably
- if(format.charAt(1) !== 'l'){
- localhtml += "<"+format+"><span>content</span></"+format+"><br/>";
- }else{
- localhtml += "<"+format+"><li>content</li></"+format+"><br/>";
- }
- }
- // queryCommandValue returns empty if we hide editNode, so move it out of screen temporary
- // Also, IE9 does weird stuff unless we do it inside the editor iframe.
- var style = { position: "absolute", top: "0px", zIndex: 10, opacity: 0.01 };
- var div = domConstruct.create('div', {style: style, innerHTML: localhtml});
- win.body().appendChild(div);
- // IE9 has a timing issue with doing this right after setting
- // the inner HTML, so put a delay in.
- var inject = lang.hitch(this, function(){
- var node = div.firstChild;
- while(node){
- try{
- selectionapi.selectElement(node.firstChild);
- var nativename = node.tagName.toLowerCase();
- this._local2NativeFormatNames[nativename] = document.queryCommandValue("formatblock");
- this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename;
- node = node.nextSibling.nextSibling;
- //console.log("Mapped: ", nativename, " to: ", this._local2NativeFormatNames[nativename]);
- }catch(e){ /*Sqelch the occasional IE9 error */ }
- }
- div.parentNode.removeChild(div);
- div.innerHTML = "";
- });
- setTimeout(inject, 0);
- },
- open: function(/*DomNode?*/ element){
- // summary:
- // Transforms the node referenced in this.domNode into a rich text editing
- // node.
- // description:
- // Sets up the editing area asynchronously. This will result in
- // the creation and replacement with an iframe.
- // tags:
- // private
- if(!this.onLoadDeferred || this.onLoadDeferred.fired >= 0){
- this.onLoadDeferred = new Deferred();
- }
- if(!this.isClosed){ this.close(); }
- topic.publish(dijit._scopeName + "._editor.RichText::open", this);
- if(arguments.length === 1 && element.nodeName){ // else unchanged
- this.domNode = element;
- }
- var dn = this.domNode;
- // "html" will hold the innerHTML of the srcNodeRef and will be used to
- // initialize the editor.
- var html;
- if(lang.isString(this.value)){
- // Allow setting the editor content programmatically instead of
- // relying on the initial content being contained within the target
- // domNode.
- html = this.value;
- delete this.value;
- dn.innerHTML = "";
- }else if(dn.nodeName && dn.nodeName.toLowerCase() == "textarea"){
- // if we were created from a textarea, then we need to create a
- // new editing harness node.
- var ta = (this.textarea = dn);
- this.name = ta.name;
- html = ta.value;
- dn = this.domNode = win.doc.createElement("div");
- dn.setAttribute('widgetId', this.id);
- ta.removeAttribute('widgetId');
- dn.cssText = ta.cssText;
- dn.className += " " + ta.className;
- domConstruct.place(dn, ta, "before");
- var tmpFunc = lang.hitch(this, function(){
- //some browsers refuse to submit display=none textarea, so
- //move the textarea off screen instead
- domStyle.set(ta, {
- display: "block",
- position: "absolute",
- top: "-1000px"
- });
- if(has("ie")){ //nasty IE bug: abnormal formatting if overflow is not hidden
- var s = ta.style;
- this.__overflow = s.overflow;
- s.overflow = "hidden";
- }
- });
- if(has("ie")){
- setTimeout(tmpFunc, 10);
- }else{
- tmpFunc();
- }
- if(ta.form){
- var resetValue = ta.value;
- this.reset = function(){
- var current = this.getValue();
- if(current !== resetValue){
- this.replaceValue(resetValue);
- }
- };
- on(ta.form, "submit", lang.hitch(this, function(){
- // Copy value to the <textarea> so it gets submitted along with form.
- // FIXME: should we be calling close() here instead?
- domAttr.set(ta, 'disabled', this.disabled); // don't submit the value if disabled
- ta.value = this.getValue();
- }));
- }
- }else{
- html = htmlapi.getChildrenHtml(dn);
- dn.innerHTML = "";
- }
- this.value = html;
- // If we're a list item we have to put in a blank line to force the
- // bullet to nicely align at the top of text
- if(dn.nodeName && dn.nodeName === "LI"){
- dn.innerHTML = " <br>";
- }
- // Construct the editor div structure.
- this.header = dn.ownerDocument.createElement("div");
- dn.appendChild(this.header);
- this.editingArea = dn.ownerDocument.createElement("div");
- dn.appendChild(this.editingArea);
- this.footer = dn.ownerDocument.createElement("div");
- dn.appendChild(this.footer);
- if(!this.name){
- this.name = this.id + "_AUTOGEN";
- }
- // User has pressed back/forward button so we lost the text in the editor, but it's saved
- // in a hidden <textarea> (which contains the data for all the editors on this page),
- // so get editor value from there
- if(this.name !== "" && (!config["useXDomain"] || config["allowXdRichTextSave"])){
- var saveTextarea = dom.byId(dijit._scopeName + "._editor.RichText.value");
- if(saveTextarea && saveTextarea.value !== ""){
- var datas = saveTextarea.value.split(this._SEPARATOR), i=0, dat;
- while((dat=datas[i++])){
- var data = dat.split(this._NAME_CONTENT_SEP);
- if(data[0] === this.name){
- html = data[1];
- datas = datas.splice(i, 1);
- saveTextarea.value = datas.join(this._SEPARATOR);
- break;
- }
- }
- }
- if(!RichText._globalSaveHandler){
- RichText._globalSaveHandler = {};
- unload.addOnUnload(function(){
- var id;
- for(id in RichText._globalSaveHandler){
- var f = RichText._globalSaveHandler[id];
- if(lang.isFunction(f)){
- f();
- }
- }
- });
- }
- RichText._globalSaveHandler[this.id] = lang.hitch(this, "_saveContent");
- }
- this.isClosed = false;
- var ifr = (this.editorObject = this.iframe = win.doc.createElement('iframe'));
- ifr.id = this.id+"_iframe";
- this._iframeSrc = this._getIframeDocTxt();
- ifr.style.border = "none";
- ifr.style.width = "100%";
- if(this._layoutMode){
- // iframe should be 100% height, thus getting it's height from surrounding
- // <div> (which has the correct height set by Editor)
- ifr.style.height = "100%";
- }else{
- if(has("ie") >= 7){
- if(this.height){
- ifr.style.height = this.height;
- }
- if(this.minHeight){
- ifr.style.minHeight = this.minHeight;
- }
- }else{
- ifr.style.height = this.height ? this.height : this.minHeight;
- }
- }
- ifr.frameBorder = 0;
- ifr._loadFunc = lang.hitch( this, function(w){
- this.window = w;
- this.document = this.window.document;
- if(has("ie")){
- this._localizeEditorCommands();
- }
- // Do final setup and set initial contents of editor
- this.onLoad(html);
- });
- // Set the iframe's initial (blank) content.
- var iframeSrcRef = 'parent.' + dijit._scopeName + '.byId("'+this.id+'")._iframeSrc';
- var s = 'javascript:(function(){try{return ' + iframeSrcRef + '}catch(e){document.open();document.domain="' +
- document.domain + '";document.write(' + iframeSrcRef + ');document.close();}})()';
- ifr.setAttribute('src', s);
- this.editingArea.appendChild(ifr);
- if(has("safari") <= 4){
- var src = ifr.getAttribute("src");
- if(!src || src.indexOf("javascript") === -1){
- // Safari 4 and earlier sometimes act oddly
- // So we have to set it again.
- setTimeout(function(){ifr.setAttribute('src', s);},0);
- }
- }
- // TODO: this is a guess at the default line-height, kinda works
- if(dn.nodeName === "LI"){
- dn.lastChild.style.marginTop = "-1.2em";
- }
- domClass.add(this.domNode, this.baseClass);
- },
- //static cache variables shared among all instance of this class
- _local2NativeFormatNames: {},
- _native2LocalFormatNames: {},
- _getIframeDocTxt: function(){
- // summary:
- // Generates the boilerplate text of the document inside the iframe (ie, <html><head>...</head><body/></html>).
- // Editor content (if not blank) should be added afterwards.
- // tags:
- // private
- var _cs = domStyle.getComputedStyle(this.domNode);
- // The contents inside of <body>. The real contents are set later via a call to setValue().
- var html = "";
- var setBodyId = true;
- if(has("ie") || has("webkit") || (!this.height && !has("mozilla"))){
- // In auto-expand mode, need a wrapper div for AlwaysShowToolbar plugin to correctly
- // expand/contract the editor as the content changes.
- html = "<div id='dijitEditorBody'></div>";
- setBodyId = false;
- }else if(has("mozilla")){
- // workaround bug where can't select then delete text (until user types something
- // into the editor)... and/or issue where typing doesn't erase selected text
- this._cursorToStart = true;
- html = " "; //
- }
- var font = [ _cs.fontWeight, _cs.fontSize, _cs.fontFamily ].join(" ");
- // line height is tricky - applying a units value will mess things up.
- // if we can't get a non-units value, bail out.
- var lineHeight = _cs.lineHeight;
- if(lineHeight.indexOf("px") >= 0){
- lineHeight = parseFloat(lineHeight)/parseFloat(_cs.fontSize);
- // console.debug(lineHeight);
- }else if(lineHeight.indexOf("em")>=0){
- lineHeight = parseFloat(lineHeight);
- }else{
- // If we can't get a non-units value, just default
- // it to the CSS spec default of 'normal'. Seems to
- // work better, esp on IE, than '1.0'
- lineHeight = "normal";
- }
- var userStyle = "";
- var self = this;
- this.style.replace(/(^|;)\s*(line-|font-?)[^;]+/ig, function(match){
- match = match.replace(/^;/ig,"") + ';';
- var s = match.split(":")[0];
- if(s){
- s = lang.trim(s);
- s = s.toLowerCase();
- var i;
- var sC = "";
- for(i = 0; i < s.length; i++){
- var c = s.charAt(i);
- switch(c){
- case "-":
- i++;
- c = s.charAt(i).toUpperCase();
- default:
- sC += c;
- }
- }
- domStyle.set(self.domNode, sC, "");
- }
- userStyle += match + ';';
- });
- // need to find any associated label element and update iframe document title
- var label=query('label[for="'+this.id+'"]');
- return [
- this.isLeftToRight() ? "<html>\n<head>\n" : "<html dir='rtl'>\n<head>\n",
- (has("mozilla") && label.length ? "<title>" + label[0].innerHTML + "</title>\n" : ""),
- "<meta http-equiv='Content-Type' content='text/html'>\n",
- "<style>\n",
- "\tbody,html {\n",
- "\t\tbackground:transparent;\n",
- "\t\tpadding: 1px 0 0 0;\n",
- "\t\tmargin: -1px 0 0 0;\n", // remove extraneous vertical scrollbar on safari and firefox
- // Set the html/body sizing. Webkit always needs this, other browsers
- // only set it when height is defined (not auto-expanding), otherwise
- // scrollers do not appear.
- ((has("webkit"))?"\t\twidth: 100%;\n":""),
- ((has("webkit"))?"\t\theight: 100%;\n":""),
- "\t}\n",
- // TODO: left positioning will cause contents to disappear out of view
- // if it gets too wide for the visible area
- "\tbody{\n",
- "\t\ttop:0px;\n",
- "\t\tleft:0px;\n",
- "\t\tright:0px;\n",
- "\t\tfont:", font, ";\n",
- ((this.height||has("opera")) ? "" : "\t\tposition: fixed;\n"),
- // FIXME: IE 6 won't understand min-height?
- "\t\tmin-height:", this.minHeight, ";\n",
- "\t\tline-height:", lineHeight,";\n",
- "\t}\n",
- "\tp{ margin: 1em 0; }\n",
- // Determine how scrollers should be applied. In autoexpand mode (height = "") no scrollers on y at all.
- // But in fixed height mode we want both x/y scrollers. Also, if it's using wrapping div and in auto-expand
- // (Mainly IE) we need to kill the y scroller on body and html.
- (!setBodyId && !this.height ? "\tbody,html {overflow-y: hidden;}\n" : ""),
- "\t#dijitEditorBody{overflow-x: auto; overflow-y:" + (this.height ? "auto;" : "hidden;") + " outline: 0px;}\n",
- "\tli > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; }\n",
- // Can't set min-height in IE9, it puts layout on li, which puts move/resize handles.
- (!has("ie") ? "\tli{ min-height:1.2em; }\n" : ""),
- "</style>\n",
- this._applyEditingAreaStyleSheets(),"\n",
- "</head>\n<body ",
- (setBodyId?"id='dijitEditorBody' ":""),
- "onload='frameElement._loadFunc(window,document)' style='"+userStyle+"'>", html, "</body>\n</html>"
- ].join(""); // String
- },
- _applyEditingAreaStyleSheets: function(){
- // summary:
- // apply the specified css files in styleSheets
- // tags:
- // private
- var files = [];
- if(this.styleSheets){
- files = this.styleSheets.split(';');
- this.styleSheets = '';
- }
- //empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheet
- files = files.concat(this.editingAreaStyleSheets);
- this.editingAreaStyleSheets = [];
- var text='', i=0, url;
- while((url=files[i++])){
- var abstring = (new _Url(win.global.location, url)).toString();
- this.editingAreaStyleSheets.push(abstring);
- text += '<link rel="stylesheet" type="text/css" href="'+abstring+'"/>';
- }
- return text;
- },
- addStyleSheet: function(/*dojo._Url*/ uri){
- // summary:
- // add an external stylesheet for the editing area
- // uri:
- // A dojo.uri.Uri pointing to the url of the external css file
- var url=uri.toString();
- //if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe
- if(url.charAt(0) === '.' || (url.charAt(0) !== '/' && !uri.host)){
- url = (new _Url(win.global.location, url)).toString();
- }
- if(array.indexOf(this.editingAreaStyleSheets, url) > -1){
- // console.debug("dijit._editor.RichText.addStyleSheet: Style sheet "+url+" is already applied");
- return;
- }
- this.editingAreaStyleSheets.push(url);
- this.onLoadDeferred.addCallback(lang.hitch(this, function(){
- if(this.document.createStyleSheet){ //IE
- this.document.createStyleSheet(url);
- }else{ //other browser
- var head = this.document.getElementsByTagName("head")[0];
- var stylesheet = this.document.createElement("link");
- stylesheet.rel="stylesheet";
- stylesheet.type="text/css";
- stylesheet.href=url;
- head.appendChild(stylesheet);
- }
- }));
- },
- removeStyleSheet: function(/*dojo._Url*/ uri){
- // summary:
- // remove an external stylesheet for the editing area
- var url=uri.toString();
- //if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe
- if(url.charAt(0) === '.' || (url.charAt(0) !== '/' && !uri.host)){
- url = (new _Url(win.global.location, url)).toString();
- }
- var index = array.indexOf(this.editingAreaStyleSheets, url);
- if(index === -1){
- // console.debug("dijit._editor.RichText.removeStyleSheet: Style sheet "+url+" has not been applied");
- return;
- }
- delete this.editingAreaStyleSheets[index];
- win.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan();
- },
- // disabled: Boolean
- // The editor is disabled; the text cannot be changed.
- disabled: false,
- _mozSettingProps: {'styleWithCSS':false},
- _setDisabledAttr: function(/*Boolean*/ value){
- value = !!value;
- this._set("disabled", value);
- if(!this.isLoaded){ return; } // this method requires init to be complete
- if(has("ie") || has("webkit") || has("opera")){
- var preventIEfocus = has("ie") && (this.isLoaded || !this.focusOnLoad);
- if(preventIEfocus){ this.editNode.unselectable = "on"; }
- this.editNode.contentEditable = !value;
- if(preventIEfocus){
- var _this = this;
- setTimeout(function(){
- if(_this.editNode){ // guard in case widget destroyed before timeout
- _this.editNode.unselectable = "off";
- }
- }, 0);
- }
- }else{ //moz
- try{
- this.document.designMode=(value?'off':'on');
- }catch(e){ return; } // ! _disabledOK
- if(!value && this._mozSettingProps){
- var ps = this._mozSettingProps;
- var n;
- for(n in ps){
- if(ps.hasOwnProperty(n)){
- try{
- this.document.execCommand(n,false,ps[n]);
- }catch(e2){}
- }
- }
- }
- // this.document.execCommand('contentReadOnly', false, value);
- // if(value){
- // this.blur(); //to remove the blinking caret
- // }
- }
- this._disabledOK = true;
- },
- /* Event handlers
- *****************/
- onLoad: function(/*String*/ html){
- // summary:
- // Handler after the iframe finishes loading.
- // html: String
- // Editor contents should be set to this value
- // tags:
- // protected
- // TODO: rename this to _onLoad, make empty public onLoad() method, deprecate/make protected onLoadDeferred handler?
- if(!this.window.__registeredWindow){
- this.window.__registeredWindow = true;
- this._iframeRegHandle = focus.registerIframe(this.iframe);
- }
- if(!has("ie") && !has("webkit") && (this.height || has("mozilla"))){
- this.editNode=this.document.body;
- }else{
- // there's a wrapper div around the content, see _getIframeDocTxt().
- this.editNode=this.document.body.firstChild;
- var _this = this;
- if(has("ie")){ // #4996 IE wants to focus the BODY tag
- this.tabStop = domConstruct.create('div', { tabIndex: -1 }, this.editingArea);
- this.iframe.onfocus = function(){ _this.editNode.setActive(); };
- }
- }
- this.focusNode = this.editNode; // for InlineEditBox
- var events = this.events.concat(this.captureEvents);
- var ap = this.iframe ? this.document : this.editNode;
- array.forEach(events, function(item){
- this.connect(ap, item.toLowerCase(), item);
- }, this);
- this.connect(ap, "onmouseup", "onClick"); // mouseup in the margin does not generate an onclick event
- if(has("ie")){ // IE contentEditable
- this.connect(this.document, "onmousedown", "_onIEMouseDown"); // #4996 fix focus
- // give the node Layout on IE
- // TODO: this may no longer be needed, since we've reverted IE to using an iframe,
- // not contentEditable. Removing it would also probably remove the need for creating
- // the extra <div> in _getIframeDocTxt()
- this.editNode.style.zoom = 1.0;
- }else{
- this.connect(this.document, "onmousedown", function(){
- // Clear the moveToStart focus, as mouse
- // down will set cursor point. Required to properly
- // work with selection/position driven plugins and clicks in
- // the window. refs: #10678
- delete this._cursorToStart;
- });
- }
- if(has("webkit")){
- //WebKit sometimes doesn't fire right on selections, so the toolbar
- //doesn't update right. Therefore, help it out a bit with an additional
- //listener. A mouse up will typically indicate a display change, so fire this
- //and get the toolbar to adapt. Reference: #9532
- this._webkitListener = this.connect(this.document, "onmouseup", "onDisplayChanged");
- this.connect(this.document, "onmousedown", function(e){
- var t = e.target;
- if(t && (t === this.document.body || t === this.document)){
- // Since WebKit uses the inner DIV, we need to check and set position.
- // See: #12024 as to why the change was made.
- setTimeout(lang.hitch(this, "placeCursorAtEnd"), 0);
- }
- });
- }
- if(has("ie")){
- // Try to make sure 'hidden' elements aren't visible in edit mode (like browsers other than IE
- // do). See #9103
- try{
- this.document.execCommand('RespectVisibilityInDesign', true, null);
- }catch(e){/* squelch */}
- }
- this.isLoaded = true;
- this.set('disabled', this.disabled); // initialize content to editable (or not)
- // Note that setValue() call will only work after isLoaded is set to true (above)
- // Set up a function to allow delaying the setValue until a callback is fired
- // This ensures extensions like dijit.Editor have a way to hold the value set
- // until plugins load (and do things like register filters).
- var setContent = lang.hitch(this, function(){
- this.setValue(html);
- if(this.onLoadDeferred){
- this.onLoadDeferred.callback(true);
- }
- this.onDisplayChanged();
- if(this.focusOnLoad){
- // after the document loads, then set focus after updateInterval expires so that
- // onNormalizedDisplayChanged has run to avoid input caret issues
- ready(lang.hitch(this, function(){ setTimeout(lang.hitch(this, "focus"), this.updateInterval); }));
- }
- // Save off the initial content now
- this.value = this.getValue(true);
- });
- if(this.setValueDeferred){
- this.setValueDeferred.addCallback(setContent);
- }else{
- setContent();
- }
- },
- onKeyDown: function(/* Event */ e){
- // summary:
- // Handler for onkeydown event
- // tags:
- // protected
- // we need this event at the moment to get the events from control keys
- // such as the backspace. It might be possible to add this to Dojo, so that
- // keyPress events can be emulated by the keyDown and keyUp detection.
- if(e.keyCode === keys.TAB && this.isTabIndent ){
- event.stop(e); //prevent tab from moving focus out of editor
- // FIXME: this is a poor-man's indent/outdent. It would be
- // better if it added 4 " " chars in an undoable way.
- // Unfortunately pasteHTML does not prove to be undoable
- if(this.queryCommandEnabled((e.shiftKey ? "outdent" : "indent"))){
- this.execCommand((e.shiftKey ? "outdent" : "indent"));
- }
- }
- if(has("ie")){
- if(e.keyCode == keys.TAB && !this.isTabIndent){
- if(e.shiftKey && !e.ctrlKey && !e.altKey){
- // focus the BODY so the browser will tab away from it instead
- this.iframe.focus();
- }else if(!e.shiftKey && !e.ctrlKey && !e.altKey){
- // focus the BODY so the browser will tab away from it instead
- this.tabStop.focus();
- }
- }else if(e.keyCode === keys.BACKSPACE && this.document.selection.type === "Control"){
- // IE has a bug where if a non-text object is selected in the editor,
- // hitting backspace would act as if the browser's back button was
- // clicked instead of deleting the object. see #1069
- event.stop(e);
- this.execCommand("delete");
- }else if((65 <= e.keyCode && e.keyCode <= 90) ||
- (e.keyCode>=37 && e.keyCode<=40) // FIXME: get this from connect() instead!
- ){ //arrow keys
- e.charCode = e.keyCode;
- this.onKeyPress(e);
- }
- }
- if(has("ff")){
- if(e.keyCode === keys.PAGE_UP || e.keyCode === keys.PAGE_DOWN ){
- if(this.editNode.clientHeight >= this.editNode.scrollHeight){
- // Stop the event to prevent firefox from trapping the cursor when there is no scroll bar.
- e.preventDefault();
- }
- }
- }
- return true;
- },
- onKeyUp: function(/*===== e =====*/){
- // summary:
- // Handler for onkeyup event
- // tags:
- // callback
- },
- setDisabled: function(/*Boolean*/ disabled){
- // summary:
- // Deprecated, use set('disabled', ...) instead.
- // tags:
- // deprecated
- kernel.deprecated('dijit.Editor::setDisabled is deprecated','use dijit.Editor::attr("disabled",boolean) instead', 2.0);
- this.set('disabled',disabled);
- },
- _setValueAttr: function(/*String*/ value){
- // summary:
- // Registers that attr("value", foo) should call setValue(foo)
- this.setValue(value);
- },
- _setDisableSpellCheckAttr: function(/*Boolean*/ disabled){
- if(this.document){
- domAttr.set(this.document.body, "spellcheck", !disabled);
- }else{
- // try again after the editor is finished loading
- this.onLoadDeferred.addCallback(lang.hitch(this, function(){
- domAttr.set(this.document.body, "spellcheck", !disabled);
- }));
- }
- this._set("disableSpellCheck", disabled);
- },
- onKeyPress: function(e){
- // summary:
- // Handle the various key events
- // tags:
- // protected
- var c = (e.keyChar && e.keyChar.toLowerCase()) || e.keyCode,
- handlers = this._keyHandlers[c],
- args = arguments;
-
- if(handlers && !e.altKey){
- array.some(handlers, function(h){
- // treat meta- same as ctrl-, for benefit of mac users
- if(!(h.shift ^ e.shiftKey) && !(h.ctrl ^ (e.ctrlKey||e.metaKey))){
- if(!h.handler.apply(this, args)){
- e.preventDefault();
- }
- return true;
- }
- }, this);
- }
- // function call after the character has been inserted
- if(!this._onKeyHitch){
- this._onKeyHitch = lang.hitch(this, "onKeyPressed");
- }
- setTimeout(this._onKeyHitch, 1);
- return true;
- },
- addKeyHandler: function(/*String*/ key, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Function*/ handler){
- // summary:
- // Add a handler for a keyboard shortcut
- // description:
- // The key argument should be in lowercase if it is a letter character
- // tags:
- // protected
- if(!lang.isArray(this._keyHandlers[key])){
- this._keyHandlers[key] = [];
- }
- //TODO: would be nice to make this a hash instead of an array for quick lookups
- this._keyHandlers[key].push({
- shift: shift || false,
- ctrl: ctrl || false,
- handler: handler
- });
- },
- onKeyPressed: function(){
- // summary:
- // Handler for after the user has pressed a key, and the display has been updated.
- // (Runs on a timer so that it runs after the display is updated)
- // tags:
- // private
- this.onDisplayChanged(/*e*/); // can't pass in e
- },
- onClick: function(/*Event*/ e){
- // summary:
- // Handler for when the user clicks.
- // tags:
- // private
- // console.info('onClick',this._tryDesignModeOn);
- this.onDisplayChanged(e);
- },
- _onIEMouseDown: function(){
- // summary:
- // IE only to prevent 2 clicks to focus
- // tags:
- // protected
- if(!this.focused && !this.disabled){
- this.focus();
- }
- },
- _onBlur: function(e){
- // summary:
- // Called from focus manager when focus has moved away from this editor
- // tags:
- // protected
- // console.info('_onBlur')
- this.inherited(arguments);
- var newValue = this.getValue(true);
- if(newValue !== this.value){
- this.onChange(newValue);
- }
- this._set("value", newValue);
- },
- _onFocus: function(/*Event*/ e){
- // summary:
- // Called from focus manager when focus has moved into this editor
- // tags:
- // protected
- // console.info('_onFocus')
- if(!this.disabled){
- if(!this._disabledOK){
- this.set('disabled', false);
- }
- this.inherited(arguments);
- }
- },
- // TODO: remove in 2.0
- blur: function(){
- // summary:
- // Remove focus from this instance.
- // tags:
- // deprecated
- if(!has("ie") && this.window.document.documentElement && this.window.document.documentElement.focus){
- this.window.document.documentElement.focus();
- }else if(win.doc.body.focus){
- win.doc.body.focus();
- }
- },
- focus: function(){
- // summary:
- // Move focus to this editor
- if(!this.isLoaded){
- this.focusOnLoad = true;
- return;
- }
- if(this._cursorToStart){
- delete this._cursorToStart;
- if(this.editNode.childNodes){
- this.placeCursorAtStart(); // this calls focus() so return
- return;
- }
- }
- if(!has("ie")){
- focus.focus(this.iframe);
- }else if(this.editNode && this.editNode.focus){
- // editNode may be hidden in display:none div, lets just punt in this case
- //this.editNode.focus(); -> causes IE to scroll always (strict and quirks mode) to the top the Iframe
- // if we fire the event manually and let the browser handle the focusing, the latest
- // cursor position is focused like in FF
- this.iframe.fireEvent('onfocus', document.createEventObject()); // createEventObject only in IE
- // }else{
- // TODO: should we throw here?
- // console.debug("Have no idea how to focus into the editor!");
- }
- },
- // _lastUpdate: 0,
- updateInterval: 200,
- _updateTimer: null,
- onDisplayChanged: function(/*Event*/ /*===== e =====*/){
- // summary:
- // This event will be fired every time the display context
- // changes and the result needs to be reflected in the UI.
- // description:
- // If you don't want to have update too often,
- // onNormalizedDisplayChanged should be used instead
- // tags:
- // private
- // var _t=new Date();
- if(this._updateTimer){
- clearTimeout(this._updateTimer);
- }
- if(!this._updateHandler){
- this._updateHandler = lang.hitch(this,"onNormalizedDisplayChanged");
- }
- this._updateTimer = setTimeout(this._updateHandler, this.updateInterval);
- // Technically this should trigger a call to watch("value", ...) registered handlers,
- // but getValue() is too slow to call on every keystroke so we don't.
- },
- onNormalizedDisplayChanged: function(){
- // summary:
- // This event is fired every updateInterval ms or more
- // description:
- // If something needs to happen immediately after a
- // user change, please use onDisplayChanged instead.
- // tags:
- // private
- delete this._updateTimer;
- },
- onChange: function(/*===== newContent =====*/){
- // summary:
- // This is fired if and only if the editor loses focus and
- // the content is changed.
- },
- _normalizeCommand: function(/*String*/ cmd, /*Anything?*/argument){
- // summary:
- // Used as the advice function to map our
- // normalized set of commands to those supported by the target
- // browser.
- // tags:
- // private
- var command = cmd.toLowerCase();
- if(command === "formatblock"){
- if(has("safari") && argument === undefined){ command = "heading"; }
- }else if(command === "hilitecolor" && !has("mozilla")){
- command = "backcolor";
- }
- return command;
- },
- _qcaCache: {},
- queryCommandAvailable: function(/*String*/ command){
- // summary:
- // Tests whether a command is supported by the host. Clients
- // SHOULD check whether a command is supported before attempting
- // to use it, behaviour for unsupported commands is undefined.
- // command:
- // The command to test for
- // tags:
- // private
- // memoizing version. See _queryCommandAvailable for computing version
- var ca = this._qcaCache[command];
- if(ca !== undefined){ return ca; }
- return (this._qcaCache[command] = this._queryCommandAvailable(command));
- },
- _queryCommandAvailable: function(/*String*/ command){
- // summary:
- // See queryCommandAvailable().
- // tags:
- // private
- var ie = 1;
- var mozilla = 1 << 1;
- var webkit = 1 << 2;
- var opera = 1 << 3;
- function isSupportedBy(browsers){
- return {
- ie: Boolean(browsers & ie),
- mozilla: Boolean(browsers & mozilla),
- webkit: Boolean(browsers & webkit),
- opera: Boolean(browsers & opera)
- };
- }
- var supportedBy = null;
- switch(command.toLowerCase()){
- case "bold": case "italic": case "underline":
- case "subscript": case "superscript":
- case "fontname": case "fontsize":
- case "forecolor": case "hilitecolor":
- case "justifycenter": case "justifyfull": case "justifyleft":
- case "justifyright": case "delete": case "selectall": case "toggledir":
- supportedBy = isSupportedBy(mozilla | ie | webkit | opera);
- break;
- case "createlink": case "unlink": case "removeformat":
- case "inserthorizontalrule": case "insertimage":
- case "insertorderedlist": case "insertunorderedlist":
- case "indent": case "outdent": case "formatblock":
- case "inserthtml": case "undo": case "redo": case "strikethrough": case "tabindent":
- supportedBy = isSupportedBy(mozilla | ie | opera | webkit);
- break;
- case "blockdirltr": case "blockdirrtl":
- case "dirltr": case "dirrtl":
- case "inlinedirltr": case "inlinedirrtl":
- supportedBy = isSupportedBy(ie);
- break;
- case "cut": case "copy": case "paste":
- supportedBy = isSupportedBy( ie | mozilla | webkit);
- break;
- case "inserttable":
- supportedBy = isSupportedBy(mozilla | ie);
- break;
- case "insertcell": case "insertcol": case "insertrow":
- case "deletecells": case "deletecols": case "deleterows":
- case "mergecells": case "splitcell":
- supportedBy = isSupportedBy(ie | mozilla);
- break;
- default: return false;
- }
- return (has("ie") && supportedBy.ie) ||
- (has("mozilla") && supportedBy.mozilla) ||
- (has("webkit") && supportedBy.webkit) ||
- (has("opera") && supportedBy.opera); // Boolean return true if the command is supported, false otherwise
- },
- execCommand: function(/*String*/ command, argument){
- // summary:
- // Executes a command in the Rich Text area
- // command:
- // The command to execute
- // argument:
- // An optional argument to the command
- // tags:
- // protected
- var returnValue;
- //focus() is required for IE to work
- //In addition, focus() makes sure after the execution of
- //the command, the editor receives the focus as expected
- this.focus();
- command = this._normalizeCommand(command, argument);
-
- if(argument !== undefined){
- if(command === "heading"){
- throw new Error("unimplemented");
- }else if((command === "formatblock") && has("ie")){
- argument = '<'+argument+'>';
- }
- }
- //Check to see if we have any over-rides for commands, they will be functions on this
- //widget of the form _commandImpl. If we don't, fall through to the basic native
- //exec command of the browser.
- var implFunc = "_" + command + "Impl";
- if(this[implFunc]){
- returnValue = this[implFunc](argument);
- }else{
- argument = arguments.length > 1 ? argument : null;
- if(argument || command !== "createlink"){
- returnValue = this.document.execCommand(command, false, argument);
- }
- }
- this.onDisplayChanged();
- return returnValue;
- },
- queryCommandEnabled: function(/*String*/ command){
- // summary:
- // Check whether a command is enabled or not.
- // command:
- // The command to execute
- // tags:
- // protected
- if(this.disabled || !this._disabledOK){ return false; }
- command = this._normalizeCommand(command);
- //Check to see if we have any over-rides for commands, they will be functions on this
- //widget of the form _commandEnabledImpl. If we don't, fall through to the basic native
- //command of the browser.
- var implFunc = "_" + command + "EnabledImpl";
- if(this[implFunc]){
- return this[implFunc](command);
- }else{
- return this._browserQueryCommandEnabled(command);
- }
- },
- queryCommandState: function(command){
- // summary:
- // Check the state of a given command and returns true or false.
- // tags:
- // protected
- if(this.disabled || !this._disabledOK){ return false; }
- command = this._normalizeCommand(command);
- try{
- return this.document.queryCommandState(command);
- }catch(e){
- //Squelch, occurs if editor is hidden on FF 3 (and maybe others.)
- return false;
- }
- },
- queryCommandValue: function(command){
- // summary:
- // Check the value of a given command. This matters most for
- // custom selections and complex values like font value setting.
- // tags:
- // protected
- if(this.disabled || !this._disabledOK){ return false; }
- var r;
- command = this._normalizeCommand(command);
- if(has("ie") && command === "formatblock"){
- r = this._native2LocalFormatNames[this.document.queryCommandValue(command)];
- }else if(has("mozilla") && command === "hilitecolor"){
- var oldValue;
- try{
- oldValue = this.document.queryCommandValue("styleWithCSS");
- }catch(e){
- oldValue = false;
- }
- this.document.execCommand("styleWithCSS", false, true);
- r = this.document.queryCommandValue(command);
- this.document.execCommand("styleWithCSS", false, oldValue);
- }else{
- r = this.document.queryCommandValue(command);
- }
- return r;
- },
- // Misc.
- _sCall: function(name, args){
- // summary:
- // Run the named method of dijit._editor.selection over the
- // current editor instance's window, with the passed args.
- // tags:
- // private
- return win.withGlobal(this.window, name, selectionapi, args);
- },
- // FIXME: this is a TON of code duplication. Why?
- placeCursorAtStart: function(){
- // summary:
- // Place the cursor at the start of the editing area.
- // tags:
- // private
- this.focus();
- //see comments in placeCursorAtEnd
- var isvalid=false;
- if(has("mozilla")){
- // TODO: Is this branch even necessary?
- var first=this.editNode.firstChild;
- while(first){
- if(first.nodeType === 3){
- if(first.nodeValue.replace(/^\s+|\s+$/g, "").length>0){
- isvalid=true;
- this._sCall("selectElement", [ first ]);
- break;
- }
- }else if(first.nodeType === 1){
- isvalid=true;
- var tg = first.tagName ? first.tagName.toLowerCase() : "";
- // Collapse before childless tags.
- if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){
- this._sCall("selectElement", [ first ]);
- }else{
- // Collapse inside tags with children.
- this._sCall("selectElementChildren", [ first ]);
- }
- break;
- }
- first = first.nextSibling;
- }
- }else{
- isvalid=true;
- this._sCall("selectElementChildren", [ this.editNode ]);
- }
- if(isvalid){
- this._sCall("collapse", [ true ]);
- }
- },
- placeCursorAtEnd: function(){
- // summary:
- // Place the cursor at the end of the editing area.
- // tags:
- // private
- this.focus();
- //In mozilla, if last child is not a text node, we have to use
- // selectElementChildren on this.editNode.lastChild otherwise the
- // cursor would be placed at the end of the closing tag of
- //this.editNode.lastChild
- var isvalid=false;
- if(has("mozilla")){
- var last=this.editNode.lastChild;
- while(last){
- if(last.nodeType === 3){
- if(last.nodeValue.replace(/^\s+|\s+$/g, "").length>0){
- isvalid=true;
- this._sCall("selectElement", [ last ]);
- break;
- }
- }else if(last.nodeType === 1){
- isvalid=true;
- if(last.lastChild){
- this._sCall("selectElement", [ last.lastChild ]);
- }else{
- this._sCall("selectElement", [ last ]);
- }
- break;
- }
- last = last.previousSibling;
- }
- }else{
- isvalid=true;
- this._sCall("selectElementChildren", [ this.editNode ]);
- }
- if(isvalid){
- this._sCall("collapse", [ false ]);
- }
- },
- getValue: function(/*Boolean?*/ nonDestructive){
- // summary:
- // Return the current content of the editing area (post filters
- // are applied). Users should call get('value') instead.
- // nonDestructive:
- // defaults to false. Should the post-filtering be run over a copy
- // of the live DOM? Most users should pass "true" here unless they
- // *really* know that none of the installed filters are going to
- // mess up the editing session.
- // tags:
- // private
- if(this.textarea){
- if(this.isClosed || !this.isLoaded){
- return this.textarea.value;
- }
- }
- return this._postFilterContent(null, nonDestructive);
- },
- _getValueAttr: function(){
- // summary:
- // Hook to make attr("value") work
- return this.getValue(true);
- },
- setValue: function(/*String*/ html){
- // summary:
- // This function sets the content. No undo history is preserved.
- // Users should use set('value', ...) instead.
- // tags:
- // deprecated
- // TODO: remove this and getValue() for 2.0, and move code to _setValueAttr()
- if(!this.isLoaded){
- // try again after the editor is finished loading
- this.onLoadDeferred.addCallback(lang.hitch(this, function(){
- this.setValue(html);
- }));
- return;
- }
- this._cursorToStart = true;
- if(this.textarea && (this.isClosed || !this.isLoaded)){
- this.textarea.value=html;
- }else{
- html = this._preFilterContent(html);
- var node = this.isClosed ? this.domNode : this.editNode;
- if(html && has("mozilla") && html.toLowerCase() === "<p></p>"){
- html = "<p> </p>"; //
- }
- // Use to avoid webkit problems where editor is disabled until the user clicks it
- if(!html && has("webkit")){
- html = " "; //
- }
- node.innerHTML = html;
- this._preDomFilterContent(node);
- }
- this.onDisplayChanged();
- this._set("value", this.getValue(true));
- },
- replaceValue: function(/*String*/ html){
- // summary:
- // This function set the content while trying to maintain the undo stack
- // (now only works fine with Moz, this is identical to setValue in all
- // other browsers)
- // tags:
- // protected
- if(this.isClosed){
- this.setValue(html);
- }else if(this.window && this.window.getSelection && !has("mozilla")){ // Safari
- // look ma! it's a totally f'd browser!
- this.setValue(html);
- }else if(this.window && this.window.getSelection){ // Moz
- html = this._preFilterContent(html);
- this.execCommand("selectall");
- if(!html){
- this._cursorToStart = true;
- html = " "; //
- }
- this.execCommand("inserthtml", html);
- this._preDomFilterContent(this.editNode);
- }else if(this.document && this.document.selection){//IE
- //In IE, when the first element is not a text node, say
- //an <a> tag, when replacing the content of the editing
- //area, the <a> tag will be around all the content
- //so for now, use setValue for IE too
- this.setValue(html);
- }
- this._set("value", this.getValue(true));
- },
- _preFilterContent: function(/*String*/ html){
- // summary:
- // Filter the input before setting the content of the editing
- // area. DOM pre-filtering may happen after this
- // string-based filtering takes place but as of 1.2, this is not
- // guaranteed for operations such as the inserthtml command.
- // tags:
- // private
- var ec = html;
- array.forEach(this.contentPreFilters, function(ef){ if(ef){ ec = ef(ec); } });
- return ec;
- },
- _preDomFilterContent: function(/*DomNode*/ dom){
- // summary:
- // filter the input's live DOM. All filter operations should be
- // considered to be "live" and operating on the DOM that the user
- // will be interacting with in their editing session.
- // tags:
- // private
- dom = dom || this.editNode;
- array.forEach(this.contentDomPreFilters, function(ef){
- if(ef && lang.isFunction(ef)){
- ef(dom);
- }
- }, this);
- },
- _postFilterContent: function(
- /*DomNode|DomNode[]|String?*/ dom,
- /*Boolean?*/ nonDestructive){
- // summary:
- // filter the output after getting the content of the editing area
- //
- // description:
- // post-filtering allows plug-ins and users to specify any number
- // of transforms over the editor's content, enabling many common
- // use-cases such as transforming absolute to relative URLs (and
- // vice-versa), ensuring conformance with a particular DTD, etc.
- // The filters are registered in the contentDomPostFilters and
- // contentPostFilters arrays. Each item in the
- // contentDomPostFilters array is a function which takes a DOM
- // Node or array of nodes as its only argument and returns the
- // same. It is then passed down the chain for further filtering.
- // The contentPostFilters array behaves the same way, except each
- // member operates on strings. Together, the DOM and string-based
- // filtering allow the full range of post-processing that should
- // be necessaray to enable even the most agressive of post-editing
- // conversions to take place.
- //
- // If nonDestructive is set to "true", the nodes are cloned before
- // filtering proceeds to avoid potentially destructive transforms
- // to the content which may still needed to be edited further.
- // Once DOM filtering has taken place, the serialized version of
- // the DOM which is passed is run through each of the
- // contentPostFilters functions.
- //
- // dom:
- // a node, set of nodes, which to filter using each of the current
- // members of the contentDomPostFilters and contentPostFilters arrays.
- //
- // nonDestructive:
- // defaults to "false". If true, ensures that filtering happens on
- // a clone of the passed-in content and not the actual node
- // itself.
- //
- // tags:
- // private
- var ec;
- if(!lang.isString(dom)){
- dom = dom || this.editNode;
- if(this.contentDomPostFilters.length){
- if(nonDestructive){
- dom = lang.clone(dom);
- }
- array.forEach(this.contentDomPostFilters, function(ef){
- dom = ef(dom);
- });
- }
- ec = htmlapi.getChildrenHtml(dom);
- }else{
- ec = dom;
- }
- if(!lang.trim(ec.replace(/^\xA0\xA0*/, '').replace(/\xA0\xA0*$/, '')).length){
- ec = "";
- }
- // if(has("ie")){
- // //removing appended <P> </P> for IE
- // ec = ec.replace(/(?:<p> </p>[\n\r]*)+$/i,"");
- // }
- array.forEach(this.contentPostFilters, function(ef){
- ec = ef(ec);
- });
- return ec;
- },
- _saveContent: function(){
- // summary:
- // Saves the content in an onunload event if the editor has not been closed
- // tags:
- // private
- var saveTextarea = dom.byId(dijit._scopeName + "._editor.RichText.value");
- if(saveTextarea){
- if(saveTextarea.value){
- saveTextarea.value += this._SEPARATOR;
- }
- saveTextarea.value += this.name + this._NAME_CONTENT_SEP + this.getValue(true);
- }
- },
- escapeXml: function(/*String*/ str, /*Boolean*/ noSingleQuotes){
- // summary:
- // Adds escape sequences for special characters in XML.
- // Optionally skips escapes for single quotes
- // tags:
- // private
- str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);
- if(!noSingleQuotes){
- str = str.replace(/'/gm, "'");
- }
- return str; // string
- },
- getNodeHtml: function(/* DomNode */ node){
- // summary:
- // Deprecated. Use dijit/_editor/html::_getNodeHtml() instead.
- // tags:
- // deprecated
- kernel.deprecated('dijit.Editor::getNodeHtml is deprecated','use dijit/_editor/html::getNodeHtml instead', 2);
- return htmlapi.getNodeHtml(node); // String
- },
- getNodeChildrenHtml: function(/* DomNode */ dom){
- // summary:
- // Deprecated. Use dijit/_editor/html::getChildrenHtml() instead.
- // tags:
- // deprecated
- kernel.deprecated('dijit.Editor::getNodeChildrenHtml is deprecated','use dijit/_editor/html::getChildrenHtml instead', 2);
- return htmlapi.getChildrenHtml(dom);
- },
- close: function(/*Boolean?*/ save){
- // summary:
- // Kills the editor and optionally writes back the modified contents to the
- // element from which it originated.
- // save:
- // Whether or not to save the changes. If false, the changes are discarded.
- // tags:
- // private
- if(this.isClosed){ return; }
- if(!arguments.length){ save = true; }
- if(save){
- this._set("value", this.getValue(true));
- }
- // line height is squashed for iframes
- // FIXME: why was this here? if(this.iframe){ this.domNode.style.lineHeight = null; }
- if(this.interval){ clearInterval(this.interval); }
- if(this._webkitListener){
- //Cleaup of WebKit fix: #9532
- this.disconnect(this._webkitListener);
- delete this._webkitListener;
- }
- // Guard against memory leaks on IE (see #9268)
- if(has("ie")){
- this.iframe.onfocus = null;
- }
- this.iframe._loadFunc = null;
- if(this._iframeRegHandle){
- this._iframeRegHandle.remove();
- delete this._iframeRegHandle;
- }
- if(this.textarea){
- var s = this.textarea.style;
- s.position = "";
- s.left = s.top = "";
- if(has("ie")){
- s.overflow = this.__overflow;
- this.__overflow = null;
- }
- this.textarea.value = this.value;
- domConstruct.destroy(this.domNode);
- this.domNode = this.textarea;
- }else{
- // Note that this destroys the iframe
- this.domNode.innerHTML = this.value;
- }
- delete this.iframe;
- domClass.remove(this.domNode, this.baseClass);
- this.isClosed = true;
- this.isLoaded = false;
- delete this.editNode;
- delete this.focusNode;
- if(this.window && this.window._frameElement){
- this.window._frameElement = null;
- }
- this.window = null;
- this.document = null;
- this.editingArea = null;
- this.editorObject = null;
- },
- destroy: function(){
- if(!this.isClosed){ this.close(false); }
- if(this._updateTimer){
- clearTimeout(this._updateTimer);
- }
- this.inherited(arguments);
- if(RichText._globalSaveHandler){
- delete RichText._globalSaveHandler[this.id];
- }
- },
- _removeMozBogus: function(/* String */ html){
- // summary:
- // Post filter to remove unwanted HTML attributes generated by mozilla
- // tags:
- // private
- return html.replace(/\stype="_moz"/gi, '').replace(/\s_moz_dirty=""/gi, '').replace(/_moz_resizing="(true|false)"/gi,''); // String
- },
- _removeWebkitBogus: function(/* String */ html){
- // summary:
- // Post filter to remove unwanted HTML attributes generated by webkit
- // tags:
- // private
- html = html.replace(/\sclass="webkit-block-placeholder"/gi, '');
- html = html.replace(/\sclass="apple-style-span"/gi, '');
- // For some reason copy/paste sometime adds extra meta tags for charset on
- // webkit (chrome) on mac.They need to be removed. See: #12007"
- html = html.replace(/<meta charset=\"utf-8\" \/>/gi, '');
- return html; // String
- },
- _normalizeFontStyle: function(/* String */ html){
- // summary:
- // Convert 'strong' and 'em' to 'b' and 'i'.
- // description:
- // Moz can not handle strong/em tags correctly, so to help
- // mozilla and also to normalize output, convert them to 'b' and 'i'.
- //
- // Note the IE generates 'strong' and 'em' rather than 'b' and 'i'
- // tags:
- // private
- return html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2')
- .replace(/<(\/)?em([ \>])/gi, '<$1i$2' ); // String
- },
- _preFixUrlAttributes: function(/* String */ html){
- // summary:
- // Pre-filter to do fixing to href attributes on <a> and <img> tags
- // tags:
- // private
- return html.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,
- '$1$4$2$3$5$2 _djrealurl=$2$3$5$2')
- .replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,
- '$1$4$2$3$5$2 _djrealurl=$2$3$5$2'); // String
- },
- /*****************************************************************************
- The following functions implement HTML manipulation commands for various
- browser/contentEditable implementations. The goal of them is to enforce
- standard behaviors of them.
- ******************************************************************************/
- /*** queryCommandEnabled implementations ***/
- _browserQueryCommandEnabled: function(command){
- // summary:
- // Implementation to call to the native queryCommandEnabled of the browser.
- // command:
- // The command to check.
- // tags:
- // protected
- if(!command) { return false; }
- var elem = has("ie") ? this.document.selection.createRange() : this.document;
- try{
- return elem.queryCommandEnabled(command);
- }catch(e){
- return false;
- }
- },
- _createlinkEnabledImpl: function(/*===== argument =====*/){
- // summary:
- // This function implements the test for if the create link
- // command should be enabled or not.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var enabled = true;
- if(has("opera")){
- var sel = this.window.getSelection();
- if(sel.isCollapsed){
- enabled = true;
- }else{
- enabled = this.document.queryCommandEnabled("createlink");
- }
- }else{
- enabled = this._browserQueryCommandEnabled("createlink");
- }
- return enabled;
- },
- _unlinkEnabledImpl: function(/*===== argument =====*/){
- // summary:
- // This function implements the test for if the unlink
- // command should be enabled or not.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var enabled = true;
- if(has("mozilla") || has("webkit")){
- enabled = this._sCall("hasAncestorElement", ["a"]);
- }else{
- enabled = this._browserQueryCommandEnabled("unlink");
- }
- return enabled;
- },
- _inserttableEnabledImpl: function(/*===== argument =====*/){
- // summary:
- // This function implements the test for if the inserttable
- // command should be enabled or not.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var enabled = true;
- if(has("mozilla") || has("webkit")){
- enabled = true;
- }else{
- enabled = this._browserQueryCommandEnabled("inserttable");
- }
- return enabled;
- },
- _cutEnabledImpl: function(/*===== argument =====*/){
- // summary:
- // This function implements the test for if the cut
- // command should be enabled or not.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var enabled = true;
- if(has("webkit")){
- // WebKit deems clipboard activity as a security threat and natively would return false
- var sel = this.window.getSelection();
- if(sel){ sel = sel.toString(); }
- enabled = !!sel;
- }else{
- enabled = this._browserQueryCommandEnabled("cut");
- }
- return enabled;
- },
- _copyEnabledImpl: function(/*===== argument =====*/){
- // summary:
- // This function implements the test for if the copy
- // command should be enabled or not.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var enabled = true;
- if(has("webkit")){
- // WebKit deems clipboard activity as a security threat and natively would return false
- var sel = this.window.getSelection();
- if(sel){ sel = sel.toString(); }
- enabled = !!sel;
- }else{
- enabled = this._browserQueryCommandEnabled("copy");
- }
- return enabled;
- },
- _pasteEnabledImpl: function(/*===== argument =====*/){
- // summary:c
- // This function implements the test for if the paste
- // command should be enabled or not.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var enabled = true;
- if(has("webkit")){
- return true;
- }else{
- enabled = this._browserQueryCommandEnabled("paste");
- }
- return enabled;
- },
- /*** execCommand implementations ***/
- _inserthorizontalruleImpl: function(argument){
- // summary:
- // This function implements the insertion of HTML 'HR' tags.
- // into a point on the page. IE doesn't to it right, so
- // we have to use an alternate form
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- if(has("ie")){
- return this._inserthtmlImpl("<hr>");
- }
- return this.document.execCommand("inserthorizontalrule", false, argument);
- },
- _unlinkImpl: function(argument){
- // summary:
- // This function implements the unlink of an 'a' tag.
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- if((this.queryCommandEnabled("unlink")) && (has("mozilla") || has("webkit"))){
- var a = this._sCall("getAncestorElement", [ "a" ]);
- this._sCall("selectElement", [ a ]);
- return this.document.execCommand("unlink", false, null);
- }
- return this.document.execCommand("unlink", false, argument);
- },
- _hilitecolorImpl: function(argument){
- // summary:
- // This function implements the hilitecolor command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var returnValue;
- var isApplied = this._handleTextColorOrProperties("hilitecolor", argument);
- if(!isApplied){
- if(has("mozilla")){
- // mozilla doesn't support hilitecolor properly when useCSS is
- // set to false (bugzilla #279330)
- this.document.execCommand("styleWithCSS", false, true);
- console.log("Executing color command.");
- returnValue = this.document.execCommand("hilitecolor", false, argument);
- this.document.execCommand("styleWithCSS", false, false);
- }else{
- returnValue = this.document.execCommand("hilitecolor", false, argument);
- }
- }
- return returnValue;
- },
- _backcolorImpl: function(argument){
- // summary:
- // This function implements the backcolor command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- if(has("ie")){
- // Tested under IE 6 XP2, no problem here, comment out
- // IE weirdly collapses ranges when we exec these commands, so prevent it
- // var tr = this.document.selection.createRange();
- argument = argument ? argument : null;
- }
- var isApplied = this._handleTextColorOrProperties("backcolor", argument);
- if(!isApplied){
- isApplied = this.document.execCommand("backcolor", false, argument);
- }
- return isApplied;
- },
- _forecolorImpl: function(argument){
- // summary:
- // This function implements the forecolor command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- if(has("ie")){
- // Tested under IE 6 XP2, no problem here, comment out
- // IE weirdly collapses ranges when we exec these commands, so prevent it
- // var tr = this.document.selection.createRange();
- argument = argument? argument : null;
- }
- var isApplied = false;
- isApplied = this._handleTextColorOrProperties("forecolor", argument);
- if(!isApplied){
- isApplied = this.document.execCommand("forecolor", false, argument);
- }
- return isApplied;
- },
- _inserthtmlImpl: function(argument){
- // summary:
- // This function implements the insertion of HTML content into
- // a point on the page.
- // argument:
- // The content to insert, if any.
- // tags:
- // protected
- argument = this._preFilterContent(argument);
- var rv = true;
- if(has("ie")){
- var insertRange = this.document.selection.createRange();
- if(this.document.selection.type.toUpperCase() === 'CONTROL'){
- var n=insertRange.item(0);
- while(insertRange.length){
- insertRange.remove(insertRange.item(0));
- }
- n.outerHTML=argument;
- }else{
- insertRange.pasteHTML(argument);
- }
- insertRange.select();
- //insertRange.collapse(true);
- }else if(has("mozilla") && !argument.length){
- //mozilla can not inserthtml an empty html to delete current selection
- //so we delete the selection instead in this case
- this._sCall("remove"); // FIXME
- }else{
- rv = this.document.execCommand("inserthtml", false, argument);
- }
- return rv;
- },
- _boldImpl: function(argument){
- // summary:
- // This function implements an over-ride of the bold command.
- // argument:
- // Not used, operates by selection.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- this._adaptIESelection();
- applied = this._adaptIEFormatAreaAndExec("bold");
- }
- if(!applied){
- applied = this.document.execCommand("bold", false, argument);
- }
- return applied;
- },
- _italicImpl: function(argument){
- // summary:
- // This function implements an over-ride of the italic command.
- // argument:
- // Not used, operates by selection.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- this._adaptIESelection();
- applied = this._adaptIEFormatAreaAndExec("italic");
- }
- if(!applied){
- applied = this.document.execCommand("italic", false, argument);
- }
- return applied;
- },
- _underlineImpl: function(argument){
- // summary:
- // This function implements an over-ride of the underline command.
- // argument:
- // Not used, operates by selection.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- this._adaptIESelection();
- applied = this._adaptIEFormatAreaAndExec("underline");
- }
- if(!applied){
- applied = this.document.execCommand("underline", false, argument);
- }
- return applied;
- },
- _strikethroughImpl: function(argument){
- // summary:
- // This function implements an over-ride of the strikethrough command.
- // argument:
- // Not used, operates by selection.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- this._adaptIESelection();
- applied = this._adaptIEFormatAreaAndExec("strikethrough");
- }
- if(!applied){
- applied = this.document.execCommand("strikethrough", false, argument);
- }
- return applied;
- },
- _superscriptImpl: function(argument){
- // summary:
- // This function implements an over-ride of the superscript command.
- // argument:
- // Not used, operates by selection.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- this._adaptIESelection();
- applied = this._adaptIEFormatAreaAndExec("superscript");
- }
- if(!applied){
- applied = this.document.execCommand("superscript", false, argument);
- }
- return applied;
- },
- _subscriptImpl: function(argument){
- // summary:
- // This function implements an over-ride of the superscript command.
- // argument:
- // Not used, operates by selection.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- this._adaptIESelection();
- applied = this._adaptIEFormatAreaAndExec("subscript");
-
- }
- if(!applied){
- applied = this.document.execCommand("subscript", false, argument);
- }
- return applied;
- },
-
- _fontnameImpl: function(argument){
- // summary:
- // This function implements the fontname command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var isApplied;
- if(has("ie")){
- isApplied = this._handleTextColorOrProperties("fontname", argument);
- }
- if(!isApplied){
- isApplied = this.document.execCommand("fontname", false, argument);
- }
- return isApplied;
- },
- _fontsizeImpl: function(argument){
- // summary:
- // This function implements the fontsize command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var isApplied;
- if(has("ie")){
- isApplied = this._handleTextColorOrProperties("fontsize", argument);
- }
- if(!isApplied){
- isApplied = this.document.execCommand("fontsize", false, argument);
- }
- return isApplied;
- },
-
- _insertorderedlistImpl: function(argument){
- // summary:
- // This function implements the insertorderedlist command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- applied = this._adaptIEList("insertorderedlist", argument);
- }
- if(!applied){
- applied = this.document.execCommand("insertorderedlist", false, argument);
- }
- return applied;
- },
-
- _insertunorderedlistImpl: function(argument){
- // summary:
- // This function implements the insertunorderedlist command
- // argument:
- // arguments to the exec command, if any.
- // tags:
- // protected
- var applied = false;
- if(has("ie")){
- applied = this._adaptIEList("insertunorderedlist", argument);
- }
- if(!applied){
- applied = this.document.execCommand("insertunorderedlist", false, argument);
- }
- return applied;
- },
-
- getHeaderHeight: function(){
- // summary:
- // A function for obtaining the height of the header node
- return this._getNodeChildrenHeight(this.header); // Number
- },
- getFooterHeight: function(){
- // summary:
- // A function for obtaining the height of the footer node
- return this._getNodeChildrenHeight(this.footer); // Number
- },
- _getNodeChildrenHeight: function(node){
- // summary:
- // An internal function for computing the cumulative height of all child nodes of 'node'
- // node:
- // The node to process the children of;
- var h = 0;
- if(node && node.childNodes){
- // IE didn't compute it right when position was obtained on the node directly is some cases,
- // so we have to walk over all the children manually.
- var i;
- for(i = 0; i < node.childNodes.length; i++){
- var size = domGeometry.position(node.childNodes[i]);
- h += size.h;
- }
- }
- return h; // Number
- },
- _isNodeEmpty: function(node, startOffset){
- // summary:
- // Function to test if a node is devoid of real content.
- // node:
- // The node to check.
- // tags:
- // private.
- if(node.nodeType === 1/*element*/){
- if(node.childNodes.length > 0){
- return this._isNodeEmpty(node.childNodes[0], startOffset);
- }
- return true;
- }else if(node.nodeType === 3/*text*/){
- return (node.nodeValue.substring(startOffset) === "");
- }
- return false;
- },
- _removeStartingRangeFromRange: function(node, range){
- // summary:
- // Function to adjust selection range by removing the current
- // start node.
- // node:
- // The node to remove from the starting range.
- // range:
- // The range to adapt.
- // tags:
- // private
- if(node.nextSibling){
- range.setStart(node.nextSibling,0);
- }else{
- var parent = node.parentNode;
- while(parent && parent.nextSibling == null){
- //move up the tree until we find a parent that has another node, that node will be the next node
- parent = parent.parentNode;
- }
- if(parent){
- range.setStart(parent.nextSibling,0);
- }
- }
- return range;
- },
- _adaptIESelection: function(){
- // summary:
- // Function to adapt the IE range by removing leading 'newlines'
- // Needed to fix issue with bold/italics/underline not working if
- // range included leading 'newlines'.
- // In IE, if a user starts a selection at the very end of a line,
- // then the native browser commands will fail to execute correctly.
- // To work around the issue, we can remove all empty nodes from
- // the start of the range selection.
- var selection = rangeapi.getSelection(this.window);
- if(selection && selection.rangeCount && !selection.isCollapsed){
- var range = selection.getRangeAt(0);
- var firstNode = range.startContainer;
- var startOffset = range.startOffset;
- while(firstNode.nodeType === 3/*text*/ && startOffset >= firstNode.length && firstNode.nextSibling){
- //traverse the text nodes until we get to the one that is actually highlighted
- startOffset = startOffset - firstNode.length;
- firstNode = firstNode.nextSibling;
- }
- //Remove the starting ranges until the range does not start with an empty node.
- var lastNode=null;
- while(this._isNodeEmpty(firstNode, startOffset) && firstNode !== lastNode){
- lastNode =firstNode; //this will break the loop in case we can't find the next sibling
- range = this._removeStartingRangeFromRange(firstNode, range); //move the start container to the next node in the range
- firstNode = range.startContainer;
- startOffset = 0; //start at the beginning of the new starting range
- }
- selection.removeAllRanges();// this will work as long as users cannot select multiple ranges. I have not been able to do that in the editor.
- selection.addRange(range);
- }
- },
-
- _adaptIEFormatAreaAndExec: function(command){
- // summary:
- // Function to handle IE's quirkiness regarding how it handles
- // format commands on a word. This involves a lit of node splitting
- // and format cloning.
- // command:
- // The format command, needed to check if the desired
- // command is true or not.
- var selection = rangeapi.getSelection(this.window);
- var doc = this.document;
- var rs, ret, range, txt, startNode, endNode, breaker, sNode;
- if(command && selection && selection.isCollapsed){
- var isApplied = this.queryCommandValue(command);
- if(isApplied){
-
- // We have to split backwards until we hit the format
- var nNames = this._tagNamesForCommand(command);
- range = selection.getRangeAt(0);
- var fs = range.startContainer;
- if(fs.nodeType === 3){
- var offset = range.endOffset;
- if(fs.length < offset){
- //We are not looking from the right node, try to locate the correct one
- ret = this._adjustNodeAndOffset(rs, offset);
- fs = ret.node;
- offset = ret.offset;
- }
- }
- var topNode;
- while(fs && fs !== this.editNode){
- // We have to walk back and see if this is still a format or not.
- // Hm, how do I do this?
- var tName = fs.tagName? fs.tagName.toLowerCase() : "";
- if(array.indexOf(nNames, tName) > -1){
- topNode = fs;
- break;
- }
- fs = fs.parentNode;
- }
- // Okay, we have a stopping place, time to split things apart.
- if(topNode){
- // Okay, we know how far we have to split backwards, so we have to split now.
- rs = range.startContainer;
- var newblock = doc.createElement(topNode.tagName);
- domConstruct.place(newblock, topNode, "after");
- if(rs && rs.nodeType === 3){
- // Text node, we have to split it.
- var nodeToMove, tNode;
- var endOffset = range.endOffset;
- if(rs.length < endOffset){
- //We are not splitting the right node, try to locate the correct one
- ret = this._adjustNodeAndOffset(rs, endOffset);
- rs = ret.node;
- endOffset = ret.offset;
- }
-
- txt = rs.nodeValue;
- startNode = doc.createTextNode(txt.substring(0, endOffset));
- var endText = txt.substring(endOffset, txt.length);
- if(endText){
- endNode = doc.createTextNode(endText);
- }
- // Place the split, then remove original nodes.
- domConstruct.place(startNode, rs, "before");
- if(endNode){
- breaker = doc.createElement("span");
- breaker.className = "ieFormatBreakerSpan";
- domConstruct.place(breaker, rs, "after");
- domConstruct.place(endNode, breaker, "after");
- endNode = breaker;
- }
- domConstruct.destroy(rs);
-
- // Okay, we split the text. Now we need to see if we're
- // parented to the block element we're splitting and if
- // not, we have to split all the way up. Ugh.
- var parentC = startNode.parentNode;
- var tagList = [];
- var tagData;
- while(parentC !== topNode){
- var tg = parentC.tagName;
- tagData = {tagName: tg};
- tagList.push(tagData);
-
- var newTg = doc.createElement(tg);
- // Clone over any 'style' data.
- if(parentC.style){
- if(newTg.style){
- if(parentC.style.cssText){
- newTg.style.cssText = parentC.style.cssText;
- tagData.cssText = parentC.style.cssText;
- }
- }
- }
- // If font also need to clone over any font data.
- if(parentC.tagName === "FONT"){
- if(parentC.color){
- newTg.color = parentC.color;
- tagData.color = parentC.color;
- }
- if(parentC.face){
- newTg.face = parentC.face;
- tagData.face = parentC.face;
- }
- if(parentC.size){ // this check was necessary on IE
- newTg.size = parentC.size;
- tagData.size = parentC.size;
- }
- }
- if(parentC.className){
- newTg.className = parentC.className;
- tagData.className = parentC.className;
- }
-
- // Now move end node and every sibling
- // after it over into the new tag.
- if(endNode){
- nodeToMove = endNode;
- while(nodeToMove){
- tNode = nodeToMove.nextSibling;
- newTg.appendChild(nodeToMove);
- nodeToMove = tNode;
- }
- }
- if(newTg.tagName == parentC.tagName){
- breaker = doc.createElement("span");
- breaker.className = "ieFormatBreakerSpan";
- domConstruct.place(breaker, parentC, "after");
- domConstruct.place(newTg, breaker, "after");
- }else{
- domConstruct.place(newTg, parentC, "after");
- }
- startNode = parentC;
- endNode = newTg;
- parentC = parentC.parentNode;
- }
- // Lastly, move the split out all the split tags
- // to the new block as they should now be split properly.
- if(endNode){
- nodeToMove = endNode;
- if(nodeToMove.nodeType === 1 || (nodeToMove.nodeType === 3 && nodeToMove.nodeValue)){
- // Non-blank text and non-text nodes need to clear out that blank space
- // before moving the contents.
- newblock.innerHTML = "";
- }
- while(nodeToMove){
- tNode = nodeToMove.nextSibling;
- newblock.appendChild(nodeToMove);
- nodeToMove = tNode;
- }
- }
-
- // We had intermediate tags, we have to now recreate them inbetween the split
- // and restore what styles, classnames, etc, we can.
- if(tagList.length){
- tagData = tagList.pop();
- var newContTag = doc.createElement(tagData.tagName);
- if(tagData.cssText && newContTag.style){
- newContTag.style.cssText = tagData.cssText;
- }
- if(tagData.className){
- newContTag.className = tagData.className;
- }
- if(tagData.tagName === "FONT"){
- if(tagData.color){
- newContTag.color = tagData.color;
- }
- if(tagData.face){
- newContTag.face = tagData.face;
- }
- if(tagData.size){
- newContTag.size = tagData.size;
- }
- }
- domConstruct.place(newContTag, newblock, "before");
- while(tagList.length){
- tagData = tagList.pop();
- var newTgNode = doc.createElement(tagData.tagName);
- if(tagData.cssText && newTgNode.style){
- newTgNode.style.cssText = tagData.cssText;
- }
- if(tagData.className){
- newTgNode.className = tagData.className;
- }
- if(tagData.tagName === "FONT"){
- if(tagData.color){
- newTgNode.color = tagData.color;
- }
- if(tagData.face){
- newTgNode.face = tagData.face;
- }
- if(tagData.size){
- newTgNode.size = tagData.size;
- }
- }
- newContTag.appendChild(newTgNode);
- newContTag = newTgNode;
- }
-
- // Okay, everything is theoretically split apart and removed from the content
- // so insert the dummy text to select, select it, then
- // clear to position cursor.
- sNode = doc.createTextNode(".");
- breaker.appendChild(sNode);
- newContTag.appendChild(sNode);
- win.withGlobal(this.window, lang.hitch(this, function(){
- var newrange = rangeapi.create();
- newrange.setStart(sNode, 0);
- newrange.setEnd(sNode, sNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- selectionapi.collapse(false);
- sNode.parentNode.innerHTML = "";
- }));
- }else{
- // No extra tags, so we have to insert a breaker point and rely
- // on filters to remove it later.
- breaker = doc.createElement("span");
- breaker.className="ieFormatBreakerSpan";
- sNode = doc.createTextNode(".");
- breaker.appendChild(sNode);
- domConstruct.place(breaker, newblock, "before");
- win.withGlobal(this.window, lang.hitch(this, function(){
- var newrange = rangeapi.create();
- newrange.setStart(sNode, 0);
- newrange.setEnd(sNode, sNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- selectionapi.collapse(false);
- sNode.parentNode.innerHTML = "";
- }));
- }
- if(!newblock.firstChild){
- // Empty, we don't need it. Split was at end or similar
- // So, remove it.
- domConstruct.destroy(newblock);
- }
- return true;
- }
- }
- return false;
- }else{
- range = selection.getRangeAt(0);
- rs = range.startContainer;
- if(rs && rs.nodeType === 3){
- // Text node, we have to split it.
- win.withGlobal(this.window, lang.hitch(this, function(){
- var offset = range.startOffset;
- if(rs.length < offset){
- //We are not splitting the right node, try to locate the correct one
- ret = this._adjustNodeAndOffset(rs, offset);
- rs = ret.node;
- offset = ret.offset;
- }
- txt = rs.nodeValue;
- startNode = doc.createTextNode(txt.substring(0, offset));
- var endText = txt.substring(offset);
- if(endText !== ""){
- endNode = doc.createTextNode(txt.substring(offset));
- }
- // Create a space, we'll select and bold it, so
- // the whole word doesn't get bolded
- breaker = doc.createElement("span");
- sNode = doc.createTextNode(".");
- breaker.appendChild(sNode);
- if(startNode.length){
- domConstruct.place(startNode, rs, "after");
- }else{
- startNode = rs;
- }
- domConstruct.place(breaker, startNode, "after");
- if(endNode){
- domConstruct.place(endNode, breaker, "after");
- }
- domConstruct.destroy(rs);
- var newrange = rangeapi.create();
- newrange.setStart(sNode, 0);
- newrange.setEnd(sNode, sNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- doc.execCommand(command);
- domConstruct.place(breaker.firstChild, breaker, "before");
- domConstruct.destroy(breaker);
- newrange.setStart(sNode, 0);
- newrange.setEnd(sNode, sNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- selectionapi.collapse(false);
- sNode.parentNode.innerHTML = "";
- }));
- return true;
- }
- }
- }else{
- return false;
- }
- },
-
- _adaptIEList: function(command /*===== , argument =====*/){
- // summary:
- // This function handles normalizing the IE list behavior as
- // much as possible.
- // command:
- // The list command to execute.
- // argument:
- // Any additional argument.
- // tags:
- // private
- var selection = rangeapi.getSelection(this.window);
- if(selection.isCollapsed){
- // In the case of no selection, lets commonize the behavior and
- // make sure that it indents if needed.
- if(selection.rangeCount && !this.queryCommandValue(command)){
- var range = selection.getRangeAt(0);
- var sc = range.startContainer;
- if(sc && sc.nodeType == 3){
- // text node. Lets see if there is a node before it that isn't
- // some sort of breaker.
- if(!range.startOffset){
- // We're at the beginning of a text area. It may have been br split
- // Who knows? In any event, we must create the list manually
- // or IE may shove too much into the list element. It seems to
- // grab content before the text node too if it's br split.
- // Why can't IE work like everyone else?
- win.withGlobal(this.window, lang.hitch(this, function(){
- // Create a space, we'll select and bold it, so
- // the whole word doesn't get bolded
- var lType = "ul";
- if(command === "insertorderedlist"){
- lType = "ol";
- }
- var list = domConstruct.create(lType);
- var li = domConstruct.create("li", null, list);
- domConstruct.place(list, sc, "before");
- // Move in the text node as part of the li.
- li.appendChild(sc);
- // We need a br after it or the enter key handler
- // sometimes throws errors.
- domConstruct.create("br", null, list, "after");
- // Okay, now lets move our cursor to the beginning.
- var newrange = rangeapi.create();
- newrange.setStart(sc, 0);
- newrange.setEnd(sc, sc.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- selectionapi.collapse(true);
- }));
- return true;
- }
- }
- }
- }
- return false;
- },
-
- _handleTextColorOrProperties: function(command, argument){
- // summary:
- // This function handles appplying text color as best it is
- // able to do so when the selection is collapsed, making the
- // behavior cross-browser consistent. It also handles the name
- // and size for IE.
- // command:
- // The command.
- // argument:
- // Any additional arguments.
- // tags:
- // private
- var selection = rangeapi.getSelection(this.window);
- var doc = this.document;
- var rs, ret, range, txt, startNode, endNode, breaker, sNode;
- argument = argument || null;
- if(command && selection && selection.isCollapsed){
- if(selection.rangeCount){
- range = selection.getRangeAt(0);
- rs = range.startContainer;
- if(rs && rs.nodeType === 3){
- // Text node, we have to split it.
- win.withGlobal(this.window, lang.hitch(this, function(){
- var offset = range.startOffset;
- if(rs.length < offset){
- //We are not splitting the right node, try to locate the correct one
- ret = this._adjustNodeAndOffset(rs, offset);
- rs = ret.node;
- offset = ret.offset;
- }
- txt = rs.nodeValue;
- startNode = doc.createTextNode(txt.substring(0, offset));
- var endText = txt.substring(offset);
- if(endText !== ""){
- endNode = doc.createTextNode(txt.substring(offset));
- }
- // Create a space, we'll select and bold it, so
- // the whole word doesn't get bolded
- breaker = domConstruct.create("span");
- sNode = doc.createTextNode(".");
- breaker.appendChild(sNode);
- // Create a junk node to avoid it trying to stlye the breaker.
- // This will get destroyed later.
- var extraSpan = domConstruct.create("span");
- breaker.appendChild(extraSpan);
- if(startNode.length){
- domConstruct.place(startNode, rs, "after");
- }else{
- startNode = rs;
- }
- domConstruct.place(breaker, startNode, "after");
- if(endNode){
- domConstruct.place(endNode, breaker, "after");
- }
- domConstruct.destroy(rs);
- var newrange = rangeapi.create();
- newrange.setStart(sNode, 0);
- newrange.setEnd(sNode, sNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- if(has("webkit")){
- // WebKit is frustrating with positioning the cursor.
- // It stinks to have a selected space, but there really
- // isn't much choice here.
- var style = "color";
- if(command === "hilitecolor" || command === "backcolor"){
- style = "backgroundColor";
- }
- domStyle.set(breaker, style, argument);
- selectionapi.remove();
- domConstruct.destroy(extraSpan);
- breaker.innerHTML = " "; //
- selectionapi.selectElement(breaker);
- this.focus();
- }else{
- this.execCommand(command, argument);
- domConstruct.place(breaker.firstChild, breaker, "before");
- domConstruct.destroy(breaker);
- newrange.setStart(sNode, 0);
- newrange.setEnd(sNode, sNode.length);
- selection.removeAllRanges();
- selection.addRange(newrange);
- selectionapi.collapse(false);
- sNode.parentNode.removeChild(sNode);
- }
- }));
- return true;
- }
- }
- }
- return false;
- },
-
- _adjustNodeAndOffset: function(/*DomNode*/node, /*Int*/offset){
- // summary:
- // In the case there are multiple text nodes in a row the offset may not be within the node.
- // If the offset is larger than the node length, it will attempt to find
- // the next text sibling until it locates the text node in which the offset refers to
- // node:
- // The node to check.
- // offset:
- // The position to find within the text node
- // tags:
- // private.
- while(node.length < offset && node.nextSibling && node.nextSibling.nodeType === 3){
- //Adjust the offset and node in the case of multiple text nodes in a row
- offset = offset - node.length;
- node = node.nextSibling;
- }
- return {"node": node, "offset": offset};
- },
-
- _tagNamesForCommand: function(command){
- // summary:
- // Function to return the tab names that are associated
- // with a particular style.
- // command: String
- // The command to return tags for.
- // tags:
- // private
- if(command === "bold"){
- return ["b", "strong"];
- }else if(command === "italic"){
- return ["i","em"];
- }else if(command === "strikethrough"){
- return ["s", "strike"];
- }else if(command === "superscript"){
- return ["sup"];
- }else if(command === "subscript"){
- return ["sub"];
- }else if(command === "underline"){
- return ["u"];
- }
- return [];
- },
- _stripBreakerNodes: function(node){
- // summary:
- // Function for stripping out the breaker spans inserted by the formatting command.
- // Registered as a filter for IE, handles the breaker spans needed to fix up
- // How bold/italic/etc, work when selection is collapsed (single cursor).
- win.withGlobal(this.window, lang.hitch(this, function(){
- var breakers = query(".ieFormatBreakerSpan", node);
- var i;
- for(i = 0; i < breakers.length; i++){
- var b = breakers[i];
- while(b.firstChild){
- domConstruct.place(b.firstChild, b, "before");
- }
- domConstruct.destroy(b);
- }
- }));
- return node;
- }
- });
- return RichText;
- });
- },
- 'dojo/dnd/Moveable':function(){
- define("dojo/dnd/Moveable", ["../main", "../Evented", "../touch", "./Mover"], function(dojo, Evented, touch) {
- // module:
- // dojo/dnd/Moveable
- // summary:
- // TODOC
- /*=====
- dojo.declare("dojo.dnd.__MoveableArgs", [], {
- // handle: Node||String
- // A node (or node's id), which is used as a mouse handle.
- // If omitted, the node itself is used as a handle.
- handle: null,
- // delay: Number
- // delay move by this number of pixels
- delay: 0,
- // skip: Boolean
- // skip move of form elements
- skip: false,
- // mover: Object
- // a constructor of custom Mover
- mover: dojo.dnd.Mover
- });
- =====*/
- dojo.declare("dojo.dnd.Moveable", [Evented], {
- // object attributes (for markup)
- handle: "",
- delay: 0,
- skip: false,
- constructor: function(node, params){
- // summary:
- // an object, which makes a node moveable
- // node: Node
- // a node (or node's id) to be moved
- // params: dojo.dnd.__MoveableArgs?
- // optional parameters
- this.node = dojo.byId(node);
- if(!params){ params = {}; }
- this.handle = params.handle ? dojo.byId(params.handle) : null;
- if(!this.handle){ this.handle = this.node; }
- this.delay = params.delay > 0 ? params.delay : 0;
- this.skip = params.skip;
- this.mover = params.mover ? params.mover : dojo.dnd.Mover;
- this.events = [
- dojo.connect(this.handle, touch.press, this, "onMouseDown"),
- // cancel text selection and text dragging
- dojo.connect(this.handle, "ondragstart", this, "onSelectStart"),
- dojo.connect(this.handle, "onselectstart", this, "onSelectStart")
- ];
- },
- // markup methods
- markupFactory: function(params, node, ctor){
- return new ctor(node, params);
- },
- // methods
- destroy: function(){
- // summary:
- // stops watching for possible move, deletes all references, so the object can be garbage-collected
- dojo.forEach(this.events, dojo.disconnect);
- this.events = this.node = this.handle = null;
- },
- // mouse event processors
- onMouseDown: function(e){
- // summary:
- // event processor for onmousedown/ontouchstart, creates a Mover for the node
- // e: Event
- // mouse/touch event
- if(this.skip && dojo.dnd.isFormElement(e)){ return; }
- if(this.delay){
- this.events.push(
- dojo.connect(this.handle, touch.move, this, "onMouseMove"),
- dojo.connect(this.handle, touch.release, this, "onMouseUp")
- );
- this._lastX = e.pageX;
- this._lastY = e.pageY;
- }else{
- this.onDragDetected(e);
- }
- dojo.stopEvent(e);
- },
- onMouseMove: function(e){
- // summary:
- // event processor for onmousemove/ontouchmove, used only for delayed drags
- // e: Event
- // mouse/touch event
- if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){
- this.onMouseUp(e);
- this.onDragDetected(e);
- }
- dojo.stopEvent(e);
- },
- onMouseUp: function(e){
- // summary:
- // event processor for onmouseup, used only for delayed drags
- // e: Event
- // mouse event
- for(var i = 0; i < 2; ++i){
- dojo.disconnect(this.events.pop());
- }
- dojo.stopEvent(e);
- },
- onSelectStart: function(e){
- // summary:
- // event processor for onselectevent and ondragevent
- // e: Event
- // mouse event
- if(!this.skip || !dojo.dnd.isFormElement(e)){
- dojo.stopEvent(e);
- }
- },
- // local events
- onDragDetected: function(/* Event */ e){
- // summary:
- // called when the drag is detected;
- // responsible for creation of the mover
- new this.mover(this.node, e, this);
- },
- onMoveStart: function(/* dojo.dnd.Mover */ mover){
- // summary:
- // called before every move operation
- dojo.publish("/dnd/move/start", [mover]);
- dojo.addClass(dojo.body(), "dojoMove");
- dojo.addClass(this.node, "dojoMoveItem");
- },
- onMoveStop: function(/* dojo.dnd.Mover */ mover){
- // summary:
- // called after every move operation
- dojo.publish("/dnd/move/stop", [mover]);
- dojo.removeClass(dojo.body(), "dojoMove");
- dojo.removeClass(this.node, "dojoMoveItem");
- },
- onFirstMove: function(/* dojo.dnd.Mover */ mover, /* Event */ e){
- // summary:
- // called during the very first move notification;
- // can be used to initialize coordinates, can be overwritten.
- // default implementation does nothing
- },
- onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop, /* Event */ e){
- // summary:
- // called during every move notification;
- // should actually move the node; can be overwritten.
- this.onMoving(mover, leftTop);
- var s = mover.node.style;
- s.left = leftTop.l + "px";
- s.top = leftTop.t + "px";
- this.onMoved(mover, leftTop);
- },
- onMoving: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
- // summary:
- // called before every incremental move; can be overwritten.
- // default implementation does nothing
- },
- onMoved: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
- // summary:
- // called after every incremental move; can be overwritten.
- // default implementation does nothing
- }
- });
- return dojo.dnd.Moveable;
- });
- },
- 'dojo/store/util/SimpleQueryEngine':function(){
- define("dojo/store/util/SimpleQueryEngine", ["../../_base/array"], function(arrayUtil) {
- // module:
- // dojo/store/util/SimpleQueryEngine
- // summary:
- // The module defines a simple filtering query engine for object stores.
- return function(query, options){
- // summary:
- // Simple query engine that matches using filter functions, named filter
- // functions or objects by name-value on a query object hash
- //
- // description:
- // The SimpleQueryEngine provides a way of getting a QueryResults through
- // the use of a simple object hash as a filter. The hash will be used to
- // match properties on data objects with the corresponding value given. In
- // other words, only exact matches will be returned.
- //
- // This function can be used as a template for more complex query engines;
- // for example, an engine can be created that accepts an object hash that
- // contains filtering functions, or a string that gets evaluated, etc.
- //
- // When creating a new dojo.store, simply set the store's queryEngine
- // field as a reference to this function.
- //
- // query: Object
- // An object hash with fields that may match fields of items in the store.
- // Values in the hash will be compared by normal == operator, but regular expressions
- // or any object that provides a test() method are also supported and can be
- // used to match strings by more complex expressions
- // (and then the regex's or object's test() method will be used to match values).
- //
- // options: dojo.store.util.SimpleQueryEngine.__queryOptions?
- // An object that contains optional information such as sort, start, and count.
- //
- // returns: Function
- // A function that caches the passed query under the field "matches". See any
- // of the "query" methods on dojo.stores.
- //
- // example:
- // Define a store with a reference to this engine, and set up a query method.
- //
- // | var myStore = function(options){
- // | // ...more properties here
- // | this.queryEngine = dojo.store.util.SimpleQueryEngine;
- // | // define our query method
- // | this.query = function(query, options){
- // | return dojo.store.util.QueryResults(this.queryEngine(query, options)(this.data));
- // | };
- // | };
- // create our matching query function
- switch(typeof query){
- default:
- throw new Error("Can not query with a " + typeof query);
- case "object": case "undefined":
- var queryObject = query;
- query = function(object){
- for(var key in queryObject){
- var required = queryObject[key];
- if(required && required.test){
- if(!required.test(object[key])){
- return false;
- }
- }else if(required != object[key]){
- return false;
- }
- }
- return true;
- };
- break;
- case "string":
- // named query
- if(!this[query]){
- throw new Error("No filter function " + query + " was found in store");
- }
- query = this[query];
- // fall through
- case "function":
- // fall through
- }
- function execute(array){
- // execute the whole query, first we filter
- var results = arrayUtil.filter(array, query);
- // next we sort
- if(options && options.sort){
- results.sort(function(a, b){
- for(var sort, i=0; sort = options.sort[i]; i++){
- var aValue = a[sort.attribute];
- var bValue = b[sort.attribute];
- if (aValue != bValue) {
- return !!sort.descending == aValue > bValue ? -1 : 1;
- }
- }
- return 0;
- });
- }
- // now we paginate
- if(options && (options.start || options.count)){
- var total = results.length;
- results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
- results.total = total;
- }
- return results;
- }
- execute.matches = query;
- return execute;
- };
- });
- },
- 'dojox/grid/_View':function(){
- require({cache:{
- 'url:dojox/grid/resources/View.html':"<div class=\"dojoxGridView\" role=\"presentation\">\r\n\t<div class=\"dojoxGridHeader\" dojoAttachPoint=\"headerNode\" role=\"presentation\">\r\n\t\t<div dojoAttachPoint=\"headerNodeContainer\" style=\"width:9000em\" role=\"presentation\">\r\n\t\t\t<div dojoAttachPoint=\"headerContentNode\" role=\"row\"></div>\r\n\t\t</div>\r\n\t</div>\r\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" dojoAttachPoint=\"hiddenFocusNode\" role=\"presentation\" />\r\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" role=\"presentation\" />\r\n\t<div class=\"dojoxGridScrollbox\" dojoAttachPoint=\"scrollboxNode\" role=\"presentation\">\r\n\t\t<div class=\"dojoxGridContent\" dojoAttachPoint=\"contentNode\" hidefocus=\"hidefocus\" role=\"presentation\"></div>\r\n\t</div>\r\n</div>\r\n"}});
- define("dojox/grid/_View", [
- "dojo",
- "dijit/registry",
- "../main",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/connect",
- "dojo/_base/sniff",
- "dojo/query",
- "dojo/_base/window",
- "dojo/text!./resources/View.html",
- "dojo/dnd/Source",
- "dijit/_Widget",
- "dijit/_TemplatedMixin",
- "dojox/html/metrics",
- "./util",
- "dojo/_base/html",
- "./_Builder",
- "dojo/dnd/Avatar",
- "dojo/dnd/Manager"
- ], function(dojo, dijit, dojox, declare, array, lang, connect, has, query,
- win, template, Source, _Widget, _TemplatedMixin, metrics, util, html, _Builder, Avatar){
- // a private function
- var getStyleText = function(inNode, inStyleText){
- return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
- };
- // some public functions
- var _View = declare('dojox.grid._View', [_Widget, _TemplatedMixin], {
- // summary:
- // A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
- // Grid creates views automatically based on grid's layout structure.
- // Users should typically not need to access individual views directly.
- //
- // defaultWidth: String
- // Default width of the view
- defaultWidth: "18em",
- // viewWidth: String
- // Width for the view, in valid css unit
- viewWidth: "",
- templateString: template,
-
- themeable: false,
- classTag: 'dojoxGrid',
- marginBottom: 0,
- rowPad: 2,
- // _togglingColumn: int
- // Width of the column being toggled (-1 for none)
- _togglingColumn: -1,
-
- // _headerBuilderClass: Object
- // The class to use for our header builder
- _headerBuilderClass: _Builder._HeaderBuilder,
-
- // _contentBuilderClass: Object
- // The class to use for our content builder
- _contentBuilderClass: _Builder._ContentBuilder,
-
- postMixInProperties: function(){
- this.rowNodes = {};
- },
- postCreate: function(){
- this.connect(this.scrollboxNode,"onscroll","doscroll");
- util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
- util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
- this.content = new this._contentBuilderClass(this);
- this.header = new this._headerBuilderClass(this);
- //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
- if(!this.grid.isLeftToRight()){
- this.headerNodeContainer.style.width = "";
- }
- },
- destroy: function(){
- html.destroy(this.headerNode);
- delete this.headerNode;
- for(var i in this.rowNodes){
- this._cleanupRowWidgets(this.rowNodes[i]);
- html.destroy(this.rowNodes[i]);
- }
- this.rowNodes = {};
- if(this.source){
- this.source.destroy();
- }
- this.inherited(arguments);
- },
- // focus
- focus: function(){
- if(has("ie") || has("webkit") || has("opera")){
- this.hiddenFocusNode.focus();
- }else{
- this.scrollboxNode.focus();
- }
- },
- setStructure: function(inStructure){
- var vs = (this.structure = inStructure);
- // FIXME: similar logic is duplicated in layout
- if(vs.width && !isNaN(vs.width)){
- this.viewWidth = vs.width + 'em';
- }else{
- this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
- }
- this._onBeforeRow = vs.onBeforeRow||function(){};
- this._onAfterRow = vs.onAfterRow||function(){};
- this.noscroll = vs.noscroll;
- if(this.noscroll){
- this.scrollboxNode.style.overflow = "hidden";
- }
- this.simpleStructure = Boolean(vs.cells.length == 1);
- // bookkeeping
- this.testFlexCells();
- // accomodate new structure
- this.updateStructure();
- },
-
- _cleanupRowWidgets: function(inRowNode){
- // Summary:
- // Cleans up the widgets for the given row node so that
- // we can reattach them if needed
- if(inRowNode){
- array.forEach(query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
- if(w._destroyOnRemove){
- w.destroy();
- delete w;
- }else if(w.domNode && w.domNode.parentNode){
- w.domNode.parentNode.removeChild(w.domNode);
- }
- });
- }
- },
-
- onBeforeRow: function(inRowIndex, cells){
- this._onBeforeRow(inRowIndex, cells);
- if(inRowIndex >= 0){
- this._cleanupRowWidgets(this.getRowNode(inRowIndex));
- }
- },
-
- onAfterRow: function(inRowIndex, cells, inRowNode){
- this._onAfterRow(inRowIndex, cells, inRowNode);
- var g = this.grid;
- array.forEach(query(".dojoxGridStubNode", inRowNode), function(n){
- if(n && n.parentNode){
- var lw = n.getAttribute("linkWidget");
- var cellIdx = window.parseInt(html.attr(n, "cellIdx"), 10);
- var cellDef = g.getCell(cellIdx);
- var w = dijit.byId(lw);
- if(w){
- n.parentNode.replaceChild(w.domNode, n);
- if(!w._started){
- w.startup();
- }
- dojo.destroy(n);
- }else{
- n.innerHTML = "";
- }
- }
- }, this);
- },
- testFlexCells: function(){
- // FIXME: cheater, this function does double duty as initializer and tester
- this.flexCells = false;
- for(var j=0, row; (row=this.structure.cells[j]); j++){
- for(var i=0, cell; (cell=row[i]); i++){
- cell.view = this;
- this.flexCells = this.flexCells || cell.isFlex();
- }
- }
- return this.flexCells;
- },
- updateStructure: function(){
- // header builder needs to update table map
- this.header.update();
- // content builder needs to update markup cache
- this.content.update();
- },
- getScrollbarWidth: function(){
- var hasScrollSpace = this.hasVScrollbar();
- var overflow = html.style(this.scrollboxNode, "overflow");
- if(this.noscroll || !overflow || overflow == "hidden"){
- hasScrollSpace = false;
- }else if(overflow == "scroll"){
- hasScrollSpace = true;
- }
- return (hasScrollSpace ? metrics.getScrollbar().w : 0); // Integer
- },
- getColumnsWidth: function(){
- var h = this.headerContentNode;
- return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
- },
- setColumnsWidth: function(width){
- this.headerContentNode.firstChild.style.width = width + 'px';
- if(this.viewWidth){
- this.viewWidth = width + 'px';
- }
- },
- getWidth: function(){
- return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
- },
- getContentWidth: function(){
- return Math.max(0, html._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
- },
- render: function(){
- this.scrollboxNode.style.height = '';
- this.renderHeader();
- if(this._togglingColumn >= 0){
- this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
- this._togglingColumn = -1;
- }
- var cells = this.grid.layout.cells;
- var getSibling = lang.hitch(this, function(node, before){
- !this.grid.isLeftToRight() && (before = !before);
- var inc = before?-1:1;
- var idx = this.header.getCellNodeIndex(node) + inc;
- var cell = cells[idx];
- while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
- idx += inc;
- cell = cells[idx];
- }
- if(cell){
- return cell.getHeaderNode();
- }
- return null;
- });
- if(this.grid.columnReordering && this.simpleStructure){
- if(this.source){
- this.source.destroy();
- }
-
- // Create the top and bottom markers
- var bottomMarkerId = "dojoxGrid_bottomMarker";
- var topMarkerId = "dojoxGrid_topMarker";
- if(this.bottomMarker){
- html.destroy(this.bottomMarker);
- }
- this.bottomMarker = html.byId(bottomMarkerId);
- if(this.topMarker){
- html.destroy(this.topMarker);
- }
- this.topMarker = html.byId(topMarkerId);
- if (!this.bottomMarker) {
- this.bottomMarker = html.create("div", {
- "id": bottomMarkerId,
- "class": "dojoxGridColPlaceBottom"
- }, win.body());
- this._hide(this.bottomMarker);
-
- this.topMarker = html.create("div", {
- "id": topMarkerId,
- "class": "dojoxGridColPlaceTop"
- }, win.body());
- this._hide(this.topMarker);
- }
- this.arrowDim = html.contentBox(this.bottomMarker);
- var headerHeight = html.contentBox(this.headerContentNode.firstChild.rows[0]).h;
-
- this.source = new Source(this.headerContentNode.firstChild.rows[0], {
- horizontal: true,
- accept: [ "gridColumn_" + this.grid.id ],
- viewIndex: this.index,
- generateText: false,
- onMouseDown: lang.hitch(this, function(e){
- this.header.decorateEvent(e);
- if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
- this.header.canResize(e) && !this.header.moveable){
- this.header.beginColumnResize(e);
- }else{
- if(this.grid.headerMenu){
- this.grid.headerMenu.onCancel(true);
- }
- // IE reports a left click as 1, where everything else reports 0
- if(e.button === (has("ie") < 9 ? 1 : 0)){
- Source.prototype.onMouseDown.call(this.source, e);
- }
- }
- }),
- onMouseOver: lang.hitch(this, function(e){
- var src = this.source;
- if(src._getChildByEvent(e)){
- Source.prototype.onMouseOver.apply(src, arguments);
- }
- }),
- _markTargetAnchor: lang.hitch(this, function(before){
- var src = this.source;
- if(src.current == src.targetAnchor && src.before == before){ return; }
- if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
- src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
- }
- Source.prototype._markTargetAnchor.call(src, before);
-
- var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
- var endAdd = 0;
- if (!target) {
- target = src.targetAnchor;
- endAdd = html.contentBox(target).w + this.arrowDim.w/2 + 2;
- }
- var pos = html.position(target, true);
- var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);
- html.style(this.bottomMarker, "visibility", "visible");
- html.style(this.topMarker, "visibility", "visible");
- html.style(this.bottomMarker, {
- "left": left + "px",
- "top" : (headerHeight + pos.y) + "px"
- });
- html.style(this.topMarker, {
- "left": left + "px",
- "top" : (pos.y - this.arrowDim.h) + "px"
- });
- if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
- src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
- }
- }),
- _unmarkTargetAnchor: lang.hitch(this, function(){
- var src = this.source;
- if(!src.targetAnchor){ return; }
- if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
- src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
- }
- this._hide(this.bottomMarker);
- this._hide(this.topMarker);
- Source.prototype._unmarkTargetAnchor.call(src);
- }),
- destroy: lang.hitch(this, function(){
- connect.disconnect(this._source_conn);
- connect.unsubscribe(this._source_sub);
- Source.prototype.destroy.call(this.source);
- if(this.bottomMarker){
- html.destroy(this.bottomMarker);
- delete this.bottomMarker;
- }
- if(this.topMarker){
- html.destroy(this.topMarker);
- delete this.topMarker;
- }
- }),
- onDndCancel: lang.hitch(this, function(){
- Source.prototype.onDndCancel.call(this.source);
- this._hide(this.bottomMarker);
- this._hide(this.topMarker);
- })
- });
- this._source_conn = connect.connect(this.source, "onDndDrop", this, "_onDndDrop");
- this._source_sub = connect.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
- this.source.startup();
- }
- },
-
- _hide: function(node){
- html.style(node, {
- top: "-10000px",
- "visibility": "hidden"
- });
- },
- _onDndDropBefore: function(source, nodes, copy){
- if(dojo.dnd.manager().target !== this.source){
- return;
- }
- this.source._targetNode = this.source.targetAnchor;
- this.source._beforeTarget = this.source.before;
- var views = this.grid.views.views;
- var srcView = views[source.viewIndex];
- var tgtView = views[this.index];
- if(tgtView != srcView){
- srcView.convertColPctToFixed();
- tgtView.convertColPctToFixed();
- }
- },
- _onDndDrop: function(source, nodes, copy){
- if(dojo.dnd.manager().target !== this.source){
- if(dojo.dnd.manager().source === this.source){
- this._removingColumn = true;
- }
- return;
- }
- this._hide(this.bottomMarker);
- this._hide(this.topMarker);
- var getIdx = function(n){
- return n ? html.attr(n, "idx") : null;
- };
- var w = html.marginBox(nodes[0]).w;
- if(source.viewIndex !== this.index){
- var views = this.grid.views.views;
- var srcView = views[source.viewIndex];
- var tgtView = views[this.index];
- if(srcView.viewWidth && srcView.viewWidth != "auto"){
- srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
- }
- if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
- tgtView.setColumnsWidth(tgtView.getColumnsWidth());
- }
- }
- var stn = this.source._targetNode;
- var stb = this.source._beforeTarget;
- !this.grid.isLeftToRight() && (stb = !stb);
- var layout = this.grid.layout;
- var idx = this.index;
- delete this.source._targetNode;
- delete this.source._beforeTarget;
-
- layout.moveColumn(
- source.viewIndex,
- idx,
- getIdx(nodes[0]),
- getIdx(stn),
- stb);
- },
- renderHeader: function(){
- this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
- if(this.flexCells){
- this.contentWidth = this.getContentWidth();
- this.headerContentNode.firstChild.style.width = this.contentWidth;
- }
- util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
- },
- // note: not called in 'view' context
- _getHeaderContent: function(inCell){
- var n = inCell.name || inCell.grid.getCellName(inCell);
- if(/^\s+$/.test(n)){
- n = ' '//otherwise arrow styles will be messed up
- }
- var ret = [ '<div class="dojoxGridSortNode' ];
-
- if(inCell.index != inCell.grid.getSortIndex()){
- ret.push('">');
- }else{
- ret = ret.concat([ ' ',
- inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
- '"><div class="dojoxGridArrowButtonChar">',
- inCell.grid.sortInfo > 0 ? '▲' : '▼',
- '</div><div class="dojoxGridArrowButtonNode" role="presentation"></div>',
- '<div class="dojoxGridColCaption">']);
- }
- ret = ret.concat([n, '</div></div>']);
- return ret.join('');
- },
- resize: function(){
- this.adaptHeight();
- this.adaptWidth();
- },
- hasHScrollbar: function(reset){
- var hadScroll = this._hasHScroll||false;
- if(this._hasHScroll == undefined || reset){
- if(this.noscroll){
- this._hasHScroll = false;
- }else{
- var style = html.style(this.scrollboxNode, "overflow");
- if(style == "hidden"){
- this._hasHScroll = false;
- }else if(style == "scroll"){
- this._hasHScroll = true;
- }else{
- this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
- }
- }
- }
- if(hadScroll !== this._hasHScroll){
- this.grid.update();
- }
- return this._hasHScroll; // Boolean
- },
- hasVScrollbar: function(reset){
- var hadScroll = this._hasVScroll||false;
- if(this._hasVScroll == undefined || reset){
- if(this.noscroll){
- this._hasVScroll = false;
- }else{
- var style = html.style(this.scrollboxNode, "overflow");
- if(style == "hidden"){
- this._hasVScroll = false;
- }else if(style == "scroll"){
- this._hasVScroll = true;
- }else{
- this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
- }
- }
- }
- if(hadScroll !== this._hasVScroll){
- this.grid.update();
- }
- return this._hasVScroll; // Boolean
- },
-
- convertColPctToFixed: function(){
- // Fix any percentage widths to be pixel values
- var hasPct = false;
- this.grid.initialWidth = "";
- var cellNodes = query("th", this.headerContentNode);
- var fixedWidths = array.map(cellNodes, function(c, vIdx){
- var w = c.style.width;
- html.attr(c, "vIdx", vIdx);
- if(w && w.slice(-1) == "%"){
- hasPct = true;
- }else if(w && w.slice(-2) == "px"){
- return window.parseInt(w, 10);
- }
- return html.contentBox(c).w;
- });
- if(hasPct){
- array.forEach(this.grid.layout.cells, function(cell, idx){
- if(cell.view == this){
- var cellNode = cell.view.getHeaderCellNode(cell.index);
- if(cellNode && html.hasAttr(cellNode, "vIdx")){
- var vIdx = window.parseInt(html.attr(cellNode, "vIdx"));
- this.setColWidth(idx, fixedWidths[vIdx]);
- html.removeAttr(cellNode, "vIdx");
- }
- }
- }, this);
- return true;
- }
- return false;
- },
- adaptHeight: function(minusScroll){
- if(!this.grid._autoHeight){
- var h = (this.domNode.style.height && parseInt(this.domNode.style.height.replace(/px/,''), 10)) || this.domNode.clientHeight;
- var self = this;
- var checkOtherViewScrollers = function(){
- var v;
- for(var i in self.grid.views.views){
- v = self.grid.views.views[i];
- if(v !== self && v.hasHScrollbar()){
- return true;
- }
- }
- return false;
- };
- if(minusScroll || (this.noscroll && checkOtherViewScrollers())){
- h -= metrics.getScrollbar().h;
- }
- util.setStyleHeightPx(this.scrollboxNode, h);
- }
- this.hasVScrollbar(true);
- },
- adaptWidth: function(){
- if(this.flexCells){
- // the view content width
- this.contentWidth = this.getContentWidth();
- this.headerContentNode.firstChild.style.width = this.contentWidth;
- }
- // FIXME: it should be easier to get w from this.scrollboxNode.clientWidth,
- // but clientWidth seemingly does not include scrollbar width in some cases
- var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
- if(!this._removingColumn){
- w = Math.max(w, this.getColumnsWidth()) + 'px';
- }else{
- w = Math.min(w, this.getColumnsWidth()) + 'px';
- this._removingColumn = false;
- }
- var cn = this.contentNode;
- cn.style.width = w;
- this.hasHScrollbar(true);
- },
- setSize: function(w, h){
- var ds = this.domNode.style;
- var hs = this.headerNode.style;
- if(w){
- ds.width = w;
- hs.width = w;
- }
- ds.height = (h >= 0 ? h + 'px' : '');
- },
- renderRow: function(inRowIndex){
- var rowNode = this.createRowNode(inRowIndex);
- this.buildRow(inRowIndex, rowNode);
- //this.grid.edit.restore(this, inRowIndex);
- return rowNode;
- },
- createRowNode: function(inRowIndex){
- var node = document.createElement("div");
- node.className = this.classTag + 'Row';
- if (this instanceof dojox.grid._RowSelector){
- html.attr(node,"role","presentation");
- }else{
- html.attr(node,"role","row");
- if (this.grid.selectionMode != "none") {
- node.setAttribute("aria-selected", "false"); //rows can be selected so add aria-selected prop
- }
- }
- node[util.gridViewTag] = this.id;
- node[util.rowIndexTag] = inRowIndex;
- this.rowNodes[inRowIndex] = node;
- return node;
- },
- buildRow: function(inRowIndex, inRowNode){
-
- this.buildRowContent(inRowIndex, inRowNode);
-
- this.styleRow(inRowIndex, inRowNode);
-
-
- },
- buildRowContent: function(inRowIndex, inRowNode){
- inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex);
- if(this.flexCells && this.contentWidth){
- // FIXME: accessing firstChild here breaks encapsulation
- inRowNode.firstChild.style.width = this.contentWidth;
- }
- util.fire(this, "onAfterRow", [inRowIndex, this.structure.cells, inRowNode]);
- },
- rowRemoved:function(inRowIndex){
- if(inRowIndex >= 0){
- this._cleanupRowWidgets(this.getRowNode(inRowIndex));
- }
- this.grid.edit.save(this, inRowIndex);
- delete this.rowNodes[inRowIndex];
- },
- getRowNode: function(inRowIndex){
- return this.rowNodes[inRowIndex];
- },
- getCellNode: function(inRowIndex, inCellIndex){
- var row = this.getRowNode(inRowIndex);
- if(row){
- return this.content.getCellNode(row, inCellIndex);
- }
- },
- getHeaderCellNode: function(inCellIndex){
- if(this.headerContentNode){
- return this.header.getCellNode(this.headerContentNode, inCellIndex);
- }
- },
- // styling
- styleRow: function(inRowIndex, inRowNode){
- inRowNode._style = getStyleText(inRowNode);
- this.styleRowNode(inRowIndex, inRowNode);
- },
- styleRowNode: function(inRowIndex, inRowNode){
- if(inRowNode){
- this.doStyleRowNode(inRowIndex, inRowNode);
- }
- },
- doStyleRowNode: function(inRowIndex, inRowNode){
- this.grid.styleRowNode(inRowIndex, inRowNode);
- },
- // updating
- updateRow: function(inRowIndex){
- var rowNode = this.getRowNode(inRowIndex);
- if(rowNode){
- rowNode.style.height = '';
- this.buildRow(inRowIndex, rowNode);
- }
- return rowNode;
- },
- updateRowStyles: function(inRowIndex){
- this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
- },
- // scrolling
- lastTop: 0,
- firstScroll:0,
- _nativeScroll: false,
- doscroll: function(inEvent){
- if(has("ff") >= 13){
- this._nativeScroll = true;
- }
- //var s = dojo.marginBox(this.headerContentNode.firstChild);
- var isLtr = this.grid.isLeftToRight();
- if(this.firstScroll < 2){
- if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll === 0)){
- var s = html.marginBox(this.headerNodeContainer);
- if(has("ie")){
- this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
- }else if(has("mozilla")){
- //TODO currently only for FF, not sure for safari and opera
- this.headerNodeContainer.style.width = s.w - this.getScrollbarWidth() + 'px';
- //this.headerNodeContainer.style.width = s.w + 'px';
- //set scroll to right in FF
- this.scrollboxNode.scrollLeft = isLtr ?
- this.scrollboxNode.clientWidth - this.scrollboxNode.scrollWidth :
- this.scrollboxNode.scrollWidth - this.scrollboxNode.clientWidth;
- }
- }
- this.firstScroll++;
- }
- this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
- // 'lastTop' is a semaphore to prevent feedback-loop with setScrollTop below
- var top = this.scrollboxNode.scrollTop;
- if(top !== this.lastTop){
- this.grid.scrollTo(top);
- }
- this._nativeScroll = false;
- },
- setScrollTop: function(inTop){
- // 'lastTop' is a semaphore to prevent feedback-loop with doScroll above
- this.lastTop = inTop;
- if(!this._nativeScroll){
- //fix #15487
- this.scrollboxNode.scrollTop = inTop;
- }
- return this.scrollboxNode.scrollTop;
- },
- // event handlers (direct from DOM)
- doContentEvent: function(e){
- if(this.content.decorateEvent(e)){
- this.grid.onContentEvent(e);
- }
- },
- doHeaderEvent: function(e){
- if(this.header.decorateEvent(e)){
- this.grid.onHeaderEvent(e);
- }
- },
- // event dispatch(from Grid)
- dispatchContentEvent: function(e){
- return this.content.dispatchEvent(e);
- },
- dispatchHeaderEvent: function(e){
- return this.header.dispatchEvent(e);
- },
- // column resizing
- setColWidth: function(inIndex, inWidth){
- this.grid.setCellWidth(inIndex, inWidth + 'px');
- },
- update: function(){
- if(!this.domNode){
- return;
- }
- this.content.update();
- this.grid.update();
- //get scroll after update or scroll left setting goes wrong on IE.
- //See trac: #8040
- var left = this.scrollboxNode.scrollLeft;
- this.scrollboxNode.scrollLeft = left;
- this.headerNode.scrollLeft = left;
- }
- });
- var _GridAvatar = declare("dojox.grid._GridAvatar", Avatar, {
- construct: function(){
- var dd = win.doc;
- var a = dd.createElement("table");
- a.cellPadding = a.cellSpacing = "0";
- a.className = "dojoxGridDndAvatar";
- a.style.position = "absolute";
- a.style.zIndex = 1999;
- a.style.margin = "0px"; // to avoid dojo.marginBox() problems with table's margins
- var b = dd.createElement("tbody");
- var tr = dd.createElement("tr");
- var td = dd.createElement("td");
- var img = dd.createElement("td");
- tr.className = "dojoxGridDndAvatarItem";
- img.className = "dojoxGridDndAvatarItemImage";
- img.style.width = "16px";
- var source = this.manager.source, node;
- if(source.creator){
- // create an avatar representation of the node
- node = source._normalizedCreator(source.getItem(this.manager.nodes[0].id).data, "avatar").node;
- }else{
- // or just clone the node and hope it works
- node = this.manager.nodes[0].cloneNode(true);
- var table, tbody;
- if(node.tagName.toLowerCase() == "tr"){
- // insert extra table nodes
- table = dd.createElement("table");
- tbody = dd.createElement("tbody");
- tbody.appendChild(node);
- table.appendChild(tbody);
- node = table;
- }else if(node.tagName.toLowerCase() == "th"){
- // insert extra table nodes
- table = dd.createElement("table");
- tbody = dd.createElement("tbody");
- var r = dd.createElement("tr");
- table.cellPadding = table.cellSpacing = "0";
- r.appendChild(node);
- tbody.appendChild(r);
- table.appendChild(tbody);
- node = table;
- }
- }
- node.id = "";
- td.appendChild(node);
- tr.appendChild(img);
- tr.appendChild(td);
- html.style(tr, "opacity", 0.9);
- b.appendChild(tr);
- a.appendChild(b);
- this.node = a;
- var m = dojo.dnd.manager();
- this.oldOffsetY = m.OFFSET_Y;
- m.OFFSET_Y = 1;
- },
- destroy: function(){
- dojo.dnd.manager().OFFSET_Y = this.oldOffsetY;
- this.inherited(arguments);
- }
- });
- var oldMakeAvatar = dojo.dnd.manager().makeAvatar;
- dojo.dnd.manager().makeAvatar = function(){
- var src = this.source;
- if(src.viewIndex !== undefined && !html.hasClass(win.body(),"dijit_a11y")){
- return new _GridAvatar(this);
- }
- return oldMakeAvatar.call(dojo.dnd.manager());
- };
- return _View;
- });
- },
- 'dijit/typematic':function(){
- define("dijit/typematic", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/connect", // connect.connect
- "dojo/_base/event", // event.stop
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/lang", // lang.mixin, lang.hitch
- "dojo/on",
- "dojo/_base/sniff", // has("ie")
- "." // setting dijit.typematic global
- ], function(array, connect, event, kernel, lang, on, has, dijit){
- // module:
- // dijit/typematic
- // summary:
- // These functions are used to repetitively call a user specified callback
- // method when a specific key or mouse click over a specific DOM node is
- // held down for a specific amount of time.
- // Only 1 such event is allowed to occur on the browser page at 1 time.
- var typematic = (dijit.typematic = {
- // summary:
- // These functions are used to repetitively call a user specified callback
- // method when a specific key or mouse click over a specific DOM node is
- // held down for a specific amount of time.
- // Only 1 such event is allowed to occur on the browser page at 1 time.
- _fireEventAndReload: function(){
- this._timer = null;
- this._callback(++this._count, this._node, this._evt);
- // Schedule next event, timer is at most minDelay (default 10ms) to avoid
- // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
- this._currentTimeout = Math.max(
- this._currentTimeout < 0 ? this._initialDelay :
- (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
- this._minDelay);
- this._timer = setTimeout(lang.hitch(this, "_fireEventAndReload"), this._currentTimeout);
- },
- trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
- // summary:
- // Start a timed, repeating callback sequence.
- // If already started, the function call is ignored.
- // This method is not normally called by the user but can be
- // when the normal listener code is insufficient.
- // evt:
- // key or mouse event object to pass to the user callback
- // _this:
- // pointer to the user's widget space.
- // node:
- // the DOM node object to pass the the callback function
- // callback:
- // function to call until the sequence is stopped called with 3 parameters:
- // count:
- // integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
- // node:
- // the DOM node object passed in
- // evt:
- // key or mouse event object
- // obj:
- // user space object used to uniquely identify each typematic sequence
- // subsequentDelay (optional):
- // if > 1, the number of milliseconds until the 3->n events occur
- // or else the fractional time multiplier for the next event's delay, default=0.9
- // initialDelay (optional):
- // the number of milliseconds until the 2nd event occurs, default=500ms
- // minDelay (optional):
- // the maximum delay in milliseconds for event to fire, default=10ms
- if(obj != this._obj){
- this.stop();
- this._initialDelay = initialDelay || 500;
- this._subsequentDelay = subsequentDelay || 0.90;
- this._minDelay = minDelay || 10;
- this._obj = obj;
- this._evt = evt;
- this._node = node;
- this._currentTimeout = -1;
- this._count = -1;
- this._callback = lang.hitch(_this, callback);
- this._fireEventAndReload();
- this._evt = lang.mixin({faux: true}, evt);
- }
- },
- stop: function(){
- // summary:
- // Stop an ongoing timed, repeating callback sequence.
- if(this._timer){
- clearTimeout(this._timer);
- this._timer = null;
- }
- if(this._obj){
- this._callback(-1, this._node, this._evt);
- this._obj = null;
- }
- },
- addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
- // summary:
- // Start listening for a specific typematic key.
- // See also the trigger method for other parameters.
- // keyObject:
- // an object defining the key to listen for:
- // charOrCode:
- // the printable character (string) or keyCode (number) to listen for.
- // keyCode:
- // (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
- // charCode:
- // (deprecated - use charOrCode) the charCode (number) to listen for.
- // ctrlKey:
- // desired ctrl key state to initiate the callback sequence:
- // - pressed (true)
- // - released (false)
- // - either (unspecified)
- // altKey:
- // same as ctrlKey but for the alt key
- // shiftKey:
- // same as ctrlKey but for the shift key
- // returns:
- // a connection handle
- if(keyObject.keyCode){
- keyObject.charOrCode = keyObject.keyCode;
- kernel.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
- }else if(keyObject.charCode){
- keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
- kernel.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
- }
- var handles = [
- on(node, connect._keypress, lang.hitch(this, function(evt){
- if(evt.charOrCode == keyObject.charOrCode &&
- (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
- (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) &&
- (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
- (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
- event.stop(evt);
- typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
- }else if(typematic._obj == keyObject){
- typematic.stop();
- }
- })),
- on(node, "keyup", lang.hitch(this, function(){
- if(typematic._obj == keyObject){
- typematic.stop();
- }
- }))
- ];
- return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
- },
- addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
- // summary:
- // Start listening for a typematic mouse click.
- // See the trigger method for other parameters.
- // returns:
- // a connection handle
- var handles = [
- on(node, "mousedown", lang.hitch(this, function(evt){
- event.stop(evt);
- typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
- })),
- on(node, "mouseup", lang.hitch(this, function(evt){
- if(this._obj){
- event.stop(evt);
- }
- typematic.stop();
- })),
- on(node, "mouseout", lang.hitch(this, function(evt){
- event.stop(evt);
- typematic.stop();
- })),
- on(node, "mousemove", lang.hitch(this, function(evt){
- evt.preventDefault();
- })),
- on(node, "dblclick", lang.hitch(this, function(evt){
- event.stop(evt);
- if(has("ie")){
- typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
- setTimeout(lang.hitch(this, typematic.stop), 50);
- }
- }))
- ];
- return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
- },
- addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
- // summary:
- // Start listening for a specific typematic key and mouseclick.
- // This is a thin wrapper to addKeyListener and addMouseListener.
- // See the addMouseListener and addKeyListener methods for other parameters.
- // mouseNode:
- // the DOM node object to listen on for mouse events.
- // keyNode:
- // the DOM node object to listen on for key events.
- // returns:
- // a connection handle
- var handles = [
- this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay),
- this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay)
- ];
- return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
- }
- });
- return typematic;
- });
- },
- 'dijit/MenuItem':function(){
- require({cache:{
- 'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\"\r\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\r\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\r\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\r\n\t</td>\r\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\r\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\r\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\r\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\r\n\t\t</div>\r\n\t</td>\r\n</tr>\r\n"}});
- define("dijit/MenuItem", [
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.setSelectable
- "dojo/dom-attr", // domAttr.set
- "dojo/dom-class", // domClass.toggle
- "dojo/_base/event", // event.stop
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/sniff", // has("ie")
- "./_Widget",
- "./_TemplatedMixin",
- "./_Contained",
- "./_CssStateMixin",
- "dojo/text!./templates/MenuItem.html"
- ], function(declare, dom, domAttr, domClass, event, kernel, has,
- _Widget, _TemplatedMixin, _Contained, _CssStateMixin, template){
- /*=====
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var _Contained = dijit._Contained;
- var _CssStateMixin = dijit._CssStateMixin;
- =====*/
- // module:
- // dijit/MenuItem
- // summary:
- // A line item in a Menu Widget
- return declare("dijit.MenuItem",
- [_Widget, _TemplatedMixin, _Contained, _CssStateMixin],
- {
- // summary:
- // A line item in a Menu Widget
- // Make 3 columns
- // icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
- templateString: template,
- baseClass: "dijitMenuItem",
- // label: String
- // Menu text
- label: '',
- _setLabelAttr: { node: "containerNode", type: "innerHTML" },
- // iconClass: String
- // Class to apply to DOMNode to make it display an icon.
- iconClass: "dijitNoIcon",
- _setIconClassAttr: { node: "iconNode", type: "class" },
- // accelKey: String
- // Text for the accelerator (shortcut) key combination.
- // Note that although Menu can display accelerator keys there
- // is no infrastructure to actually catch and execute these
- // accelerators.
- accelKey: "",
- // disabled: Boolean
- // If true, the menu item is disabled.
- // If false, the menu item is enabled.
- disabled: false,
- _fillContent: function(/*DomNode*/ source){
- // If button label is specified as srcNodeRef.innerHTML rather than
- // this.params.label, handle it here.
- if(source && !("label" in this.params)){
- this.set('label', source.innerHTML);
- }
- },
- buildRendering: function(){
- this.inherited(arguments);
- var label = this.id+"_text";
- domAttr.set(this.containerNode, "id", label);
- if(this.accelKeyNode){
- domAttr.set(this.accelKeyNode, "id", this.id + "_accel");
- label += " " + this.id + "_accel";
- }
- this.domNode.setAttribute("aria-labelledby", label);
- dom.setSelectable(this.domNode, false);
- },
- _onHover: function(){
- // summary:
- // Handler when mouse is moved onto menu item
- // tags:
- // protected
- this.getParent().onItemHover(this);
- },
- _onUnhover: function(){
- // summary:
- // Handler when mouse is moved off of menu item,
- // possibly to a child menu, or maybe to a sibling
- // menuitem or somewhere else entirely.
- // tags:
- // protected
- // if we are unhovering the currently selected item
- // then unselect it
- this.getParent().onItemUnhover(this);
- // When menu is hidden (collapsed) due to clicking a MenuItem and having it execute,
- // FF and IE don't generate an onmouseout event for the MenuItem.
- // So, help out _CssStateMixin in this case.
- this._set("hovering", false);
- },
- _onClick: function(evt){
- // summary:
- // Internal handler for click events on MenuItem.
- // tags:
- // private
- this.getParent().onItemClick(this, evt);
- event.stop(evt);
- },
- onClick: function(/*Event*/){
- // summary:
- // User defined function to handle clicks
- // tags:
- // callback
- },
- focus: function(){
- // summary:
- // Focus on this MenuItem
- try{
- if(has("ie") == 8){
- // needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
- this.containerNode.focus();
- }
- this.focusNode.focus();
- }catch(e){
- // this throws on IE (at least) in some scenarios
- }
- },
- _onFocus: function(){
- // summary:
- // This is called by the focus manager when focus
- // goes to this MenuItem or a child menu.
- // tags:
- // protected
- this._setSelected(true);
- this.getParent()._onItemFocus(this);
- this.inherited(arguments);
- },
- _setSelected: function(selected){
- // summary:
- // Indicate that this node is the currently selected one
- // tags:
- // private
- /***
- * TODO: remove this method and calls to it, when _onBlur() is working for MenuItem.
- * Currently _onBlur() gets called when focus is moved from the MenuItem to a child menu.
- * That's not supposed to happen, but the problem is:
- * In order to allow dijit.popup's getTopPopup() to work,a sub menu's popupParent
- * points to the parent Menu, bypassing the parent MenuItem... thus the
- * MenuItem is not in the chain of active widgets and gets a premature call to
- * _onBlur()
- */
- domClass.toggle(this.domNode, "dijitMenuItemSelected", selected);
- },
- setLabel: function(/*String*/ content){
- // summary:
- // Deprecated. Use set('label', ...) instead.
- // tags:
- // deprecated
- kernel.deprecated("dijit.MenuItem.setLabel() is deprecated. Use set('label', ...) instead.", "", "2.0");
- this.set("label", content);
- },
- setDisabled: function(/*Boolean*/ disabled){
- // summary:
- // Deprecated. Use set('disabled', bool) instead.
- // tags:
- // deprecated
- kernel.deprecated("dijit.Menu.setDisabled() is deprecated. Use set('disabled', bool) instead.", "", "2.0");
- this.set('disabled', disabled);
- },
- _setDisabledAttr: function(/*Boolean*/ value){
- // summary:
- // Hook for attr('disabled', ...) to work.
- // Enable or disable this menu item.
- this.focusNode.setAttribute('aria-disabled', value ? 'true' : 'false');
- this._set("disabled", value);
- },
- _setAccelKeyAttr: function(/*String*/ value){
- // summary:
- // Hook for attr('accelKey', ...) to work.
- // Set accelKey on this menu item.
- this.accelKeyNode.style.display=value?"":"none";
- this.accelKeyNode.innerHTML=value;
- //have to use colSpan to make it work in IE
- domAttr.set(this.containerNode,'colSpan',value?"1":"2");
- this._set("accelKey", value);
- }
- });
- });
- },
- 'dojo/cldr/supplemental':function(){
- define("dojo/cldr/supplemental", ["../_base/kernel", "../_base/lang", "../i18n"], function(dojo, lang) {
- // module:
- // dojo/cldr/supplemental
- // summary:
- // TODOC
- lang.getObject("cldr.supplemental", true, dojo);
- dojo.cldr.supplemental.getFirstDayOfWeek = function(/*String?*/locale){
- // summary: Returns a zero-based index for first day of the week
- // description:
- // Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar.
- // e.g. Sunday (returns 0), or Monday (returns 1)
- // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDay
- var firstDay = {/*default is 1=Monday*/
- mv:5,
- 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,
- ly:6,ma:6,om:6,qa:6,sa:6,sd:6,so:6,sy:6,tn:6,ye:6,
- ar:0,as:0,az:0,bw:0,ca:0,cn:0,fo:0,ge:0,gl:0,gu:0,hk:0,
- il:0,'in':0,jm:0,jp:0,kg:0,kr:0,la:0,mh:0,mn:0,mo:0,mp:0,
- mt:0,nz:0,ph:0,pk:0,sg:0,th:0,tt:0,tw:0,um:0,us:0,uz:0,
- vi:0,zw:0
- // variant. do not use? gb:0,
- };
- var country = dojo.cldr.supplemental._region(locale);
- var dow = firstDay[country];
- return (dow === undefined) ? 1 : dow; /*Number*/
- };
- dojo.cldr.supplemental._region = function(/*String?*/locale){
- locale = dojo.i18n.normalizeLocale(locale);
- var tags = locale.split('-');
- var region = tags[1];
- if(!region){
- // IE often gives language only (#2269)
- // Arbitrary mappings of language-only locales to a country:
- region = {de:"de", en:"us", es:"es", fi:"fi", fr:"fr", he:"il", hu:"hu", it:"it",
- ja:"jp", ko:"kr", nl:"nl", pt:"br", sv:"se", zh:"cn"}[tags[0]];
- }else if(region.length == 4){
- // The ISO 3166 country code is usually in the second position, unless a
- // 4-letter script is given. See http://www.ietf.org/rfc/rfc4646.txt
- region = tags[2];
- }
- return region;
- };
- dojo.cldr.supplemental.getWeekend = function(/*String?*/locale){
- // summary: Returns a hash containing the start and end days of the weekend
- // description:
- // Returns a hash containing the start and end days of the weekend according to local custom using locale,
- // or by default in the user's locale.
- // e.g. {start:6, end:0}
- // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End}
- var weekendStart = {/*default is 6=Saturday*/
- 'in':0,
- af:4,dz:4,ir:4,om:4,sa:4,ye:4,
- 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
- };
- var weekendEnd = {/*default is 0=Sunday*/
- af:5,dz:5,ir:5,om:5,sa:5,ye:5,
- 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
- };
- var country = dojo.cldr.supplemental._region(locale);
- var start = weekendStart[country];
- var end = weekendEnd[country];
- if(start === undefined){start=6;}
- if(end === undefined){end=0;}
- return {start:start, end:end}; /*Object {start,end}*/
- };
- return dojo.cldr.supplemental;
- });
- },
- 'dijit/ToolbarSeparator':function(){
- define("dijit/ToolbarSeparator", [
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.setSelectable
- "./_Widget",
- "./_TemplatedMixin"
- ], function(declare, dom, _Widget, _TemplatedMixin){
- /*=====
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- =====*/
- // module:
- // dijit/ToolbarSeparator
- // summary:
- // A spacer between two `dijit.Toolbar` items
- return declare("dijit.ToolbarSeparator", [_Widget, _TemplatedMixin], {
- // summary:
- // A spacer between two `dijit.Toolbar` items
- templateString: '<div class="dijitToolbarSeparator dijitInline" role="presentation"></div>',
- buildRendering: function(){
- this.inherited(arguments);
- dom.setSelectable(this.domNode, false);
- },
- isFocusable: function(){
- // summary:
- // This widget isn't focusable, so pass along that fact.
- // tags:
- // protected
- return false;
- }
- });
- });
- },
- 'dijit/layout/_LayoutWidget':function(){
- define("dijit/layout/_LayoutWidget", [
- "dojo/_base/lang", // lang.mixin
- "../_Widget",
- "../_Container",
- "../_Contained",
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.add domClass.remove
- "dojo/dom-geometry", // domGeometry.marginBox
- "dojo/dom-style", // domStyle.getComputedStyle
- "dojo/_base/sniff", // has("ie")
- "dojo/_base/window" // win.global
- ], function(lang, _Widget, _Container, _Contained,
- declare, domClass, domGeometry, domStyle, has, win){
- /*=====
- var _Widget = dijit._Widget;
- var _Container = dijit._Container;
- var _Contained = dijit._Contained;
- =====*/
- // module:
- // dijit/layout/_LayoutWidget
- // summary:
- // _LayoutWidget Base class for a _Container widget which is responsible for laying out its children.
- // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
- return declare("dijit.layout._LayoutWidget", [_Widget, _Container, _Contained], {
- // summary:
- // Base class for a _Container widget which is responsible for laying out its children.
- // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
- // baseClass: [protected extension] String
- // This class name is applied to the widget's domNode
- // and also may be used to generate names for sub nodes,
- // for example dijitTabContainer-content.
- baseClass: "dijitLayoutContainer",
- // isLayoutContainer: [protected] Boolean
- // Indicates that this widget is going to call resize() on its
- // children widgets, setting their size, when they become visible.
- isLayoutContainer: true,
- buildRendering: function(){
- this.inherited(arguments);
- domClass.add(this.domNode, "dijitContainer");
- },
- startup: function(){
- // summary:
- // Called after all the widgets have been instantiated and their
- // dom nodes have been inserted somewhere under win.doc.body.
- //
- // Widgets should override this method to do any initialization
- // dependent on other widgets existing, and then call
- // this superclass method to finish things off.
- //
- // startup() in subclasses shouldn't do anything
- // size related because the size of the widget hasn't been set yet.
- if(this._started){ return; }
- // Need to call inherited first - so that child widgets get started
- // up correctly
- this.inherited(arguments);
- // If I am a not being controlled by a parent layout widget...
- var parent = this.getParent && this.getParent();
- if(!(parent && parent.isLayoutContainer)){
- // Do recursive sizing and layout of all my descendants
- // (passing in no argument to resize means that it has to glean the size itself)
- this.resize();
- // Since my parent isn't a layout container, and my style *may be* width=height=100%
- // or something similar (either set directly or via a CSS class),
- // monitor when viewport size changes so that I can re-layout.
- this.connect(win.global, 'onresize', function(){
- // Using function(){} closure to ensure no arguments passed to resize().
- this.resize();
- });
- }
- },
- resize: function(changeSize, resultSize){
- // summary:
- // Call this to resize a widget, or after its size has changed.
- // description:
- // Change size mode:
- // When changeSize is specified, changes the marginBox of this widget
- // and forces it to relayout its contents accordingly.
- // changeSize may specify height, width, or both.
- //
- // If resultSize is specified it indicates the size the widget will
- // become after changeSize has been applied.
- //
- // Notification mode:
- // When changeSize is null, indicates that the caller has already changed
- // the size of the widget, or perhaps it changed because the browser
- // window was resized. Tells widget to relayout its contents accordingly.
- //
- // If resultSize is also specified it indicates the size the widget has
- // become.
- //
- // In either mode, this method also:
- // 1. Sets this._borderBox and this._contentBox to the new size of
- // the widget. Queries the current domNode size if necessary.
- // 2. Calls layout() to resize contents (and maybe adjust child widgets).
- //
- // changeSize: Object?
- // Sets the widget to this margin-box size and position.
- // May include any/all of the following properties:
- // | {w: int, h: int, l: int, t: int}
- //
- // resultSize: Object?
- // The margin-box size of this widget after applying changeSize (if
- // changeSize is specified). If caller knows this size and
- // passes it in, we don't need to query the browser to get the size.
- // | {w: int, h: int}
- var node = this.domNode;
- // set margin box size, unless it wasn't specified, in which case use current size
- if(changeSize){
- domGeometry.setMarginBox(node, changeSize);
- }
- // If either height or width wasn't specified by the user, then query node for it.
- // But note that setting the margin box and then immediately querying dimensions may return
- // inaccurate results, so try not to depend on it.
- var mb = resultSize || {};
- lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
- if( !("h" in mb) || !("w" in mb) ){
- mb = lang.mixin(domGeometry.getMarginBox(node), mb); // just use domGeometry.marginBox() to fill in missing values
- }
- // Compute and save the size of my border box and content box
- // (w/out calling domGeometry.getContentBox() since that may fail if size was recently set)
- var cs = domStyle.getComputedStyle(node);
- var me = domGeometry.getMarginExtents(node, cs);
- var be = domGeometry.getBorderExtents(node, cs);
- var bb = (this._borderBox = {
- w: mb.w - (me.w + be.w),
- h: mb.h - (me.h + be.h)
- });
- var pe = domGeometry.getPadExtents(node, cs);
- this._contentBox = {
- l: domStyle.toPixelValue(node, cs.paddingLeft),
- t: domStyle.toPixelValue(node, cs.paddingTop),
- w: bb.w - pe.w,
- h: bb.h - pe.h
- };
- // Callback for widget to adjust size of its children
- this.layout();
- },
- layout: function(){
- // summary:
- // Widgets override this method to size and position their contents/children.
- // When this is called this._contentBox is guaranteed to be set (see resize()).
- //
- // This is called after startup(), and also when the widget's size has been
- // changed.
- // tags:
- // protected extension
- },
- _setupChild: function(/*dijit._Widget*/child){
- // summary:
- // Common setup for initial children and children which are added after startup
- // tags:
- // protected extension
- var cls = this.baseClass + "-child "
- + (child.baseClass ? this.baseClass + "-" + child.baseClass : "");
- domClass.add(child.domNode, cls);
- },
- addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
- // Overrides _Container.addChild() to call _setupChild()
- this.inherited(arguments);
- if(this._started){
- this._setupChild(child);
- }
- },
- removeChild: function(/*dijit._Widget*/ child){
- // Overrides _Container.removeChild() to remove class added by _setupChild()
- var cls = this.baseClass + "-child"
- + (child.baseClass ?
- " " + this.baseClass + "-" + child.baseClass : "");
- domClass.remove(child.domNode, cls);
- this.inherited(arguments);
- }
- });
- });
- },
- 'dojox/uuid/_base':function(){
- define("dojox/uuid/_base", ['dojo/_base/kernel', 'dojo/_base/lang'], function(dojo){
- dojo.getObject("uuid", true, dojox);
- // Public constants:
- dojox.uuid.NIL_UUID = "00000000-0000-0000-0000-000000000000";
- dojox.uuid.version = {
- // Enumeration for the different UUID versions.
- UNKNOWN: 0,
- TIME_BASED: 1,
- DCE_SECURITY: 2,
- NAME_BASED_MD5: 3,
- RANDOM: 4,
- NAME_BASED_SHA1: 5 };
- dojox.uuid.variant = {
- // Enumeration for the different UUID variants.
- NCS: "0",
- DCE: "10",
- MICROSOFT: "110",
- UNKNOWN: "111" };
- dojox.uuid.assert = function(/*Boolean*/ booleanValue, /*String?*/ message){
- // summary:
- // Throws an exception if the assertion fails.
- // description:
- // If the asserted condition is true, this method does nothing. If the
- // condition is false, we throw an error with a error message.
- // booleanValue: Must be true for the assertion to succeed.
- // message: A string describing the assertion.
- // throws: Throws an Error if 'booleanValue' is false.
- if(!booleanValue){
- if(!message){
- message = "An assert statement failed.\n" +
- "The method dojox.uuid.assert() was called with a 'false' value.\n";
- }
- throw new Error(message);
- }
- };
- dojox.uuid.generateNilUuid = function(){
- // summary:
- // This function returns the Nil UUID: "00000000-0000-0000-0000-000000000000".
- // description:
- // The Nil UUID is described in section 4.1.7 of
- // RFC 4122: http://tools.ietf.org/html/rfc4122#section-4.1.7
- // examples:
- // var string = dojox.uuid.generateNilUuid();
- return dojox.uuid.NIL_UUID; // String
- };
- dojox.uuid.isValid = function(/*String*/ uuidString){
- // summary:
- // Returns true if the UUID was initialized with a valid value.
- uuidString = uuidString.toString();
- var valid = (dojo.isString(uuidString) &&
- (uuidString.length == 36) &&
- (uuidString == uuidString.toLowerCase()));
- if(valid){
- var arrayOfParts = uuidString.split("-");
- valid = ((arrayOfParts.length == 5) &&
- (arrayOfParts[0].length == 8) &&
- (arrayOfParts[1].length == 4) &&
- (arrayOfParts[2].length == 4) &&
- (arrayOfParts[3].length == 4) &&
- (arrayOfParts[4].length == 12));
- var HEX_RADIX = 16;
- for (var i in arrayOfParts) {
- var part = arrayOfParts[i];
- var integer = parseInt(part, HEX_RADIX);
- valid = valid && isFinite(integer);
- }
- }
- return valid; // boolean
- };
- dojox.uuid.getVariant = function(/*String*/ uuidString){
- // summary:
- // Returns a variant code that indicates what type of UUID this is.
- // Returns one of the enumerated dojox.uuid.variant values.
- // example:
- // var variant = dojox.uuid.getVariant("3b12f1df-5232-4804-897e-917bf397618a");
- // dojox.uuid.assert(variant == dojox.uuid.variant.DCE);
- // example:
- // "3b12f1df-5232-4804-897e-917bf397618a"
- // ^
- // |
- // (variant "10__" == DCE)
- if(!dojox.uuid._ourVariantLookupTable){
- var variant = dojox.uuid.variant;
- var lookupTable = [];
- lookupTable[0x0] = variant.NCS; // 0000
- lookupTable[0x1] = variant.NCS; // 0001
- lookupTable[0x2] = variant.NCS; // 0010
- lookupTable[0x3] = variant.NCS; // 0011
- lookupTable[0x4] = variant.NCS; // 0100
- lookupTable[0x5] = variant.NCS; // 0101
- lookupTable[0x6] = variant.NCS; // 0110
- lookupTable[0x7] = variant.NCS; // 0111
- lookupTable[0x8] = variant.DCE; // 1000
- lookupTable[0x9] = variant.DCE; // 1001
- lookupTable[0xA] = variant.DCE; // 1010
- lookupTable[0xB] = variant.DCE; // 1011
- lookupTable[0xC] = variant.MICROSOFT; // 1100
- lookupTable[0xD] = variant.MICROSOFT; // 1101
- lookupTable[0xE] = variant.UNKNOWN; // 1110
- lookupTable[0xF] = variant.UNKNOWN; // 1111
-
- dojox.uuid._ourVariantLookupTable = lookupTable;
- }
- uuidString = uuidString.toString();
- var variantCharacter = uuidString.charAt(19);
- var HEX_RADIX = 16;
- var variantNumber = parseInt(variantCharacter, HEX_RADIX);
- dojox.uuid.assert((variantNumber >= 0) && (variantNumber <= 16));
- return dojox.uuid._ourVariantLookupTable[variantNumber]; // dojox.uuid.variant
- };
- dojox.uuid.getVersion = function(/*String*/ uuidString){
- // summary:
- // Returns a version number that indicates what type of UUID this is.
- // Returns one of the enumerated dojox.uuid.version values.
- // example:
- // var version = dojox.uuid.getVersion("b4308fb0-86cd-11da-a72b-0800200c9a66");
- // dojox.uuid.assert(version == dojox.uuid.version.TIME_BASED);
- // exceptions:
- // Throws an Error if this is not a DCE Variant UUID.
- var errorMessage = "dojox.uuid.getVersion() was not passed a DCE Variant UUID.";
- dojox.uuid.assert(dojox.uuid.getVariant(uuidString) == dojox.uuid.variant.DCE, errorMessage);
- uuidString = uuidString.toString();
-
- // "b4308fb0-86cd-11da-a72b-0800200c9a66"
- // ^
- // |
- // (version 1 == TIME_BASED)
- var versionCharacter = uuidString.charAt(14);
- var HEX_RADIX = 16;
- var versionNumber = parseInt(versionCharacter, HEX_RADIX);
- return versionNumber; // dojox.uuid.version
- };
- dojox.uuid.getNode = function(/*String*/ uuidString){
- // summary:
- // If this is a version 1 UUID (a time-based UUID), getNode() returns a
- // 12-character string with the "node" or "pseudonode" portion of the UUID,
- // which is the rightmost 12 characters.
- // exceptions:
- // Throws an Error if this is not a version 1 UUID.
- var errorMessage = "dojox.uuid.getNode() was not passed a TIME_BASED UUID.";
- dojox.uuid.assert(dojox.uuid.getVersion(uuidString) == dojox.uuid.version.TIME_BASED, errorMessage);
- uuidString = uuidString.toString();
- var arrayOfStrings = uuidString.split('-');
- var nodeString = arrayOfStrings[4];
- return nodeString; // String (a 12-character string, which will look something like "917bf397618a")
- };
- dojox.uuid.getTimestamp = function(/*String*/ uuidString, /*String?*/ returnType){
- // summary:
- // If this is a version 1 UUID (a time-based UUID), this method returns
- // the timestamp value encoded in the UUID. The caller can ask for the
- // timestamp to be returned either as a JavaScript Date object or as a
- // 15-character string of hex digits.
- // returnType: Any of these five values: "string", String, "hex", "date", Date
- // returns:
- // Returns the timestamp value as a JavaScript Date object or a 15-character string of hex digits.
- // examples:
- // var uuidString = "b4308fb0-86cd-11da-a72b-0800200c9a66";
- // var date, string, hexString;
- // date = dojox.uuid.getTimestamp(uuidString); // returns a JavaScript Date
- // date = dojox.uuid.getTimestamp(uuidString, Date); //
- // string = dojox.uuid.getTimestamp(uuidString, String); // "Mon, 16 Jan 2006 20:21:41 GMT"
- // hexString = dojox.uuid.getTimestamp(uuidString, "hex"); // "1da86cdb4308fb0"
- // exceptions:
- // Throws an Error if this is not a version 1 UUID.
- var errorMessage = "dojox.uuid.getTimestamp() was not passed a TIME_BASED UUID.";
- dojox.uuid.assert(dojox.uuid.getVersion(uuidString) == dojox.uuid.version.TIME_BASED, errorMessage);
-
- uuidString = uuidString.toString();
- if(!returnType){returnType = null};
- switch(returnType){
- case "string":
- case String:
- return dojox.uuid.getTimestamp(uuidString, Date).toUTCString(); // String (e.g. "Mon, 16 Jan 2006 20:21:41 GMT")
- break;
- case "hex":
- // Return a 15-character string of hex digits containing the
- // timestamp for this UUID, with the high-order bits first.
- var arrayOfStrings = uuidString.split('-');
- var hexTimeLow = arrayOfStrings[0];
- var hexTimeMid = arrayOfStrings[1];
- var hexTimeHigh = arrayOfStrings[2];
-
- // Chop off the leading "1" character, which is the UUID
- // version number for time-based UUIDs.
- hexTimeHigh = hexTimeHigh.slice(1);
-
- var timestampAsHexString = hexTimeHigh + hexTimeMid + hexTimeLow;
- dojox.uuid.assert(timestampAsHexString.length == 15);
- return timestampAsHexString; // String (e.g. "1da86cdb4308fb0")
- break;
- case null: // no returnType was specified, so default to Date
- case "date":
- case Date:
- // Return a JavaScript Date object.
- var GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
- var HEX_RADIX = 16;
-
- var arrayOfParts = uuidString.split('-');
- var timeLow = parseInt(arrayOfParts[0], HEX_RADIX);
- var timeMid = parseInt(arrayOfParts[1], HEX_RADIX);
- var timeHigh = parseInt(arrayOfParts[2], HEX_RADIX);
- var hundredNanosecondIntervalsSince1582 = timeHigh & 0x0FFF;
- hundredNanosecondIntervalsSince1582 <<= 16;
- hundredNanosecondIntervalsSince1582 += timeMid;
- // What we really want to do next is shift left 32 bits, but the
- // result will be too big to fit in an int, so we'll multiply by 2^32,
- // and the result will be a floating point approximation.
- hundredNanosecondIntervalsSince1582 *= 0x100000000;
- hundredNanosecondIntervalsSince1582 += timeLow;
- var millisecondsSince1582 = hundredNanosecondIntervalsSince1582 / 10000;
-
- // Again, this will be a floating point approximation.
- // We can make things exact later if we need to.
- var secondsPerHour = 60 * 60;
- var hoursBetween1582and1970 = GREGORIAN_CHANGE_OFFSET_IN_HOURS;
- var secondsBetween1582and1970 = hoursBetween1582and1970 * secondsPerHour;
- var millisecondsBetween1582and1970 = secondsBetween1582and1970 * 1000;
- var millisecondsSince1970 = millisecondsSince1582 - millisecondsBetween1582and1970;
-
- var timestampAsDate = new Date(millisecondsSince1970);
- return timestampAsDate; // Date
- break;
- default:
- // we got passed something other than a valid returnType
- dojox.uuid.assert(false, "dojox.uuid.getTimestamp was not passed a valid returnType: " + returnType);
- break;
- }
- };
- return dojox.uuid;
- });
- },
- 'dijit/popup':function(){
- define("dijit/popup", [
- "dojo/_base/array", // array.forEach array.some
- "dojo/aspect",
- "dojo/_base/connect", // connect._keypress
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.isDescendant
- "dojo/dom-attr", // domAttr.set
- "dojo/dom-construct", // domConstruct.create domConstruct.destroy
- "dojo/dom-geometry", // domGeometry.isBodyLtr
- "dojo/dom-style", // domStyle.set
- "dojo/_base/event", // event.stop
- "dojo/keys",
- "dojo/_base/lang", // lang.hitch
- "dojo/on",
- "dojo/_base/sniff", // has("ie") has("mozilla")
- "dojo/_base/window", // win.body
- "./place",
- "./BackgroundIframe",
- "." // dijit (defining dijit.popup to match API doc)
- ], function(array, aspect, connect, declare, dom, domAttr, domConstruct, domGeometry, domStyle, event, keys, lang, on, has, win,
- place, BackgroundIframe, dijit){
- // module:
- // dijit/popup
- // summary:
- // Used to show drop downs (ex: the select list of a ComboBox)
- // or popups (ex: right-click context menus)
- /*=====
- dijit.popup.__OpenArgs = function(){
- // popup: Widget
- // widget to display
- // parent: Widget
- // the button etc. that is displaying this popup
- // around: DomNode
- // DOM node (typically a button); place popup relative to this node. (Specify this *or* "x" and "y" parameters.)
- // x: Integer
- // Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
- // y: Integer
- // Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
- // orient: Object|String
- // When the around parameter is specified, orient should be a list of positions to try, ex:
- // | [ "below", "above" ]
- // For backwards compatibility it can also be an (ordered) hash of tuples of the form
- // (around-node-corner, popup-node-corner), ex:
- // | { "BL": "TL", "TL": "BL" }
- // where BL means "bottom left" and "TL" means "top left", etc.
- //
- // dijit.popup.open() tries to position the popup according to each specified position, in order,
- // until the popup appears fully within the viewport.
- //
- // The default value is ["below", "above"]
- //
- // When an (x,y) position is specified rather than an around node, orient is either
- // "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
- // specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
- // fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
- // and the top-right corner.
- // onCancel: Function
- // callback when user has canceled the popup by
- // 1. hitting ESC or
- // 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
- // i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
- // onClose: Function
- // callback whenever this popup is closed
- // onExecute: Function
- // callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
- // padding: dijit.__Position
- // adding a buffer around the opening position. This is only useful when around is not set.
- this.popup = popup;
- this.parent = parent;
- this.around = around;
- this.x = x;
- this.y = y;
- this.orient = orient;
- this.onCancel = onCancel;
- this.onClose = onClose;
- this.onExecute = onExecute;
- this.padding = padding;
- }
- =====*/
- /*=====
- dijit.popup = {
- // summary:
- // Used to show drop downs (ex: the select list of a ComboBox)
- // or popups (ex: right-click context menus).
- //
- // Access via require(["dijit/popup"], function(popup){ ... }).
- moveOffScreen: function(widget){
- // summary:
- // Moves the popup widget off-screen.
- // Do not use this method to hide popups when not in use, because
- // that will create an accessibility issue: the offscreen popup is
- // still in the tabbing order.
- // widget: dijit._WidgetBase
- // The widget
- },
- hide: function(widget){
- // summary:
- // Hide this popup widget (until it is ready to be shown).
- // Initialization for widgets that will be used as popups
- //
- // Also puts widget inside a wrapper DIV (if not already in one)
- //
- // If popup widget needs to layout it should
- // do so when it is made visible, and popup._onShow() is called.
- // widget: dijit._WidgetBase
- // The widget
- },
- open: function(args){
- // summary:
- // Popup the widget at the specified position
- // example:
- // opening at the mouse position
- // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
- // example:
- // opening the widget as a dropdown
- // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
- //
- // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
- // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
- // args: dijit.popup.__OpenArgs
- // Parameters
- return {}; // Object specifying which position was chosen
- },
- close: function(popup){
- // summary:
- // Close specified popup and any popups that it parented.
- // If no popup is specified, closes all popups.
- // widget: dijit._WidgetBase?
- // The widget, optional
- }
- };
- =====*/
- function destroyWrapper(){
- // summary:
- // Function to destroy wrapper when popup widget is destroyed.
- // Left in this scope to avoid memory leak on IE8 on refresh page, see #15206.
- if(this._popupWrapper){
- domConstruct.destroy(this._popupWrapper);
- delete this._popupWrapper;
- }
- }
- var PopupManager = declare(null, {
- // _stack: dijit._Widget[]
- // Stack of currently popped up widgets.
- // (someone opened _stack[0], and then it opened _stack[1], etc.)
- _stack: [],
- // _beginZIndex: Number
- // Z-index of the first popup. (If first popup opens other
- // popups they get a higher z-index.)
- _beginZIndex: 1000,
- _idGen: 1,
- _createWrapper: function(/*Widget*/ widget){
- // summary:
- // Initialization for widgets that will be used as popups.
- // Puts widget inside a wrapper DIV (if not already in one),
- // and returns pointer to that wrapper DIV.
- var wrapper = widget._popupWrapper,
- node = widget.domNode;
- if(!wrapper){
- // Create wrapper <div> for when this widget [in the future] will be used as a popup.
- // This is done early because of IE bugs where creating/moving DOM nodes causes focus
- // to go wonky, see tests/robot/Toolbar.html to reproduce
- wrapper = domConstruct.create("div", {
- "class":"dijitPopup",
- style:{ display: "none"},
- role: "presentation"
- }, win.body());
- wrapper.appendChild(node);
- var s = node.style;
- s.display = "";
- s.visibility = "";
- s.position = "";
- s.top = "0px";
- widget._popupWrapper = wrapper;
- aspect.after(widget, "destroy", destroyWrapper, true);
- }
- return wrapper;
- },
- moveOffScreen: function(/*Widget*/ widget){
- // summary:
- // Moves the popup widget off-screen.
- // Do not use this method to hide popups when not in use, because
- // that will create an accessibility issue: the offscreen popup is
- // still in the tabbing order.
- // Create wrapper if not already there
- var wrapper = this._createWrapper(widget);
- domStyle.set(wrapper, {
- visibility: "hidden",
- top: "-9999px", // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
- display: ""
- });
- },
- hide: function(/*Widget*/ widget){
- // summary:
- // Hide this popup widget (until it is ready to be shown).
- // Initialization for widgets that will be used as popups
- //
- // Also puts widget inside a wrapper DIV (if not already in one)
- //
- // If popup widget needs to layout it should
- // do so when it is made visible, and popup._onShow() is called.
- // Create wrapper if not already there
- var wrapper = this._createWrapper(widget);
- domStyle.set(wrapper, "display", "none");
- },
- getTopPopup: function(){
- // summary:
- // Compute the closest ancestor popup that's *not* a child of another popup.
- // Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
- var stack = this._stack;
- for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
- /* do nothing, just trying to get right value for pi */
- }
- return stack[pi];
- },
- open: function(/*dijit.popup.__OpenArgs*/ args){
- // summary:
- // Popup the widget at the specified position
- //
- // example:
- // opening at the mouse position
- // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
- //
- // example:
- // opening the widget as a dropdown
- // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
- //
- // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
- // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
- var stack = this._stack,
- widget = args.popup,
- orient = args.orient || ["below", "below-alt", "above", "above-alt"],
- ltr = args.parent ? args.parent.isLeftToRight() : domGeometry.isBodyLtr(),
- around = args.around,
- id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
- // If we are opening a new popup that isn't a child of a currently opened popup, then
- // close currently opened popup(s). This should happen automatically when the old popups
- // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198].
- while(stack.length && (!args.parent || !dom.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){
- this.close(stack[stack.length-1].widget);
- }
- // Get pointer to popup wrapper, and create wrapper if it doesn't exist
- var wrapper = this._createWrapper(widget);
- domAttr.set(wrapper, {
- id: id,
- style: {
- zIndex: this._beginZIndex + stack.length
- },
- "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
- dijitPopupParent: args.parent ? args.parent.id : ""
- });
- if(has("ie") || has("mozilla")){
- if(!widget.bgIframe){
- // setting widget.bgIframe triggers cleanup in _Widget.destroy()
- widget.bgIframe = new BackgroundIframe(wrapper);
- }
- }
- // position the wrapper node and make it visible
- var best = around ?
- place.around(wrapper, around, orient, ltr, widget.orient ? lang.hitch(widget, "orient") : null) :
- place.at(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
- wrapper.style.display = "";
- wrapper.style.visibility = "visible";
- widget.domNode.style.visibility = "visible"; // counteract effects from _HasDropDown
- var handlers = [];
- // provide default escape and tab key handling
- // (this will work for any widget, not just menu)
- handlers.push(on(wrapper, connect._keypress, lang.hitch(this, function(evt){
- if(evt.charOrCode == keys.ESCAPE && args.onCancel){
- event.stop(evt);
- args.onCancel();
- }else if(evt.charOrCode === keys.TAB){
- event.stop(evt);
- var topPopup = this.getTopPopup();
- if(topPopup && topPopup.onCancel){
- topPopup.onCancel();
- }
- }
- })));
- // watch for cancel/execute events on the popup and notify the caller
- // (for a menu, "execute" means clicking an item)
- if(widget.onCancel && args.onCancel){
- handlers.push(widget.on("cancel", args.onCancel));
- }
- handlers.push(widget.on(widget.onExecute ? "execute" : "change", lang.hitch(this, function(){
- var topPopup = this.getTopPopup();
- if(topPopup && topPopup.onExecute){
- topPopup.onExecute();
- }
- })));
- stack.push({
- widget: widget,
- parent: args.parent,
- onExecute: args.onExecute,
- onCancel: args.onCancel,
- onClose: args.onClose,
- handlers: handlers
- });
- if(widget.onOpen){
- // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
- widget.onOpen(best);
- }
- return best;
- },
- close: function(/*Widget?*/ popup){
- // summary:
- // Close specified popup and any popups that it parented.
- // If no popup is specified, closes all popups.
- var stack = this._stack;
- // Basically work backwards from the top of the stack closing popups
- // until we hit the specified popup, but IIRC there was some issue where closing
- // a popup would cause others to close too. Thus if we are trying to close B in [A,B,C]
- // closing C might close B indirectly and then the while() condition will run where stack==[A]...
- // so the while condition is constructed defensively.
- while((popup && array.some(stack, function(elem){return elem.widget == popup;})) ||
- (!popup && stack.length)){
- var top = stack.pop(),
- widget = top.widget,
- onClose = top.onClose;
- if(widget.onClose){
- // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
- widget.onClose();
- }
- var h;
- while(h = top.handlers.pop()){ h.remove(); }
- // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc.
- if(widget && widget.domNode){
- this.hide(widget);
- }
- if(onClose){
- onClose();
- }
- }
- }
- });
- return (dijit.popup = new PopupManager());
- });
- },
- 'dijit/_base/manager':function(){
- define("dijit/_base/manager", [
- "dojo/_base/array",
- "dojo/_base/config", // defaultDuration
- "../registry",
- ".." // for setting exports to dijit namespace
- ], function(array, config, registry, dijit){
- // module:
- // dijit/_base/manager
- // summary:
- // Shim to methods on registry, plus a few other declarations.
- // New code should access dijit/registry directly when possible.
- /*=====
- dijit.byId = function(id){
- // summary:
- // Returns a widget by it's id, or if passed a widget, no-op (like dom.byId())
- // id: String|dijit._Widget
- return registry.byId(id); // dijit._Widget
- };
- dijit.getUniqueId = function(widgetType){
- // summary:
- // Generates a unique id for a given widgetType
- // widgetType: String
- return registry.getUniqueId(widgetType); // String
- };
- dijit.findWidgets = function(root){
- // summary:
- // Search subtree under root returning widgets found.
- // Doesn't search for nested widgets (ie, widgets inside other widgets).
- // root: DOMNode
- return registry.findWidgets(root);
- };
- dijit._destroyAll = function(){
- // summary:
- // Code to destroy all widgets and do other cleanup on page unload
- return registry._destroyAll();
- };
- dijit.byNode = function(node){
- // summary:
- // Returns the widget corresponding to the given DOMNode
- // node: DOMNode
- return registry.byNode(node); // dijit._Widget
- };
- dijit.getEnclosingWidget = function(node){
- // summary:
- // Returns the widget whose DOM tree contains the specified DOMNode, or null if
- // the node is not contained within the DOM tree of any widget
- // node: DOMNode
- return registry.getEnclosingWidget(node);
- };
- =====*/
- array.forEach(["byId", "getUniqueId", "findWidgets", "_destroyAll", "byNode", "getEnclosingWidget"], function(name){
- dijit[name] = registry[name];
- });
- /*=====
- dojo.mixin(dijit, {
- // defaultDuration: Integer
- // The default fx.animation speed (in ms) to use for all Dijit
- // transitional fx.animations, unless otherwise specified
- // on a per-instance basis. Defaults to 200, overrided by
- // `djConfig.defaultDuration`
- defaultDuration: 200
- });
- =====*/
- dijit.defaultDuration = config["defaultDuration"] || 200;
- return dijit;
- });
- },
- 'dojox/grid/enhanced/plugins/_SelectionPreserver':function(){
- define("dojox/grid/enhanced/plugins/_SelectionPreserver", [
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/connect",
- '../../_SelectionPreserver'
- ], function(declare, lang, connect, _SelectionPreserver){
- return declare("dojox.grid.enhanced.plugins._SelectionPreserver", _SelectionPreserver, {
- // summary:
- // Preserve selections across various user actions.
- //
- // description:
- // Extends dojox.grid._SelectionPreserver adding a bit more support to make selection persistence working well
- // with various EnhancedGrid features, e.g. filtering, nested sorting, pagination, select all etc.
- //
- // Precondition - Identifier(id) is required for store, as id is used for differentiating row items.
- // Known issue - The preserved selections might be inaccurate if some unloaded rows are previously selected by range(e.g.SHIFT + click)
- //
- // example:
- // | //To turn on this - set 'keepSelection' attribute to true
- // | <div dojoType="dojox.grid.EnhancedGrid" keepSelection = true .../>
-
- constructor: function(selection){
- var grid = this.grid;
- grid.onSelectedById = this.onSelectedById;
- this._oldClearData = grid._clearData;
- var self = this;
- grid._clearData = function(){
- self._updateMapping(!grid._noInternalMapping);
- self._trustSelection = [];
- self._oldClearData.apply(grid, arguments);
- };
- this._connects.push(
- connect.connect(selection, 'selectRange', lang.hitch(this, '_updateMapping', true, true, false)),
- connect.connect(selection, 'deselectRange', lang.hitch(this, '_updateMapping', true, false, false)),
- connect.connect(selection, 'deselectAll', lang.hitch(this, '_updateMapping', true, false, true))
- );
- },
- destroy: function(){
- this.inherited(arguments);
- this.grid._clearData = this._oldClearData;
- },
- reset: function(){
- this.inherited(arguments);
- this._idMap = [];
- this._trustSelection = [];
- this._defaultSelected = false;
- },
- _reSelectById: function(item, index){
- // summary:
- // Overwritten
- var s = this.selection, g = this.grid;
- if(item && g._hasIdentity){
- var id = g.store.getIdentity(item);
- if(this._selectedById[id] === undefined){
- if(!this._trustSelection[index]){
- s.selected[index] = this._defaultSelected;
- }
- }else{
- s.selected[index] = this._selectedById[id];
- }
- this._idMap.push(id);
- g.onSelectedById(id, index, s.selected[index]);
- }
- },
- _selectById: function(toSelect, inItemOrIndex){
- // summary:
- // Overwritten
- if(!this.inherited(arguments)){
- this._trustSelection[inItemOrIndex] = true;
- }
- },
- onSelectedById: function(id, rowIndex, value){},
-
- _updateMapping: function(trustSelection, isSelect, isForAll, from, to){
- // summary:
- // This function try to keep the selection info updated when range selection is performed.
- // 1. Calculate how many unloaded rows are there;
- // 2. update _selectedById data if grid.selection._selected can be trusted, so loaded but unselected rows can
- // be properly recorded.
- var s = this.selection, g = this.grid, flag = 0, unloaded = 0, i, id;
- for(i = g.rowCount - 1; i >= 0; --i){
- if(!g._by_idx[i]){
- ++unloaded;
- flag += s.selected[i] ? 1 : -1;
- }else{
- id = g._by_idx[i].idty;
- if(id && (trustSelection || this._selectedById[id] === undefined)){
- this._selectedById[id] = !!s.selected[i];
- }
- }
- }
- if(unloaded){
- this._defaultSelected = flag > 0;
- }
- if(!isForAll && from !== undefined && to !== undefined){
- isForAll = !g.usingPagination && Math.abs(to - from + 1) === g.rowCount;
- }
- // When deselectAll, make sure every thing is deselected, even if it was selected but not loaded now.
- // This occurs only when pagination's "All" is used.
- if(isForAll && (!g.usingPagination || g.selectionMode === 'single')){
- for(i = this._idMap.length - 1; i >= 0; --i){
- this._selectedById[this._idMap[i]] = isSelect;
- }
- }
- }
- });
- });
- },
- 'dojox/grid/_RowManager':function(){
- define("dojox/grid/_RowManager", [
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/dom-class"
- ], function(declare, lang, domClass){
- var setStyleText = function(inNode, inStyleText){
- if(inNode.style.cssText == undefined){
- inNode.setAttribute("style", inStyleText);
- }else{
- inNode.style.cssText = inStyleText;
- }
- };
- return declare("dojox.grid._RowManager", null, {
- // Stores information about grid rows. Owned by grid and used internally.
- constructor: function(inGrid){
- this.grid = inGrid;
- },
- linesToEms: 2,
- overRow: -2,
- // styles
- prepareStylingRow: function(inRowIndex, inRowNode){
- return {
- index: inRowIndex,
- node: inRowNode,
- odd: Boolean(inRowIndex&1),
- selected: !!this.grid.selection.isSelected(inRowIndex),
- over: this.isOver(inRowIndex),
- customStyles: "",
- customClasses: "dojoxGridRow"
- };
- },
- styleRowNode: function(inRowIndex, inRowNode){
- var row = this.prepareStylingRow(inRowIndex, inRowNode);
- this.grid.onStyleRow(row);
- this.applyStyles(row);
- },
- applyStyles: function(inRow){
- var i = inRow;
- i.node.className = i.customClasses;
- var h = i.node.style.height;
- setStyleText(i.node, i.customStyles + ';' + (i.node._style||''));
- i.node.style.height = h;
- },
- updateStyles: function(inRowIndex){
- this.grid.updateRowStyles(inRowIndex);
- },
- // states and events
- setOverRow: function(inRowIndex){
- var last = this.overRow;
- this.overRow = inRowIndex;
- if((last!=this.overRow)&&(lang.isString(last) || last >= 0)){
- this.updateStyles(last);
- }
- this.updateStyles(this.overRow);
- },
- isOver: function(inRowIndex){
- return (this.overRow == inRowIndex && !domClass.contains(this.grid.domNode, "dojoxGridColumnResizing"));
- }
- });
- });
- },
- 'dojo/dnd/Mover':function(){
- define("dojo/dnd/Mover", ["../main", "../Evented", "../touch", "./common", "./autoscroll"], function(dojo, Evented, touch) {
- // module:
- // dojo/dnd/Mover
- // summary:
- // TODOC
- dojo.declare("dojo.dnd.Mover", [Evented], {
- constructor: function(node, e, host){
- // summary:
- // an object which makes a node follow the mouse, or touch-drag on touch devices.
- // Used as a default mover, and as a base class for custom movers.
- // node: Node
- // a node (or node's id) to be moved
- // e: Event
- // a mouse event, which started the move;
- // only pageX and pageY properties are used
- // host: Object?
- // object which implements the functionality of the move,
- // and defines proper events (onMoveStart and onMoveStop)
- this.node = dojo.byId(node);
- this.marginBox = {l: e.pageX, t: e.pageY};
- this.mouseButton = e.button;
- var h = (this.host = host), d = node.ownerDocument;
- this.events = [
- // At the start of a drag, onFirstMove is called, and then the following two
- // connects are disconnected
- dojo.connect(d, touch.move, this, "onFirstMove"),
- // These are called continually during the drag
- dojo.connect(d, touch.move, this, "onMouseMove"),
- // And these are called at the end of the drag
- dojo.connect(d, touch.release, this, "onMouseUp"),
- // cancel text selection and text dragging
- dojo.connect(d, "ondragstart", dojo.stopEvent),
- dojo.connect(d.body, "onselectstart", dojo.stopEvent)
- ];
- // notify that the move has started
- if(h && h.onMoveStart){
- h.onMoveStart(this);
- }
- },
- // mouse event processors
- onMouseMove: function(e){
- // summary:
- // event processor for onmousemove/ontouchmove
- // e: Event
- // mouse/touch event
- dojo.dnd.autoScroll(e);
- var m = this.marginBox;
- this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e);
- dojo.stopEvent(e);
- },
- onMouseUp: function(e){
- if(dojo.isWebKit && dojo.isMac && this.mouseButton == 2 ?
- e.button == 0 : this.mouseButton == e.button){ // TODO Should condition be met for touch devices, too?
- this.destroy();
- }
- dojo.stopEvent(e);
- },
- // utilities
- onFirstMove: function(e){
- // summary:
- // makes the node absolute; it is meant to be called only once.
- // relative and absolutely positioned nodes are assumed to use pixel units
- var s = this.node.style, l, t, h = this.host;
- switch(s.position){
- case "relative":
- case "absolute":
- // assume that left and top values are in pixels already
- l = Math.round(parseFloat(s.left)) || 0;
- t = Math.round(parseFloat(s.top)) || 0;
- break;
- default:
- s.position = "absolute"; // enforcing the absolute mode
- var m = dojo.marginBox(this.node);
- // event.pageX/pageY (which we used to generate the initial
- // margin box) includes padding and margin set on the body.
- // However, setting the node's position to absolute and then
- // doing dojo.marginBox on it *doesn't* take that additional
- // space into account - so we need to subtract the combined
- // padding and margin. We use getComputedStyle and
- // _getMarginBox/_getContentBox to avoid the extra lookup of
- // the computed style.
- var b = dojo.doc.body;
- var bs = dojo.getComputedStyle(b);
- var bm = dojo._getMarginBox(b, bs);
- var bc = dojo._getContentBox(b, bs);
- l = m.l - (bc.l - bm.l);
- t = m.t - (bc.t - bm.t);
- break;
- }
- this.marginBox.l = l - this.marginBox.l;
- this.marginBox.t = t - this.marginBox.t;
- if(h && h.onFirstMove){
- h.onFirstMove(this, e);
- }
- // Disconnect onmousemove and ontouchmove events that call this function
- dojo.disconnect(this.events.shift());
- },
- destroy: function(){
- // summary:
- // stops the move, deletes all references, so the object can be garbage-collected
- dojo.forEach(this.events, dojo.disconnect);
- // undo global settings
- var h = this.host;
- if(h && h.onMoveStop){
- h.onMoveStop(this);
- }
- // destroy objects
- this.events = this.node = this.host = null;
- }
- });
- return dojo.dnd.Mover;
- });
- },
- 'dijit/BackgroundIframe':function(){
- define("dijit/BackgroundIframe", [
- "require", // require.toUrl
- ".", // to export dijit.BackgroundIframe
- "dojo/_base/config",
- "dojo/dom-construct", // domConstruct.create
- "dojo/dom-style", // domStyle.set
- "dojo/_base/lang", // lang.extend lang.hitch
- "dojo/on",
- "dojo/_base/sniff", // has("ie"), has("mozilla"), has("quirks")
- "dojo/_base/window" // win.doc.createElement
- ], function(require, dijit, config, domConstruct, domStyle, lang, on, has, win){
- // module:
- // dijit/BackgroundIFrame
- // summary:
- // new dijit.BackgroundIframe(node)
- // Makes a background iframe as a child of node, that fills
- // area (and position) of node
- // TODO: remove _frames, it isn't being used much, since popups never release their
- // iframes (see [22236])
- var _frames = new function(){
- // summary:
- // cache of iframes
- var queue = [];
- this.pop = function(){
- var iframe;
- if(queue.length){
- iframe = queue.pop();
- iframe.style.display="";
- }else{
- if(has("ie") < 9){
- var burl = config["dojoBlankHtmlUrl"] || require.toUrl("dojo/resources/blank.html") || "javascript:\"\"";
- var html="<iframe src='" + burl + "' role='presentation'"
- + " style='position: absolute; left: 0px; top: 0px;"
- + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
- iframe = win.doc.createElement(html);
- }else{
- iframe = domConstruct.create("iframe");
- iframe.src = 'javascript:""';
- iframe.className = "dijitBackgroundIframe";
- iframe.setAttribute("role", "presentation");
- domStyle.set(iframe, "opacity", 0.1);
- }
- iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didn't work.
- }
- return iframe;
- };
- this.push = function(iframe){
- iframe.style.display="none";
- queue.push(iframe);
- }
- }();
- dijit.BackgroundIframe = function(/*DomNode*/ node){
- // summary:
- // For IE/FF z-index schenanigans. id attribute is required.
- //
- // description:
- // new dijit.BackgroundIframe(node)
- // Makes a background iframe as a child of node, that fills
- // area (and position) of node
- if(!node.id){ throw new Error("no id"); }
- if(has("ie") || has("mozilla")){
- var iframe = (this.iframe = _frames.pop());
- node.appendChild(iframe);
- if(has("ie")<7 || has("quirks")){
- this.resize(node);
- this._conn = on(node, 'resize', lang.hitch(this, function(){
- this.resize(node);
- }));
- }else{
- domStyle.set(iframe, {
- width: '100%',
- height: '100%'
- });
- }
- }
- };
- lang.extend(dijit.BackgroundIframe, {
- resize: function(node){
- // summary:
- // Resize the iframe so it's the same size as node.
- // Needed on IE6 and IE/quirks because height:100% doesn't work right.
- if(this.iframe){
- domStyle.set(this.iframe, {
- width: node.offsetWidth + 'px',
- height: node.offsetHeight + 'px'
- });
- }
- },
- destroy: function(){
- // summary:
- // destroy the iframe
- if(this._conn){
- this._conn.remove();
- this._conn = null;
- }
- if(this.iframe){
- _frames.push(this.iframe);
- delete this.iframe;
- }
- }
- });
- return dijit.BackgroundIframe;
- });
- },
- 'dojo/dnd/Avatar':function(){
- define("dojo/dnd/Avatar", ["../main", "./common"], function(dojo) {
- // module:
- // dojo/dnd/Avatar
- // summary:
- // TODOC
- dojo.declare("dojo.dnd.Avatar", null, {
- // summary:
- // Object that represents transferred DnD items visually
- // manager: Object
- // a DnD manager object
- constructor: function(manager){
- this.manager = manager;
- this.construct();
- },
- // methods
- construct: function(){
- // summary:
- // constructor function;
- // it is separate so it can be (dynamically) overwritten in case of need
- this.isA11y = dojo.hasClass(dojo.body(),"dijit_a11y");
- var a = dojo.create("table", {
- "class": "dojoDndAvatar",
- style: {
- position: "absolute",
- zIndex: "1999",
- margin: "0px"
- }
- }),
- source = this.manager.source, node,
- b = dojo.create("tbody", null, a),
- tr = dojo.create("tr", null, b),
- td = dojo.create("td", null, tr),
- icon = this.isA11y ? dojo.create("span", {
- id : "a11yIcon",
- innerHTML : this.manager.copy ? '+' : "<"
- }, td) : null,
- span = dojo.create("span", {
- innerHTML: source.generateText ? this._generateText() : ""
- }, td),
- k = Math.min(5, this.manager.nodes.length), i = 0;
- // we have to set the opacity on IE only after the node is live
- dojo.attr(tr, {
- "class": "dojoDndAvatarHeader",
- style: {opacity: 0.9}
- });
- for(; i < k; ++i){
- if(source.creator){
- // create an avatar representation of the node
- node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node;
- }else{
- // or just clone the node and hope it works
- node = this.manager.nodes[i].cloneNode(true);
- if(node.tagName.toLowerCase() == "tr"){
- // insert extra table nodes
- var table = dojo.create("table"),
- tbody = dojo.create("tbody", null, table);
- tbody.appendChild(node);
- node = table;
- }
- }
- node.id = "";
- tr = dojo.create("tr", null, b);
- td = dojo.create("td", null, tr);
- td.appendChild(node);
- dojo.attr(tr, {
- "class": "dojoDndAvatarItem",
- style: {opacity: (9 - i) / 10}
- });
- }
- this.node = a;
- },
- destroy: function(){
- // summary:
- // destructor for the avatar; called to remove all references so it can be garbage-collected
- dojo.destroy(this.node);
- this.node = false;
- },
- update: function(){
- // summary:
- // updates the avatar to reflect the current DnD state
- dojo[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop");
- if (this.isA11y){
- var icon = dojo.byId("a11yIcon");
- var text = '+'; // assume canDrop && copy
- if (this.manager.canDropFlag && !this.manager.copy) {
- text = '< '; // canDrop && move
- }else if (!this.manager.canDropFlag && !this.manager.copy) {
- text = "o"; //!canDrop && move
- }else if(!this.manager.canDropFlag){
- text = 'x'; // !canDrop && copy
- }
- icon.innerHTML=text;
- }
- // replace text
- dojo.query(("tr.dojoDndAvatarHeader td span" +(this.isA11y ? " span" : "")), this.node).forEach(
- function(node){
- node.innerHTML = this._generateText();
- }, this);
- },
- _generateText: function(){
- // summary: generates a proper text to reflect copying or moving of items
- return this.manager.nodes.length.toString();
- }
- });
- return dojo.dnd.Avatar;
- });
- },
- 'dijit/form/_Spinner':function(){
- require({cache:{
- 'url:dijit/form/templates/Spinner.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\" role=\"presentation\"\r\n\t><div class=\"dijitReset dijitButtonNode dijitSpinnerButtonContainer\"\r\n\t\t><input class=\"dijitReset dijitInputField dijitSpinnerButtonInner\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t/><div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton\"\r\n\t\t\tdata-dojo-attach-point=\"upArrowNode\"\r\n\t\t\t><div class=\"dijitArrowButtonInner\"\r\n\t\t\t\t><input class=\"dijitReset dijitInputField\" value=\"▲\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t\t\t${_buttonInputDisabled}\r\n\t\t\t/></div\r\n\t\t></div\r\n\t\t><div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton\"\r\n\t\t\tdata-dojo-attach-point=\"downArrowNode\"\r\n\t\t\t><div class=\"dijitArrowButtonInner\"\r\n\t\t\t\t><input class=\"dijitReset dijitInputField\" value=\"▼\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t\t\t${_buttonInputDisabled}\r\n\t\t\t/></div\r\n\t\t></div\r\n\t></div\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class='dijitReset dijitInputInner' data-dojo-attach-point=\"textbox,focusNode\" type=\"${type}\" data-dojo-attach-event=\"onkeypress:_onKeyPress\"\r\n\t\t\trole=\"spinbutton\" autocomplete=\"off\" ${!nameAttrSetting}\r\n\t/></div\r\n></div>\r\n"}});
- define("dijit/form/_Spinner", [
- "dojo/_base/declare", // declare
- "dojo/_base/event", // event.stop
- "dojo/keys", // keys keys.DOWN_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.UP_ARROW
- "dojo/_base/lang", // lang.hitch
- "dojo/_base/sniff", // has("mozilla")
- "dijit/typematic",
- "./RangeBoundTextBox",
- "dojo/text!./templates/Spinner.html",
- "./_TextBoxMixin" // selectInputText
- ], function(declare, event, keys, lang, has, typematic, RangeBoundTextBox, template, _TextBoxMixin){
- /*=====
- var RangeBoundTextBox = dijit.form.RangeBoundTextBox;
- =====*/
- // module:
- // dijit/form/_Spinner
- // summary:
- // Mixin for validation widgets with a spinner.
- return declare("dijit.form._Spinner", RangeBoundTextBox, {
- // summary:
- // Mixin for validation widgets with a spinner.
- // description:
- // This class basically (conceptually) extends `dijit.form.ValidationTextBox`.
- // It modifies the template to have up/down arrows, and provides related handling code.
- // defaultTimeout: Number
- // Number of milliseconds before a held arrow key or up/down button becomes typematic
- defaultTimeout: 500,
- // minimumTimeout: Number
- // minimum number of milliseconds that typematic event fires when held key or button is held
- minimumTimeout: 10,
- // timeoutChangeRate: Number
- // Fraction of time used to change the typematic timer between events.
- // 1.0 means that each typematic event fires at defaultTimeout intervals.
- // < 1.0 means that each typematic event fires at an increasing faster rate.
- timeoutChangeRate: 0.90,
- // smallDelta: Number
- // Adjust the value by this much when spinning using the arrow keys/buttons
- smallDelta: 1,
- // largeDelta: Number
- // Adjust the value by this much when spinning using the PgUp/Dn keys
- largeDelta: 10,
- templateString: template,
- baseClass: "dijitTextBox dijitSpinner",
- // Set classes like dijitUpArrowButtonHover or dijitDownArrowButtonActive depending on
- // mouse action over specified node
- cssStateNodes: {
- "upArrowNode": "dijitUpArrowButton",
- "downArrowNode": "dijitDownArrowButton"
- },
- adjust: function(val /*=====, delta =====*/){
- // summary:
- // Overridable function used to adjust a primitive value(Number/Date/...) by the delta amount specified.
- // The val is adjusted in a way that makes sense to the object type.
- // val: Object
- // delta: Number
- // tags:
- // protected extension
- return val;
- },
- _arrowPressed: function(/*Node*/ nodePressed, /*Number*/ direction, /*Number*/ increment){
- // summary:
- // Handler for arrow button or arrow key being pressed
- if(this.disabled || this.readOnly){ return; }
- this._setValueAttr(this.adjust(this.get('value'), direction*increment), false);
- _TextBoxMixin.selectInputText(this.textbox, this.textbox.value.length);
- },
- _arrowReleased: function(/*Node*/ /*===== node =====*/){
- // summary:
- // Handler for arrow button or arrow key being released
- this._wheelTimer = null;
- },
- _typematicCallback: function(/*Number*/ count, /*DOMNode*/ node, /*Event*/ evt){
- var inc=this.smallDelta;
- if(node == this.textbox){
- var key = evt.charOrCode;
- inc = (key == keys.PAGE_UP || key == keys.PAGE_DOWN) ? this.largeDelta : this.smallDelta;
- node = (key == keys.UP_ARROW || key == keys.PAGE_UP) ? this.upArrowNode : this.downArrowNode;
- }
- if(count == -1){ this._arrowReleased(node); }
- else{ this._arrowPressed(node, (node == this.upArrowNode) ? 1 : -1, inc); }
- },
- _wheelTimer: null,
- _mouseWheeled: function(/*Event*/ evt){
- // summary:
- // Mouse wheel listener where supported
- event.stop(evt);
- // FIXME: Safari bubbles
- // be nice to DOH and scroll as much as the event says to
- var wheelDelta = evt.wheelDelta / 120;
- if(Math.floor(wheelDelta) != wheelDelta){
- // If not an int multiple of 120, then its touchpad scrolling.
- // This can change very fast so just assume 1 wheel click to make it more manageable.
- wheelDelta = evt.wheelDelta > 0 ? 1 : -1;
- }
- var scrollAmount = evt.detail ? (evt.detail * -1) : wheelDelta;
- if(scrollAmount !== 0){
- var node = this[(scrollAmount > 0 ? "upArrowNode" : "downArrowNode" )];
- this._arrowPressed(node, scrollAmount, this.smallDelta);
- if(!this._wheelTimer){
- clearTimeout(this._wheelTimer);
- }
- this._wheelTimer = setTimeout(lang.hitch(this,"_arrowReleased",node), 50);
- }
- },
- postCreate: function(){
- this.inherited(arguments);
- // extra listeners
- this.connect(this.domNode, !has("mozilla") ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
- this._connects.push(typematic.addListener(this.upArrowNode, this.textbox, {charOrCode:keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
- this._connects.push(typematic.addListener(this.downArrowNode, this.textbox, {charOrCode:keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
- this._connects.push(typematic.addListener(this.upArrowNode, this.textbox, {charOrCode:keys.PAGE_UP,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
- this._connects.push(typematic.addListener(this.downArrowNode, this.textbox, {charOrCode:keys.PAGE_DOWN,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
- }
- });
- });
- },
- 'dijit/form/Button':function(){
- require({cache:{
- 'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\r\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\r\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\r\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\r\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\r\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\r\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\r\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\r\n\t\t\t\tid=\"${id}_label\"\r\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\r\n\t\t\t></span\r\n\t\t></span\r\n\t></span\r\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\r\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\r\n/></span>\r\n"}});
- define("dijit/form/Button", [
- "require",
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.toggle
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/lang", // lang.trim
- "dojo/ready",
- "./_FormWidget",
- "./_ButtonMixin",
- "dojo/text!./templates/Button.html"
- ], function(require, declare, domClass, kernel, lang, ready, _FormWidget, _ButtonMixin, template){
- /*=====
- var _FormWidget = dijit.form._FormWidget;
- var _ButtonMixin = dijit.form._ButtonMixin;
- =====*/
- // module:
- // dijit/form/Button
- // summary:
- // Button widget
- // Back compat w/1.6, remove for 2.0
- if(!kernel.isAsync){
- ready(0, function(){
- var requires = ["dijit/form/DropDownButton", "dijit/form/ComboButton", "dijit/form/ToggleButton"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- return declare("dijit.form.Button", [_FormWidget, _ButtonMixin], {
- // summary:
- // Basically the same thing as a normal HTML button, but with special styling.
- // description:
- // Buttons can display a label, an icon, or both.
- // A label should always be specified (through innerHTML) or the label
- // attribute. It can be hidden via showLabel=false.
- // example:
- // | <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
- //
- // example:
- // | var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
- // | dojo.body().appendChild(button1.domNode);
- // showLabel: Boolean
- // Set this to true to hide the label text and display only the icon.
- // (If showLabel=false then iconClass must be specified.)
- // Especially useful for toolbars.
- // If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon.
- //
- // The exception case is for computers in high-contrast mode, where the label
- // will still be displayed, since the icon doesn't appear.
- showLabel: true,
- // iconClass: String
- // Class to apply to DOMNode in button to make it display an icon
- iconClass: "dijitNoIcon",
- _setIconClassAttr: { node: "iconNode", type: "class" },
- baseClass: "dijitButton",
- templateString: template,
- // Map widget attributes to DOMNode attributes.
- _setValueAttr: "valueNode",
- _onClick: function(/*Event*/ e){
- // summary:
- // Internal function to handle click actions
- var ok = this.inherited(arguments);
- if(ok){
- if(this.valueNode){
- this.valueNode.click();
- e.preventDefault(); // cancel BUTTON click and continue with hidden INPUT click
- // leave ok = true so that subclasses can do what they need to do
- }
- }
- return ok;
- },
- _fillContent: function(/*DomNode*/ source){
- // Overrides _Templated._fillContent().
- // If button label is specified as srcNodeRef.innerHTML rather than
- // this.params.label, handle it here.
- // TODO: remove the method in 2.0, parser will do it all for me
- if(source && (!this.params || !("label" in this.params))){
- var sourceLabel = lang.trim(source.innerHTML);
- if(sourceLabel){
- this.label = sourceLabel; // _applyAttributes will be called after buildRendering completes to update the DOM
- }
- }
- },
- _setShowLabelAttr: function(val){
- if(this.containerNode){
- domClass.toggle(this.containerNode, "dijitDisplayNone", !val);
- }
- this._set("showLabel", val);
- },
- setLabel: function(/*String*/ content){
- // summary:
- // Deprecated. Use set('label', ...) instead.
- kernel.deprecated("dijit.form.Button.setLabel() is deprecated. Use set('label', ...) instead.", "", "2.0");
- this.set("label", content);
- },
- _setLabelAttr: function(/*String*/ content){
- // summary:
- // Hook for set('label', ...) to work.
- // description:
- // Set the label (text) of the button; takes an HTML string.
- // If the label is hidden (showLabel=false) then and no title has
- // been specified, then label is also set as title attribute of icon.
- this.inherited(arguments);
- if(!this.showLabel && !("title" in this.params)){
- this.titleNode.title = lang.trim(this.containerNode.innerText || this.containerNode.textContent || '');
- }
- }
- });
- });
- },
- 'dojo/dnd/move':function(){
- define("dojo/dnd/move", ["../main", "./Mover", "./Moveable"], function(dojo) {
- // module:
- // dojo/dnd/move
- // summary:
- // TODOC
- /*=====
- dojo.declare("dojo.dnd.move.__constrainedMoveableArgs", [dojo.dnd.__MoveableArgs], {
- // constraints: Function
- // Calculates a constraint box.
- // It is called in a context of the moveable object.
- constraints: function(){},
- // within: Boolean
- // restrict move within boundaries.
- within: false
- });
- =====*/
- dojo.declare("dojo.dnd.move.constrainedMoveable", dojo.dnd.Moveable, {
- // object attributes (for markup)
- constraints: function(){},
- within: false,
- constructor: function(node, params){
- // summary:
- // an object that makes a node moveable
- // node: Node
- // a node (or node's id) to be moved
- // params: dojo.dnd.move.__constrainedMoveableArgs?
- // an optional object with additional parameters;
- // the rest is passed to the base class
- if(!params){ params = {}; }
- this.constraints = params.constraints;
- this.within = params.within;
- },
- onFirstMove: function(/* dojo.dnd.Mover */ mover){
- // summary:
- // called during the very first move notification;
- // can be used to initialize coordinates, can be overwritten.
- var c = this.constraintBox = this.constraints.call(this, mover);
- c.r = c.l + c.w;
- c.b = c.t + c.h;
- if(this.within){
- var mb = dojo._getMarginSize(mover.node);
- c.r -= mb.w;
- c.b -= mb.h;
- }
- },
- onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
- // summary:
- // called during every move notification;
- // should actually move the node; can be overwritten.
- var c = this.constraintBox, s = mover.node.style;
- this.onMoving(mover, leftTop);
- leftTop.l = leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l;
- leftTop.t = leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t;
- s.left = leftTop.l + "px";
- s.top = leftTop.t + "px";
- this.onMoved(mover, leftTop);
- }
- });
- /*=====
- dojo.declare("dojo.dnd.move.__boxConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
- // box: Object
- // a constraint box
- box: {}
- });
- =====*/
- dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
- // box:
- // object attributes (for markup)
- box: {},
- constructor: function(node, params){
- // summary:
- // an object, which makes a node moveable
- // node: Node
- // a node (or node's id) to be moved
- // params: dojo.dnd.move.__boxConstrainedMoveableArgs?
- // an optional object with parameters
- var box = params && params.box;
- this.constraints = function(){ return box; };
- }
- });
- /*=====
- dojo.declare("dojo.dnd.move.__parentConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
- // area: String
- // A parent's area to restrict the move.
- // Can be "margin", "border", "padding", or "content".
- area: ""
- });
- =====*/
- dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
- // area:
- // object attributes (for markup)
- area: "content",
- constructor: function(node, params){
- // summary:
- // an object, which makes a node moveable
- // node: Node
- // a node (or node's id) to be moved
- // params: dojo.dnd.move.__parentConstrainedMoveableArgs?
- // an optional object with parameters
- var area = params && params.area;
- this.constraints = function(){
- var n = this.node.parentNode,
- s = dojo.getComputedStyle(n),
- mb = dojo._getMarginBox(n, s);
- if(area == "margin"){
- return mb; // Object
- }
- var t = dojo._getMarginExtents(n, s);
- mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
- if(area == "border"){
- return mb; // Object
- }
- t = dojo._getBorderExtents(n, s);
- mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
- if(area == "padding"){
- return mb; // Object
- }
- t = dojo._getPadExtents(n, s);
- mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
- return mb; // Object
- };
- }
- });
- // patching functions one level up for compatibility
- dojo.dnd.constrainedMover = dojo.dnd.move.constrainedMover;
- dojo.dnd.boxConstrainedMover = dojo.dnd.move.boxConstrainedMover;
- dojo.dnd.parentConstrainedMover = dojo.dnd.move.parentConstrainedMover;
- return dojo.dnd.move;
- });
- },
- 'dijit/_WidgetBase':function(){
- define("dijit/_WidgetBase", [
- "require", // require.toUrl
- "dojo/_base/array", // array.forEach array.map
- "dojo/aspect",
- "dojo/_base/config", // config.blankGif
- "dojo/_base/connect", // connect.connect
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.byId
- "dojo/dom-attr", // domAttr.set domAttr.remove
- "dojo/dom-class", // domClass.add domClass.replace
- "dojo/dom-construct", // domConstruct.create domConstruct.destroy domConstruct.place
- "dojo/dom-geometry", // isBodyLtr
- "dojo/dom-style", // domStyle.set, domStyle.get
- "dojo/_base/kernel",
- "dojo/_base/lang", // mixin(), isArray(), etc.
- "dojo/on",
- "dojo/ready",
- "dojo/Stateful", // Stateful
- "dojo/topic",
- "dojo/_base/window", // win.doc.createTextNode
- "./registry" // registry.getUniqueId(), registry.findWidgets()
- ], function(require, array, aspect, config, connect, declare,
- dom, domAttr, domClass, domConstruct, domGeometry, domStyle, kernel,
- lang, on, ready, Stateful, topic, win, registry){
- /*=====
- var Stateful = dojo.Stateful;
- =====*/
- // module:
- // dijit/_WidgetBase
- // summary:
- // Future base class for all Dijit widgets.
- // For back-compat, remove in 2.0.
- if(!kernel.isAsync){
- ready(0, function(){
- var requires = ["dijit/_base/manager"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- // Nested hash listing attributes for each tag, all strings in lowercase.
- // ex: {"div": {"style": true, "tabindex" true}, "form": { ...
- var tagAttrs = {};
- function getAttrs(obj){
- var ret = {};
- for(var attr in obj){
- ret[attr.toLowerCase()] = true;
- }
- return ret;
- }
- function nonEmptyAttrToDom(attr){
- // summary:
- // Returns a setter function that copies the attribute to this.domNode,
- // or removes the attribute from this.domNode, depending on whether the
- // value is defined or not.
- return function(val){
- domAttr[val ? "set" : "remove"](this.domNode, attr, val);
- this._set(attr, val);
- };
- }
- return declare("dijit._WidgetBase", Stateful, {
- // summary:
- // Future base class for all Dijit widgets.
- // description:
- // Future base class for all Dijit widgets.
- // _Widget extends this class adding support for various features needed by desktop.
- //
- // Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(),
- // postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch().
- //
- // Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value).
- // For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr().
- //
- // _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes:
- //
- // - DOM node attribute
- // | _setFocusAttr: {node: "focusNode", type: "attribute"}
- // | _setFocusAttr: "focusNode" (shorthand)
- // | _setFocusAttr: "" (shorthand, maps to this.domNode)
- // Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus
- //
- // - DOM node innerHTML
- // | _setTitleAttr: { node: "titleNode", type: "innerHTML" }
- // Maps this.title to this.titleNode.innerHTML
- //
- // - DOM node innerText
- // | _setTitleAttr: { node: "titleNode", type: "innerText" }
- // Maps this.title to this.titleNode.innerText
- //
- // - DOM node CSS class
- // | _setMyClassAttr: { node: "domNode", type: "class" }
- // Maps this.myClass to this.domNode.className
- //
- // If the value of _setXXXAttr is an array, then each element in the array matches one of the
- // formats of the above list.
- //
- // If the custom setter is null, no action is performed other than saving the new value
- // in the widget (in this).
- //
- // If no custom setter is defined for an attribute, then it will be copied
- // to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise.
- // That's only done though for attributes that match DOMNode attributes (title,
- // alt, aria-labelledby, etc.)
- // id: [const] String
- // A unique, opaque ID string that can be assigned by users or by the
- // system. If the developer passes an ID which is known not to be
- // unique, the specified ID is ignored and the system-generated ID is
- // used instead.
- id: "",
- _setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's
- // lang: [const] String
- // Rarely used. Overrides the default Dojo locale used to render this widget,
- // as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
- // Value must be among the list of locales specified during by the Dojo bootstrap,
- // formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
- lang: "",
- // set on domNode even when there's a focus node. but don't set lang="", since that's invalid.
- _setLangAttr: nonEmptyAttrToDom("lang"),
- // dir: [const] String
- // Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
- // attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's
- // default direction.
- dir: "",
- // set on domNode even when there's a focus node. but don't set dir="", since that's invalid.
- _setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node
- // textDir: String
- // Bi-directional support, the main variable which is responsible for the direction of the text.
- // The text direction can be different than the GUI direction by using this parameter in creation
- // of a widget.
- // Allowed values:
- // 1. "ltr"
- // 2. "rtl"
- // 3. "auto" - contextual the direction of a text defined by first strong letter.
- // By default is as the page direction.
- textDir: "",
- // class: String
- // HTML class attribute
- "class": "",
- _setClassAttr: { node: "domNode", type: "class" },
- // style: String||Object
- // HTML style attributes as cssText string or name/value hash
- style: "",
- // title: String
- // HTML title attribute.
- //
- // For form widgets this specifies a tooltip to display when hovering over
- // the widget (just like the native HTML title attribute).
- //
- // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
- // etc., it's used to specify the tab label, accordion pane title, etc.
- title: "",
- // tooltip: String
- // When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
- // this specifies the tooltip to appear when the mouse is hovered over that text.
- tooltip: "",
- // baseClass: [protected] String
- // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
- // widget state.
- baseClass: "",
- // srcNodeRef: [readonly] DomNode
- // pointer to original DOM node
- srcNodeRef: null,
- // domNode: [readonly] DomNode
- // This is our visible representation of the widget! Other DOM
- // Nodes may by assigned to other properties, usually through the
- // template system's data-dojo-attach-point syntax, but the domNode
- // property is the canonical "top level" node in widget UI.
- domNode: null,
- // containerNode: [readonly] DomNode
- // Designates where children of the source DOM node will be placed.
- // "Children" in this case refers to both DOM nodes and widgets.
- // For example, for myWidget:
- //
- // | <div data-dojo-type=myWidget>
- // | <b> here's a plain DOM node
- // | <span data-dojo-type=subWidget>and a widget</span>
- // | <i> and another plain DOM node </i>
- // | </div>
- //
- // containerNode would point to:
- //
- // | <b> here's a plain DOM node
- // | <span data-dojo-type=subWidget>and a widget</span>
- // | <i> and another plain DOM node </i>
- //
- // In templated widgets, "containerNode" is set via a
- // data-dojo-attach-point assignment.
- //
- // containerNode must be defined for any widget that accepts innerHTML
- // (like ContentPane or BorderContainer or even Button), and conversely
- // is null for widgets that don't, like TextBox.
- containerNode: null,
- /*=====
- // _started: Boolean
- // startup() has completed.
- _started: false,
- =====*/
- // attributeMap: [protected] Object
- // Deprecated. Instead of attributeMap, widget should have a _setXXXAttr attribute
- // for each XXX attribute to be mapped to the DOM.
- //
- // attributeMap sets up a "binding" between attributes (aka properties)
- // of the widget and the widget's DOM.
- // Changes to widget attributes listed in attributeMap will be
- // reflected into the DOM.
- //
- // For example, calling set('title', 'hello')
- // on a TitlePane will automatically cause the TitlePane's DOM to update
- // with the new title.
- //
- // attributeMap is a hash where the key is an attribute of the widget,
- // and the value reflects a binding to a:
- //
- // - DOM node attribute
- // | focus: {node: "focusNode", type: "attribute"}
- // Maps this.focus to this.focusNode.focus
- //
- // - DOM node innerHTML
- // | title: { node: "titleNode", type: "innerHTML" }
- // Maps this.title to this.titleNode.innerHTML
- //
- // - DOM node innerText
- // | title: { node: "titleNode", type: "innerText" }
- // Maps this.title to this.titleNode.innerText
- //
- // - DOM node CSS class
- // | myClass: { node: "domNode", type: "class" }
- // Maps this.myClass to this.domNode.className
- //
- // If the value is an array, then each element in the array matches one of the
- // formats of the above list.
- //
- // There are also some shorthands for backwards compatibility:
- // - string --> { node: string, type: "attribute" }, for example:
- // | "focusNode" ---> { node: "focusNode", type: "attribute" }
- // - "" --> { node: "domNode", type: "attribute" }
- attributeMap: {},
- // _blankGif: [protected] String
- // Path to a blank 1x1 image.
- // Used by <img> nodes in templates that really get their image via CSS background-image.
- _blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
- //////////// INITIALIZATION METHODS ///////////////////////////////////////
- postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
- // summary:
- // Kicks off widget instantiation. See create() for details.
- // tags:
- // private
- this.create(params, srcNodeRef);
- },
- create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
- // summary:
- // Kick off the life-cycle of a widget
- // params:
- // Hash of initialization parameters for widget, including
- // scalar values (like title, duration etc.) and functions,
- // typically callbacks like onClick.
- // srcNodeRef:
- // If a srcNodeRef (DOM node) is specified:
- // - use srcNodeRef.innerHTML as my contents
- // - if this is a behavioral widget then apply behavior
- // to that srcNodeRef
- // - otherwise, replace srcNodeRef with my generated DOM
- // tree
- // description:
- // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
- // etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html
- // for a discussion of the widget creation lifecycle.
- //
- // Of course, adventurous developers could override create entirely, but this should
- // only be done as a last resort.
- // tags:
- // private
- // store pointer to original DOM tree
- this.srcNodeRef = dom.byId(srcNodeRef);
- // For garbage collection. An array of listener handles returned by this.connect() / this.subscribe()
- this._connects = [];
- // For widgets internal to this widget, invisible to calling code
- this._supportingWidgets = [];
- // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
- if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
- // mix in our passed parameters
- if(params){
- this.params = params;
- lang.mixin(this, params);
- }
- this.postMixInProperties();
- // generate an id for the widget if one wasn't specified
- // (be sure to do this before buildRendering() because that function might
- // expect the id to be there.)
- if(!this.id){
- this.id = registry.getUniqueId(this.declaredClass.replace(/\./g,"_"));
- }
- registry.add(this);
- this.buildRendering();
- if(this.domNode){
- // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
- // Also calls custom setters for all attributes with custom setters.
- this._applyAttributes();
- // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
- // For 2.0, move this after postCreate(). postCreate() shouldn't depend on the
- // widget being attached to the DOM since it isn't when a widget is created programmatically like
- // new MyWidget({}). See #11635.
- var source = this.srcNodeRef;
- if(source && source.parentNode && this.domNode !== source){
- source.parentNode.replaceChild(this.domNode, source);
- }
- }
- if(this.domNode){
- // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
- // assuming that dojo._scopeName even exists in 2.0
- this.domNode.setAttribute("widgetId", this.id);
- }
- this.postCreate();
- // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
- if(this.srcNodeRef && !this.srcNodeRef.parentNode){
- delete this.srcNodeRef;
- }
- this._created = true;
- },
- _applyAttributes: function(){
- // summary:
- // Step during widget creation to copy widget attributes to the
- // DOM according to attributeMap and _setXXXAttr objects, and also to call
- // custom _setXXXAttr() methods.
- //
- // Skips over blank/false attribute values, unless they were explicitly specified
- // as parameters to the widget, since those are the default anyway,
- // and setting tabIndex="" is different than not setting tabIndex at all.
- //
- // For backwards-compatibility reasons attributeMap overrides _setXXXAttr when
- // _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap.
- // tags:
- // private
- // Get list of attributes where this.set(name, value) will do something beyond
- // setting this[name] = value. Specifically, attributes that have:
- // - associated _setXXXAttr() method/hash/string/array
- // - entries in attributeMap.
- var ctor = this.constructor,
- list = ctor._setterAttrs;
- if(!list){
- list = (ctor._setterAttrs = []);
- for(var attr in this.attributeMap){
- list.push(attr);
- }
- var proto = ctor.prototype;
- for(var fxName in proto){
- if(fxName in this.attributeMap){ continue; }
- var setterName = "_set" + fxName.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }) + "Attr";
- if(setterName in proto){
- list.push(fxName);
- }
- }
- }
- // Call this.set() for each attribute that was either specified as parameter to constructor,
- // or was found above and has a default non-null value. For correlated attributes like value and displayedValue, the one
- // specified as a parameter should take precedence, so apply attributes in this.params last.
- // Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
- // NaN and thus is not ignored like a default value of "".
- array.forEach(list, function(attr){
- if(this.params && attr in this.params){
- // skip this one, do it below
- }else if(this[attr]){
- this.set(attr, this[attr]);
- }
- }, this);
- for(var param in this.params){
- this.set(param, this[param]);
- }
- },
- postMixInProperties: function(){
- // summary:
- // Called after the parameters to the widget have been read-in,
- // but before the widget template is instantiated. Especially
- // useful to set properties that are referenced in the widget
- // template.
- // tags:
- // protected
- },
- buildRendering: function(){
- // summary:
- // Construct the UI for this widget, setting this.domNode.
- // Most widgets will mixin `dijit._TemplatedMixin`, which implements this method.
- // tags:
- // protected
- if(!this.domNode){
- // Create root node if it wasn't created by _Templated
- this.domNode = this.srcNodeRef || domConstruct.create('div');
- }
- // baseClass is a single class name or occasionally a space-separated list of names.
- // Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix.
- // TODO: make baseClass custom setter
- if(this.baseClass){
- var classes = this.baseClass.split(" ");
- if(!this.isLeftToRight()){
- classes = classes.concat( array.map(classes, function(name){ return name+"Rtl"; }));
- }
- domClass.add(this.domNode, classes);
- }
- },
- postCreate: function(){
- // summary:
- // Processing after the DOM fragment is created
- // description:
- // Called after the DOM fragment has been created, but not necessarily
- // added to the document. Do not include any operations which rely on
- // node dimensions or placement.
- // tags:
- // protected
- },
- startup: function(){
- // summary:
- // Processing after the DOM fragment is added to the document
- // description:
- // Called after a widget and its children have been created and added to the page,
- // and all related widgets have finished their create() cycle, up through postCreate().
- // This is useful for composite widgets that need to control or layout sub-widgets.
- // Many layout widgets can use this as a wiring phase.
- if(this._started){ return; }
- this._started = true;
- array.forEach(this.getChildren(), function(obj){
- if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
- obj.startup();
- obj._started = true;
- }
- });
- },
- //////////// DESTROY FUNCTIONS ////////////////////////////////
- destroyRecursive: function(/*Boolean?*/ preserveDom){
- // summary:
- // Destroy this widget and its descendants
- // description:
- // This is the generic "destructor" function that all widget users
- // should call to cleanly discard with a widget. Once a widget is
- // destroyed, it is removed from the manager object.
- // preserveDom:
- // If true, this method will leave the original DOM structure
- // alone of descendant Widgets. Note: This will NOT work with
- // dijit._Templated widgets.
- this._beingDestroyed = true;
- this.destroyDescendants(preserveDom);
- this.destroy(preserveDom);
- },
- destroy: function(/*Boolean*/ preserveDom){
- // summary:
- // Destroy this widget, but not its descendants.
- // This method will, however, destroy internal widgets such as those used within a template.
- // preserveDom: Boolean
- // If true, this method will leave the original DOM structure alone.
- // Note: This will not yet work with _Templated widgets
- this._beingDestroyed = true;
- this.uninitialize();
- // remove this.connect() and this.subscribe() listeners
- var c;
- while((c = this._connects.pop())){
- c.remove();
- }
- // destroy widgets created as part of template, etc.
- var w;
- while((w = this._supportingWidgets.pop())){
- if(w.destroyRecursive){
- w.destroyRecursive();
- }else if(w.destroy){
- w.destroy();
- }
- }
- this.destroyRendering(preserveDom);
- registry.remove(this.id);
- this._destroyed = true;
- },
- destroyRendering: function(/*Boolean?*/ preserveDom){
- // summary:
- // Destroys the DOM nodes associated with this widget
- // preserveDom:
- // If true, this method will leave the original DOM structure alone
- // during tear-down. Note: this will not work with _Templated
- // widgets yet.
- // tags:
- // protected
- if(this.bgIframe){
- this.bgIframe.destroy(preserveDom);
- delete this.bgIframe;
- }
- if(this.domNode){
- if(preserveDom){
- domAttr.remove(this.domNode, "widgetId");
- }else{
- domConstruct.destroy(this.domNode);
- }
- delete this.domNode;
- }
- if(this.srcNodeRef){
- if(!preserveDom){
- domConstruct.destroy(this.srcNodeRef);
- }
- delete this.srcNodeRef;
- }
- },
- destroyDescendants: function(/*Boolean?*/ preserveDom){
- // summary:
- // Recursively destroy the children of this widget and their
- // descendants.
- // preserveDom:
- // If true, the preserveDom attribute is passed to all descendant
- // widget's .destroy() method. Not for use with _Templated
- // widgets.
- // get all direct descendants and destroy them recursively
- array.forEach(this.getChildren(), function(widget){
- if(widget.destroyRecursive){
- widget.destroyRecursive(preserveDom);
- }
- });
- },
- uninitialize: function(){
- // summary:
- // Stub function. Override to implement custom widget tear-down
- // behavior.
- // tags:
- // protected
- return false;
- },
- ////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
- _setStyleAttr: function(/*String||Object*/ value){
- // summary:
- // Sets the style attribute of the widget according to value,
- // which is either a hash like {height: "5px", width: "3px"}
- // or a plain string
- // description:
- // Determines which node to set the style on based on style setting
- // in attributeMap.
- // tags:
- // protected
- var mapNode = this.domNode;
- // Note: technically we should revert any style setting made in a previous call
- // to his method, but that's difficult to keep track of.
- if(lang.isObject(value)){
- domStyle.set(mapNode, value);
- }else{
- if(mapNode.style.cssText){
- mapNode.style.cssText += "; " + value;
- }else{
- mapNode.style.cssText = value;
- }
- }
- this._set("style", value);
- },
- _attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
- // summary:
- // Reflect a widget attribute (title, tabIndex, duration etc.) to
- // the widget DOM, as specified by commands parameter.
- // If commands isn't specified then it's looked up from attributeMap.
- // Note some attributes like "type"
- // cannot be processed this way as they are not mutable.
- //
- // tags:
- // private
- commands = arguments.length >= 3 ? commands : this.attributeMap[attr];
- array.forEach(lang.isArray(commands) ? commands : [commands], function(command){
- // Get target node and what we are doing to that node
- var mapNode = this[command.node || command || "domNode"]; // DOM node
- var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
- switch(type){
- case "attribute":
- if(lang.isFunction(value)){ // functions execute in the context of the widget
- value = lang.hitch(this, value);
- }
- // Get the name of the DOM node attribute; usually it's the same
- // as the name of the attribute in the widget (attr), but can be overridden.
- // Also maps handler names to lowercase, like onSubmit --> onsubmit
- var attrName = command.attribute ? command.attribute :
- (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
- domAttr.set(mapNode, attrName, value);
- break;
- case "innerText":
- mapNode.innerHTML = "";
- mapNode.appendChild(win.doc.createTextNode(value));
- break;
- case "innerHTML":
- mapNode.innerHTML = value;
- break;
- case "class":
- domClass.replace(mapNode, value, this[attr]);
- break;
- }
- }, this);
- },
- get: function(name){
- // summary:
- // Get a property from a widget.
- // name:
- // The property to get.
- // description:
- // Get a named property from a widget. The property may
- // potentially be retrieved via a getter method. If no getter is defined, this
- // just retrieves the object's property.
- //
- // For example, if the widget has properties `foo` and `bar`
- // and a method named `_getFooAttr()`, calling:
- // `myWidget.get("foo")` would be equivalent to calling
- // `widget._getFooAttr()` and `myWidget.get("bar")`
- // would be equivalent to the expression
- // `widget.bar2`
- var names = this._getAttrNames(name);
- return this[names.g] ? this[names.g]() : this[name];
- },
- set: function(name, value){
- // summary:
- // Set a property on a widget
- // name:
- // The property to set.
- // value:
- // The value to set in the property.
- // description:
- // Sets named properties on a widget which may potentially be handled by a
- // setter in the widget.
- //
- // For example, if the widget has properties `foo` and `bar`
- // and a method named `_setFooAttr()`, calling
- // `myWidget.set("foo", "Howdy!")` would be equivalent to calling
- // `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)`
- // would be equivalent to the statement `widget.bar = 3;`
- //
- // set() may also be called with a hash of name/value pairs, ex:
- //
- // | myWidget.set({
- // | foo: "Howdy",
- // | bar: 3
- // | });
- //
- // This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)`
- if(typeof name === "object"){
- for(var x in name){
- this.set(x, name[x]);
- }
- return this;
- }
- var names = this._getAttrNames(name),
- setter = this[names.s];
- if(lang.isFunction(setter)){
- // use the explicit setter
- var result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
- }else{
- // Mapping from widget attribute to DOMNode attribute/value/etc.
- // Map according to:
- // 1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0)
- // 2. _setFooAttr: {...} type attribute in the widget (if one exists)
- // 3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick.
- // Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar
- // attribute name (ex: accept-charset attribute matches jsObject.acceptCharset).
- // Note also that Tree.focusNode() is a function not a DOMNode, so test for that.
- var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode",
- tag = this[defaultNode].tagName,
- attrsForTag = tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode])),
- map = name in this.attributeMap ? this.attributeMap[name] :
- names.s in this ? this[names.s] :
- ((names.l in attrsForTag && typeof value != "function") ||
- /^aria-|^data-|^role$/.test(name)) ? defaultNode : null;
- if(map != null){
- this._attrToDom(name, value, map);
- }
- this._set(name, value);
- }
- return result || this;
- },
- _attrPairNames: {}, // shared between all widgets
- _getAttrNames: function(name){
- // summary:
- // Helper function for get() and set().
- // Caches attribute name values so we don't do the string ops every time.
- // tags:
- // private
- var apn = this._attrPairNames;
- if(apn[name]){ return apn[name]; }
- var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); });
- return (apn[name] = {
- n: name+"Node",
- s: "_set"+uc+"Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr
- g: "_get"+uc+"Attr",
- l: uc.toLowerCase() // lowercase name w/out dashes, ex: acceptcharset
- });
- },
- _set: function(/*String*/ name, /*anything*/ value){
- // summary:
- // Helper function to set new value for specified attribute, and call handlers
- // registered with watch() if the value has changed.
- var oldValue = this[name];
- this[name] = value;
- if(this._watchCallbacks && this._created && value !== oldValue){
- this._watchCallbacks(name, oldValue, value);
- }
- },
- on: function(/*String*/ type, /*Function*/ func){
- // summary:
- // Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
- // description:
- // Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`.
- // Note that the function is not run in any particular scope, so if (for example) you want it to run in the
- // widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`.
- return aspect.after(this, this._onMap(type), func, true);
- },
- _onMap: function(/*String*/ type){
- // summary:
- // Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove")
- var ctor = this.constructor, map = ctor._onMap;
- if(!map){
- map = (ctor._onMap = {});
- for(var attr in ctor.prototype){
- if(/^on/.test(attr)){
- map[attr.replace(/^on/, "").toLowerCase()] = attr;
- }
- }
- }
- return map[type.toLowerCase()]; // String
- },
- toString: function(){
- // summary:
- // Returns a string that represents the widget
- // description:
- // When a widget is cast to a string, this method will be used to generate the
- // output. Currently, it does not implement any sort of reversible
- // serialization.
- return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
- },
- getChildren: function(){
- // summary:
- // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
- // Does not return nested widgets, nor widgets that are part of this widget's template.
- return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit._Widget[]
- },
- getParent: function(){
- // summary:
- // Returns the parent widget of this widget
- return registry.getEnclosingWidget(this.domNode.parentNode);
- },
- connect: function(
- /*Object|null*/ obj,
- /*String|Function*/ event,
- /*String|Function*/ method){
- // summary:
- // Connects specified obj/event to specified method of this object
- // and registers for disconnect() on widget destroy.
- // description:
- // Provide widget-specific analog to dojo.connect, except with the
- // implicit use of this widget as the target object.
- // Events connected with `this.connect` are disconnected upon
- // destruction.
- // returns:
- // A handle that can be passed to `disconnect` in order to disconnect before
- // the widget is destroyed.
- // example:
- // | var btn = new dijit.form.Button();
- // | // when foo.bar() is called, call the listener we're going to
- // | // provide in the scope of btn
- // | btn.connect(foo, "bar", function(){
- // | console.debug(this.toString());
- // | });
- // tags:
- // protected
- var handle = connect.connect(obj, event, this, method);
- this._connects.push(handle);
- return handle; // _Widget.Handle
- },
- disconnect: function(handle){
- // summary:
- // Disconnects handle created by `connect`.
- // Also removes handle from this widget's list of connects.
- // tags:
- // protected
- var i = array.indexOf(this._connects, handle);
- if(i != -1){
- handle.remove();
- this._connects.splice(i, 1);
- }
- },
- subscribe: function(t, method){
- // summary:
- // Subscribes to the specified topic and calls the specified method
- // of this object and registers for unsubscribe() on widget destroy.
- // description:
- // Provide widget-specific analog to dojo.subscribe, except with the
- // implicit use of this widget as the target object.
- // t: String
- // The topic
- // method: Function
- // The callback
- // example:
- // | var btn = new dijit.form.Button();
- // | // when /my/topic is published, this button changes its label to
- // | // be the parameter of the topic.
- // | btn.subscribe("/my/topic", function(v){
- // | this.set("label", v);
- // | });
- // tags:
- // protected
- var handle = topic.subscribe(t, lang.hitch(this, method));
- this._connects.push(handle);
- return handle; // _Widget.Handle
- },
- unsubscribe: function(/*Object*/ handle){
- // summary:
- // Unsubscribes handle created by this.subscribe.
- // Also removes handle from this widget's list of subscriptions
- // tags:
- // protected
- this.disconnect(handle);
- },
- isLeftToRight: function(){
- // summary:
- // Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
- // tags:
- // protected
- return this.dir ? (this.dir == "ltr") : domGeometry.isBodyLtr(); //Boolean
- },
- isFocusable: function(){
- // summary:
- // Return true if this widget can currently be focused
- // and false if not
- return this.focus && (domStyle.get(this.domNode, "display") != "none");
- },
- placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
- // summary:
- // Place this widget's domNode reference somewhere in the DOM based
- // on standard domConstruct.place conventions, or passing a Widget reference that
- // contains and addChild member.
- //
- // description:
- // A convenience function provided in all _Widgets, providing a simple
- // shorthand mechanism to put an existing (or newly created) Widget
- // somewhere in the dom, and allow chaining.
- //
- // reference:
- // The String id of a domNode, a domNode reference, or a reference to a Widget possessing
- // an addChild method.
- //
- // position:
- // If passed a string or domNode reference, the position argument
- // accepts a string just as domConstruct.place does, one of: "first", "last",
- // "before", or "after".
- //
- // If passed a _Widget reference, and that widget reference has an ".addChild" method,
- // it will be called passing this widget instance into that method, supplying the optional
- // position index passed.
- //
- // returns:
- // dijit._Widget
- // Provides a useful return of the newly created dijit._Widget instance so you
- // can "chain" this function by instantiating, placing, then saving the return value
- // to a variable.
- //
- // example:
- // | // create a Button with no srcNodeRef, and place it in the body:
- // | var button = new dijit.form.Button({ label:"click" }).placeAt(win.body());
- // | // now, 'button' is still the widget reference to the newly created button
- // | button.on("click", function(e){ console.log('click'); }));
- //
- // example:
- // | // create a button out of a node with id="src" and append it to id="wrapper":
- // | var button = new dijit.form.Button({},"src").placeAt("wrapper");
- //
- // example:
- // | // place a new button as the first element of some div
- // | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
- //
- // example:
- // | // create a contentpane and add it to a TabContainer
- // | var tc = dijit.byId("myTabs");
- // | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
- if(reference.declaredClass && reference.addChild){
- reference.addChild(this, position);
- }else{
- domConstruct.place(this.domNode, reference, position);
- }
- return this;
- },
- getTextDir: function(/*String*/ text,/*String*/ originalDir){
- // summary:
- // Return direction of the text.
- // The function overridden in the _BidiSupport module,
- // its main purpose is to calculate the direction of the
- // text, if was defined by the programmer through textDir.
- // tags:
- // protected.
- return originalDir;
- },
- applyTextDir: function(/*===== element, text =====*/){
- // summary:
- // The function overridden in the _BidiSupport module,
- // originally used for setting element.dir according to this.textDir.
- // In this case does nothing.
- // element: DOMNode
- // text: String
- // tags:
- // protected.
- },
- defer: function(fcn, delay){
- // summary:
- // Wrapper to setTimeout to avoid deferred functions executing
- // after the originating widget has been destroyed.
- // Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
- // fcn: function reference
- // delay: Optional number (defaults to 0)
- // tags:
- // protected.
- var timer = setTimeout(lang.hitch(this,
- function(){
- timer = null;
- if(!this._destroyed){
- lang.hitch(this, fcn)();
- }
- }),
- delay || 0
- );
- return {
- remove: function(){
- if(timer){
- clearTimeout(timer);
- timer = null;
- }
- return null; // so this works well: handle = handle.remove();
- }
- };
- }
- });
- });
- },
- 'dojo/store/Memory':function(){
- define("dojo/store/Memory", ["../_base/declare", "./util/QueryResults", "./util/SimpleQueryEngine"], function(declare, QueryResults, SimpleQueryEngine) {
- // module:
- // dojo/store/Memory
- // summary:
- // The module defines an in-memory object store.
- return declare("dojo.store.Memory", null, {
- // summary:
- // This is a basic in-memory object store. It implements dojo.store.api.Store.
- constructor: function(/*dojo.store.Memory*/ options){
- // summary:
- // Creates a memory object store.
- // options:
- // This provides any configuration information that will be mixed into the store.
- // This should generally include the data property to provide the starting set of data.
- for(var i in options){
- this[i] = options[i];
- }
- this.setData(this.data || []);
- },
- // data: Array
- // The array of all the objects in the memory store
- data:null,
- // idProperty: String
- // Indicates the property to use as the identity property. The values of this
- // property should be unique.
- idProperty: "id",
- // index: Object
- // An index of data indices into the data array by id
- index:null,
- // queryEngine: Function
- // Defines the query engine to use for querying the data store
- queryEngine: SimpleQueryEngine,
- get: function(id){
- // summary:
- // Retrieves an object by its identity
- // id: Number
- // The identity to use to lookup the object
- // returns: Object
- // The object in the store that matches the given id.
- return this.data[this.index[id]];
- },
- getIdentity: function(object){
- // summary:
- // Returns an object's identity
- // object: Object
- // The object to get the identity from
- // returns: Number
- return object[this.idProperty];
- },
- put: function(object, options){
- // summary:
- // Stores an object
- // object: Object
- // The object to store.
- // options: dojo.store.api.Store.PutDirectives??
- // Additional metadata for storing the data. Includes an "id"
- // property if a specific id is to be used.
- // returns: Number
- var data = this.data,
- index = this.index,
- idProperty = this.idProperty;
- var id = (options && "id" in options) ? options.id : idProperty in object ? object[idProperty] : Math.random();
- if(id in index){
- // object exists
- if(options && options.overwrite === false){
- throw new Error("Object already exists");
- }
- // replace the entry in data
- data[index[id]] = object;
- }else{
- // add the new object
- index[id] = data.push(object) - 1;
- }
- return id;
- },
- add: function(object, options){
- // summary:
- // Creates an object, throws an error if the object already exists
- // object: Object
- // The object to store.
- // options: dojo.store.api.Store.PutDirectives??
- // Additional metadata for storing the data. Includes an "id"
- // property if a specific id is to be used.
- // returns: Number
- (options = options || {}).overwrite = false;
- // call put with overwrite being false
- return this.put(object, options);
- },
- remove: function(id){
- // summary:
- // Deletes an object by its identity
- // id: Number
- // The identity to use to delete the object
- // returns: Boolean
- // Returns true if an object was removed, falsy (undefined) if no object matched the id
- var index = this.index;
- var data = this.data;
- if(id in index){
- data.splice(index[id], 1);
- // now we have to reindex
- this.setData(data);
- return true;
- }
- },
- query: function(query, options){
- // summary:
- // Queries the store for objects.
- // query: Object
- // The query to use for retrieving objects from the store.
- // options: dojo.store.api.Store.QueryOptions?
- // The optional arguments to apply to the resultset.
- // returns: dojo.store.api.Store.QueryResults
- // The results of the query, extended with iterative methods.
- //
- // example:
- // Given the following store:
- //
- // | var store = new dojo.store.Memory({
- // | data: [
- // | {id: 1, name: "one", prime: false },
- // | {id: 2, name: "two", even: true, prime: true},
- // | {id: 3, name: "three", prime: true},
- // | {id: 4, name: "four", even: true, prime: false},
- // | {id: 5, name: "five", prime: true}
- // | ]
- // | });
- //
- // ...find all items where "prime" is true:
- //
- // | var results = store.query({ prime: true });
- //
- // ...or find all items where "even" is true:
- //
- // | var results = store.query({ even: true });
- return QueryResults(this.queryEngine(query, options)(this.data));
- },
- setData: function(data){
- // summary:
- // Sets the given data as the source for this store, and indexes it
- // data: Object[]
- // An array of objects to use as the source of data.
- if(data.items){
- // just for convenience with the data format IFRS expects
- this.idProperty = data.identifier;
- data = this.data = data.items;
- }else{
- this.data = data;
- }
- this.index = {};
- for(var i = 0, l = data.length; i < l; i++){
- this.index[data[i][this.idProperty]] = i;
- }
- }
- });
- });
- },
- 'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\r\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\r\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\r\n></div>\r\n",
- 'dojox/grid/_Grid':function(){
- require({cache:{
- 'url:dojox/grid/resources/_Grid.html':"<div hidefocus=\"hidefocus\" role=\"grid\" dojoAttachEvent=\"onmouseout:_mouseOut\">\r\n\t<div class=\"dojoxGridMasterHeader\" dojoAttachPoint=\"viewsHeaderNode\" role=\"presentation\"></div>\r\n\t<div class=\"dojoxGridMasterView\" dojoAttachPoint=\"viewsNode\" role=\"presentation\"></div>\r\n\t<div class=\"dojoxGridMasterMessages\" style=\"display: none;\" dojoAttachPoint=\"messagesNode\"></div>\r\n\t<span dojoAttachPoint=\"lastFocusNode\" tabindex=\"0\"></span>\r\n</div>\r\n"}});
- define("dojox/grid/_Grid", [
- "dojo/_base/kernel",
- "../main",
- "dojo/_base/declare",
- "./_Events",
- "./_Scroller",
- "./_Layout",
- "./_View",
- "./_ViewManager",
- "./_RowManager",
- "./_FocusManager",
- "./_EditManager",
- "./Selection",
- "./_RowSelector",
- "./util",
- "dijit/_Widget",
- "dijit/_TemplatedMixin",
- "dijit/CheckedMenuItem",
- "dojo/text!./resources/_Grid.html",
- "dojo/string",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/sniff",
- "dojox/html/metrics",
- "dojo/_base/html",
- "dojo/query",
- "dojo/dnd/common",
- "dojo/i18n!dijit/nls/loading"
- ], function(dojo, dojox, declare, _Events, _Scroller, _Layout, _View, _ViewManager,
- _RowManager, _FocusManager, _EditManager, Selection, _RowSelector, util, _Widget,
- _TemplatedMixin, CheckedMenuItem, template, string, array, lang, has, metrics, html, query){
- // NOTE: this is for backwards compatibility with Dojo 1.3
- if(!dojo.isCopyKey){
- dojo.isCopyKey = dojo.dnd.getCopyKeyState;
- }
- /*=====
- dojox.grid.__CellDef = function(){
- // name: String?
- // The text to use in the header of the grid for this cell.
- // get: Function?
- // function(rowIndex){} rowIndex is of type Integer. This
- // function will be called when a cell requests data. Returns the
- // unformatted data for the cell.
- // value: String?
- // If "get" is not specified, this is used as the data for the cell.
- // defaultValue: String?
- // If "get" and "value" aren't specified or if "get" returns an undefined
- // value, this is used as the data for the cell. "formatter" is not run
- // on this if "get" returns an undefined value.
- // formatter: Function?
- // function(data, rowIndex){} data is of type anything, rowIndex
- // is of type Integer. This function will be called after the cell
- // has its data but before it passes it back to the grid to render.
- // Returns the formatted version of the cell's data.
- // type: dojox.grid.cells._Base|Function?
- // TODO
- // editable: Boolean?
- // Whether this cell should be editable or not.
- // hidden: Boolean?
- // If true, the cell will not be displayed.
- // noresize: Boolean?
- // If true, the cell will not be able to be resized.
- // width: Integer|String?
- // A CSS size. If it's an Integer, the width will be in em's.
- // colSpan: Integer?
- // How many columns to span this cell. Will not work in the first
- // sub-row of cells.
- // rowSpan: Integer?
- // How many sub-rows to span this cell.
- // styles: String?
- // A string of styles to apply to both the header cell and main
- // grid cells. Must end in a ';'.
- // headerStyles: String?
- // A string of styles to apply to just the header cell. Must end
- // in a ';'
- // cellStyles: String?
- // A string of styles to apply to just the main grid cells. Must
- // end in a ';'
- // classes: String?
- // A space separated list of classes to apply to both the header
- // cell and the main grid cells.
- // headerClasses: String?
- // A space separated list of classes to apply to just the header
- // cell.
- // cellClasses: String?
- // A space separated list of classes to apply to just the main
- // grid cells.
- // attrs: String?
- // A space separated string of attribute='value' pairs to add to
- // the header cell element and main grid cell elements.
- this.name = name;
- this.value = value;
- this.get = get;
- this.formatter = formatter;
- this.type = type;
- this.editable = editable;
- this.hidden = hidden;
- this.width = width;
- this.colSpan = colSpan;
- this.rowSpan = rowSpan;
- this.styles = styles;
- this.headerStyles = headerStyles;
- this.cellStyles = cellStyles;
- this.classes = classes;
- this.headerClasses = headerClasses;
- this.cellClasses = cellClasses;
- this.attrs = attrs;
- }
- =====*/
- /*=====
- dojox.grid.__ViewDef = function(){
- // noscroll: Boolean?
- // If true, no scrollbars will be rendered without scrollbars.
- // width: Integer|String?
- // A CSS size. If it's an Integer, the width will be in em's. If
- // "noscroll" is true, this value is ignored.
- // cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
- // The structure of the cells within this grid.
- // type: String?
- // A string containing the constructor of a subclass of
- // dojox.grid._View. If this is not specified, dojox.grid._View
- // is used.
- // defaultCell: dojox.grid.__CellDef?
- // A cell definition with default values for all cells in this view. If
- // a property is defined in a cell definition in the "cells" array and
- // this property, the cell definition's property will override this
- // property's property.
- // onBeforeRow: Function?
- // function(rowIndex, cells){} rowIndex is of type Integer, cells
- // is of type Array[dojox.grid.__CellDef[]]. This function is called
- // before each row of data is rendered. Before the header is
- // rendered, rowIndex will be -1. "cells" is a reference to the
- // internal structure of this view's cells so any changes you make to
- // it will persist between calls.
- // onAfterRow: Function?
- // function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
- // is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
- // This function is called after each row of data is rendered. After the
- // header is rendered, rowIndex will be -1. "cells" is a reference to the
- // internal structure of this view's cells so any changes you make to
- // it will persist between calls.
- this.noscroll = noscroll;
- this.width = width;
- this.cells = cells;
- this.type = type;
- this.defaultCell = defaultCell;
- this.onBeforeRow = onBeforeRow;
- this.onAfterRow = onAfterRow;
- }
- =====*/
- var _Grid = declare('dojox.grid._Grid',
- [ _Widget, _TemplatedMixin, _Events ],
- {
- // summary:
- // A grid widget with virtual scrolling, cell editing, complex rows,
- // sorting, fixed columns, sizeable columns, etc.
- //
- // description:
- // _Grid provides the full set of grid features without any
- // direct connection to a data store.
- //
- // The grid exposes a get function for the grid, or optionally
- // individual columns, to populate cell contents.
- //
- // The grid is rendered based on its structure, an object describing
- // column and cell layout.
- //
- // example:
- // A quick sample:
- //
- // define a get function
- // | function get(inRowIndex){ // called in cell context
- // | return [this.index, inRowIndex].join(', ');
- // | }
- //
- // define the grid structure:
- // | var structure = [ // array of view objects
- // | { cells: [// array of rows, a row is an array of cells
- // | [
- // | { name: "Alpha", width: 6 },
- // | { name: "Beta" },
- // | { name: "Gamma", get: get }]
- // | ]}
- // | ];
- //
- // | <div id="grid"
- // | rowCount="100" get="get"
- // | structure="structure"
- // | dojoType="dojox.grid._Grid"></div>
- templateString: template,
- // classTag: String
- // CSS class applied to the grid's domNode
- classTag: 'dojoxGrid',
- // settings
- // rowCount: Integer
- // Number of rows to display.
- rowCount: 5,
- // keepRows: Integer
- // Number of rows to keep in the rendering cache.
- keepRows: 75,
- // rowsPerPage: Integer
- // Number of rows to render at a time.
- rowsPerPage: 25,
- // autoWidth: Boolean
- // If autoWidth is true, grid width is automatically set to fit the data.
- autoWidth: false,
-
- // initialWidth: String
- // A css string to use to set our initial width (only used if autoWidth
- // is true). The first rendering of the grid will be this width, any
- // resizing of columns, etc will result in the grid switching to
- // autoWidth mode. Note, this width will override any styling in a
- // stylesheet or directly on the node.
- initialWidth: "",
- // autoHeight: Boolean|Integer
- // If autoHeight is true, grid height is automatically set to fit the data.
- // If it is an integer, the height will be automatically set to fit the data
- // if there are fewer than that many rows - and the height will be set to show
- // that many rows if there are more
- autoHeight: '',
- // rowHeight: Integer
- // If rowHeight is set to a positive number, it will define the height of the rows
- // in pixels. This can provide a significant performance advantage, since it
- // eliminates the need to measure row sizes during rendering, which is one
- // the primary bottlenecks in the DataGrid's performance.
- rowHeight: 0,
-
- // autoRender: Boolean
- // If autoRender is true, grid will render itself after initialization.
- autoRender: true,
- // defaultHeight: String
- // default height of the grid, measured in any valid css unit.
- defaultHeight: '15em',
-
- // height: String
- // explicit height of the grid, measured in any valid css unit. This will be populated (and overridden)
- // if the height: css attribute exists on the source node.
- height: '',
- // structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
- // View layout defintion.
- structure: null,
- // elasticView: Integer
- // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
- elasticView: -1,
- // singleClickEdit: boolean
- // Single-click starts editing. Default is double-click
- singleClickEdit: false,
- // selectionMode: String
- // Set the selection mode of grid's Selection. Value must be 'single', 'multiple',
- // or 'extended'. Default is 'extended'.
- selectionMode: 'extended',
- // rowSelector: Boolean|String
- // If set to true, will add a row selector view to this grid. If set to a CSS width, will add
- // a row selector of that width to this grid.
- rowSelector: '',
- // columnReordering: Boolean
- // If set to true, will add drag and drop reordering to views with one row of columns.
- columnReordering: false,
- // headerMenu: dijit.Menu
- // If set to a dijit.Menu, will use this as a context menu for the grid headers.
- headerMenu: null,
- // placeholderLabel: String
- // Label of placeholders to search for in the header menu to replace with column toggling
- // menu items.
- placeholderLabel: "GridColumns",
-
- // selectable: Boolean
- // Set to true if you want to be able to select the text within the grid.
- selectable: false,
-
- // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
- _click: null,
-
- // loadingMessage: String
- // Message that shows while the grid is loading
- loadingMessage: "<span class='dojoxGridLoading'>${loadingState}</span>",
- // errorMessage: String
- // Message that shows when the grid encounters an error loading
- errorMessage: "<span class='dojoxGridError'>${errorState}</span>",
- // noDataMessage: String
- // Message that shows if the grid has no data - wrap it in a
- // span with class 'dojoxGridNoData' if you want it to be
- // styled similar to the loading and error messages
- noDataMessage: "",
-
- // escapeHTMLInData: Boolean
- // This will escape HTML brackets from the data to prevent HTML from
- // user-inputted data being rendered with may contain JavaScript and result in
- // XSS attacks. This is true by default, and it is recommended that it remain
- // true. Setting this to false will allow data to be displayed in the grid without
- // filtering, and should be only used if it is known that the data won't contain
- // malicious scripts. If HTML is needed in grid cells, it is recommended that
- // you use the formatter function to generate the HTML (the output of
- // formatter functions is not filtered, even with escapeHTMLInData set to true).
- escapeHTMLInData: true,
-
- // formatterScope: Object
- // An object to execute format functions within. If not set, the
- // format functions will execute within the scope of the cell that
- // has a format function.
- formatterScope: null,
-
- // editable: boolean
- // indicates if the grid contains editable cells, default is false
- // set to true if editable cell encountered during rendering
- editable: false,
-
- // private
- sortInfo: 0,
- themeable: true,
- _placeholders: null,
- // _layoutClass: Object
- // The class to use for our layout - can be overridden by grid subclasses
- _layoutClass: _Layout,
- // initialization
- buildRendering: function(){
- this.inherited(arguments);
- if(!this.domNode.getAttribute('tabIndex')){
- this.domNode.tabIndex = "0";
- }
- this.createScroller();
- this.createLayout();
- this.createViews();
- this.createManagers();
- this.createSelection();
- this.connect(this.selection, "onSelected", "onSelected");
- this.connect(this.selection, "onDeselected", "onDeselected");
- this.connect(this.selection, "onChanged", "onSelectionChanged");
- metrics.initOnFontResize();
- this.connect(metrics, "onFontResize", "textSizeChanged");
- util.funnelEvents(this.domNode, this, 'doKeyEvent', util.keyEvents);
- if (this.selectionMode != "none") {
- this.domNode.setAttribute("aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
- }
- html.addClass(this.domNode, this.classTag);
- if(!this.isLeftToRight()){
- html.addClass(this.domNode, this.classTag+"Rtl");
- }
- },
-
- postMixInProperties: function(){
- this.inherited(arguments);
- var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
- this.loadingMessage = string.substitute(this.loadingMessage, messages);
- this.errorMessage = string.substitute(this.errorMessage, messages);
- if(this.srcNodeRef && this.srcNodeRef.style.height){
- this.height = this.srcNodeRef.style.height;
- }
- // Call this to update our autoheight to start out
- this._setAutoHeightAttr(this.autoHeight, true);
- this.lastScrollTop = this.scrollTop = 0;
- },
-
- postCreate: function(){
- this._placeholders = [];
- this._setHeaderMenuAttr(this.headerMenu);
- this._setStructureAttr(this.structure);
- this._click = [];
- this.inherited(arguments);
- if(this.domNode && this.autoWidth && this.initialWidth){
- this.domNode.style.width = this.initialWidth;
- }
- if (this.domNode && !this.editable){
- // default value for aria-readonly is false, set to true if grid is not editable
- html.attr(this.domNode,"aria-readonly", "true");
- }
- },
- destroy: function(){
- this.domNode.onReveal = null;
- this.domNode.onSizeChange = null;
- // Fixes IE domNode leak
- delete this._click;
- if(this.scroller){
- this.scroller.destroy();
- delete this.scroller;
- }
- this.edit.destroy();
- delete this.edit;
- this.views.destroyViews();
- if(this.focus){
- this.focus.destroy();
- delete this.focus;
- }
- if(this.headerMenu&&this._placeholders.length){
- array.forEach(this._placeholders, function(p){ p.unReplace(true); });
- this.headerMenu.unBindDomNode(this.viewsHeaderNode);
- }
- this.inherited(arguments);
- },
- _setAutoHeightAttr: function(ah, skipRender){
- // Calculate our autoheight - turn it into a boolean or an integer
- if(typeof ah == "string"){
- if(!ah || ah == "false"){
- ah = false;
- }else if (ah == "true"){
- ah = true;
- }else{
- ah = window.parseInt(ah, 10);
- }
- }
- if(typeof ah == "number"){
- if(isNaN(ah)){
- ah = false;
- }
- // Autoheight must be at least 1, if it's a number. If it's
- // less than 0, we'll take that to mean "all" rows (same as
- // autoHeight=true - if it is equal to zero, we'll take that
- // to mean autoHeight=false
- if(ah < 0){
- ah = true;
- }else if (ah === 0){
- ah = false;
- }
- }
- this.autoHeight = ah;
- if(typeof ah == "boolean"){
- this._autoHeight = ah;
- }else if(typeof ah == "number"){
- this._autoHeight = (ah >= this.get('rowCount'));
- }else{
- this._autoHeight = false;
- }
- if(this._started && !skipRender){
- this.render();
- }
- },
- _getRowCountAttr: function(){
- return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
- this.invalidated.rowCount : this.rowCount;
- },
-
- textSizeChanged: function(){
- this.render();
- },
- sizeChange: function(){
- this.update();
- },
- createManagers: function(){
- // summary:
- // create grid managers for various tasks including rows, focus, selection, editing
- // row manager
- this.rows = new _RowManager(this);
- // focus manager
- this.focus = new _FocusManager(this);
- // edit manager
- this.edit = new _EditManager(this);
- },
- createSelection: function(){
- // summary: Creates a new Grid selection manager.
- // selection manager
- this.selection = new Selection(this);
- },
- createScroller: function(){
- // summary: Creates a new virtual scroller
- this.scroller = new _Scroller();
- this.scroller.grid = this;
- this.scroller.renderRow = lang.hitch(this, "renderRow");
- this.scroller.removeRow = lang.hitch(this, "rowRemoved");
- },
- createLayout: function(){
- // summary: Creates a new Grid layout
- this.layout = new this._layoutClass(this);
- this.connect(this.layout, "moveColumn", "onMoveColumn");
- },
- onMoveColumn: function(){
- this.update();
- },
-
- onResizeColumn: function(/*int*/ cellIdx){
- // Called when a column is resized.
- },
- // views
- createViews: function(){
- this.views = new _ViewManager(this);
- this.views.createView = lang.hitch(this, "createView");
- },
- createView: function(inClass, idx){
- var c = lang.getObject(inClass);
- var view = new c({ grid: this, index: idx });
- this.viewsNode.appendChild(view.domNode);
- this.viewsHeaderNode.appendChild(view.headerNode);
- this.views.addView(view);
- html.attr(this.domNode, "align", this.isLeftToRight() ? 'left' : 'right');
- return view;
- },
- buildViews: function(){
- for(var i=0, vs; (vs=this.layout.structure[i]); i++){
- this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
- }
- this.scroller.setContentNodes(this.views.getContentNodes());
- },
- _setStructureAttr: function(structure){
- var s = structure;
- if(s && lang.isString(s)){
- dojo.deprecated("dojox.grid._Grid.set('structure', 'objVar')", "use dojox.grid._Grid.set('structure', objVar) instead", "2.0");
- s=lang.getObject(s);
- }
- this.structure = s;
- if(!s){
- if(this.layout.structure){
- s = this.layout.structure;
- }else{
- return;
- }
- }
- this.views.destroyViews();
- this.focus.focusView = null;
- if(s !== this.layout.structure){
- this.layout.setStructure(s);
- }
- this._structureChanged();
- },
- setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
- // summary:
- // Install a new structure and rebuild the grid.
- dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.set('structure', obj) instead.", "2.0");
- this._setStructureAttr(inStructure);
- },
-
- getColumnTogglingItems: function(){
- // Summary: returns an array of dijit.CheckedMenuItem widgets that can be
- // added to a menu for toggling columns on and off.
- var items, checkedItems = [];
- items = array.map(this.layout.cells, function(cell){
- if(!cell.menuItems){ cell.menuItems = []; }
- var self = this;
- var item = new CheckedMenuItem({
- label: cell.name,
- checked: !cell.hidden,
- _gridCell: cell,
- onChange: function(checked){
- if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
- var items = this._gridCell.menuItems;
- if(items.length > 1){
- array.forEach(items, function(item){
- if(item !== this){
- item.setAttribute("checked", checked);
- }
- }, this);
- }
- checked = array.filter(self.layout.cells, function(c){
- if(c.menuItems.length > 1){
- array.forEach(c.menuItems, "item.set('disabled', false);");
- }else{
- c.menuItems[0].set('disabled', false);
- }
- return !c.hidden;
- });
- if(checked.length == 1){
- array.forEach(checked[0].menuItems, "item.set('disabled', true);");
- }
- }
- },
- destroy: function(){
- var index = array.indexOf(this._gridCell.menuItems, this);
- this._gridCell.menuItems.splice(index, 1);
- delete this._gridCell;
- CheckedMenuItem.prototype.destroy.apply(this, arguments);
- }
- });
- cell.menuItems.push(item);
- if(!cell.hidden) {
- checkedItems.push(item);
- }
- return item;
- }, this); // dijit.CheckedMenuItem[]
- if(checkedItems.length == 1) {
- checkedItems[0].set('disabled', true);
- }
- return items;
- },
- _setHeaderMenuAttr: function(menu){
- if(this._placeholders && this._placeholders.length){
- array.forEach(this._placeholders, function(p){
- p.unReplace(true);
- });
- this._placeholders = [];
- }
- if(this.headerMenu){
- this.headerMenu.unBindDomNode(this.viewsHeaderNode);
- }
- this.headerMenu = menu;
- if(!menu){ return; }
- this.headerMenu.bindDomNode(this.viewsHeaderNode);
- if(this.headerMenu.getPlaceholders){
- this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
- }
- },
- setHeaderMenu: function(/* dijit.Menu */ menu){
- dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.set('headerMenu', obj) instead.", "2.0");
- this._setHeaderMenuAttr(menu);
- },
-
- setupHeaderMenu: function(){
- if(this._placeholders && this._placeholders.length){
- array.forEach(this._placeholders, function(p){
- if(p._replaced){
- p.unReplace(true);
- }
- p.replace(this.getColumnTogglingItems());
- }, this);
- }
- },
- _fetch: function(start){
- this.setScrollTop(0);
- },
- getItem: function(inRowIndex){
- return null;
- },
-
- showMessage: function(message){
- if(message){
- this.messagesNode.innerHTML = message;
- this.messagesNode.style.display = "";
- }else{
- this.messagesNode.innerHTML = "";
- this.messagesNode.style.display = "none";
- }
- },
- _structureChanged: function() {
- this.buildViews();
- if(this.autoRender && this._started){
- this.render();
- }
- },
- hasLayout: function() {
- return this.layout.cells.length;
- },
- // sizing
- resize: function(changeSize, resultSize){
- // summary:
- // Update the grid's rendering dimensions and resize it
-
- // Calling sizeChange calls update() which calls _resize...so let's
- // save our input values, if any, and use them there when it gets
- // called. This saves us an extra call to _resize(), which can
- // get kind of heavy.
-
- // fixes #11101, should ignore resize when in autoheight mode(IE) to avoid a deadlock
- // e.g when an autoheight editable grid put in dijit.form.Form or other similar containers,
- // grid switch to editing mode --> grid height change --> From height change
- // ---> Form call grid.resize() ---> grid height change --> deaklock
- if(dojo.isIE && !changeSize && !resultSize && this._autoHeight){
- return;
- }
- this._pendingChangeSize = changeSize;
- this._pendingResultSize = resultSize;
- this.sizeChange();
- },
- _getPadBorder: function() {
- this._padBorder = this._padBorder || html._getPadBorderExtents(this.domNode);
- return this._padBorder;
- },
- _getHeaderHeight: function(){
- var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
- vns.height = t + 'px';
- // header heights are reset during measuring so must be normalized after measuring.
- this.views.normalizeHeaderNodeHeight();
- return t;
- },
-
- _resize: function(changeSize, resultSize){
- // Restore our pending values, if any
- changeSize = changeSize || this._pendingChangeSize;
- resultSize = resultSize || this._pendingResultSize;
- delete this._pendingChangeSize;
- delete this._pendingResultSize;
- // if we have set up everything except the DOM, we cannot resize
- if(!this.domNode){ return; }
- var pn = this.domNode.parentNode;
- if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
- return;
- }
- // useful measurement
- var padBorder = this._getPadBorder();
- var hh = undefined;
- var h;
- // grid height
- if(this._autoHeight){
- this.domNode.style.height = 'auto';
- }else if(typeof this.autoHeight == "number"){
- h = hh = this._getHeaderHeight();
- h += (this.scroller.averageRowHeight * this.autoHeight);
- this.domNode.style.height = h + "px";
- }else if(this.domNode.clientHeight <= padBorder.h){
- if(pn == document.body){
- this.domNode.style.height = this.defaultHeight;
- }else if(this.height){
- this.domNode.style.height = this.height;
- }else{
- this.fitTo = "parent";
- }
- }
- // if we are given dimensions, size the grid's domNode to those dimensions
- if(resultSize){
- changeSize = resultSize;
- }
- if(!this._autoHeight && changeSize){
- html.marginBox(this.domNode, changeSize);
- this.height = this.domNode.style.height;
- delete this.fitTo;
- }else if(this.fitTo == "parent"){
- h = this._parentContentBoxHeight = this._parentContentBoxHeight || html._getContentBox(pn).h;
- this.domNode.style.height = Math.max(0, h) + "px";
- }
-
- var hasFlex = array.some(this.views.views, function(v){ return v.flexCells; });
- if(!this._autoHeight && (h || html._getContentBox(this.domNode).h) === 0){
- // We need to hide the header, since the Grid is essentially hidden.
- this.viewsHeaderNode.style.display = "none";
- }else{
- // Otherwise, show the header and give it an appropriate height.
- this.viewsHeaderNode.style.display = "block";
- if(!hasFlex && hh === undefined){
- hh = this._getHeaderHeight();
- }
- }
- if(hasFlex){
- hh = undefined;
- }
- // NOTE: it is essential that width be applied before height
- // Header height can only be calculated properly after view widths have been set.
- // This is because flex column width is naturally 0 in Firefox.
- // Therefore prior to width sizing flex columns with spaces are maximally wrapped
- // and calculated to be too tall.
- this.adaptWidth();
- this.adaptHeight(hh);
- this.postresize();
- },
- adaptWidth: function() {
- // private: sets width and position for views and update grid width if necessary
- var doAutoWidth = (!this.initialWidth && this.autoWidth);
- var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
- vw = this.views.arrange(1, w);
- this.views.onEach("adaptWidth");
- if(doAutoWidth){
- this.domNode.style.width = vw + "px";
- }
- },
- adaptHeight: function(inHeaderHeight){
- // private: measures and normalizes header height, then sets view heights, and then updates scroller
- // content extent
- var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
- var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
- this.views.onEach('setSize', [0, h]);
- this.views.onEach('adaptHeight');
- if(!this._autoHeight){
- var numScroll = 0, numNoScroll = 0;
- var noScrolls = array.filter(this.views.views, function(v){
- var has = v.hasHScrollbar();
- if(has){ numScroll++; }else{ numNoScroll++; }
- return (!has);
- });
- if(numScroll > 0 && numNoScroll > 0){
- array.forEach(noScrolls, function(v){
- v.adaptHeight(true);
- });
- }
- }
- if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.get('rowCount'))){
- this.scroller.windowHeight = h;
- }else{
- this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
- }
- },
- // startup
- startup: function(){
- if(this._started){return;}
- this.inherited(arguments);
- if(this.autoRender){
- this.render();
- }
- },
- // render
- render: function(){
- // summary:
- // Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
- // scrolling states, see Update.
- if(!this.domNode){return;}
- if(!this._started){return;}
- if(!this.hasLayout()) {
- this.scroller.init(0, this.keepRows, this.rowsPerPage);
- return;
- }
- //
- this.update = this.defaultUpdate;
- this._render();
- },
- _render: function(){
- this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
- this.prerender();
- this.setScrollTop(0);
- this.postrender();
- },
- prerender: function(){
- // if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
- this.keepRows = this._autoHeight ? 0 : this.keepRows;
- this.scroller.setKeepInfo(this.keepRows);
- this.views.render();
- this._resize();
- },
- postrender: function(){
- this.postresize();
- this.focus.initFocusView();
- // make rows unselectable
- html.setSelectable(this.domNode, this.selectable);
- },
- postresize: function(){
- // views are position absolute, so they do not inflate the parent
- if(this._autoHeight){
- var size = Math.max(this.views.measureContent()) + 'px';
-
- this.viewsNode.style.height = size;
- }
- },
- renderRow: function(inRowIndex, inNodes){
- // summary: private, used internally to render rows
- this.views.renderRow(inRowIndex, inNodes, this._skipRowRenormalize);
- },
- rowRemoved: function(inRowIndex){
- // summary: private, used internally to remove rows
- this.views.rowRemoved(inRowIndex);
- },
- invalidated: null,
- updating: false,
- beginUpdate: function(){
- // summary:
- // Use to make multiple changes to rows while queueing row updating.
- // NOTE: not currently supporting nested begin/endUpdate calls
- this.invalidated = [];
- this.updating = true;
- },
- endUpdate: function(){
- // summary:
- // Use after calling beginUpdate to render any changes made to rows.
- this.updating = false;
- var i = this.invalidated, r;
- if(i.all){
- this.update();
- }else if(i.rowCount != undefined){
- this.updateRowCount(i.rowCount);
- }else{
- for(r in i){
- this.updateRow(Number(r));
- }
- }
- this.invalidated = [];
- },
- // update
- defaultUpdate: function(){
- // note: initial update calls render and subsequently this function.
- if(!this.domNode){return;}
- if(this.updating){
- this.invalidated.all = true;
- return;
- }
- //this.edit.saveState(inRowIndex);
- this.lastScrollTop = this.scrollTop;
- this.prerender();
- this.scroller.invalidateNodes();
- this.setScrollTop(this.lastScrollTop);
- this.postrender();
- //this.edit.restoreState(inRowIndex);
- },
- update: function(){
- // summary:
- // Update the grid, retaining edit and scrolling states.
- this.render();
- },
- updateRow: function(inRowIndex){
- // summary:
- // Render a single row.
- // inRowIndex: Integer
- // Index of the row to render
- inRowIndex = Number(inRowIndex);
- if(this.updating){
- this.invalidated[inRowIndex]=true;
- }else{
- this.views.updateRow(inRowIndex);
- this.scroller.rowHeightChanged(inRowIndex);
- }
- },
- updateRows: function(startIndex, howMany){
- // summary:
- // Render consecutive rows at once.
- // startIndex: Integer
- // Index of the starting row to render
- // howMany: Integer
- // How many rows to update.
- startIndex = Number(startIndex);
- howMany = Number(howMany);
- var i;
- if(this.updating){
- for(i=0; i<howMany; i++){
- this.invalidated[i+startIndex]=true;
- }
- }else{
- for(i=0; i<howMany; i++){
- this.views.updateRow(i+startIndex, this._skipRowRenormalize);
- }
- this.scroller.rowHeightChanged(startIndex);
- }
- },
- updateRowCount: function(inRowCount){
- //summary:
- // Change the number of rows.
- // inRowCount: int
- // Number of rows in the grid.
- if(this.updating){
- this.invalidated.rowCount = inRowCount;
- }else{
- this.rowCount = inRowCount;
- this._setAutoHeightAttr(this.autoHeight, true);
- if(this.layout.cells.length){
- this.scroller.updateRowCount(inRowCount);
- }
- this._resize();
- if(this.layout.cells.length){
- this.setScrollTop(this.scrollTop);
- }
- }
- },
- updateRowStyles: function(inRowIndex){
- // summary:
- // Update the styles for a row after it's state has changed.
- this.views.updateRowStyles(inRowIndex);
- },
- getRowNode: function(inRowIndex){
- // summary:
- // find the rowNode that is not a rowSelector
- if (this.focus.focusView && !(this.focus.focusView instanceof _RowSelector)){
- return this.focus.focusView.rowNodes[inRowIndex];
- }else{ // search through views
- for (var i = 0, cView; (cView = this.views.views[i]); i++) {
- if (!(cView instanceof _RowSelector)) {
- return cView.rowNodes[inRowIndex];
- }
- }
- }
- return null;
- },
- rowHeightChanged: function(inRowIndex){
- // summary:
- // Update grid when the height of a row has changed. Row height is handled automatically as rows
- // are rendered. Use this function only to update a row's height outside the normal rendering process.
- // inRowIndex: Integer
- // index of the row that has changed height
- this.views.renormalizeRow(inRowIndex);
- this.scroller.rowHeightChanged(inRowIndex);
- },
- // fastScroll: Boolean
- // flag modifies vertical scrolling behavior. Defaults to true but set to false for slower
- // scroll performance but more immediate scrolling feedback
- fastScroll: true,
- delayScroll: false,
- // scrollRedrawThreshold: int
- // pixel distance a user must scroll vertically to trigger grid scrolling.
- scrollRedrawThreshold: (has("ie") ? 100 : 50),
- // scroll methods
- scrollTo: function(inTop){
- // summary:
- // Vertically scroll the grid to a given pixel position
- // inTop: Integer
- // vertical position of the grid in pixels
- if(!this.fastScroll){
- this.setScrollTop(inTop);
- return;
- }
- var delta = Math.abs(this.lastScrollTop - inTop);
- this.lastScrollTop = inTop;
- if(delta > this.scrollRedrawThreshold || this.delayScroll){
- this.delayScroll = true;
- this.scrollTop = inTop;
- this.views.setScrollTop(inTop);
- if(this._pendingScroll){
- window.clearTimeout(this._pendingScroll);
- }
- var _this = this;
- this._pendingScroll = window.setTimeout(function(){
- delete _this._pendingScroll;
- _this.finishScrollJob();
- }, 200);
- }else{
- this.setScrollTop(inTop);
- }
- },
- finishScrollJob: function(){
- this.delayScroll = false;
- this.setScrollTop(this.scrollTop);
- },
- setScrollTop: function(inTop){
- this.scroller.scroll(this.views.setScrollTop(inTop));
- },
- scrollToRow: function(inRowIndex){
- // summary:
- // Scroll the grid to a specific row.
- // inRowIndex: Integer
- // grid row index
- this.setScrollTop(this.scroller.findScrollTop(inRowIndex) + 1);
- },
- // styling (private, used internally to style individual parts of a row)
- styleRowNode: function(inRowIndex, inRowNode){
- if(inRowNode){
- this.rows.styleRowNode(inRowIndex, inRowNode);
- }
- },
-
- // called when the mouse leaves the grid so we can deselect all hover rows
- _mouseOut: function(e){
- this.rows.setOverRow(-2);
- },
-
- // cells
- getCell: function(inIndex){
- // summary:
- // Retrieves the cell object for a given grid column.
- // inIndex: Integer
- // Grid column index of cell to retrieve
- // returns:
- // a grid cell
- return this.layout.cells[inIndex];
- },
- setCellWidth: function(inIndex, inUnitWidth){
- this.getCell(inIndex).unitWidth = inUnitWidth;
- },
- getCellName: function(inCell){
- // summary: Returns the cell name of a passed cell
- return "Cell " + inCell.index; // String
- },
- // sorting
- canSort: function(inSortInfo){
- // summary:
- // Determines if the grid can be sorted
- // inSortInfo: Integer
- // Sort information, 1-based index of column on which to sort, positive for an ascending sort
- // and negative for a descending sort
- // returns: Boolean
- // True if grid can be sorted on the given column in the given direction
- },
- sort: function(){
- },
- getSortAsc: function(inSortInfo){
- // summary:
- // Returns true if grid is sorted in an ascending direction.
- inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
- return Boolean(inSortInfo > 0); // Boolean
- },
- getSortIndex: function(inSortInfo){
- // summary:
- // Returns the index of the column on which the grid is sorted
- inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
- return Math.abs(inSortInfo) - 1; // Integer
- },
- setSortIndex: function(inIndex, inAsc){
- // summary:
- // Sort the grid on a column in a specified direction
- // inIndex: Integer
- // Column index on which to sort.
- // inAsc: Boolean
- // If true, sort the grid in ascending order, otherwise in descending order
- var si = inIndex +1;
- if(inAsc != undefined){
- si *= (inAsc ? 1 : -1);
- } else if(this.getSortIndex() == inIndex){
- si = -this.sortInfo;
- }
- this.setSortInfo(si);
- },
- setSortInfo: function(inSortInfo){
- if(this.canSort(inSortInfo)){
- this.sortInfo = inSortInfo;
- this.sort();
- this.update();
- }
- },
- // DOM event handler
- doKeyEvent: function(e){
- e.dispatch = 'do' + e.type;
- this.onKeyEvent(e);
- },
- // event dispatch
- //: protected
- _dispatch: function(m, e){
- if(m in this){
- return this[m](e);
- }
- return false;
- },
- dispatchKeyEvent: function(e){
- this._dispatch(e.dispatch, e);
- },
- dispatchContentEvent: function(e){
- this.edit.dispatchEvent(e) || e.sourceView.dispatchContentEvent(e) || this._dispatch(e.dispatch, e);
- },
- dispatchHeaderEvent: function(e){
- e.sourceView.dispatchHeaderEvent(e) || this._dispatch('doheader' + e.type, e);
- },
- dokeydown: function(e){
- this.onKeyDown(e);
- },
- doclick: function(e){
- if(e.cellNode){
- this.onCellClick(e);
- }else{
- this.onRowClick(e);
- }
- },
- dodblclick: function(e){
- if(e.cellNode){
- this.onCellDblClick(e);
- }else{
- this.onRowDblClick(e);
- }
- },
- docontextmenu: function(e){
- if(e.cellNode){
- this.onCellContextMenu(e);
- }else{
- this.onRowContextMenu(e);
- }
- },
- doheaderclick: function(e){
- if(e.cellNode){
- this.onHeaderCellClick(e);
- }else{
- this.onHeaderClick(e);
- }
- },
- doheaderdblclick: function(e){
- if(e.cellNode){
- this.onHeaderCellDblClick(e);
- }else{
- this.onHeaderDblClick(e);
- }
- },
- doheadercontextmenu: function(e){
- if(e.cellNode){
- this.onHeaderCellContextMenu(e);
- }else{
- this.onHeaderContextMenu(e);
- }
- },
- // override to modify editing process
- doStartEdit: function(inCell, inRowIndex){
- this.onStartEdit(inCell, inRowIndex);
- },
- doApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
- this.onApplyCellEdit(inValue, inRowIndex, inFieldIndex);
- },
- doCancelEdit: function(inRowIndex){
- this.onCancelEdit(inRowIndex);
- },
- doApplyEdit: function(inRowIndex){
- this.onApplyEdit(inRowIndex);
- },
- // row editing
- addRow: function(){
- // summary:
- // Add a row to the grid.
- this.updateRowCount(this.get('rowCount')+1);
- },
- removeSelectedRows: function(){
- // summary:
- // Remove the selected rows from the grid.
- if(this.allItemsSelected){
- this.updateRowCount(0);
- }else{
- this.updateRowCount(Math.max(0, this.get('rowCount') - this.selection.getSelected().length));
- }
- this.selection.clear();
- }
- });
- _Grid.markupFactory = function(props, node, ctor, cellFunc){
- var widthFromAttr = function(n){
- var w = html.attr(n, "width")||"auto";
- if((w != "auto")&&(w.slice(-2) != "em")&&(w.slice(-1) != "%")){
- w = parseInt(w, 10)+"px";
- }
- return w;
- };
- // if(!props.store){ console.debug("no store!"); }
- // if a structure isn't referenced, do we have enough
- // data to try to build one automatically?
- if( !props.structure &&
- node.nodeName.toLowerCase() == "table"){
- // try to discover a structure
- props.structure = query("> colgroup", node).map(function(cg){
- var sv = html.attr(cg, "span");
- var v = {
- noscroll: (html.attr(cg, "noscroll") == "true") ? true : false,
- __span: (!!sv ? parseInt(sv, 10) : 1),
- cells: []
- };
- if(html.hasAttr(cg, "width")){
- v.width = widthFromAttr(cg);
- }
- return v; // for vendetta
- });
- if(!props.structure.length){
- props.structure.push({
- __span: Infinity,
- cells: [] // catch-all view
- });
- }
- // check to see if we're gonna have more than one view
- // for each tr in our th, create a row of cells
- query("thead > tr", node).forEach(function(tr, tr_idx){
- var cellCount = 0;
- var viewIdx = 0;
- var lastViewIdx;
- var cView = null;
- query("> th", tr).map(function(th){
- // what view will this cell go into?
- // NOTE:
- // to prevent extraneous iteration, we start counters over
- // for each row, incrementing over the surface area of the
- // structure that colgroup processing generates and
- // creating cell objects for each <th> to place into those
- // cell groups. There's a lot of state-keepking logic
- // here, but it is what it has to be.
- if(!cView){ // current view book keeping
- lastViewIdx = 0;
- cView = props.structure[0];
- }else if(cellCount >= (lastViewIdx+cView.__span)){
- viewIdx++;
- // move to allocating things into the next view
- lastViewIdx += cView.__span;
- var lastView = cView;
- cView = props.structure[viewIdx];
- }
- // actually define the cell from what markup hands us
- var cell = {
- name: lang.trim(html.attr(th, "name")||th.innerHTML),
- colSpan: parseInt(html.attr(th, "colspan")||1, 10),
- type: lang.trim(html.attr(th, "cellType")||""),
- id: lang.trim(html.attr(th,"id")||"")
- };
- cellCount += cell.colSpan;
- var rowSpan = html.attr(th, "rowspan");
- if(rowSpan){
- cell.rowSpan = rowSpan;
- }
- if(html.hasAttr(th, "width")){
- cell.width = widthFromAttr(th);
- }
- if(html.hasAttr(th, "relWidth")){
- cell.relWidth = window.parseInt(html.attr(th, "relWidth"), 10);
- }
- if(html.hasAttr(th, "hidden")){
- cell.hidden = (html.attr(th, "hidden") == "true" || html.attr(th, "hidden") === true/*always boolean true in Chrome*/);
- }
- if(cellFunc){
- cellFunc(th, cell);
- }
- cell.type = cell.type ? lang.getObject(cell.type) : dojox.grid.cells.Cell;
- if(cell.type && cell.type.markupFactory){
- cell.type.markupFactory(th, cell);
- }
- if(!cView.cells[tr_idx]){
- cView.cells[tr_idx] = [];
- }
- cView.cells[tr_idx].push(cell);
- });
- });
- }
- return new ctor(props, node);
- };
- return _Grid;
- });
- },
- 'dojox/grid/enhanced/plugins/IndirectSelection':function(){
- define("dojox/grid/enhanced/plugins/IndirectSelection", [
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/event",
- "dojo/_base/lang",
- "dojo/_base/html",
- "dojo/_base/window",
- "dojo/_base/connect",
- "dojo/_base/sniff",
- "dojo/query",
- "dojo/keys",
- "dojo/string",
- "../_Plugin",
- "../../EnhancedGrid",
- "../../cells/dijit"
- ], function(declare, array, evt, lang, html, win, connect, has, query, keys, string, _Plugin, EnhancedGrid){
- var gridCells = lang.getObject("dojox.grid.cells");
- var RowSelector = declare("dojox.grid.cells.RowSelector", gridCells._Widget, {
- // summary:
- // Common attributes & functions for row selectors(Radio|CheckBox)
- //inputType: String
- // Input type - Radio|CheckBox
- inputType: "",
-
- //map: Object
- // Cache div refs of radio|checkbox to avoid querying each time
- map: null,
-
- //disabledMap: Object
- // Cache index of disabled rows
- disabledMap: null,
-
- //isRowSelector: Boolean
- // Marker of indirectSelection cell(column)
- isRowSelector: true,
- //_connects: Array
- // List of all connections.
- _connects: null,
-
- //_subscribes: Array
- // List of all subscribes.
- _subscribes: null,
- //checkedText: String
- // Checked character for high contrast mode
- checkedText: '✓',
- //unCheckedText: String
- // Unchecked character for high contrast mode
- unCheckedText: 'O',
- constructor: function(){
- this.map = {}; this.disabledMap = {}, this.disabledCount= 0;
- this._connects = []; this._subscribes = [];
- this.inA11YMode = html.hasClass(win.body(), "dijit_a11y");
-
- this.baseClass = "dojoxGridRowSelector dijitReset dijitInline dijit" + this.inputType;
- this.checkedClass = " dijit" + this.inputType + "Checked";
- this.disabledClass = " dijit" + this.inputType + "Disabled";
- this.checkedDisabledClass = " dijit" + this.inputType + "CheckedDisabled";
- this.statusTextClass = " dojoxGridRowSelectorStatusText";//a11y use
- this._connects.push(connect.connect(this.grid, 'dokeyup', this, '_dokeyup'));
- this._connects.push(connect.connect(this.grid.selection, 'onSelected', this, '_onSelected'));
- this._connects.push(connect.connect(this.grid.selection, 'onDeselected', this, '_onDeselected'));
- this._connects.push(connect.connect(this.grid.scroller, 'invalidatePageNode', this, '_pageDestroyed'));
- this._connects.push(connect.connect(this.grid, 'onCellClick', this, '_onClick'));
- this._connects.push(connect.connect(this.grid, 'updateRow', this, '_onUpdateRow'));
- },
- formatter: function(data, rowIndex, scope){
- // summary:
- // Overwritten, see dojox.grid.cells._Widget
- var _this = scope;
- var clazz = _this.baseClass;
- var checked = _this.getValue(rowIndex);
- var disabled = !!_this.disabledMap[rowIndex];//normalize 'undefined'
-
- if(checked){
- clazz += _this.checkedClass;
- if(disabled){ clazz += _this.checkedDisabledClass; }
- }else if(disabled){
- clazz += _this.disabledClass;
- }
- return ["<div tabindex = -1 ",
- "id = '" + _this.grid.id + "_rowSelector_" + rowIndex + "' ",
- "name = '" + _this.grid.id + "_rowSelector' class = '" + clazz + "' ",
- "role = 'presentation' aria-pressed = '" + checked + "' aria-disabled = '" + disabled +
- "' aria-label = '" + string.substitute(_this.grid._nls["indirectSelection" + _this.inputType], [rowIndex + 1]) + "'>",
- "<span class = '" + _this.statusTextClass + "'>" + (checked ? _this.checkedText : _this.unCheckedText) + "</span>",
- "</div>"].join("");
- },
- setValue: function(rowIndex, inValue){
- // summary:
- // Overwritten, see dojox.grid.cells._Widget
- // Simply return, no action
- },
- getValue: function(rowIndex){
- // summary:
- // Overwritten, see dojox.grid.cells._Widget
- return this.grid.selection.isSelected(rowIndex);
- },
- toggleRow: function(index, value){
- // summary:
- // toggle checked | unchecked state for given row
- // index: Integer
- // Row index
- // value: Boolean
- // True - checked | False - unchecked
- this._nativeSelect(index, value);
- },
- setDisabled: function(index, disabled){
- // summary:
- // toggle disabled | enabled state for given row
- // idx: Integer
- // Row index
- // disabled: Boolean
- // True - disabled | False - enabled
- if(index < 0){ return; }
- this._toggleDisabledStyle(index, disabled);
- },
- disabled: function(index){
- // summary:
- // Check if one row is disabled
- return !!this.disabledMap[index];
- },
- _onClick: function(e){
- // summary:
- // When mouse click on the selector cell, select/deselect the row.
- if(e.cell === this){
- this._selectRow(e);
- }
- },
- _dokeyup: function(e){
- // summary:
- // Event handler for key up event
- // - from dojox.grid.enhanced._Events.dokeyup()
- // e: Event
- // Key up event
- if(e.cellIndex == this.index && e.rowIndex >= 0 && e.keyCode == keys.SPACE){
- this._selectRow(e);
- }
- },
- focus: function(rowIndex){
- // summary:
- // Set focus to given row
- // rowIndex: Integer
- // Target row
- var selector = this.map[rowIndex];
- if(selector){ selector.focus(); }
- },
- _focusEndingCell: function(rowIndex, cellIndex){
- // summary:
- // Set focus to the ending grid cell(rowIndex,cellIndex) when swipe selection finished
- // rowIndex: Integer
- // Row index
- // cellIndex: Integer
- // Column index
- var cell = this.grid.getCell(cellIndex);
- this.grid.focus.setFocusCell(cell, rowIndex);
- },
- _nativeSelect: function(index, value){
- // summary:
- // Use grid's native selection
- this.grid.selection[value ? 'select' : 'deselect'](index);
- },
- _onSelected: function(index){
- // summary:
- // Triggered when a row is selected
- this._toggleCheckedStyle(index, true);
- },
- _onDeselected: function(index){
- // summary:
- // Triggered when a row is deselected
- this._toggleCheckedStyle(index, false);
- },
- _onUpdateRow: function(index){
- // summary:
- // Clear cache when row is re-built.
- delete this.map[index];
- },
- _toggleCheckedStyle: function(index, value){
- // summary:
- // Change css styles for checked | unchecked
- var selector = this._getSelector(index);
- if(selector){
- html.toggleClass(selector, this.checkedClass, value);
- if(this.disabledMap[index]){
- html.toggleClass(selector, this.checkedDisabledClass, value);
- }
- selector.setAttribute("aria-pressed", value);
- if(this.inA11YMode){
- selector.firstChild.innerHTML = (value ? this.checkedText : this.unCheckedText);
- }
- }
- },
- _toggleDisabledStyle: function(index, disabled){
- // summary:
- // Change css styles for disabled | enabled
- var selector = this._getSelector(index);
- if(selector){
- html.toggleClass(selector, this.disabledClass, disabled);
- if(this.getValue(index)){
- html.toggleClass(selector, this.checkedDisabledClass, disabled);
- }
- selector.setAttribute("aria-disabled", disabled);
- }
- this.disabledMap[index] = disabled;
- if(index >= 0){
- this.disabledCount += disabled ? 1 : -1;
- }
- },
- _getSelector: function(index){
- // summary:
- // Find selector for given row caching it if 1st time found
- var selector = this.map[index];
- if(!selector){//use accurate query for better performance
- var rowNode = this.view.rowNodes[index];
- if(rowNode){
- selector = query('.dojoxGridRowSelector', rowNode)[0];
- if(selector){ this.map[index] = selector; }
- }
- }
- return selector;
- },
- _pageDestroyed: function(pageIndex){
- // summary:
- // Explicitly empty map cache when a page destroyed
- // See dojox.grid._Scroller.invalidatePageNode()
- // pageIndex: Integer
- // Index of destroyed page
- var rowsPerPage = this.grid.scroller.rowsPerPage;
- var start = pageIndex * rowsPerPage, end = start + rowsPerPage - 1;
- for(var i = start; i <= end; i++){
- if(!this.map[i]){continue;}
- html.destroy(this.map[i]);
- delete this.map[i];
- }
- //console.log("Page ",pageIndex, " destroyed, Map=",this.map);
- },
- destroy: function(){
- for(var i in this.map){
- html.destroy(this.map[i]);
- delete this.map[i];
- }
- for(i in this.disabledMap){ delete this.disabledMap[i]; }
- array.forEach(this._connects, connect.disconnect);
- array.forEach(this._subscribes, connect.unsubscribe);
- delete this._connects;
- delete this._subscribes;
- //console.log('Single(Multiple)RowSelector.destroy() executed!');
- }
- });
- var SingleRowSelector = declare("dojox.grid.cells.SingleRowSelector", RowSelector, {
- // summary:
- // IndirectSelection cell(column) for single selection mode, using styles of dijit.form.RadioButton
- inputType: "Radio",
- _selectRow: function(e){
- // summary:
- // Select the target row
- // e: Event
- // Event fired on the target row
- var index = e.rowIndex;
- if(this.disabledMap[index]){ return; }
- this._focusEndingCell(index, 0);
- this._nativeSelect(index, !this.grid.selection.selected[index]);
- }
- });
- var MultipleRowSelector = declare("dojox.grid.cells.MultipleRowSelector", RowSelector, {
- // summary:
- // Indirect selection cell for multiple or extended mode, using dijit.form.CheckBox
- inputType: "CheckBox",
-
- //swipeStartRowIndex: Integer
- // Start row index for swipe selection
- swipeStartRowIndex: -1,
- //swipeMinRowIndex: Integer
- // Min row index for swipe selection
- swipeMinRowIndex: -1,
-
- //swipeMinRowIndex: Integer
- // Max row index for swipe selection
- swipeMaxRowIndex: -1,
-
- //toSelect: Boolean
- // new state for selection
- toSelect: false,
-
- //lastClickRowIdx: Integer
- // Row index for last click, used for range selection via Shift + click
- lastClickRowIdx: -1,
-
- //toggleAllTrigerred: Boolean
- // Whether toggle all has been triggered or not
- toggleAllTrigerred: false,
-
- unCheckedText: '□',
- constructor: function(){
- this._connects.push(connect.connect(win.doc, 'onmouseup', this, '_domouseup'));
- this._connects.push(connect.connect(this.grid, 'onRowMouseOver', this, '_onRowMouseOver'));
- this._connects.push(connect.connect(this.grid.focus, 'move', this, '_swipeByKey'));
- this._connects.push(connect.connect(this.grid, 'onCellMouseDown', this, '_onMouseDown'));
- if(this.headerSelector){//option set by user to add a select-all checkbox in column header
- this._connects.push(connect.connect(this.grid.views, 'render', this, '_addHeaderSelector'));
- this._connects.push(connect.connect(this.grid, '_onFetchComplete', this, '_addHeaderSelector'));
- this._connects.push(connect.connect(this.grid, 'onSelectionChanged', this, '_onSelectionChanged'));
- this._connects.push(connect.connect(this.grid, 'onKeyDown', this, function(e){
- if(e.rowIndex == -1 && e.cellIndex == this.index && e.keyCode == keys.SPACE){
- this._toggletHeader();//TBD - a better way
- }
- }));
- }
- },
- toggleAllSelection:function(checked){
- // summary:
- // Toggle select all|deselect all
- // checked: Boolean
- // True - select all, False - deselect all
- var grid = this.grid, selection = grid.selection;
- if(checked){
- selection.selectRange(0, grid.rowCount-1);
- }else{
- selection.deselectAll();
- }
- this.toggleAllTrigerred = true;
- },
- _onMouseDown: function(e){
- if(e.cell == this){
- this._startSelection(e.rowIndex);
- evt.stop(e);
- }
- },
- _onRowMouseOver: function(e){
- // summary:
- // Event fired when mouse moves over a data row(outside of this column).
- // - from dojox.grid.enhanced._Events.onRowMouseOver()
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this._updateSelection(e, 0);
- },
- _domouseup: function(e){
- // summary:
- // Event handler for mouse up event - from dojo.doc.domouseup()
- // e: Event
- // Mouse up event
- if(has("ie")){
- this.view.content.decorateEvent(e);//TODO - why only e in IE hasn't been decorated?
- }
- var inSwipeSelection = e.cellIndex >= 0 && this.inSwipeSelection() && !this.grid.edit.isEditRow(e.rowIndex);
- if(inSwipeSelection){
- this._focusEndingCell(e.rowIndex, e.cellIndex);
- }
- this._finishSelect();
- },
- _dokeyup: function(e){
- // summary:
- // Event handler for key up event
- // - from dojox.grid.enhanced._Events.dokeyup()
- // e: Event
- // Key up event
- this.inherited(arguments);
- if(!e.shiftKey){
- this._finishSelect();
- }
- },
- _startSelection: function(rowIndex){
- // summary:
- // Initialize parameters to start a new swipe selection
- // rowIndex: Integer
- // Index of the start row
- this.swipeStartRowIndex = this.swipeMinRowIndex = this.swipeMaxRowIndex = rowIndex;
- this.toSelect = !this.getValue(rowIndex);
- },
- _updateSelection: function(e, delta){
- // summary:
- // Update row selections, fired during a swipe selection
- // e: Event
- // Event of the current row,
- // delta: Integer
- // Row index delta, used for swipe selection via Shift + Arrow key
- // 0: not via key, -1 : Shift + Up, 1 : Shift + Down
- if(!this.inSwipeSelection()){ return; }
-
- var byKey = delta !== 0;//whether via Shift + Arrow Key
- var currRow = e.rowIndex, deltaRow = currRow - this.swipeStartRowIndex + delta;
- if(deltaRow > 0 && this.swipeMaxRowIndex < currRow + delta){
- this.swipeMaxRowIndex = currRow + delta;
- }
- if(deltaRow < 0 && this.swipeMinRowIndex > currRow + delta){
- this.swipeMinRowIndex = currRow + delta;
- }
- var min = deltaRow > 0 ? this.swipeStartRowIndex : currRow + delta;
- var max = deltaRow > 0 ? currRow + delta : this.swipeStartRowIndex;
- for(var i = this.swipeMinRowIndex; i <= this.swipeMaxRowIndex; i++){
- if(this.disabledMap[i] || i < 0){ continue; }
- if(i >= min && i <= max){//deltaRow != 0 || this.toSelect
- this._nativeSelect(i, this.toSelect);
- }else if(!byKey){
- this._nativeSelect(i, !this.toSelect);
- }
- }
- },
- _swipeByKey: function(rowOffset, colOffset, e){
- // summary:
- // Update row selections, fired when Shift + Cursor is used for swipe selection
- // See dojox.grid.enhanced._Events.onKeyDown
- // e: Event
- // Event of the current row,
- // rowOffset: Integer
- // Row offset, used for swipe selection via Shift + Cursor
- // -1 : Shift + Up, 1 : Shift + Down
- if(!e || rowOffset === 0 || !e.shiftKey || e.cellIndex != this.index ||
- this.grid.focus.rowIndex < 0){ //TBD - e.rowIndex == 0 && delta == -1
- return;
- }
- var rowIndex = e.rowIndex;
- if(this.swipeStartRowIndex < 0){
- //A new swipe selection starts via Shift + Arrow key
- this.swipeStartRowIndex = rowIndex;
- if(rowOffset > 0){//Shift + Down
- this.swipeMaxRowIndex = rowIndex + rowOffset;
- this.swipeMinRowIndex = rowIndex;
- }else{//Shift + UP
- this.swipeMinRowIndex = rowIndex + rowOffset;
- this.swipeMaxRowIndex = rowIndex;
- }
- this.toSelect = this.getValue(rowIndex);
- }
- this._updateSelection(e, rowOffset);
- },
- _finishSelect: function(){
- // summary:
- // Reset parameters to end a swipe selection
- this.swipeStartRowIndex = -1;
- this.swipeMinRowIndex = -1;
- this.swipeMaxRowIndex = -1;
- this.toSelect = false;
- },
- inSwipeSelection: function(){
- // summary:
- // Check if during a swipe selection
- // return: Boolean
- // Whether in swipe selection
- return this.swipeStartRowIndex >= 0;
- },
- _nativeSelect: function(index, value){
- // summary:
- // Overwritten
- this.grid.selection[value ? 'addToSelection' : 'deselect'](index);
- },
- _selectRow: function(e){
- // summary:
- // Select the target row or range or rows
- // e: Event
- // Event fired on the target row
- var rowIndex = e.rowIndex;
- if(this.disabledMap[rowIndex]){ return; }
- evt.stop(e);
- this._focusEndingCell(rowIndex, 0);
-
- var delta = rowIndex - this.lastClickRowIdx;
- var newValue = !this.grid.selection.selected[rowIndex];
- if(this.lastClickRowIdx >= 0 && !e.ctrlKey && !e.altKey && e.shiftKey){
- var min = delta > 0 ? this.lastClickRowIdx : rowIndex;
- var max = delta > 0 ? rowIndex : this.lastClickRowIdx;
- for(var i = min; i >= 0 && i <= max; i++){
- this._nativeSelect(i, newValue);
- }
- }else{
- this._nativeSelect(rowIndex, newValue);
- }
- this.lastClickRowIdx = rowIndex;
- },
- getValue: function(rowIndex){
- // summary:
- // Overwritten
- if(rowIndex == -1){//header selector
- var g = this.grid;
- return g.rowCount > 0 && g.rowCount <= g.selection.getSelectedCount();
- }
- return this.inherited(arguments);
- },
- _addHeaderSelector: function(){
- // summary:
- // Add selector in column header for selecting|deselecting all
- var headerCellNode = this.view.getHeaderCellNode(this.index);
- if(!headerCellNode){ return; }
- html.empty(headerCellNode);
- var g = this.grid;
- var selector = headerCellNode.appendChild(html.create("div", {
- 'aria-label': g._nls["selectAll"],
- "tabindex": -1, "id": g.id + "_rowSelector_-1", "class": this.baseClass, "role": "presentation",
- "innerHTML": "<span class = '" + this.statusTextClass +
- "'></span><span style='height: 0; width: 0; overflow: hidden; display: block;'>" +
- g._nls["selectAll"] + "</span>"
- }));
- this.map[-1] = selector;
- var idx = this._headerSelectorConnectIdx;
- if(idx !== undefined){
- connect.disconnect(this._connects[idx]);
- this._connects.splice(idx, 1);
- }
- this._headerSelectorConnectIdx = this._connects.length;
- this._connects.push(connect.connect(selector, 'onclick', this, '_toggletHeader'));
- this._onSelectionChanged();
- },
- _toggletHeader: function(){
- // summary:
- // Toggle state for head selector
- if(!!this.disabledMap[-1]){ return; }
- this.grid._selectingRange = true;
- this.toggleAllSelection(!this.getValue(-1));
- this._onSelectionChanged();
- this.grid._selectingRange = false;
- },
- _onSelectionChanged: function(){
- // summary:
- // Update header selector anytime selection changed
- var g = this.grid;
- if(!this.map[-1] || g._selectingRange){ return; }
- g.allItemsSelected = this.getValue(-1);
- this._toggleCheckedStyle(-1, g.allItemsSelected);
- },
- _toggleDisabledStyle: function(index, disabled){
- // summary:
- // Overwritten
- this.inherited(arguments);
- if(this.headerSelector){
- var allDisabled = (this.grid.rowCount == this.disabledCount);
- if(allDisabled != !!this.disabledMap[-1]){//only if needed
- arguments[0] = -1;
- arguments[1] = allDisabled;
- this.inherited(arguments);
- }
- }
- }
- });
- var IndirectSelection = declare("dojox.grid.enhanced.plugins.IndirectSelection", _Plugin, {
- // summary:
- // A handy way for adding check boxe/radio button for rows, and selecting rows by swiping(or keyboard)
- // description:
- // For better rendering performance, div(images) are used to simulate radio button|check boxes
- //
- // example:
- // <div dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: true}" ...></div>
- // or <div dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: {name: 'xxx', width:'30px', styles:'text-align: center;'}}" ...></div>
- //name: String
- // Plugin name
- name: "indirectSelection",
-
- constructor: function(){
- //Hook layout.setStructure(), so that indirectSelection is always included
- var layout = this.grid.layout;
- this.connect(layout, 'setStructure', lang.hitch(layout, this.addRowSelectCell, this.option));
- },
- addRowSelectCell: function(option){
- // summary:
- // Add indirectSelection cell(mapped to a column of radio button|check boxes)
- if(!this.grid.indirectSelection || this.grid.selectionMode == 'none'){
- return;
- }
- var rowSelectCellAdded = false, inValidFields = ['get', 'formatter', 'field', 'fields'],
- defaultCellDef = {type: MultipleRowSelector, name: '', width:'30px', styles:'text-align: center;'};
- if(option.headerSelector){ option.name = ''; }//mutual conflicting attrs
- if(this.grid.rowSelectCell){//remove the existed one
- this.grid.rowSelectCell.destroy();
- }
-
- array.forEach(this.structure, function(view){
- var cells = view.cells;
- if(cells && cells.length > 0 && !rowSelectCellAdded){
- var firstRow = cells[0];
- if(firstRow[0] && firstRow[0].isRowSelector){
- console.debug('addRowSelectCell() - row selector cells already added, return.');
- rowSelectCellAdded = true;
- return;
- }
- var selectDef, cellType = this.grid.selectionMode == 'single' ? SingleRowSelector : MultipleRowSelector;
- selectDef = lang.mixin(defaultCellDef, option, {type: cellType, editable: false, notselectable: true, filterable: false, navigatable: true, nosort: true});
- array.forEach(inValidFields, function(field){//remove invalid fields
- if(field in selectDef){ delete selectDef[field]; }
- });
- if(cells.length > 1){ selectDef.rowSpan = cells.length; }//for complicate layout
- array.forEach(this.cells, function(cell, i){
- if(cell.index >= 0){
- cell.index += 1;
- //console.debug('cell '+ (cell.index - 1) + ' is updated to index ' + cell.index);
- }else{
- console.warn('Error:IndirectSelection.addRowSelectCell()- cell ' + i + ' has no index!');
- }
- });
- var rowSelectCell = this.addCellDef(0, 0, selectDef);
- rowSelectCell.index = 0;
- firstRow.unshift(rowSelectCell);
- this.cells.unshift(rowSelectCell);
- this.grid.rowSelectCell = rowSelectCell;
- rowSelectCellAdded = true;
- }
- }, this);
- this.cellCount = this.cells.length;
- },
- destroy: function(){
- this.grid.rowSelectCell.destroy();
- delete this.grid.rowSelectCell;
- this.inherited(arguments);
- }
- });
- EnhancedGrid.registerPlugin(IndirectSelection/*name:'indirectSelection'*/, {"preInit": true});
- return IndirectSelection;
- });
- },
- 'dijit/Editor':function(){
- define("dijit/Editor", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/_base/Deferred", // Deferred
- "dojo/i18n", // i18n.getLocalization
- "dojo/dom-attr", // domAttr.set
- "dojo/dom-class", // domClass.add
- "dojo/dom-geometry",
- "dojo/dom-style", // domStyle.set, get
- "dojo/_base/event", // event.stop
- "dojo/keys", // keys.F1 keys.F15 keys.TAB
- "dojo/_base/lang", // lang.getObject lang.hitch
- "dojo/_base/sniff", // has("ie") has("mac") has("webkit")
- "dojo/string", // string.substitute
- "dojo/topic", // topic.publish()
- "dojo/_base/window", // win.withGlobal
- "./_base/focus", // dijit.getBookmark()
- "./_Container",
- "./Toolbar",
- "./ToolbarSeparator",
- "./layout/_LayoutWidget",
- "./form/ToggleButton",
- "./_editor/_Plugin",
- "./_editor/plugins/EnterKeyHandling",
- "./_editor/html",
- "./_editor/range",
- "./_editor/RichText",
- ".", // dijit._scopeName
- "dojo/i18n!./_editor/nls/commands"
- ], function(array, declare, Deferred, i18n, domAttr, domClass, domGeometry, domStyle,
- event, keys, lang, has, string, topic, win,
- focusBase, _Container, Toolbar, ToolbarSeparator, _LayoutWidget, ToggleButton,
- _Plugin, EnterKeyHandling, html, rangeapi, RichText, dijit){
- // module:
- // dijit/Editor
- // summary:
- // A rich text Editing widget
- var Editor = declare("dijit.Editor", RichText, {
- // summary:
- // A rich text Editing widget
- //
- // description:
- // This widget provides basic WYSIWYG editing features, based on the browser's
- // underlying rich text editing capability, accompanied by a toolbar (`dijit.Toolbar`).
- // A plugin model is available to extend the editor's capabilities as well as the
- // the options available in the toolbar. Content generation may vary across
- // browsers, and clipboard operations may have different results, to name
- // a few limitations. Note: this widget should not be used with the HTML
- // <TEXTAREA> tag -- see dijit._editor.RichText for details.
- // plugins: [const] Object[]
- // A list of plugin names (as strings) or instances (as objects)
- // for this widget.
- //
- // When declared in markup, it might look like:
- // | plugins="['bold',{name:'dijit._editor.plugins.FontChoice', command:'fontName', generic:true}]"
- plugins: null,
- // extraPlugins: [const] Object[]
- // A list of extra plugin names which will be appended to plugins array
- extraPlugins: null,
- constructor: function(){
- // summary:
- // Runs on widget initialization to setup arrays etc.
- // tags:
- // private
- if(!lang.isArray(this.plugins)){
- this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|",
- "insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull",
- EnterKeyHandling /*, "createLink"*/];
- }
- this._plugins=[];
- this._editInterval = this.editActionInterval * 1000;
- //IE will always lose focus when other element gets focus, while for FF and safari,
- //when no iframe is used, focus will be lost whenever another element gets focus.
- //For IE, we can connect to onBeforeDeactivate, which will be called right before
- //the focus is lost, so we can obtain the selected range. For other browsers,
- //no equivalent of onBeforeDeactivate, so we need to do two things to make sure
- //selection is properly saved before focus is lost: 1) when user clicks another
- //element in the page, in which case we listen to mousedown on the entire page and
- //see whether user clicks out of a focus editor, if so, save selection (focus will
- //only lost after onmousedown event is fired, so we can obtain correct caret pos.)
- //2) when user tabs away from the editor, which is handled in onKeyDown below.
- if(has("ie")){
- this.events.push("onBeforeDeactivate");
- this.events.push("onBeforeActivate");
- }
- },
- postMixInProperties: function(){
- // summary:
- // Extension to make sure a deferred is in place before certain functions
- // execute, like making sure all the plugins are properly inserted.
- // Set up a deferred so that the value isn't applied to the editor
- // until all the plugins load, needed to avoid timing condition
- // reported in #10537.
- this.setValueDeferred = new Deferred();
- this.inherited(arguments);
- },
- postCreate: function(){
- //for custom undo/redo, if enabled.
- this._steps=this._steps.slice(0);
- this._undoedSteps=this._undoedSteps.slice(0);
- if(lang.isArray(this.extraPlugins)){
- this.plugins=this.plugins.concat(this.extraPlugins);
- }
- this.inherited(arguments);
- this.commands = i18n.getLocalization("dijit._editor", "commands", this.lang);
- if(!this.toolbar){
- // if we haven't been assigned a toolbar, create one
- this.toolbar = new Toolbar({
- dir: this.dir,
- lang: this.lang
- });
- this.header.appendChild(this.toolbar.domNode);
- }
- array.forEach(this.plugins, this.addPlugin, this);
- // Okay, denote the value can now be set.
- this.setValueDeferred.callback(true);
- domClass.add(this.iframe.parentNode, "dijitEditorIFrameContainer");
- domClass.add(this.iframe, "dijitEditorIFrame");
- domAttr.set(this.iframe, "allowTransparency", true);
- if(has("webkit")){
- // Disable selecting the entire editor by inadvertent double-clicks.
- // on buttons, title bar, etc. Otherwise clicking too fast on
- // a button such as undo/redo selects the entire editor.
- domStyle.set(this.domNode, "KhtmlUserSelect", "none");
- }
- this.toolbar.startup();
- this.onNormalizedDisplayChanged(); //update toolbar button status
- },
- destroy: function(){
- array.forEach(this._plugins, function(p){
- if(p && p.destroy){
- p.destroy();
- }
- });
- this._plugins=[];
- this.toolbar.destroyRecursive();
- delete this.toolbar;
- this.inherited(arguments);
- },
- addPlugin: function(/*String||Object||Function*/plugin, /*Integer?*/index){
- // summary:
- // takes a plugin name as a string or a plugin instance and
- // adds it to the toolbar and associates it with this editor
- // instance. The resulting plugin is added to the Editor's
- // plugins array. If index is passed, it's placed in the plugins
- // array at that index. No big magic, but a nice helper for
- // passing in plugin names via markup.
- //
- // plugin: String, args object, plugin instance, or plugin constructor
- //
- // args:
- // This object will be passed to the plugin constructor
- //
- // index: Integer
- // Used when creating an instance from
- // something already in this.plugins. Ensures that the new
- // instance is assigned to this.plugins at that index.
- var args=lang.isString(plugin)?{name:plugin}:lang.isFunction(plugin)?{ctor:plugin}:plugin;
- if(!args.setEditor){
- var o={"args":args,"plugin":null,"editor":this};
- if(args.name){
- // search registry for a plugin factory matching args.name, if it's not there then
- // fallback to 1.0 API:
- // ask all loaded plugin modules to fill in o.plugin if they can (ie, if they implement args.name)
- // remove fallback for 2.0.
- if(_Plugin.registry[args.name]){
- o.plugin = _Plugin.registry[args.name](args);
- }else{
- topic.publish(dijit._scopeName + ".Editor.getPlugin", o); // publish
- }
- }
- if(!o.plugin){
- var pc = args.ctor || lang.getObject(args.name);
- if(pc){
- o.plugin=new pc(args);
- }
- }
- if(!o.plugin){
- console.warn('Cannot find plugin',plugin);
- return;
- }
- plugin=o.plugin;
- }
- if(arguments.length > 1){
- this._plugins[index] = plugin;
- }else{
- this._plugins.push(plugin);
- }
- plugin.setEditor(this);
- if(lang.isFunction(plugin.setToolbar)){
- plugin.setToolbar(this.toolbar);
- }
- },
- //the following 2 functions are required to make the editor play nice under a layout widget, see #4070
- resize: function(size){
- // summary:
- // Resize the editor to the specified size, see `dijit.layout._LayoutWidget.resize`
- if(size){
- // we've been given a height/width for the entire editor (toolbar + contents), calls layout()
- // to split the allocated size between the toolbar and the contents
- _LayoutWidget.prototype.resize.apply(this, arguments);
- }
- /*
- else{
- // do nothing, the editor is already laid out correctly. The user has probably specified
- // the height parameter, which was used to set a size on the iframe
- }
- */
- },
- layout: function(){
- // summary:
- // Called from `dijit.layout._LayoutWidget.resize`. This shouldn't be called directly
- // tags:
- // protected
- // Converts the iframe (or rather the <div> surrounding it) to take all the available space
- // except what's needed for the header (toolbars) and footer (breadcrumbs, etc).
- // A class was added to the iframe container and some themes style it, so we have to
- // calc off the added margins and padding too. See tracker: #10662
- var areaHeight = (this._contentBox.h -
- (this.getHeaderHeight() + this.getFooterHeight() +
- domGeometry.getPadBorderExtents(this.iframe.parentNode).h +
- domGeometry.getMarginExtents(this.iframe.parentNode).h));
- this.editingArea.style.height = areaHeight + "px";
- if(this.iframe){
- this.iframe.style.height="100%";
- }
- this._layoutMode = true;
- },
- _onIEMouseDown: function(/*Event*/ e){
- // summary:
- // IE only to prevent 2 clicks to focus
- // tags:
- // private
- var outsideClientArea;
- // IE 8's componentFromPoint is broken, which is a shame since it
- // was smaller code, but oh well. We have to do this brute force
- // to detect if the click was scroller or not.
- var b = this.document.body;
- var clientWidth = b.clientWidth;
- var clientHeight = b.clientHeight;
- var clientLeft = b.clientLeft;
- var offsetWidth = b.offsetWidth;
- var offsetHeight = b.offsetHeight;
- var offsetLeft = b.offsetLeft;
- //Check for vertical scroller click.
- if(/^rtl$/i.test(b.dir || "")){
- if(clientWidth < offsetWidth && e.x > clientWidth && e.x < offsetWidth){
- // Check the click was between width and offset width, if so, scroller
- outsideClientArea = true;
- }
- }else{
- // RTL mode, we have to go by the left offsets.
- if(e.x < clientLeft && e.x > offsetLeft){
- // Check the click was between width and offset width, if so, scroller
- outsideClientArea = true;
- }
- }
- if(!outsideClientArea){
- // Okay, might be horiz scroller, check that.
- if(clientHeight < offsetHeight && e.y > clientHeight && e.y < offsetHeight){
- // Horizontal scroller.
- outsideClientArea = true;
- }
- }
- if(!outsideClientArea){
- delete this._cursorToStart; // Remove the force to cursor to start position.
- delete this._savedSelection; // new mouse position overrides old selection
- if(e.target.tagName == "BODY"){
- setTimeout(lang.hitch(this, "placeCursorAtEnd"), 0);
- }
- this.inherited(arguments);
- }
- },
- onBeforeActivate: function(){
- this._restoreSelection();
- },
- onBeforeDeactivate: function(e){
- // summary:
- // Called on IE right before focus is lost. Saves the selected range.
- // tags:
- // private
- if(this.customUndo){
- this.endEditing(true);
- }
- //in IE, the selection will be lost when other elements get focus,
- //let's save focus before the editor is deactivated
- if(e.target.tagName != "BODY"){
- this._saveSelection();
- }
- //console.log('onBeforeDeactivate',this);
- },
- /* beginning of custom undo/redo support */
- // customUndo: Boolean
- // Whether we shall use custom undo/redo support instead of the native
- // browser support. By default, we now use custom undo. It works better
- // than native browser support and provides a consistent behavior across
- // browsers with a minimal performance hit. We already had the hit on
- // the slowest browser, IE, anyway.
- customUndo: true,
- // editActionInterval: Integer
- // When using customUndo, not every keystroke will be saved as a step.
- // Instead typing (including delete) will be grouped together: after
- // a user stops typing for editActionInterval seconds, a step will be
- // saved; if a user resume typing within editActionInterval seconds,
- // the timeout will be restarted. By default, editActionInterval is 3
- // seconds.
- editActionInterval: 3,
- beginEditing: function(cmd){
- // summary:
- // Called to note that the user has started typing alphanumeric characters, if it's not already noted.
- // Deals with saving undo; see editActionInterval parameter.
- // tags:
- // private
- if(!this._inEditing){
- this._inEditing=true;
- this._beginEditing(cmd);
- }
- if(this.editActionInterval>0){
- if(this._editTimer){
- clearTimeout(this._editTimer);
- }
- this._editTimer = setTimeout(lang.hitch(this, this.endEditing), this._editInterval);
- }
- },
- // TODO: declaring these in the prototype is meaningless, just create in the constructor/postCreate
- _steps:[],
- _undoedSteps:[],
- execCommand: function(cmd){
- // summary:
- // Main handler for executing any commands to the editor, like paste, bold, etc.
- // Called by plugins, but not meant to be called by end users.
- // tags:
- // protected
- if(this.customUndo && (cmd == 'undo' || cmd == 'redo')){
- return this[cmd]();
- }else{
- if(this.customUndo){
- this.endEditing();
- this._beginEditing();
- }
- var r = this.inherited(arguments);
- if(this.customUndo){
- this._endEditing();
- }
- return r;
- }
- },
- _pasteImpl: function(){
- // summary:
- // Over-ride of paste command control to make execCommand cleaner
- // tags:
- // Protected
- return this._clipboardCommand("paste");
- },
- _cutImpl: function(){
- // summary:
- // Over-ride of cut command control to make execCommand cleaner
- // tags:
- // Protected
- return this._clipboardCommand("cut");
- },
- _copyImpl: function(){
- // summary:
- // Over-ride of copy command control to make execCommand cleaner
- // tags:
- // Protected
- return this._clipboardCommand("copy");
- },
- _clipboardCommand: function(cmd){
- // summary:
- // Function to handle processing clipboard commands (or at least try to).
- // tags:
- // Private
- var r;
- try{
- // Try to exec the superclass exec-command and see if it works.
- r = this.document.execCommand(cmd, false, null);
- if(has("webkit") && !r){ //see #4598: webkit does not guarantee clipboard support from js
- throw { code: 1011 }; // throw an object like Mozilla's error
- }
- }catch(e){
- //TODO: when else might we get an exception? Do we need the Mozilla test below?
- if(e.code == 1011 /* Mozilla: service denied */){
- // Warn user of platform limitation. Cannot programmatically access clipboard. See ticket #4136
- var sub = string.substitute,
- accel = {cut:'X', copy:'C', paste:'V'};
- alert(sub(this.commands.systemShortcut,
- [this.commands[cmd], sub(this.commands[has("mac") ? 'appleKey' : 'ctrlKey'], [accel[cmd]])]));
- }
- r = false;
- }
- return r;
- },
- queryCommandEnabled: function(cmd){
- // summary:
- // Returns true if specified editor command is enabled.
- // Used by the plugins to know when to highlight/not highlight buttons.
- // tags:
- // protected
- if(this.customUndo && (cmd == 'undo' || cmd == 'redo')){
- return cmd == 'undo' ? (this._steps.length > 1) : (this._undoedSteps.length > 0);
- }else{
- return this.inherited(arguments);
- }
- },
- _moveToBookmark: function(b){
- // summary:
- // Selects the text specified in bookmark b
- // tags:
- // private
- var bookmark = b.mark;
- var mark = b.mark;
- var col = b.isCollapsed;
- var r, sNode, eNode, sel;
- if(mark){
- if(has("ie") < 9){
- if(lang.isArray(mark)){
- //IE CONTROL, have to use the native bookmark.
- bookmark = [];
- array.forEach(mark,function(n){
- bookmark.push(rangeapi.getNode(n,this.editNode));
- },this);
- win.withGlobal(this.window,'moveToBookmark',dijit,[{mark: bookmark, isCollapsed: col}]);
- }else{
- if(mark.startContainer && mark.endContainer){
- // Use the pseudo WC3 range API. This works better for positions
- // than the IE native bookmark code.
- sel = rangeapi.getSelection(this.window);
- if(sel && sel.removeAllRanges){
- sel.removeAllRanges();
- r = rangeapi.create(this.window);
- sNode = rangeapi.getNode(mark.startContainer,this.editNode);
- eNode = rangeapi.getNode(mark.endContainer,this.editNode);
- if(sNode && eNode){
- // Okay, we believe we found the position, so add it into the selection
- // There are cases where it may not be found, particularly in undo/redo, when
- // IE changes the underlying DOM on us (wraps text in a <p> tag or similar.
- // So, in those cases, don't bother restoring selection.
- r.setStart(sNode,mark.startOffset);
- r.setEnd(eNode,mark.endOffset);
- sel.addRange(r);
- }
- }
- }
- }
- }else{//w3c range
- sel = rangeapi.getSelection(this.window);
- if(sel && sel.removeAllRanges){
- sel.removeAllRanges();
- r = rangeapi.create(this.window);
- sNode = rangeapi.getNode(mark.startContainer,this.editNode);
- eNode = rangeapi.getNode(mark.endContainer,this.editNode);
- if(sNode && eNode){
- // Okay, we believe we found the position, so add it into the selection
- // There are cases where it may not be found, particularly in undo/redo, when
- // formatting as been done and so on, so don't restore selection then.
- r.setStart(sNode,mark.startOffset);
- r.setEnd(eNode,mark.endOffset);
- sel.addRange(r);
- }
- }
- }
- }
- },
- _changeToStep: function(from, to){
- // summary:
- // Reverts editor to "to" setting, from the undo stack.
- // tags:
- // private
- this.setValue(to.text);
- var b=to.bookmark;
- if(!b){ return; }
- this._moveToBookmark(b);
- },
- undo: function(){
- // summary:
- // Handler for editor undo (ex: ctrl-z) operation
- // tags:
- // private
- //console.log('undo');
- var ret = false;
- if(!this._undoRedoActive){
- this._undoRedoActive = true;
- this.endEditing(true);
- var s=this._steps.pop();
- if(s && this._steps.length>0){
- this.focus();
- this._changeToStep(s,this._steps[this._steps.length-1]);
- this._undoedSteps.push(s);
- this.onDisplayChanged();
- delete this._undoRedoActive;
- ret = true;
- }
- delete this._undoRedoActive;
- }
- return ret;
- },
- redo: function(){
- // summary:
- // Handler for editor redo (ex: ctrl-y) operation
- // tags:
- // private
- //console.log('redo');
- var ret = false;
- if(!this._undoRedoActive){
- this._undoRedoActive = true;
- this.endEditing(true);
- var s=this._undoedSteps.pop();
- if(s && this._steps.length>0){
- this.focus();
- this._changeToStep(this._steps[this._steps.length-1],s);
- this._steps.push(s);
- this.onDisplayChanged();
- ret = true;
- }
- delete this._undoRedoActive;
- }
- return ret;
- },
- endEditing: function(ignore_caret){
- // summary:
- // Called to note that the user has stopped typing alphanumeric characters, if it's not already noted.
- // Deals with saving undo; see editActionInterval parameter.
- // tags:
- // private
- if(this._editTimer){
- clearTimeout(this._editTimer);
- }
- if(this._inEditing){
- this._endEditing(ignore_caret);
- this._inEditing=false;
- }
- },
- _getBookmark: function(){
- // summary:
- // Get the currently selected text
- // tags:
- // protected
- var b=win.withGlobal(this.window,focusBase.getBookmark);
- var tmp=[];
- if(b && b.mark){
- var mark = b.mark;
- if(has("ie") < 9){
- // Try to use the pseudo range API on IE for better accuracy.
- var sel = rangeapi.getSelection(this.window);
- if(!lang.isArray(mark)){
- if(sel){
- var range;
- if(sel.rangeCount){
- range = sel.getRangeAt(0);
- }
- if(range){
- b.mark = range.cloneRange();
- }else{
- b.mark = win.withGlobal(this.window,focusBase.getBookmark);
- }
- }
- }else{
- // Control ranges (img, table, etc), handle differently.
- array.forEach(b.mark,function(n){
- tmp.push(rangeapi.getIndex(n,this.editNode).o);
- },this);
- b.mark = tmp;
- }
- }
- try{
- if(b.mark && b.mark.startContainer){
- tmp=rangeapi.getIndex(b.mark.startContainer,this.editNode).o;
- b.mark={startContainer:tmp,
- startOffset:b.mark.startOffset,
- endContainer:b.mark.endContainer===b.mark.startContainer?tmp:rangeapi.getIndex(b.mark.endContainer,this.editNode).o,
- endOffset:b.mark.endOffset};
- }
- }catch(e){
- b.mark = null;
- }
- }
- return b;
- },
- _beginEditing: function(){
- // summary:
- // Called when the user starts typing alphanumeric characters.
- // Deals with saving undo; see editActionInterval parameter.
- // tags:
- // private
- if(this._steps.length === 0){
- // You want to use the editor content without post filtering
- // to make sure selection restores right for the 'initial' state.
- // and undo is called. So not using this.value, as it was 'processed'
- // and the line-up for selections may have been altered.
- this._steps.push({'text':html.getChildrenHtml(this.editNode),'bookmark':this._getBookmark()});
- }
- },
- _endEditing: function(){
- // summary:
- // Called when the user stops typing alphanumeric characters.
- // Deals with saving undo; see editActionInterval parameter.
- // tags:
- // private
- // Avoid filtering to make sure selections restore.
- var v = html.getChildrenHtml(this.editNode);
- this._undoedSteps=[];//clear undoed steps
- this._steps.push({text: v, bookmark: this._getBookmark()});
- },
- onKeyDown: function(e){
- // summary:
- // Handler for onkeydown event.
- // tags:
- // private
- //We need to save selection if the user TAB away from this editor
- //no need to call _saveSelection for IE, as that will be taken care of in onBeforeDeactivate
- if(!has("ie") && !this.iframe && e.keyCode == keys.TAB && !this.tabIndent){
- this._saveSelection();
- }
- if(!this.customUndo){
- this.inherited(arguments);
- return;
- }
- var k = e.keyCode;
- if(e.ctrlKey && !e.altKey){//undo and redo only if the special right Alt + z/y are not pressed #5892
- if(k == 90 || k == 122){ //z
- event.stop(e);
- this.undo();
- return;
- }else if(k == 89 || k == 121){ //y
- event.stop(e);
- this.redo();
- return;
- }
- }
- this.inherited(arguments);
- switch(k){
- case keys.ENTER:
- case keys.BACKSPACE:
- case keys.DELETE:
- this.beginEditing();
- break;
- case 88: //x
- case 86: //v
- if(e.ctrlKey && !e.altKey && !e.metaKey){
- this.endEditing();//end current typing step if any
- if(e.keyCode == 88){
- this.beginEditing('cut');
- //use timeout to trigger after the cut is complete
- setTimeout(lang.hitch(this, this.endEditing), 1);
- }else{
- this.beginEditing('paste');
- //use timeout to trigger after the paste is complete
- setTimeout(lang.hitch(this, this.endEditing), 1);
- }
- break;
- }
- //pass through
- default:
- if(!e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode<keys.F1 || e.keyCode>keys.F15)){
- this.beginEditing();
- break;
- }
- //pass through
- case keys.ALT:
- this.endEditing();
- break;
- case keys.UP_ARROW:
- case keys.DOWN_ARROW:
- case keys.LEFT_ARROW:
- case keys.RIGHT_ARROW:
- case keys.HOME:
- case keys.END:
- case keys.PAGE_UP:
- case keys.PAGE_DOWN:
- this.endEditing(true);
- break;
- //maybe ctrl+backspace/delete, so don't endEditing when ctrl is pressed
- case keys.CTRL:
- case keys.SHIFT:
- case keys.TAB:
- break;
- }
- },
- _onBlur: function(){
- // summary:
- // Called from focus manager when focus has moved away from this editor
- // tags:
- // protected
- //this._saveSelection();
- this.inherited(arguments);
- this.endEditing(true);
- },
- _saveSelection: function(){
- // summary:
- // Save the currently selected text in _savedSelection attribute
- // tags:
- // private
- try{
- this._savedSelection=this._getBookmark();
- }catch(e){ /* Squelch any errors that occur if selection save occurs due to being hidden simultaneously. */}
- },
- _restoreSelection: function(){
- // summary:
- // Re-select the text specified in _savedSelection attribute;
- // see _saveSelection().
- // tags:
- // private
- if(this._savedSelection){
- // Clear off cursor to start, we're deliberately going to a selection.
- delete this._cursorToStart;
- // only restore the selection if the current range is collapsed
- // if not collapsed, then it means the editor does not lose
- // selection and there is no need to restore it
- if(win.withGlobal(this.window,'isCollapsed',dijit)){
- this._moveToBookmark(this._savedSelection);
- }
- delete this._savedSelection;
- }
- },
- onClick: function(){
- // summary:
- // Handler for when editor is clicked
- // tags:
- // protected
- this.endEditing(true);
- this.inherited(arguments);
- },
- replaceValue: function(/*String*/ html){
- // summary:
- // over-ride of replaceValue to support custom undo and stack maintenance.
- // tags:
- // protected
- if(!this.customUndo){
- this.inherited(arguments);
- }else{
- if(this.isClosed){
- this.setValue(html);
- }else{
- this.beginEditing();
- if(!html){
- html = " "; //
- }
- this.setValue(html);
- this.endEditing();
- }
- }
- },
- _setDisabledAttr: function(/*Boolean*/ value){
- var disableFunc = lang.hitch(this, function(){
- if((!this.disabled && value) || (!this._buttonEnabledPlugins && value)){
- // Disable editor: disable all enabled buttons and remember that list
- array.forEach(this._plugins, function(p){
- p.set("disabled", true);
- });
- }else if(this.disabled && !value){
- // Restore plugins to being active.
- array.forEach(this._plugins, function(p){
- p.set("disabled", false);
- });
- }
- });
- this.setValueDeferred.addCallback(disableFunc);
- this.inherited(arguments);
- },
- _setStateClass: function(){
- try{
- this.inherited(arguments);
- // Let theme set the editor's text color based on editor enabled/disabled state.
- // We need to jump through hoops because the main document (where the theme CSS is)
- // is separate from the iframe's document.
- if(this.document && this.document.body){
- domStyle.set(this.document.body, "color", domStyle.get(this.iframe, "color"));
- }
- }catch(e){ /* Squelch any errors caused by focus change if hidden during a state change */}
- }
- });
- // Register the "default plugins", ie, the built-in editor commands
- function simplePluginFactory(args){
- return new _Plugin({ command: args.name });
- }
- function togglePluginFactory(args){
- return new _Plugin({ buttonClass: ToggleButton, command: args.name });
- }
- lang.mixin(_Plugin.registry, {
- "undo": simplePluginFactory,
- "redo": simplePluginFactory,
- "cut": simplePluginFactory,
- "copy": simplePluginFactory,
- "paste": simplePluginFactory,
- "insertOrderedList": simplePluginFactory,
- "insertUnorderedList": simplePluginFactory,
- "indent": simplePluginFactory,
- "outdent": simplePluginFactory,
- "justifyCenter": simplePluginFactory,
- "justifyFull": simplePluginFactory,
- "justifyLeft": simplePluginFactory,
- "justifyRight": simplePluginFactory,
- "delete": simplePluginFactory,
- "selectAll": simplePluginFactory,
- "removeFormat": simplePluginFactory,
- "unlink": simplePluginFactory,
- "insertHorizontalRule": simplePluginFactory,
- "bold": togglePluginFactory,
- "italic": togglePluginFactory,
- "underline": togglePluginFactory,
- "strikethrough": togglePluginFactory,
- "subscript": togglePluginFactory,
- "superscript": togglePluginFactory,
- "|": function(){
- return new _Plugin({ button: new ToolbarSeparator(), setEditor: function(editor){this.editor = editor;}});
- }
- });
- return Editor;
- });
- },
- 'dojox/grid/cells/dijit':function(){
- define("dojox/grid/cells/dijit", [
- "dojo/_base/kernel",
- "../../main",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/json",
- "dojo/_base/connect",
- "dojo/_base/sniff",
- "dojo/dom",
- "dojo/dom-attr",
- "dojo/dom-construct",
- "dojo/dom-geometry",
- "dojo/data/ItemFileReadStore",
- "dijit/form/DateTextBox",
- "dijit/form/TimeTextBox",
- "dijit/form/ComboBox",
- "dijit/form/CheckBox",
- "dijit/form/TextBox",
- "dijit/form/NumberSpinner",
- "dijit/form/NumberTextBox",
- "dijit/form/CurrencyTextBox",
- "dijit/form/HorizontalSlider",
- "dijit/Editor",
- "../util",
- "./_base"
- ], function(dojo, dojox, declare, array, lang, json, connect, has, dom, domAttr, domConstruct,
- domGeometry, ItemFileReadStore, DateTextBox, TimeTextBox, ComboBox, CheckBox, TextBox,
- NumberSpinner, NumberTextBox, CurrencyTextBox, HorizontalSlider, Editor, util, BaseCell){
-
- // TODO: shouldn't it be the test file's job to require these modules,
- // if it is using them? Most of these modules aren't referenced by this file.
-
- var _Widget = declare("dojox.grid.cells._Widget", BaseCell, {
- widgetClass: TextBox,
- constructor: function(inCell){
- this.widget = null;
- if(typeof this.widgetClass == "string"){
- dojo.deprecated("Passing a string to widgetClass is deprecated", "pass the widget class object instead", "2.0");
- this.widgetClass = lang.getObject(this.widgetClass);
- }
- },
- formatEditing: function(inDatum, inRowIndex){
- this.needFormatNode(inDatum, inRowIndex);
- return "<div></div>";
- },
- getValue: function(inRowIndex){
- return this.widget.get('value');
- },
- _unescapeHTML: function(value){
- return (value && value.replace && this.grid.escapeHTMLInData) ?
- value.replace(/</g, '<').replace(/&/g, '&') : value;
- },
- setValue: function(inRowIndex, inValue){
- if(this.widget&&this.widget.set){
- inValue = this._unescapeHTML(inValue);
- //Look for lazy-loading editor and handle it via its deferred.
- if(this.widget.onLoadDeferred){
- var self = this;
- this.widget.onLoadDeferred.addCallback(function(){
- self.widget.set("value",inValue===null?"":inValue);
- });
- }else{
- this.widget.set("value", inValue);
- }
- }else{
- this.inherited(arguments);
- }
- },
- getWidgetProps: function(inDatum){
- return lang.mixin(
- {
- dir: this.dir,
- lang: this.lang
- },
- this.widgetProps||{},
- {
- constraints: lang.mixin({}, this.constraint) || {}, //TODO: really just for ValidationTextBoxes
- value: this._unescapeHTML(inDatum)
- }
- );
- },
- createWidget: function(inNode, inDatum, inRowIndex){
- return new this.widgetClass(this.getWidgetProps(inDatum), inNode);
- },
- attachWidget: function(inNode, inDatum, inRowIndex){
- inNode.appendChild(this.widget.domNode);
- this.setValue(inRowIndex, inDatum);
- },
- formatNode: function(inNode, inDatum, inRowIndex){
- if(!this.widgetClass){
- return inDatum;
- }
- if(!this.widget){
- this.widget = this.createWidget.apply(this, arguments);
- }else{
- this.attachWidget.apply(this, arguments);
- }
- this.sizeWidget.apply(this, arguments);
- this.grid.views.renormalizeRow(inRowIndex);
- this.grid.scroller.rowHeightChanged(inRowIndex, true/*fix #11101*/);
- this.focus();
- return undefined;
- },
- sizeWidget: function(inNode, inDatum, inRowIndex){
- var
- p = this.getNode(inRowIndex),
- box = dojo.contentBox(p);
- dojo.marginBox(this.widget.domNode, {w: box.w});
- },
- focus: function(inRowIndex, inNode){
- if(this.widget){
- setTimeout(lang.hitch(this.widget, function(){
- util.fire(this, "focus");
- }), 0);
- }
- },
- _finish: function(inRowIndex){
- this.inherited(arguments);
- util.removeNode(this.widget.domNode);
- if(has("ie")){
- dom.setSelectable(this.widget.domNode, true);
- }
- }
- });
- _Widget.markupFactory = function(node, cell){
- BaseCell.markupFactory(node, cell);
- var widgetProps = lang.trim(domAttr.get(node, "widgetProps")||"");
- var constraint = lang.trim(domAttr.get(node, "constraint")||"");
- var widgetClass = lang.trim(domAttr.get(node, "widgetClass")||"");
- if(widgetProps){
- cell.widgetProps = json.fromJson(widgetProps);
- }
- if(constraint){
- cell.constraint = json.fromJson(constraint);
- }
- if(widgetClass){
- cell.widgetClass = lang.getObject(widgetClass);
- }
- };
- var ComboBox = declare("dojox.grid.cells.ComboBox", _Widget, {
- widgetClass: ComboBox,
- getWidgetProps: function(inDatum){
- var items=[];
- array.forEach(this.options, function(o){
- items.push({name: o, value: o});
- });
- var store = new ItemFileReadStore({data: {identifier:"name", items: items}});
- return lang.mixin({}, this.widgetProps||{}, {
- value: inDatum,
- store: store
- });
- },
- getValue: function(){
- var e = this.widget;
- // make sure to apply the displayed value
- e.set('displayedValue', e.get('displayedValue'));
- return e.get('value');
- }
- });
- ComboBox.markupFactory = function(node, cell){
- _Widget.markupFactory(node, cell);
- var options = lang.trim(domAttr.get(node, "options")||"");
- if(options){
- var o = options.split(',');
- if(o[0] != options){
- cell.options = o;
- }
- }
- };
- var DateTextBox = declare("dojox.grid.cells.DateTextBox", _Widget, {
- widgetClass: DateTextBox,
- setValue: function(inRowIndex, inValue){
- if(this.widget){
- this.widget.set('value', new Date(inValue));
- }else{
- this.inherited(arguments);
- }
- },
- getWidgetProps: function(inDatum){
- return lang.mixin(this.inherited(arguments), {
- value: new Date(inDatum)
- });
- }
- });
- DateTextBox.markupFactory = function(node, cell){
- _Widget.markupFactory(node, cell);
- };
- var CheckBox = declare("dojox.grid.cells.CheckBox", _Widget, {
- widgetClass: CheckBox,
- getValue: function(){
- return this.widget.checked;
- },
- setValue: function(inRowIndex, inValue){
- if(this.widget&&this.widget.attributeMap.checked){
- this.widget.set("checked", inValue);
- }else{
- this.inherited(arguments);
- }
- },
- sizeWidget: function(inNode, inDatum, inRowIndex){
- return;
- }
- });
- CheckBox.markupFactory = function(node, cell){
- _Widget.markupFactory(node, cell);
- };
- var Editor = declare("dojox.grid.cells.Editor", _Widget, {
- widgetClass: Editor,
- getWidgetProps: function(inDatum){
- return lang.mixin({}, this.widgetProps||{}, {
- height: this.widgetHeight || "100px"
- });
- },
- createWidget: function(inNode, inDatum, inRowIndex){
- // widget needs its value set after creation
- var widget = new this.widgetClass(this.getWidgetProps(inDatum), inNode);
- // use onLoadDeferred because onLoad may have already fired
- widget.onLoadDeferred.then(lang.hitch(this, 'populateEditor'));
- return widget;
- },
- formatNode: function(inNode, inDatum, inRowIndex){
- this.content = inDatum;
- this.inherited(arguments);
- if(has("mozilla")){
- // FIXME: seem to need to reopen the editor and display the toolbar
- var e = this.widget;
- e.open();
- if(this.widgetToolbar){
- domConstruct.place(e.toolbar.domNode, e.editingArea, "before");
- }
- }
- },
- populateEditor: function(){
- this.widget.set('value', this.content);
- this.widget.placeCursorAtEnd();
- }
- });
- Editor.markupFactory = function(node, cell){
- _Widget.markupFactory(node, cell);
- var h = lang.trim(domAttr.get(node, "widgetHeight")||"");
- if(h){
- if((h != "auto")&&(h.substr(-2) != "em")){
- h = parseInt(h, 10)+"px";
- }
- cell.widgetHeight = h;
- }
- };
- return dojox.grid.cells.dijit;
- });
- },
- 'dojox/form/uploader/plugins/HTML5':function(){
- define("dojox/form/uploader/plugins/HTML5", [
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/array",
- "dojo"
- ],function(declare, lang, array, dojo){
- var pluginsHTML5 = declare("dojox.form.uploader.plugins.HTML5", [], {
- //
- // Version: 1.6
- //
- // summary:
- // A plugin for dojox.form.Uploader that adds HTML5 multiple-file upload capabilities and
- // progress events.
- //
- // description:
- // Add this plugin to have HTML5 capabilities in the Uploader. Note that it does not add
- // these capabilities to browsers that don't support them. For IE or older browsers, add
- // additional plugins: IFrame or Flash.
- //
- errMsg:"Error uploading files. Try checking permissions",
- // Overwrites "form" and could possibly be overwritten again by iframe or flash plugin.
- uploadType:"html5",
- postCreate: function(){
- this.connectForm();
- this.inherited(arguments);
- if(this.uploadOnSelect){
- this.connect(this, "onChange", function(data){
- this.upload(data[0]);
- });
- }
- },
- _drop: function(e){
- dojo.stopEvent(e);
- var dt = e.dataTransfer;
- this._files = dt.files;
- this.onChange(this.getFileList());
- },
- /*************************
- * Public Methods *
- *************************/
- upload: function(/*Object ? */formData){
- // summary:
- // See: dojox.form.Uploader.upload
- //
- this.onBegin(this.getFileList());
- if(this.supports("FormData")){
- this.uploadWithFormData(formData);
- }else if(this.supports("sendAsBinary")){
- this.sendAsBinary(formData);
- }
- },
- addDropTarget: function(node, /*Boolean?*/onlyConnectDrop){
- // summary:
- // Add a dom node which will act as the drop target area so user
- // can drop files to this node.
- // description:
- // If onlyConnectDrop is true, dragenter/dragover/dragleave events
- // won't be connected to dojo.stopEvent, and they need to be
- // canceled by user code to allow DnD files to happen.
- // This API is only available in HTML5 plugin (only HTML5 allows
- // DnD files).
- if(!onlyConnectDrop){
- this.connect(node, 'dragenter', dojo.stopEvent);
- this.connect(node, 'dragover', dojo.stopEvent);
- this.connect(node, 'dragleave', dojo.stopEvent);
- }
- this.connect(node, 'drop', '_drop');
- },
-
- sendAsBinary: function(/* Object */data){
- // summary:
- // Used primarily in FF < 4.0. Sends files and form object as binary data, written to
- // still enable use of $_FILES in PHP (or equivalent).
- // tags:
- // private
- //
- if(!this.getUrl()){
- console.error("No upload url found.", this); return;
- }
- // The date/number doesn't matter but amount of dashes do. The actual boundary
- // will have two more dashes than this one which is used in the header.
- var boundary = "---------------------------" + (new Date).getTime();
- var xhr = this.createXhr();
- xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
- // finally send the request as binary data
- // still accessed as $_FILES
- var msg = this._buildRequestBody(data, boundary);
- if(!msg){
- this.onError(this.errMsg);
- }else{
- console.log("msg:", msg)
- console.log("xhr:", xhr)
- xhr.sendAsBinary(msg);
- }
- },
- uploadWithFormData: function(/* Object */data){
- // summary
- // Used with WebKit and Firefox 4+
- // Upload files using the much friendlier FormData browser object.
- // tags:
- // private
- //
- if(!this.getUrl()){
- console.error("No upload url found.", this); return;
- }
- var fd = new FormData();
- array.forEach(this._files, function(f, i){
- fd.append(this.name+"s[]", f);
- }, this);
- if(data){
- for(var nm in data){
- fd.append(nm, data[nm]);
- }
- }
- var xhr = this.createXhr();
- xhr.send(fd);
- },
- _xhrProgress: function(evt){
- if(evt.lengthComputable){
- var o = {
- bytesLoaded:evt.loaded,
- bytesTotal:evt.total,
- type:evt.type,
- timeStamp:evt.timeStamp
- };
- if(evt.type == "load"){
- // 100%
- o.percent = "100%",
- o.decimal = 1;
- }else{
- o.decimal = evt.loaded / evt.total;
- o.percent = Math.ceil((evt.loaded / evt.total)*100)+"%";
- }
- this.onProgress(o);
- }
- },
- createXhr: function(){
- var xhr = new XMLHttpRequest();
- var timer;
- xhr.upload.addEventListener("progress", lang.hitch(this, "_xhrProgress"), false);
- xhr.addEventListener("load", lang.hitch(this, "_xhrProgress"), false);
- xhr.addEventListener("error", lang.hitch(this, function(evt){
- this.onError(evt);
- clearInterval(timer);
- }), false);
- xhr.addEventListener("abort", lang.hitch(this, function(evt){
- this.onAbort(evt);
- clearInterval(timer);
- }), false);
- xhr.onreadystatechange = lang.hitch(this, function(){
- if(xhr.readyState === 4){
- // console.info("COMPLETE")
- clearInterval(timer);
- this.onComplete(JSON.parse(xhr.responseText.replace(/^\{\}&&/,'')));
- }
- });
- xhr.open("POST", this.getUrl());
- timer = setInterval(lang.hitch(this, function(){
- try{
- if(typeof(xhr.statusText)){} // accessing this error throws an error. Awesomeness.
- }catch(e){
- //this.onError("Error uploading file."); // not always an error.
- clearInterval(timer);
- }
- }),250);
- return xhr;
- },
- _buildRequestBody : function(data, boundary){
- var EOL = "\r\n";
- var part = "";
- boundary = "--" + boundary;
- var filesInError = [], files = this._files;
- array.forEach(files, function(f, i){
- var fieldName = this.name+"s[]";//+i;
- var fileName = f.fileName;
- var binary;
- try{
- binary = f.getAsBinary() + EOL;
- part += boundary + EOL;
- part += 'Content-Disposition: form-data; ';
- part += 'name="' + fieldName + '"; ';
- part += 'filename="'+ fileName + '"' + EOL;
- part += "Content-Type: " + this.getMimeType() + EOL + EOL;
- part += binary;
- }catch(e){
- filesInError.push({index:i, name:fileName});
- }
- }, this);
- if(filesInError.length){
- if(filesInError.length >= files.length){
- // all files were bad. Nothing to upload.
- this.onError({
- message:this.errMsg,
- filesInError:filesInError
- });
- part = false;
- }
- }
- if(!part) return false;
- if(data){
- for(var nm in data){
- part += boundary + EOL;
- part += 'Content-Disposition: form-data; ';
- part += 'name="' + nm + '"' + EOL + EOL;
- part += data[nm] + EOL;
- }
- }
- part += boundary + "--" + EOL;
- return part;
- }
- });
- dojox.form.addUploaderPlugin(pluginsHTML5);
- return pluginsHTML5;
- });
- },
- 'dojox/uuid/generateRandomUuid':function(){
- define("dojox/uuid/generateRandomUuid", ['./_base'], function(){
- dojox.uuid.generateRandomUuid = function(){
- // summary:
- // This function generates random UUIDs, meaning "version 4" UUIDs.
- // description:
- // A typical generated value would be something like this:
- // "3b12f1df-5232-4804-897e-917bf397618a"
- //
- // For more information about random UUIDs, see sections 4.4 and
- // 4.5 of RFC 4122: http://tools.ietf.org/html/rfc4122#section-4.4
- //
- // This generator function is designed to be small and fast,
- // but not necessarily good.
- //
- // Small: This generator has a small footprint. Once comments are
- // stripped, it's only about 25 lines of code, and it doesn't
- // dojo.require() any other modules.
- //
- // Fast: This generator can generate lots of new UUIDs fairly quickly
- // (at least, more quickly than the other dojo UUID generators).
- //
- // Not necessarily good: We use Math.random() as our source
- // of randomness, which may or may not provide much randomness.
- // examples:
- // var string = dojox.uuid.generateRandomUuid();
- var HEX_RADIX = 16;
- function _generateRandomEightCharacterHexString(){
- // Make random32bitNumber be a randomly generated floating point number
- // between 0 and (4,294,967,296 - 1), inclusive.
- var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
- var eightCharacterHexString = random32bitNumber.toString(HEX_RADIX);
- while(eightCharacterHexString.length < 8){
- eightCharacterHexString = "0" + eightCharacterHexString;
- }
- return eightCharacterHexString; // for example: "3B12F1DF"
- }
- var hyphen = "-";
- var versionCodeForRandomlyGeneratedUuids = "4"; // 8 == binary2hex("0100")
- var variantCodeForDCEUuids = "8"; // 8 == binary2hex("1000")
- var a = _generateRandomEightCharacterHexString();
- var b = _generateRandomEightCharacterHexString();
- b = b.substring(0, 4) + hyphen + versionCodeForRandomlyGeneratedUuids + b.substring(5, 8);
- var c = _generateRandomEightCharacterHexString();
- c = variantCodeForDCEUuids + c.substring(1, 4) + hyphen + c.substring(4, 8);
- var d = _generateRandomEightCharacterHexString();
- var returnValue = a + hyphen + b + hyphen + c + d;
- returnValue = returnValue.toLowerCase();
- return returnValue; // String
- };
- return dojox.uuid.generateRandomUuid;
- });
- },
- 'dijit/Toolbar':function(){
- define("dijit/Toolbar", [
- "require",
- "dojo/_base/declare", // declare
- "dojo/_base/kernel",
- "dojo/keys", // keys.LEFT_ARROW keys.RIGHT_ARROW
- "dojo/ready",
- "./_Widget",
- "./_KeyNavContainer",
- "./_TemplatedMixin"
- ], function(require, declare, kernel, keys, ready, _Widget, _KeyNavContainer, _TemplatedMixin){
- /*=====
- var _Widget = dijit._Widget;
- var _KeyNavContainer = dijit._KeyNavContainer;
- var _TemplatedMixin = dijit._TemplatedMixin;
- =====*/
- // module:
- // dijit/Toolbar
- // summary:
- // A Toolbar widget, used to hold things like `dijit.Editor` buttons
- // Back compat w/1.6, remove for 2.0
- if(!kernel.isAsync){
- ready(0, function(){
- var requires = ["dijit/ToolbarSeparator"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- return declare("dijit.Toolbar", [_Widget, _TemplatedMixin, _KeyNavContainer], {
- // summary:
- // A Toolbar widget, used to hold things like `dijit.Editor` buttons
- templateString:
- '<div class="dijit" role="toolbar" tabIndex="${tabIndex}" data-dojo-attach-point="containerNode">' +
- '</div>',
- baseClass: "dijitToolbar",
- postCreate: function(){
- this.inherited(arguments);
- this.connectKeyNavHandlers(
- this.isLeftToRight() ? [keys.LEFT_ARROW] : [keys.RIGHT_ARROW],
- this.isLeftToRight() ? [keys.RIGHT_ARROW] : [keys.LEFT_ARROW]
- );
- }
- });
- });
- },
- 'url:dojox/grid/resources/_Grid.html':"<div hidefocus=\"hidefocus\" role=\"grid\" dojoAttachEvent=\"onmouseout:_mouseOut\">\r\n\t<div class=\"dojoxGridMasterHeader\" dojoAttachPoint=\"viewsHeaderNode\" role=\"presentation\"></div>\r\n\t<div class=\"dojoxGridMasterView\" dojoAttachPoint=\"viewsNode\" role=\"presentation\"></div>\r\n\t<div class=\"dojoxGridMasterMessages\" style=\"display: none;\" dojoAttachPoint=\"messagesNode\"></div>\r\n\t<span dojoAttachPoint=\"lastFocusNode\" tabindex=\"0\"></span>\r\n</div>\r\n",
- 'dojo/regexp':function(){
- define("dojo/regexp", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
- // module:
- // dojo/regexp
- // summary:
- // TODOC
- lang.getObject("regexp", true, dojo);
- /*=====
- dojo.regexp = {
- // summary: Regular expressions and Builder resources
- };
- =====*/
- dojo.regexp.escapeString = function(/*String*/str, /*String?*/except){
- // summary:
- // Adds escape sequences for special characters in regular expressions
- // except:
- // a String with special characters to be left unescaped
- return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(ch){
- if(except && except.indexOf(ch) != -1){
- return ch;
- }
- return "\\" + ch;
- }); // String
- };
- dojo.regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){
- // summary:
- // Builds a regular expression that groups subexpressions
- // description:
- // A utility function used by some of the RE generators. The
- // subexpressions are constructed by the function, re, in the second
- // parameter. re builds one subexpression for each elem in the array
- // a, in the first parameter. Returns a string for a regular
- // expression that groups all the subexpressions.
- // arr:
- // A single value or an array of values.
- // re:
- // A function. Takes one parameter and converts it to a regular
- // expression.
- // nonCapture:
- // If true, uses non-capturing match, otherwise matches are retained
- // by regular expression. Defaults to false
- // case 1: a is a single value.
- if(!(arr instanceof Array)){
- return re(arr); // String
- }
- // case 2: a is an array
- var b = [];
- for(var i = 0; i < arr.length; i++){
- // convert each elem to a RE
- b.push(re(arr[i]));
- }
- // join the REs as alternatives in a RE group.
- return dojo.regexp.group(b.join("|"), nonCapture); // String
- };
- dojo.regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){
- // summary:
- // adds group match to expression
- // nonCapture:
- // If true, uses non-capturing match, otherwise matches are retained
- // by regular expression.
- return "(" + (nonCapture ? "?:":"") + expression + ")"; // String
- };
- return dojo.regexp;
- });
- },
- 'dijit/form/ComboBox':function(){
- define("dijit/form/ComboBox", [
- "dojo/_base/declare", // declare
- "./ValidationTextBox",
- "./ComboBoxMixin"
- ], function(declare, ValidationTextBox, ComboBoxMixin){
- /*=====
- var ValidationTextBox = dijit.form.ValidationTextBox;
- var ComboBoxMixin = dijit.form.ComboBoxMixin;
- =====*/
- // module:
- // dijit/form/ComboBox
- // summary:
- // Auto-completing text box
- return declare("dijit.form.ComboBox", [ValidationTextBox, ComboBoxMixin], {
- // summary:
- // Auto-completing text box
- //
- // description:
- // The drop down box's values are populated from an class called
- // a data provider, which returns a list of values based on the characters
- // that the user has typed into the input box.
- // If OPTION tags are used as the data provider via markup,
- // then the OPTION tag's child text node is used as the widget value
- // when selected. The OPTION tag's value attribute is ignored.
- // To set the default value when using OPTION tags, specify the selected
- // attribute on 1 of the child OPTION tags.
- //
- // Some of the options to the ComboBox are actually arguments to the data
- // provider.
- });
- });
- },
- 'dojo/data/util/simpleFetch':function(){
- define("dojo/data/util/simpleFetch", ["dojo/_base/lang", "dojo/_base/window", "./sorter"],
- function(lang, winUtil, sorter) {
- // module:
- // dojo/data/util/simpleFetch
- // summary:
- // TODOC
- var simpleFetch = lang.getObject("dojo.data.util.simpleFetch", true);
- simpleFetch.fetch = function(/* Object? */ request){
- // summary:
- // The simpleFetch mixin is designed to serve as a set of function(s) that can
- // be mixed into other datastore implementations to accelerate their development.
- // The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems()
- // call by returning an array of all the found items that matched the query. The simpleFetch mixin
- // is not designed to work for datastores that respond to a fetch() call by incrementally
- // loading items, or sequentially loading partial batches of the result
- // set. For datastores that mixin simpleFetch, simpleFetch
- // implements a fetch method that automatically handles eight of the fetch()
- // arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope
- // The class mixing in simpleFetch should not implement fetch(),
- // but should instead implement a _fetchItems() method. The _fetchItems()
- // method takes three arguments, the keywordArgs object that was passed
- // to fetch(), a callback function to be called when the result array is
- // available, and an error callback to be called if something goes wrong.
- // The _fetchItems() method should ignore any keywordArgs parameters for
- // start, count, onBegin, onItem, onComplete, onError, sort, and scope.
- // The _fetchItems() method needs to correctly handle any other keywordArgs
- // parameters, including the query parameter and any optional parameters
- // (such as includeChildren). The _fetchItems() method should create an array of
- // result items and pass it to the fetchHandler along with the original request object
- // -- or, the _fetchItems() method may, if it wants to, create an new request object
- // with other specifics about the request that are specific to the datastore and pass
- // that as the request object to the handler.
- //
- // For more information on this specific function, see dojo.data.api.Read.fetch()
- request = request || {};
- if(!request.store){
- request.store = this;
- }
- var self = this;
- var _errorHandler = function(errorData, requestObject){
- if(requestObject.onError){
- var scope = requestObject.scope || winUtil.global;
- requestObject.onError.call(scope, errorData, requestObject);
- }
- };
- var _fetchHandler = function(items, requestObject){
- var oldAbortFunction = requestObject.abort || null;
- var aborted = false;
- var startIndex = requestObject.start?requestObject.start:0;
- var endIndex = (requestObject.count && (requestObject.count !== Infinity))?(startIndex + requestObject.count):items.length;
- requestObject.abort = function(){
- aborted = true;
- if(oldAbortFunction){
- oldAbortFunction.call(requestObject);
- }
- };
- var scope = requestObject.scope || winUtil.global;
- if(!requestObject.store){
- requestObject.store = self;
- }
- if(requestObject.onBegin){
- requestObject.onBegin.call(scope, items.length, requestObject);
- }
- if(requestObject.sort){
- items.sort(sorter.createSortFunction(requestObject.sort, self));
- }
- if(requestObject.onItem){
- for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){
- var item = items[i];
- if(!aborted){
- requestObject.onItem.call(scope, item, requestObject);
- }
- }
- }
- if(requestObject.onComplete && !aborted){
- var subset = null;
- if(!requestObject.onItem){
- subset = items.slice(startIndex, endIndex);
- }
- requestObject.onComplete.call(scope, subset, requestObject);
- }
- };
- this._fetchItems(request, _fetchHandler, _errorHandler);
- return request; // Object
- };
- return simpleFetch;
- });
- },
- 'dijit/form/_CheckBoxMixin':function(){
- define("dijit/form/_CheckBoxMixin", [
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.set
- "dojo/_base/event" // event.stop
- ], function(declare, domAttr, event){
- // module:
- // dijit/form/_CheckBoxMixin
- // summary:
- // Mixin to provide widget functionality corresponding to an HTML checkbox
- return declare("dijit.form._CheckBoxMixin", null, {
- // summary:
- // Mixin to provide widget functionality corresponding to an HTML checkbox
- //
- // description:
- // User interacts with real html inputs.
- // On onclick (which occurs by mouse click, space-bar, or
- // using the arrow keys to switch the selected radio button),
- // we update the state of the checkbox/radio.
- //
- // type: [private] String
- // type attribute on <input> node.
- // Overrides `dijit.form.Button.type`. Users should not change this value.
- type: "checkbox",
- // value: String
- // As an initialization parameter, equivalent to value field on normal checkbox
- // (if checked, the value is passed as the value when form is submitted).
- value: "on",
- // readOnly: Boolean
- // Should this widget respond to user input?
- // In markup, this is specified as "readOnly".
- // Similar to disabled except readOnly form values are submitted.
- readOnly: false,
-
- // aria-pressed for toggle buttons, and aria-checked for checkboxes
- _aria_attr: "aria-checked",
- _setReadOnlyAttr: function(/*Boolean*/ value){
- this._set("readOnly", value);
- domAttr.set(this.focusNode, 'readOnly', value);
- this.focusNode.setAttribute("aria-readonly", value);
- },
- // Override dijit.form.Button._setLabelAttr() since we don't even have a containerNode.
- // Normally users won't try to set label, except when CheckBox or RadioButton is the child of a dojox.layout.TabContainer
- _setLabelAttr: undefined,
- postMixInProperties: function(){
- if(this.value == ""){
- this.value = "on";
- }
- this.inherited(arguments);
- },
- reset: function(){
- this.inherited(arguments);
- // Handle unlikely event that the <input type=checkbox> value attribute has changed
- this._set("value", this.params.value || "on");
- domAttr.set(this.focusNode, 'value', this.value);
- },
- _onClick: function(/*Event*/ e){
- // summary:
- // Internal function to handle click actions - need to check
- // readOnly, since button no longer does that check.
- if(this.readOnly){
- event.stop(e);
- return false;
- }
- return this.inherited(arguments);
- }
- });
- });
- },
- 'dijit/layout/ContentPane':function(){
- define("dijit/layout/ContentPane", [
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/lang", // lang.mixin lang.delegate lang.hitch lang.isFunction lang.isObject
- "../_Widget",
- "./_ContentPaneResizeMixin",
- "dojo/string", // string.substitute
- "dojo/html", // html._ContentSetter html._emptyNode
- "dojo/i18n!../nls/loading",
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/_base/Deferred", // Deferred
- "dojo/dom", // dom.byId
- "dojo/dom-attr", // domAttr.attr
- "dojo/_base/window", // win.body win.doc.createDocumentFragment
- "dojo/_base/xhr", // xhr.get
- "dojo/i18n" // i18n.getLocalization
- ], function(kernel, lang, _Widget, _ContentPaneResizeMixin, string, html, nlsLoading,
- array, declare, Deferred, dom, domAttr, win, xhr, i18n){
- /*=====
- var _Widget = dijit._Widget;
- var _ContentPaneResizeMixin = dijit.layout._ContentPaneResizeMixin;
- =====*/
- // module:
- // dijit/layout/ContentPane
- // summary:
- // A widget containing an HTML fragment, specified inline
- // or by uri. Fragment may include widgets.
- return declare("dijit.layout.ContentPane", [_Widget, _ContentPaneResizeMixin], {
- // summary:
- // A widget containing an HTML fragment, specified inline
- // or by uri. Fragment may include widgets.
- //
- // description:
- // This widget embeds a document fragment in the page, specified
- // either by uri, javascript generated markup or DOM reference.
- // Any widgets within this content are instantiated and managed,
- // but laid out according to the HTML structure. Unlike IFRAME,
- // ContentPane embeds a document fragment as would be found
- // inside the BODY tag of a full HTML document. It should not
- // contain the HTML, HEAD, or BODY tags.
- // For more advanced functionality with scripts and
- // stylesheets, see dojox.layout.ContentPane. This widget may be
- // used stand alone or as a base class for other widgets.
- // ContentPane is useful as a child of other layout containers
- // such as BorderContainer or TabContainer, but note that those
- // widgets can contain any widget as a child.
- //
- // example:
- // Some quick samples:
- // To change the innerHTML: cp.set('content', '<b>new content</b>')
- //
- // Or you can send it a NodeList: cp.set('content', dojo.query('div [class=selected]', userSelection))
- //
- // To do an ajax update: cp.set('href', url)
- // href: String
- // The href of the content that displays now.
- // Set this at construction if you want to load data externally when the
- // pane is shown. (Set preload=true to load it immediately.)
- // Changing href after creation doesn't have any effect; Use set('href', ...);
- href: "",
- // content: String || DomNode || NodeList || dijit._Widget
- // The innerHTML of the ContentPane.
- // Note that the initialization parameter / argument to set("content", ...)
- // can be a String, DomNode, Nodelist, or _Widget.
- content: "",
- // extractContent: Boolean
- // Extract visible content from inside of <body> .... </body>.
- // I.e., strip <html> and <head> (and it's contents) from the href
- extractContent: false,
- // parseOnLoad: Boolean
- // Parse content and create the widgets, if any.
- parseOnLoad: true,
- // parserScope: String
- // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo,
- // will search for data-dojo-type (or dojoType). For backwards compatibility
- // reasons defaults to dojo._scopeName (which is "dojo" except when
- // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
- parserScope: kernel._scopeName,
- // preventCache: Boolean
- // Prevent caching of data from href's by appending a timestamp to the href.
- preventCache: false,
- // preload: Boolean
- // Force load of data on initialization even if pane is hidden.
- preload: false,
- // refreshOnShow: Boolean
- // Refresh (re-download) content when pane goes from hidden to shown
- refreshOnShow: false,
- // loadingMessage: String
- // Message that shows while downloading
- loadingMessage: "<span class='dijitContentPaneLoading'><span class='dijitInline dijitIconLoading'></span>${loadingState}</span>",
- // errorMessage: String
- // Message that shows if an error occurs
- errorMessage: "<span class='dijitContentPaneError'><span class='dijitInline dijitIconError'></span>${errorState}</span>",
- // isLoaded: [readonly] Boolean
- // True if the ContentPane has data in it, either specified
- // during initialization (via href or inline content), or set
- // via set('content', ...) / set('href', ...)
- //
- // False if it doesn't have any content, or if ContentPane is
- // still in the process of downloading href.
- isLoaded: false,
- baseClass: "dijitContentPane",
- /*======
- // ioMethod: dojo.xhrGet|dojo.xhrPost
- // Function that should grab the content specified via href.
- ioMethod: dojo.xhrGet,
- ======*/
- // ioArgs: Object
- // Parameters to pass to xhrGet() request, for example:
- // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="href: './bar', ioArgs: {timeout: 500}">
- ioArgs: {},
- // onLoadDeferred: [readonly] dojo.Deferred
- // This is the `dojo.Deferred` returned by set('href', ...) and refresh().
- // Calling onLoadDeferred.addCallback() or addErrback() registers your
- // callback to be called only once, when the prior set('href', ...) call or
- // the initial href parameter to the constructor finishes loading.
- //
- // This is different than an onLoad() handler which gets called any time any href
- // or content is loaded.
- onLoadDeferred: null,
- // Cancel _WidgetBase's _setTitleAttr because we don't want the title attribute (used to specify
- // tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the
- // entire pane.
- _setTitleAttr: null,
- // Flag to parser that I'll parse my contents, so it shouldn't.
- stopParser: true,
- // template: [private] Boolean
- // Flag from the parser that this ContentPane is inside a template
- // so the contents are pre-parsed.
- // (TODO: this declaration can be commented out in 2.0)
- template: false,
- create: function(params, srcNodeRef){
- // Convert a srcNodeRef argument into a content parameter, so that the original contents are
- // processed in the same way as contents set via set("content", ...), calling the parser etc.
- // Avoid modifying original params object since that breaks NodeList instantiation, see #11906.
- if((!params || !params.template) && srcNodeRef && !("href" in params) && !("content" in params)){
- var df = win.doc.createDocumentFragment();
- srcNodeRef = dom.byId(srcNodeRef);
- while(srcNodeRef.firstChild){
- df.appendChild(srcNodeRef.firstChild);
- }
- params = lang.delegate(params, {content: df});
- }
- this.inherited(arguments, [params, srcNodeRef]);
- },
- postMixInProperties: function(){
- this.inherited(arguments);
- var messages = i18n.getLocalization("dijit", "loading", this.lang);
- this.loadingMessage = string.substitute(this.loadingMessage, messages);
- this.errorMessage = string.substitute(this.errorMessage, messages);
- },
- buildRendering: function(){
- this.inherited(arguments);
- // Since we have no template we need to set this.containerNode ourselves, to make getChildren() work.
- // For subclasses of ContentPane that do have a template, does nothing.
- if(!this.containerNode){
- this.containerNode = this.domNode;
- }
- // remove the title attribute so it doesn't show up when hovering
- // over a node (TODO: remove in 2.0, no longer needed after #11490)
- this.domNode.title = "";
- if(!domAttr.get(this.domNode,"role")){
- this.domNode.setAttribute("role", "group");
- }
- },
- startup: function(){
- // summary:
- // Call startup() on all children including non _Widget ones like dojo.dnd.Source objects
- // This starts all the widgets
- this.inherited(arguments);
- // And this catches stuff like dojo.dnd.Source
- if(this._contentSetter){
- array.forEach(this._contentSetter.parseResults, function(obj){
- if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
- obj.startup();
- obj._started = true;
- }
- }, this);
- }
- },
- setHref: function(/*String|Uri*/ href){
- // summary:
- // Deprecated. Use set('href', ...) instead.
- kernel.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0");
- return this.set("href", href);
- },
- _setHrefAttr: function(/*String|Uri*/ href){
- // summary:
- // Hook so set("href", ...) works.
- // description:
- // Reset the (external defined) content of this pane and replace with new url
- // Note: It delays the download until widget is shown if preload is false.
- // href:
- // url to the page you want to get, must be within the same domain as your mainpage
- // Cancel any in-flight requests (a set('href', ...) will cancel any in-flight set('href', ...))
- this.cancel();
- this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
- this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
- this._set("href", href);
- // _setHrefAttr() is called during creation and by the user, after creation.
- // Assuming preload == false, only in the second case do we actually load the URL;
- // otherwise it's done in startup(), and only if this widget is shown.
- if(this.preload || (this._created && this._isShown())){
- this._load();
- }else{
- // Set flag to indicate that href needs to be loaded the next time the
- // ContentPane is made visible
- this._hrefChanged = true;
- }
- return this.onLoadDeferred; // Deferred
- },
- setContent: function(/*String|DomNode|Nodelist*/data){
- // summary:
- // Deprecated. Use set('content', ...) instead.
- kernel.deprecated("dijit.layout.ContentPane.setContent() is deprecated. Use set('content', ...) instead.", "", "2.0");
- this.set("content", data);
- },
- _setContentAttr: function(/*String|DomNode|Nodelist*/data){
- // summary:
- // Hook to make set("content", ...) work.
- // Replaces old content with data content, include style classes from old content
- // data:
- // the new Content may be String, DomNode or NodeList
- //
- // if data is a NodeList (or an array of nodes) nodes are copied
- // so you can import nodes from another document implicitly
- // clear href so we can't run refresh and clear content
- // refresh should only work if we downloaded the content
- this._set("href", "");
- // Cancel any in-flight requests (a set('content', ...) will cancel any in-flight set('href', ...))
- this.cancel();
- // Even though user is just setting content directly, still need to define an onLoadDeferred
- // because the _onLoadHandler() handler is still getting called from setContent()
- this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
- if(this._created){
- // For back-compat reasons, call onLoad() for set('content', ...)
- // calls but not for content specified in srcNodeRef (ie: <div data-dojo-type=ContentPane>...</div>)
- // or as initialization parameter (ie: new ContentPane({content: ...})
- this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
- }
- this._setContent(data || "");
- this._isDownloaded = false; // mark that content is from a set('content') not a set('href')
- return this.onLoadDeferred; // Deferred
- },
- _getContentAttr: function(){
- // summary:
- // Hook to make get("content") work
- return this.containerNode.innerHTML;
- },
- cancel: function(){
- // summary:
- // Cancels an in-flight download of content
- if(this._xhrDfd && (this._xhrDfd.fired == -1)){
- this._xhrDfd.cancel();
- }
- delete this._xhrDfd; // garbage collect
- this.onLoadDeferred = null;
- },
- uninitialize: function(){
- if(this._beingDestroyed){
- this.cancel();
- }
- this.inherited(arguments);
- },
- destroyRecursive: function(/*Boolean*/ preserveDom){
- // summary:
- // Destroy the ContentPane and its contents
- // if we have multiple controllers destroying us, bail after the first
- if(this._beingDestroyed){
- return;
- }
- this.inherited(arguments);
- },
- _onShow: function(){
- // summary:
- // Called when the ContentPane is made visible
- // description:
- // For a plain ContentPane, this is called on initialization, from startup().
- // If the ContentPane is a hidden pane of a TabContainer etc., then it's
- // called whenever the pane is made visible.
- //
- // Does necessary processing, including href download and layout/resize of
- // child widget(s)
- this.inherited(arguments);
- if(this.href){
- if(!this._xhrDfd && // if there's an href that isn't already being loaded
- (!this.isLoaded || this._hrefChanged || this.refreshOnShow)
- ){
- return this.refresh(); // If child has an href, promise that fires when the load is complete
- }
- }
- },
- refresh: function(){
- // summary:
- // [Re]download contents of href and display
- // description:
- // 1. cancels any currently in-flight requests
- // 2. posts "loading..." message
- // 3. sends XHR to download new data
- // Cancel possible prior in-flight request
- this.cancel();
- this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
- this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
- this._load();
- return this.onLoadDeferred; // If child has an href, promise that fires when refresh is complete
- },
- _load: function(){
- // summary:
- // Load/reload the href specified in this.href
- // display loading message
- this._setContent(this.onDownloadStart(), true);
- var self = this;
- var getArgs = {
- preventCache: (this.preventCache || this.refreshOnShow),
- url: this.href,
- handleAs: "text"
- };
- if(lang.isObject(this.ioArgs)){
- lang.mixin(getArgs, this.ioArgs);
- }
- var hand = (this._xhrDfd = (this.ioMethod || xhr.get)(getArgs));
- hand.addCallback(function(html){
- try{
- self._isDownloaded = true;
- self._setContent(html, false);
- self.onDownloadEnd();
- }catch(err){
- self._onError('Content', err); // onContentError
- }
- delete self._xhrDfd;
- return html;
- });
- hand.addErrback(function(err){
- if(!hand.canceled){
- // show error message in the pane
- self._onError('Download', err); // onDownloadError
- }
- delete self._xhrDfd;
- return err;
- });
- // Remove flag saying that a load is needed
- delete this._hrefChanged;
- },
- _onLoadHandler: function(data){
- // summary:
- // This is called whenever new content is being loaded
- this._set("isLoaded", true);
- try{
- this.onLoadDeferred.callback(data);
- }catch(e){
- console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message);
- }
- },
- _onUnloadHandler: function(){
- // summary:
- // This is called whenever the content is being unloaded
- this._set("isLoaded", false);
- try{
- this.onUnload();
- }catch(e){
- console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message);
- }
- },
- destroyDescendants: function(/*Boolean*/ preserveDom){
- // summary:
- // Destroy all the widgets inside the ContentPane and empty containerNode
- // Make sure we call onUnload (but only when the ContentPane has real content)
- if(this.isLoaded){
- this._onUnloadHandler();
- }
- // Even if this.isLoaded == false there might still be a "Loading..." message
- // to erase, so continue...
- // For historical reasons we need to delete all widgets under this.containerNode,
- // even ones that the user has created manually.
- var setter = this._contentSetter;
- array.forEach(this.getChildren(), function(widget){
- if(widget.destroyRecursive){
- widget.destroyRecursive(preserveDom);
- }
- });
- if(setter){
- // Most of the widgets in setter.parseResults have already been destroyed, but
- // things like Menu that have been moved to <body> haven't yet
- array.forEach(setter.parseResults, function(widget){
- if(widget.destroyRecursive && widget.domNode && widget.domNode.parentNode == win.body()){
- widget.destroyRecursive(preserveDom);
- }
- });
- delete setter.parseResults;
- }
- // And then clear away all the DOM nodes
- if(!preserveDom){
- html._emptyNode(this.containerNode);
- }
- // Delete any state information we have about current contents
- delete this._singleChild;
- },
- _setContent: function(/*String|DocumentFragment*/ cont, /*Boolean*/ isFakeContent){
- // summary:
- // Insert the content into the container node
- // first get rid of child widgets
- this.destroyDescendants();
- // html.set will take care of the rest of the details
- // we provide an override for the error handling to ensure the widget gets the errors
- // configure the setter instance with only the relevant widget instance properties
- // NOTE: unless we hook into attr, or provide property setters for each property,
- // we need to re-configure the ContentSetter with each use
- var setter = this._contentSetter;
- if(! (setter && setter instanceof html._ContentSetter)){
- setter = this._contentSetter = new html._ContentSetter({
- node: this.containerNode,
- _onError: lang.hitch(this, this._onError),
- onContentError: lang.hitch(this, function(e){
- // fires if a domfault occurs when we are appending this.errorMessage
- // like for instance if domNode is a UL and we try append a DIV
- var errMess = this.onContentError(e);
- try{
- this.containerNode.innerHTML = errMess;
- }catch(e){
- console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
- }
- })/*,
- _onError */
- });
- }
- var setterParams = lang.mixin({
- cleanContent: this.cleanContent,
- extractContent: this.extractContent,
- parseContent: !cont.domNode && this.parseOnLoad,
- parserScope: this.parserScope,
- startup: false,
- dir: this.dir,
- lang: this.lang,
- textDir: this.textDir
- }, this._contentSetterParams || {});
- setter.set( (lang.isObject(cont) && cont.domNode) ? cont.domNode : cont, setterParams );
- // setter params must be pulled afresh from the ContentPane each time
- delete this._contentSetterParams;
- if(this.doLayout){
- this._checkIfSingleChild();
- }
- if(!isFakeContent){
- if(this._started){
- // Startup each top level child widget (and they will start their children, recursively)
- delete this._started;
- this.startup();
- // Call resize() on each of my child layout widgets,
- // or resize() on my single child layout widget...
- // either now (if I'm currently visible) or when I become visible
- this._scheduleLayout();
- }
- this._onLoadHandler(cont);
- }
- },
- _onError: function(type, err, consoleText){
- this.onLoadDeferred.errback(err);
- // shows user the string that is returned by on[type]Error
- // override on[type]Error and return your own string to customize
- var errText = this['on' + type + 'Error'].call(this, err);
- if(consoleText){
- console.error(consoleText, err);
- }else if(errText){// a empty string won't change current content
- this._setContent(errText, true);
- }
- },
- // EVENT's, should be overide-able
- onLoad: function(/*===== data =====*/){
- // summary:
- // Event hook, is called after everything is loaded and widgetified
- // tags:
- // callback
- },
- onUnload: function(){
- // summary:
- // Event hook, is called before old content is cleared
- // tags:
- // callback
- },
- onDownloadStart: function(){
- // summary:
- // Called before download starts.
- // description:
- // The string returned by this function will be the html
- // that tells the user we are loading something.
- // Override with your own function if you want to change text.
- // tags:
- // extension
- return this.loadingMessage;
- },
- onContentError: function(/*Error*/ /*===== error =====*/){
- // summary:
- // Called on DOM faults, require faults etc. in content.
- //
- // In order to display an error message in the pane, return
- // the error message from this method, as an HTML string.
- //
- // By default (if this method is not overriden), it returns
- // nothing, so the error message is just printed to the console.
- // tags:
- // extension
- },
- onDownloadError: function(/*Error*/ /*===== error =====*/){
- // summary:
- // Called when download error occurs.
- //
- // In order to display an error message in the pane, return
- // the error message from this method, as an HTML string.
- //
- // Default behavior (if this method is not overriden) is to display
- // the error message inside the pane.
- // tags:
- // extension
- return this.errorMessage;
- },
- onDownloadEnd: function(){
- // summary:
- // Called when download is finished.
- // tags:
- // callback
- }
- });
- });
- },
- 'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\" role=\"presentation\"\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\r\n\t\t\t${!nameAttrSetting} type='${type}'\r\n\t/></div\r\n></div>\r\n",
- 'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\r\n\t\t\t${!nameAttrSetting} type='${type}'\r\n\t/></div\r\n></div>\r\n",
- 'dijit/layout/utils':function(){
- define("dijit/layout/utils", [
- "dojo/_base/array", // array.filter array.forEach
- "dojo/dom-class", // domClass.add domClass.remove
- "dojo/dom-geometry", // domGeometry.marginBox
- "dojo/dom-style", // domStyle.getComputedStyle
- "dojo/_base/lang", // lang.mixin
- ".." // for exporting symbols to dijit, remove in 2.0
- ], function(array, domClass, domGeometry, domStyle, lang, dijit){
- // module:
- // dijit/layout/utils
- // summary:
- // marginBox2contentBox() and layoutChildren()
- var layout = lang.getObject("layout", true, dijit);
- /*===== layout = dijit.layout =====*/
- layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
- // summary:
- // Given the margin-box size of a node, return its content box size.
- // Functions like domGeometry.contentBox() but is more reliable since it doesn't have
- // to wait for the browser to compute sizes.
- var cs = domStyle.getComputedStyle(node);
- var me = domGeometry.getMarginExtents(node, cs);
- var pb = domGeometry.getPadBorderExtents(node, cs);
- return {
- l: domStyle.toPixelValue(node, cs.paddingLeft),
- t: domStyle.toPixelValue(node, cs.paddingTop),
- w: mb.w - (me.w + pb.w),
- h: mb.h - (me.h + pb.h)
- };
- };
- function capitalize(word){
- return word.substring(0,1).toUpperCase() + word.substring(1);
- }
- function size(widget, dim){
- // size the child
- var newSize = widget.resize ? widget.resize(dim) : domGeometry.setMarginBox(widget.domNode, dim);
- // record child's size
- if(newSize){
- // if the child returned it's new size then use that
- lang.mixin(widget, newSize);
- }else{
- // otherwise, call getMarginBox(), but favor our own numbers when we have them.
- // the browser lies sometimes
- lang.mixin(widget, domGeometry.getMarginBox(widget.domNode));
- lang.mixin(widget, dim);
- }
- }
- layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children,
- /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){
- // summary:
- // Layout a bunch of child dom nodes within a parent dom node
- // container:
- // parent node
- // dim:
- // {l, t, w, h} object specifying dimensions of container into which to place children
- // children:
- // an array of Widgets or at least objects containing:
- // * domNode: pointer to DOM node to position
- // * region or layoutAlign: position to place DOM node
- // * resize(): (optional) method to set size of node
- // * id: (optional) Id of widgets, referenced from resize object, below.
- // changedRegionId:
- // If specified, the slider for the region with the specified id has been dragged, and thus
- // the region's height or width should be adjusted according to changedRegionSize
- // changedRegionSize:
- // See changedRegionId.
- // copy dim because we are going to modify it
- dim = lang.mixin({}, dim);
- domClass.add(container, "dijitLayoutContainer");
- // Move "client" elements to the end of the array for layout. a11y dictates that the author
- // needs to be able to put them in the document in tab-order, but this algorithm requires that
- // client be last. TODO: move these lines to LayoutContainer? Unneeded other places I think.
- children = array.filter(children, function(item){ return item.region != "center" && item.layoutAlign != "client"; })
- .concat(array.filter(children, function(item){ return item.region == "center" || item.layoutAlign == "client"; }));
- // set positions/sizes
- array.forEach(children, function(child){
- var elm = child.domNode,
- pos = (child.region || child.layoutAlign);
- if(!pos){
- throw new Error("No region setting for " + child.id)
- }
- // set elem to upper left corner of unused space; may move it later
- var elmStyle = elm.style;
- elmStyle.left = dim.l+"px";
- elmStyle.top = dim.t+"px";
- elmStyle.position = "absolute";
- domClass.add(elm, "dijitAlign" + capitalize(pos));
- // Size adjustments to make to this child widget
- var sizeSetting = {};
- // Check for optional size adjustment due to splitter drag (height adjustment for top/bottom align
- // panes and width adjustment for left/right align panes.
- if(changedRegionId && changedRegionId == child.id){
- sizeSetting[child.region == "top" || child.region == "bottom" ? "h" : "w"] = changedRegionSize;
- }
- // set size && adjust record of remaining space.
- // note that setting the width of a <div> may affect its height.
- if(pos == "top" || pos == "bottom"){
- sizeSetting.w = dim.w;
- size(child, sizeSetting);
- dim.h -= child.h;
- if(pos == "top"){
- dim.t += child.h;
- }else{
- elmStyle.top = dim.t + dim.h + "px";
- }
- }else if(pos == "left" || pos == "right"){
- sizeSetting.h = dim.h;
- size(child, sizeSetting);
- dim.w -= child.w;
- if(pos == "left"){
- dim.l += child.w;
- }else{
- elmStyle.left = dim.l + dim.w + "px";
- }
- }else if(pos == "client" || pos == "center"){
- size(child, dim);
- }
- });
- };
- return {
- marginBox2contentBox: layout.marginBox2contentBox,
- layoutChildren: layout.layoutChildren
- };
- });
- },
- 'dijit/_Contained':function(){
- define("dijit/_Contained", [
- "dojo/_base/declare", // declare
- "./registry" // registry.getEnclosingWidget(), registry.byNode()
- ], function(declare, registry){
- // module:
- // dijit/_Contained
- // summary:
- // Mixin for widgets that are children of a container widget
- return declare("dijit._Contained", null, {
- // summary:
- // Mixin for widgets that are children of a container widget
- //
- // example:
- // | // make a basic custom widget that knows about it's parents
- // | declare("my.customClass",[dijit._Widget,dijit._Contained],{});
- _getSibling: function(/*String*/ which){
- // summary:
- // Returns next or previous sibling
- // which:
- // Either "next" or "previous"
- // tags:
- // private
- var node = this.domNode;
- do{
- node = node[which+"Sibling"];
- }while(node && node.nodeType != 1);
- return node && registry.byNode(node); // dijit._Widget
- },
- getPreviousSibling: function(){
- // summary:
- // Returns null if this is the first child of the parent,
- // otherwise returns the next element sibling to the "left".
- return this._getSibling("previous"); // dijit._Widget
- },
- getNextSibling: function(){
- // summary:
- // Returns null if this is the last child of the parent,
- // otherwise returns the next element sibling to the "right".
- return this._getSibling("next"); // dijit._Widget
- },
- getIndexInParent: function(){
- // summary:
- // Returns the index of this widget within its container parent.
- // It returns -1 if the parent does not exist, or if the parent
- // is not a dijit._Container
- var p = this.getParent();
- if(!p || !p.getIndexOfChild){
- return -1; // int
- }
- return p.getIndexOfChild(this); // int
- }
- });
- });
- },
- 'dijit/_KeyNavContainer':function(){
- define("dijit/_KeyNavContainer", [
- "dojo/_base/kernel", // kernel.deprecated
- "./_Container",
- "./_FocusMixin",
- "dojo/_base/array", // array.forEach
- "dojo/keys", // keys.END keys.HOME
- "dojo/_base/declare", // declare
- "dojo/_base/event", // event.stop
- "dojo/dom-attr", // domAttr.set
- "dojo/_base/lang" // lang.hitch
- ], function(kernel, _Container, _FocusMixin, array, keys, declare, event, domAttr, lang){
- /*=====
- var _FocusMixin = dijit._FocusMixin;
- var _Container = dijit._Container;
- =====*/
- // module:
- // dijit/_KeyNavContainer
- // summary:
- // A _Container with keyboard navigation of its children.
- return declare("dijit._KeyNavContainer", [_FocusMixin, _Container], {
- // summary:
- // A _Container with keyboard navigation of its children.
- // description:
- // To use this mixin, call connectKeyNavHandlers() in
- // postCreate().
- // It provides normalized keyboard and focusing code for Container
- // widgets.
- /*=====
- // focusedChild: [protected] Widget
- // The currently focused child widget, or null if there isn't one
- focusedChild: null,
- =====*/
- // tabIndex: Integer
- // Tab index of the container; same as HTML tabIndex attribute.
- // Note then when user tabs into the container, focus is immediately
- // moved to the first item in the container.
- tabIndex: "0",
- connectKeyNavHandlers: function(/*keys[]*/ prevKeyCodes, /*keys[]*/ nextKeyCodes){
- // summary:
- // Call in postCreate() to attach the keyboard handlers
- // to the container.
- // preKeyCodes: keys[]
- // Key codes for navigating to the previous child.
- // nextKeyCodes: keys[]
- // Key codes for navigating to the next child.
- // tags:
- // protected
- // TODO: call this automatically from my own postCreate()
- var keyCodes = (this._keyNavCodes = {});
- var prev = lang.hitch(this, "focusPrev");
- var next = lang.hitch(this, "focusNext");
- array.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; });
- array.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; });
- keyCodes[keys.HOME] = lang.hitch(this, "focusFirstChild");
- keyCodes[keys.END] = lang.hitch(this, "focusLastChild");
- this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
- this.connect(this.domNode, "onfocus", "_onContainerFocus");
- },
- startupKeyNavChildren: function(){
- kernel.deprecated("startupKeyNavChildren() call no longer needed", "", "2.0");
- },
- startup: function(){
- this.inherited(arguments);
- array.forEach(this.getChildren(), lang.hitch(this, "_startupChild"));
- },
- addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
- this.inherited(arguments);
- this._startupChild(widget);
- },
- focus: function(){
- // summary:
- // Default focus() implementation: focus the first child.
- this.focusFirstChild();
- },
- focusFirstChild: function(){
- // summary:
- // Focus the first focusable child in the container.
- // tags:
- // protected
- this.focusChild(this._getFirstFocusableChild());
- },
- focusLastChild: function(){
- // summary:
- // Focus the last focusable child in the container.
- // tags:
- // protected
- this.focusChild(this._getLastFocusableChild());
- },
- focusNext: function(){
- // summary:
- // Focus the next widget
- // tags:
- // protected
- this.focusChild(this._getNextFocusableChild(this.focusedChild, 1));
- },
- focusPrev: function(){
- // summary:
- // Focus the last focusable node in the previous widget
- // (ex: go to the ComboButton icon section rather than button section)
- // tags:
- // protected
- this.focusChild(this._getNextFocusableChild(this.focusedChild, -1), true);
- },
- focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
- // summary:
- // Focus specified child widget.
- // widget:
- // Reference to container's child widget
- // last:
- // If true and if widget has multiple focusable nodes, focus the
- // last one instead of the first one
- // tags:
- // protected
- if(!widget){ return; }
- if(this.focusedChild && widget !== this.focusedChild){
- this._onChildBlur(this.focusedChild); // used by _MenuBase
- }
- widget.set("tabIndex", this.tabIndex); // for IE focus outline to appear, must set tabIndex before focs
- widget.focus(last ? "end" : "start");
- this._set("focusedChild", widget);
- },
- _startupChild: function(/*dijit._Widget*/ widget){
- // summary:
- // Setup for each child widget
- // description:
- // Sets tabIndex=-1 on each child, so that the tab key will
- // leave the container rather than visiting each child.
- // tags:
- // private
- widget.set("tabIndex", "-1");
- this.connect(widget, "_onFocus", function(){
- // Set valid tabIndex so tabbing away from widget goes to right place, see #10272
- widget.set("tabIndex", this.tabIndex);
- });
- this.connect(widget, "_onBlur", function(){
- widget.set("tabIndex", "-1");
- });
- },
- _onContainerFocus: function(evt){
- // summary:
- // Handler for when the container gets focus
- // description:
- // Initially the container itself has a tabIndex, but when it gets
- // focus, switch focus to first child...
- // tags:
- // private
- // Note that we can't use _onFocus() because switching focus from the
- // _onFocus() handler confuses the focus.js code
- // (because it causes _onFocusNode() to be called recursively)
- // Also, _onFocus() would fire when focus went directly to a child widget due to mouse click.
- // Ignore spurious focus events:
- // 1. focus on a child widget bubbles on FF
- // 2. on IE, clicking the scrollbar of a select dropdown moves focus from the focused child item to me
- if(evt.target !== this.domNode || this.focusedChild){ return; }
- this.focusFirstChild();
- // and then set the container's tabIndex to -1,
- // (don't remove as that breaks Safari 4)
- // so that tab or shift-tab will go to the fields after/before
- // the container, rather than the container itself
- domAttr.set(this.domNode, "tabIndex", "-1");
- },
- _onBlur: function(evt){
- // When focus is moved away the container, and its descendant (popup) widgets,
- // then restore the container's tabIndex so that user can tab to it again.
- // Note that using _onBlur() so that this doesn't happen when focus is shifted
- // to one of my child widgets (typically a popup)
- if(this.tabIndex){
- domAttr.set(this.domNode, "tabIndex", this.tabIndex);
- }
- this.focusedChild = null;
- this.inherited(arguments);
- },
- _onContainerKeypress: function(evt){
- // summary:
- // When a key is pressed, if it's an arrow key etc. then
- // it's handled here.
- // tags:
- // private
- if(evt.ctrlKey || evt.altKey){ return; }
- var func = this._keyNavCodes[evt.charOrCode];
- if(func){
- func();
- event.stop(evt);
- }
- },
- _onChildBlur: function(/*dijit._Widget*/ /*===== widget =====*/){
- // summary:
- // Called when focus leaves a child widget to go
- // to a sibling widget.
- // Used by MenuBase.js (TODO: move code there)
- // tags:
- // protected
- },
- _getFirstFocusableChild: function(){
- // summary:
- // Returns first child that can be focused
- return this._getNextFocusableChild(null, 1); // dijit._Widget
- },
- _getLastFocusableChild: function(){
- // summary:
- // Returns last child that can be focused
- return this._getNextFocusableChild(null, -1); // dijit._Widget
- },
- _getNextFocusableChild: function(child, dir){
- // summary:
- // Returns the next or previous focusable child, compared
- // to "child"
- // child: Widget
- // The current widget
- // dir: Integer
- // * 1 = after
- // * -1 = before
- if(child){
- child = this._getSiblingOfChild(child, dir);
- }
- var children = this.getChildren();
- for(var i=0; i < children.length; i++){
- if(!child){
- child = children[(dir>0) ? 0 : (children.length-1)];
- }
- if(child.isFocusable()){
- return child; // dijit._Widget
- }
- child = this._getSiblingOfChild(child, dir);
- }
- // no focusable child found
- return null; // dijit._Widget
- }
- });
- });
- },
- 'dijit/form/DataList':function(){
- define("dijit/form/DataList", [
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.byId
- "dojo/_base/lang", // lang.trim
- "dojo/query", // query
- "dojo/store/Memory", // dojo.store.Memory
- "../registry" // registry.add registry.remove
- ], function(declare, dom, lang, query, MemoryStore, registry){
- // module:
- // dijit/form/DataList
- // summary:
- // Inefficient but small data store specialized for inlined data via OPTION tags
- function toItem(/*DOMNode*/ option){
- // summary:
- // Convert <option> node to hash
- return {
- id: option.value,
- value: option.value,
- name: lang.trim(option.innerText || option.textContent || '')
- };
- }
- return declare("dijit.form.DataList", MemoryStore, {
- // summary:
- // Inefficient but small data store specialized for inlined data via OPTION tags
- //
- // description:
- // Provides a store for inlined data like:
- //
- // | <datalist>
- // | <option value="AL">Alabama</option>
- // | ...
- constructor: function(/*Object?*/ params, /*DomNode|String*/ srcNodeRef){
- // store pointer to original DOM tree
- this.domNode = dom.byId(srcNodeRef);
- lang.mixin(this, params);
- if(this.id){
- registry.add(this); // add to registry so it can be easily found by id
- }
- this.domNode.style.display = "none";
- this.inherited(arguments, [{
- data: query("option", this.domNode).map(toItem)
- }]);
- },
- destroy: function(){
- registry.remove(this.id);
- },
- fetchSelectedItem: function(){
- // summary:
- // Get the option marked as selected, like `<option selected>`.
- // Not part of dojo.data API.
- var option = query("> option[selected]", this.domNode)[0] || query("> option", this.domNode)[0];
- return option && toItem(option);
- }
- });
- });
- },
- 'dojox/timing/_base':function(){
- define("dojox/timing/_base", ["dojo/_base/kernel", "dojo/_base/lang"], function(dojo){
- dojo.experimental("dojox.timing");
- dojo.getObject("timing", true, dojox);
- dojox.timing.Timer = function(/*int*/ interval){
- // summary: Timer object executes an "onTick()" method repeatedly at a specified interval.
- // repeatedly at a given interval.
- // interval: Interval between function calls, in milliseconds.
- this.timer = null;
- this.isRunning = false;
- this.interval = interval;
- this.onStart = null;
- this.onStop = null;
- };
- dojo.extend(dojox.timing.Timer, {
- onTick: function(){
- // summary: Method called every time the interval passes. Override to do something useful.
- },
-
- setInterval: function(interval){
- // summary: Reset the interval of a timer, whether running or not.
- // interval: New interval, in milliseconds.
- if (this.isRunning){
- window.clearInterval(this.timer);
- }
- this.interval = interval;
- if (this.isRunning){
- this.timer = window.setInterval(dojo.hitch(this, "onTick"), this.interval);
- }
- },
-
- start: function(){
- // summary: Start the timer ticking.
- // description: Calls the "onStart()" handler, if defined.
- // Note that the onTick() function is not called right away,
- // only after first interval passes.
- if (typeof this.onStart == "function"){
- this.onStart();
- }
- this.isRunning = true;
- this.timer = window.setInterval(dojo.hitch(this, "onTick"), this.interval);
- },
-
- stop: function(){
- // summary: Stop the timer.
- // description: Calls the "onStop()" handler, if defined.
- if (typeof this.onStop == "function"){
- this.onStop();
- }
- this.isRunning = false;
- window.clearInterval(this.timer);
- }
- });
- return dojox.timing;
- });
- },
- 'dijit/form/CheckBox':function(){
- require({cache:{
- 'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\r\n\t><input\r\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\r\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\r\n\t\tdata-dojo-attach-point=\"focusNode\"\r\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\r\n/></div>\r\n"}});
- define("dijit/form/CheckBox", [
- "require",
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.set
- "dojo/_base/kernel",
- "dojo/query", // query
- "dojo/ready",
- "./ToggleButton",
- "./_CheckBoxMixin",
- "dojo/text!./templates/CheckBox.html",
- "dojo/NodeList-dom" // NodeList.addClass/removeClass
- ], function(require, declare, domAttr, kernel, query, ready, ToggleButton, _CheckBoxMixin, template){
- /*=====
- var ToggleButton = dijit.form.ToggleButton;
- var _CheckBoxMixin = dijit.form._CheckBoxMixin;
- =====*/
- // module:
- // dijit/form/CheckBox
- // summary:
- // Checkbox widget
- // Back compat w/1.6, remove for 2.0
- if(!kernel.isAsync){
- ready(0, function(){
- var requires = ["dijit/form/RadioButton"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- return declare("dijit.form.CheckBox", [ToggleButton, _CheckBoxMixin], {
- // summary:
- // Same as an HTML checkbox, but with fancy styling.
- //
- // description:
- // User interacts with real html inputs.
- // On onclick (which occurs by mouse click, space-bar, or
- // using the arrow keys to switch the selected radio button),
- // we update the state of the checkbox/radio.
- //
- // There are two modes:
- // 1. High contrast mode
- // 2. Normal mode
- //
- // In case 1, the regular html inputs are shown and used by the user.
- // In case 2, the regular html inputs are invisible but still used by
- // the user. They are turned quasi-invisible and overlay the background-image.
- templateString: template,
- baseClass: "dijitCheckBox",
- _setValueAttr: function(/*String|Boolean*/ newValue, /*Boolean*/ priorityChange){
- // summary:
- // Handler for value= attribute to constructor, and also calls to
- // set('value', val).
- // description:
- // During initialization, just saves as attribute to the <input type=checkbox>.
- //
- // After initialization,
- // when passed a boolean, controls whether or not the CheckBox is checked.
- // If passed a string, changes the value attribute of the CheckBox (the one
- // specified as "value" when the CheckBox was constructed (ex: <input
- // data-dojo-type="dijit.CheckBox" value="chicken">)
- // widget.set('value', string) will check the checkbox and change the value to the
- // specified string
- // widget.set('value', boolean) will change the checked state.
- if(typeof newValue == "string"){
- this._set("value", newValue);
- domAttr.set(this.focusNode, 'value', newValue);
- newValue = true;
- }
- if(this._created){
- this.set('checked', newValue, priorityChange);
- }
- },
- _getValueAttr: function(){
- // summary:
- // Hook so get('value') works.
- // description:
- // If the CheckBox is checked, returns the value attribute.
- // Otherwise returns false.
- return (this.checked ? this.value : false);
- },
- // Override behavior from Button, since we don't have an iconNode
- _setIconClassAttr: null,
- postMixInProperties: function(){
- this.inherited(arguments);
- // Need to set initial checked state as part of template, so that form submit works.
- // domAttr.set(node, "checked", bool) doesn't work on IE until node has been attached
- // to <body>, see #8666
- this.checkedAttrSetting = this.checked ? "checked" : "";
- },
- _fillContent: function(){
- // Override Button::_fillContent() since it doesn't make sense for CheckBox,
- // since CheckBox doesn't even have a container
- },
- _onFocus: function(){
- if(this.id){
- query("label[for='"+this.id+"']").addClass("dijitFocusedLabel");
- }
- this.inherited(arguments);
- },
- _onBlur: function(){
- if(this.id){
- query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel");
- }
- this.inherited(arguments);
- }
- });
- });
- },
- 'dijit/_editor/_Plugin':function(){
- define("dijit/_editor/_Plugin", [
- "dojo/_base/connect", // connect.connect
- "dojo/_base/declare", // declare
- "dojo/_base/lang", // lang.mixin, lang.hitch
- "../form/Button"
- ], function(connect, declare, lang, Button){
- // module:
- // dijit/_editor/_Plugin
- // summary:
- // Base class for a "plugin" to the editor, which is usually
- // a single button on the Toolbar and some associated code
- var _Plugin = declare("dijit._editor._Plugin", null, {
- // summary:
- // Base class for a "plugin" to the editor, which is usually
- // a single button on the Toolbar and some associated code
- constructor: function(/*Object?*/args){
- this.params = args || {};
- lang.mixin(this, this.params);
- this._connects=[];
- this._attrPairNames = {};
- },
- // editor: [const] dijit.Editor
- // Points to the parent editor
- editor: null,
- // iconClassPrefix: [const] String
- // The CSS class name for the button node is formed from `iconClassPrefix` and `command`
- iconClassPrefix: "dijitEditorIcon",
- // button: dijit._Widget?
- // Pointer to `dijit.form.Button` or other widget (ex: `dijit.form.FilteringSelect`)
- // that is added to the toolbar to control this plugin.
- // If not specified, will be created on initialization according to `buttonClass`
- button: null,
- // command: String
- // String like "insertUnorderedList", "outdent", "justifyCenter", etc. that represents an editor command.
- // Passed to editor.execCommand() if `useDefaultCommand` is true.
- command: "",
- // useDefaultCommand: Boolean
- // If true, this plugin executes by calling Editor.execCommand() with the argument specified in `command`.
- useDefaultCommand: true,
- // buttonClass: Widget Class
- // Class of widget (ex: dijit.form.Button or dijit.form.FilteringSelect)
- // that is added to the toolbar to control this plugin.
- // This is used to instantiate the button, unless `button` itself is specified directly.
- buttonClass: Button,
- // disabled: Boolean
- // Flag to indicate if this plugin has been disabled and should do nothing
- // helps control button state, among other things. Set via the setter api.
- disabled: false,
- getLabel: function(/*String*/key){
- // summary:
- // Returns the label to use for the button
- // tags:
- // private
- return this.editor.commands[key]; // String
- },
- _initButton: function(){
- // summary:
- // Initialize the button or other widget that will control this plugin.
- // This code only works for plugins controlling built-in commands in the editor.
- // tags:
- // protected extension
- if(this.command.length){
- var label = this.getLabel(this.command),
- editor = this.editor,
- className = this.iconClassPrefix+" "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);
- if(!this.button){
- var props = lang.mixin({
- label: label,
- dir: editor.dir,
- lang: editor.lang,
- showLabel: false,
- iconClass: className,
- dropDown: this.dropDown,
- tabIndex: "-1"
- }, this.params || {});
- this.button = new this.buttonClass(props);
- }
- }
- if(this.get("disabled") && this.button){
- this.button.set("disabled", this.get("disabled"));
- }
- },
- destroy: function(){
- // summary:
- // Destroy this plugin
- var h;
- while(h = this._connects.pop()){ h.remove(); }
- if(this.dropDown){
- this.dropDown.destroyRecursive();
- }
- },
- connect: function(o, f, tf){
- // summary:
- // Make a connect.connect() that is automatically disconnected when this plugin is destroyed.
- // Similar to `dijit._Widget.connect`.
- // tags:
- // protected
- this._connects.push(connect.connect(o, f, this, tf));
- },
- updateState: function(){
- // summary:
- // Change state of the plugin to respond to events in the editor.
- // description:
- // This is called on meaningful events in the editor, such as change of selection
- // or caret position (but not simple typing of alphanumeric keys). It gives the
- // plugin a chance to update the CSS of its button.
- //
- // For example, the "bold" plugin will highlight/unhighlight the bold button depending on whether the
- // characters next to the caret are bold or not.
- //
- // Only makes sense when `useDefaultCommand` is true, as it calls Editor.queryCommandEnabled(`command`).
- var e = this.editor,
- c = this.command,
- checked, enabled;
- if(!e || !e.isLoaded || !c.length){ return; }
- var disabled = this.get("disabled");
- if(this.button){
- try{
- enabled = !disabled && e.queryCommandEnabled(c);
- if(this.enabled !== enabled){
- this.enabled = enabled;
- this.button.set('disabled', !enabled);
- }
- if(typeof this.button.checked == 'boolean'){
- checked = e.queryCommandState(c);
- if(this.checked !== checked){
- this.checked = checked;
- this.button.set('checked', e.queryCommandState(c));
- }
- }
- }catch(e){
- console.log(e); // FIXME: we shouldn't have debug statements in our code. Log as an error?
- }
- }
- },
- setEditor: function(/*dijit.Editor*/ editor){
- // summary:
- // Tell the plugin which Editor it is associated with.
- // TODO: refactor code to just pass editor to constructor.
- // FIXME: detach from previous editor!!
- this.editor = editor;
- // FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
- this._initButton();
- // Processing for buttons that execute by calling editor.execCommand()
- if(this.button && this.useDefaultCommand){
- if(this.editor.queryCommandAvailable(this.command)){
- this.connect(this.button, "onClick",
- lang.hitch(this.editor, "execCommand", this.command, this.commandArg)
- );
- }else{
- // hide button because editor doesn't support command (due to browser limitations)
- this.button.domNode.style.display = "none";
- }
- }
- this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
- },
- setToolbar: function(/*dijit.Toolbar*/ toolbar){
- // summary:
- // Tell the plugin to add it's controller widget (often a button)
- // to the toolbar. Does nothing if there is no controller widget.
- // TODO: refactor code to just pass toolbar to constructor.
- if(this.button){
- toolbar.addChild(this.button);
- }
- // console.debug("adding", this.button, "to:", toolbar);
- },
- set: function(/* attribute */ name, /* anything */ value){
- // summary:
- // Set a property on a plugin
- // name:
- // The property to set.
- // value:
- // The value to set in the property.
- // description:
- // Sets named properties on a plugin which may potentially be handled by a
- // setter in the plugin.
- // For example, if the plugin has a properties "foo"
- // and "bar" and a method named "_setFooAttr", calling:
- // | plugin.set("foo", "Howdy!");
- // would be equivalent to writing:
- // | plugin._setFooAttr("Howdy!");
- // and:
- // | plugin.set("bar", 3);
- // would be equivalent to writing:
- // | plugin.bar = 3;
- //
- // set() may also be called with a hash of name/value pairs, ex:
- // | plugin.set({
- // | foo: "Howdy",
- // | bar: 3
- // | })
- // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
- if(typeof name === "object"){
- for(var x in name){
- this.set(x, name[x]);
- }
- return this;
- }
- var names = this._getAttrNames(name);
- if(this[names.s]){
- // use the explicit setter
- var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1));
- }else{
- this._set(name, value);
- }
- return result || this;
- },
- get: function(name){
- // summary:
- // Get a property from a plugin.
- // name:
- // The property to get.
- // description:
- // Get a named property from a plugin. The property may
- // potentially be retrieved via a getter method. If no getter is defined, this
- // just retrieves the object's property.
- // For example, if the plugin has a properties "foo"
- // and "bar" and a method named "_getFooAttr", calling:
- // | plugin.get("foo");
- // would be equivalent to writing:
- // | plugin._getFooAttr();
- // and:
- // | plugin.get("bar");
- // would be equivalent to writing:
- // | plugin.bar;
- var names = this._getAttrNames(name);
- return this[names.g] ? this[names.g]() : this[name];
- },
- _setDisabledAttr: function(disabled){
- // summary:
- // Function to set the plugin state and call updateState to make sure the
- // button is updated appropriately.
- this.disabled = disabled;
- this.updateState();
- },
- _getAttrNames: function(name){
- // summary:
- // Helper function for get() and set().
- // Caches attribute name values so we don't do the string ops every time.
- // tags:
- // private
- var apn = this._attrPairNames;
- if(apn[name]){ return apn[name]; }
- var uc = name.charAt(0).toUpperCase() + name.substr(1);
- return (apn[name] = {
- s: "_set"+uc+"Attr",
- g: "_get"+uc+"Attr"
- });
- },
- _set: function(/*String*/ name, /*anything*/ value){
- // summary:
- // Helper function to set new value for specified attribute
- this[name] = value;
- }
- });
- // Hash mapping plugin name to factory, used for registering plugins
- _Plugin.registry = {};
- return _Plugin;
- });
- },
- 'dijit/_Container':function(){
- define("dijit/_Container", [
- "dojo/_base/array", // array.forEach array.indexOf
- "dojo/_base/declare", // declare
- "dojo/dom-construct", // domConstruct.place
- "./registry" // registry.byNode()
- ], function(array, declare, domConstruct, registry){
- // module:
- // dijit/_Container
- // summary:
- // Mixin for widgets that contain a set of widget children.
- return declare("dijit._Container", null, {
- // summary:
- // Mixin for widgets that contain a set of widget children.
- // description:
- // Use this mixin for widgets that needs to know about and
- // keep track of their widget children. Suitable for widgets like BorderContainer
- // and TabContainer which contain (only) a set of child widgets.
- //
- // It's not suitable for widgets like ContentPane
- // which contains mixed HTML (plain DOM nodes in addition to widgets),
- // and where contained widgets are not necessarily directly below
- // this.containerNode. In that case calls like addChild(node, position)
- // wouldn't make sense.
- buildRendering: function(){
- this.inherited(arguments);
- if(!this.containerNode){
- // all widgets with descendants must set containerNode
- this.containerNode = this.domNode;
- }
- },
- addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
- // summary:
- // Makes the given widget a child of this widget.
- // description:
- // Inserts specified child widget's dom node as a child of this widget's
- // container node, and possibly does other processing (such as layout).
- var refNode = this.containerNode;
- if(insertIndex && typeof insertIndex == "number"){
- var children = this.getChildren();
- if(children && children.length >= insertIndex){
- refNode = children[insertIndex-1].domNode;
- insertIndex = "after";
- }
- }
- domConstruct.place(widget.domNode, refNode, insertIndex);
- // If I've been started but the child widget hasn't been started,
- // start it now. Make sure to do this after widget has been
- // inserted into the DOM tree, so it can see that it's being controlled by me,
- // so it doesn't try to size itself.
- if(this._started && !widget._started){
- widget.startup();
- }
- },
- removeChild: function(/*Widget|int*/ widget){
- // summary:
- // Removes the passed widget instance from this widget but does
- // not destroy it. You can also pass in an integer indicating
- // the index within the container to remove
- if(typeof widget == "number"){
- widget = this.getChildren()[widget];
- }
- if(widget){
- var node = widget.domNode;
- if(node && node.parentNode){
- node.parentNode.removeChild(node); // detach but don't destroy
- }
- }
- },
- hasChildren: function(){
- // summary:
- // Returns true if widget has children, i.e. if this.containerNode contains something.
- return this.getChildren().length > 0; // Boolean
- },
- _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
- // summary:
- // Get the next or previous widget sibling of child
- // dir:
- // if 1, get the next sibling
- // if -1, get the previous sibling
- // tags:
- // private
- var node = child.domNode,
- which = (dir>0 ? "nextSibling" : "previousSibling");
- do{
- node = node[which];
- }while(node && (node.nodeType != 1 || !registry.byNode(node)));
- return node && registry.byNode(node); // dijit._Widget
- },
- getIndexOfChild: function(/*dijit._Widget*/ child){
- // summary:
- // Gets the index of the child in this container or -1 if not found
- return array.indexOf(this.getChildren(), child); // int
- }
- });
- });
- },
- 'dojo/dnd/Source':function(){
- define("dojo/dnd/Source", ["../main", "./Selector", "./Manager"], function(dojo, Selector, Manager) {
- // module:
- // dojo/dnd/Source
- // summary:
- // TODOC
- /*=====
- Selector = dojo.dnd.Selector;
- =====*/
- /*
- Container property:
- "Horizontal"- if this is the horizontal container
- Source states:
- "" - normal state
- "Moved" - this source is being moved
- "Copied" - this source is being copied
- Target states:
- "" - normal state
- "Disabled" - the target cannot accept an avatar
- Target anchor state:
- "" - item is not selected
- "Before" - insert point is before the anchor
- "After" - insert point is after the anchor
- */
- /*=====
- dojo.dnd.__SourceArgs = function(){
- // summary:
- // a dict of parameters for DnD Source configuration. Note that any
- // property on Source elements may be configured, but this is the
- // short-list
- // isSource: Boolean?
- // can be used as a DnD source. Defaults to true.
- // accept: Array?
- // list of accepted types (text strings) for a target; defaults to
- // ["text"]
- // autoSync: Boolean
- // if true refreshes the node list on every operation; false by default
- // copyOnly: Boolean?
- // copy items, if true, use a state of Ctrl key otherwise,
- // see selfCopy and selfAccept for more details
- // delay: Number
- // the move delay in pixels before detecting a drag; 0 by default
- // horizontal: Boolean?
- // a horizontal container, if true, vertical otherwise or when omitted
- // selfCopy: Boolean?
- // copy items by default when dropping on itself,
- // false by default, works only if copyOnly is true
- // selfAccept: Boolean?
- // accept its own items when copyOnly is true,
- // true by default, works only if copyOnly is true
- // withHandles: Boolean?
- // allows dragging only by handles, false by default
- // generateText: Boolean?
- // generate text node for drag and drop, true by default
- this.isSource = isSource;
- this.accept = accept;
- this.autoSync = autoSync;
- this.copyOnly = copyOnly;
- this.delay = delay;
- this.horizontal = horizontal;
- this.selfCopy = selfCopy;
- this.selfAccept = selfAccept;
- this.withHandles = withHandles;
- this.generateText = true;
- }
- =====*/
- // For back-compat, remove in 2.0.
- if(!dojo.isAsync){
- dojo.ready(0, function(){
- var requires = ["dojo/dnd/AutoSource", "dojo/dnd/Target"];
- require(requires); // use indirection so modules not rolled into a build
- })
- }
- return dojo.declare("dojo.dnd.Source", Selector, {
- // summary:
- // a Source object, which can be used as a DnD source, or a DnD target
- // object attributes (for markup)
- isSource: true,
- horizontal: false,
- copyOnly: false,
- selfCopy: false,
- selfAccept: true,
- skipForm: false,
- withHandles: false,
- autoSync: false,
- delay: 0, // pixels
- accept: ["text"],
- generateText: true,
- constructor: function(/*DOMNode|String*/node, /*dojo.dnd.__SourceArgs?*/params){
- // summary:
- // a constructor of the Source
- // node:
- // node or node's id to build the source on
- // params:
- // any property of this class may be configured via the params
- // object which is mixed-in to the `dojo.dnd.Source` instance
- dojo.mixin(this, dojo.mixin({}, params));
- var type = this.accept;
- if(type.length){
- this.accept = {};
- for(var i = 0; i < type.length; ++i){
- this.accept[type[i]] = 1;
- }
- }
- // class-specific variables
- this.isDragging = false;
- this.mouseDown = false;
- this.targetAnchor = null;
- this.targetBox = null;
- this.before = true;
- this._lastX = 0;
- this._lastY = 0;
- // states
- this.sourceState = "";
- if(this.isSource){
- dojo.addClass(this.node, "dojoDndSource");
- }
- this.targetState = "";
- if(this.accept){
- dojo.addClass(this.node, "dojoDndTarget");
- }
- if(this.horizontal){
- dojo.addClass(this.node, "dojoDndHorizontal");
- }
- // set up events
- this.topics = [
- dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
- dojo.subscribe("/dnd/start", this, "onDndStart"),
- dojo.subscribe("/dnd/drop", this, "onDndDrop"),
- dojo.subscribe("/dnd/cancel", this, "onDndCancel")
- ];
- },
- // methods
- checkAcceptance: function(source, nodes){
- // summary:
- // checks if the target can accept nodes from this source
- // source: Object
- // the source which provides items
- // nodes: Array
- // the list of transferred items
- if(this == source){
- return !this.copyOnly || this.selfAccept;
- }
- for(var i = 0; i < nodes.length; ++i){
- var type = source.getItem(nodes[i].id).type;
- // type instanceof Array
- var flag = false;
- for(var j = 0; j < type.length; ++j){
- if(type[j] in this.accept){
- flag = true;
- break;
- }
- }
- if(!flag){
- return false; // Boolean
- }
- }
- return true; // Boolean
- },
- copyState: function(keyPressed, self){
- // summary:
- // Returns true if we need to copy items, false to move.
- // It is separated to be overwritten dynamically, if needed.
- // keyPressed: Boolean
- // the "copy" key was pressed
- // self: Boolean?
- // optional flag that means that we are about to drop on itself
- if(keyPressed){ return true; }
- if(arguments.length < 2){
- self = this == Manager.manager().target;
- }
- if(self){
- if(this.copyOnly){
- return this.selfCopy;
- }
- }else{
- return this.copyOnly;
- }
- return false; // Boolean
- },
- destroy: function(){
- // summary:
- // prepares the object to be garbage-collected
- dojo.dnd.Source.superclass.destroy.call(this);
- dojo.forEach(this.topics, dojo.unsubscribe);
- this.targetAnchor = null;
- },
- // mouse event processors
- onMouseMove: function(e){
- // summary:
- // event processor for onmousemove
- // e: Event
- // mouse event
- if(this.isDragging && this.targetState == "Disabled"){ return; }
- dojo.dnd.Source.superclass.onMouseMove.call(this, e);
- var m = Manager.manager();
- if(!this.isDragging){
- if(this.mouseDown && this.isSource &&
- (Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay)){
- var nodes = this.getSelectedNodes();
- if(nodes.length){
- m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e), true));
- }
- }
- }
- if(this.isDragging){
- // calculate before/after
- var before = false;
- if(this.current){
- if(!this.targetBox || this.targetAnchor != this.current){
- this.targetBox = dojo.position(this.current, true);
- }
- if(this.horizontal){
- before = (e.pageX - this.targetBox.x) < (this.targetBox.w / 2);
- }else{
- before = (e.pageY - this.targetBox.y) < (this.targetBox.h / 2);
- }
- }
- if(this.current != this.targetAnchor || before != this.before){
- this._markTargetAnchor(before);
- m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
- }
- }
- },
- onMouseDown: function(e){
- // summary:
- // event processor for onmousedown
- // e: Event
- // mouse event
- if(!this.mouseDown && this._legalMouseDown(e) && (!this.skipForm || !dojo.dnd.isFormElement(e))){
- this.mouseDown = true;
- this._lastX = e.pageX;
- this._lastY = e.pageY;
- dojo.dnd.Source.superclass.onMouseDown.call(this, e);
- }
- },
- onMouseUp: function(e){
- // summary:
- // event processor for onmouseup
- // e: Event
- // mouse event
- if(this.mouseDown){
- this.mouseDown = false;
- dojo.dnd.Source.superclass.onMouseUp.call(this, e);
- }
- },
- // topic event processors
- onDndSourceOver: function(source){
- // summary:
- // topic event processor for /dnd/source/over, called when detected a current source
- // source: Object
- // the source which has the mouse over it
- if(this != source){
- this.mouseDown = false;
- if(this.targetAnchor){
- this._unmarkTargetAnchor();
- }
- }else if(this.isDragging){
- var m = Manager.manager();
- m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
- }
- },
- onDndStart: function(source, nodes, copy){
- // summary:
- // topic event processor for /dnd/start, called to initiate the DnD operation
- // source: Object
- // the source which provides items
- // nodes: Array
- // the list of transferred items
- // copy: Boolean
- // copy items, if true, move items otherwise
- if(this.autoSync){ this.sync(); }
- if(this.isSource){
- this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
- }
- var accepted = this.accept && this.checkAcceptance(source, nodes);
- this._changeState("Target", accepted ? "" : "Disabled");
- if(this == source){
- Manager.manager().overSource(this);
- }
- this.isDragging = true;
- },
- onDndDrop: function(source, nodes, copy, target){
- // summary:
- // topic event processor for /dnd/drop, called to finish the DnD operation
- // source: Object
- // the source which provides items
- // nodes: Array
- // the list of transferred items
- // copy: Boolean
- // copy items, if true, move items otherwise
- // target: Object
- // the target which accepts items
- if(this == target){
- // this one is for us => move nodes!
- this.onDrop(source, nodes, copy);
- }
- this.onDndCancel();
- },
- onDndCancel: function(){
- // summary:
- // topic event processor for /dnd/cancel, called to cancel the DnD operation
- if(this.targetAnchor){
- this._unmarkTargetAnchor();
- this.targetAnchor = null;
- }
- this.before = true;
- this.isDragging = false;
- this.mouseDown = false;
- this._changeState("Source", "");
- this._changeState("Target", "");
- },
- // local events
- onDrop: function(source, nodes, copy){
- // summary:
- // called only on the current target, when drop is performed
- // source: Object
- // the source which provides items
- // nodes: Array
- // the list of transferred items
- // copy: Boolean
- // copy items, if true, move items otherwise
- if(this != source){
- this.onDropExternal(source, nodes, copy);
- }else{
- this.onDropInternal(nodes, copy);
- }
- },
- onDropExternal: function(source, nodes, copy){
- // summary:
- // called only on the current target, when drop is performed
- // from an external source
- // source: Object
- // the source which provides items
- // nodes: Array
- // the list of transferred items
- // copy: Boolean
- // copy items, if true, move items otherwise
- var oldCreator = this._normalizedCreator;
- // transferring nodes from the source to the target
- if(this.creator){
- // use defined creator
- this._normalizedCreator = function(node, hint){
- return oldCreator.call(this, source.getItem(node.id).data, hint);
- };
- }else{
- // we have no creator defined => move/clone nodes
- if(copy){
- // clone nodes
- this._normalizedCreator = function(node, hint){
- var t = source.getItem(node.id);
- var n = node.cloneNode(true);
- n.id = dojo.dnd.getUniqueId();
- return {node: n, data: t.data, type: t.type};
- };
- }else{
- // move nodes
- this._normalizedCreator = function(node, hint){
- var t = source.getItem(node.id);
- source.delItem(node.id);
- return {node: node, data: t.data, type: t.type};
- };
- }
- }
- this.selectNone();
- if(!copy && !this.creator){
- source.selectNone();
- }
- this.insertNodes(true, nodes, this.before, this.current);
- if(!copy && this.creator){
- source.deleteSelectedNodes();
- }
- this._normalizedCreator = oldCreator;
- },
- onDropInternal: function(nodes, copy){
- // summary:
- // called only on the current target, when drop is performed
- // from the same target/source
- // nodes: Array
- // the list of transferred items
- // copy: Boolean
- // copy items, if true, move items otherwise
- var oldCreator = this._normalizedCreator;
- // transferring nodes within the single source
- if(this.current && this.current.id in this.selection){
- // do nothing
- return;
- }
- if(copy){
- if(this.creator){
- // create new copies of data items
- this._normalizedCreator = function(node, hint){
- return oldCreator.call(this, this.getItem(node.id).data, hint);
- };
- }else{
- // clone nodes
- this._normalizedCreator = function(node, hint){
- var t = this.getItem(node.id);
- var n = node.cloneNode(true);
- n.id = dojo.dnd.getUniqueId();
- return {node: n, data: t.data, type: t.type};
- };
- }
- }else{
- // move nodes
- if(!this.current){
- // do nothing
- return;
- }
- this._normalizedCreator = function(node, hint){
- var t = this.getItem(node.id);
- return {node: node, data: t.data, type: t.type};
- };
- }
- this._removeSelection();
- this.insertNodes(true, nodes, this.before, this.current);
- this._normalizedCreator = oldCreator;
- },
- onDraggingOver: function(){
- // summary:
- // called during the active DnD operation, when items
- // are dragged over this target, and it is not disabled
- },
- onDraggingOut: function(){
- // summary:
- // called during the active DnD operation, when items
- // are dragged away from this target, and it is not disabled
- },
- // utilities
- onOverEvent: function(){
- // summary:
- // this function is called once, when mouse is over our container
- dojo.dnd.Source.superclass.onOverEvent.call(this);
- Manager.manager().overSource(this);
- if(this.isDragging && this.targetState != "Disabled"){
- this.onDraggingOver();
- }
- },
- onOutEvent: function(){
- // summary:
- // this function is called once, when mouse is out of our container
- dojo.dnd.Source.superclass.onOutEvent.call(this);
- Manager.manager().outSource(this);
- if(this.isDragging && this.targetState != "Disabled"){
- this.onDraggingOut();
- }
- },
- _markTargetAnchor: function(before){
- // summary:
- // assigns a class to the current target anchor based on "before" status
- // before: Boolean
- // insert before, if true, after otherwise
- if(this.current == this.targetAnchor && this.before == before){ return; }
- if(this.targetAnchor){
- this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
- }
- this.targetAnchor = this.current;
- this.targetBox = null;
- this.before = before;
- if(this.targetAnchor){
- this._addItemClass(this.targetAnchor, this.before ? "Before" : "After");
- }
- },
- _unmarkTargetAnchor: function(){
- // summary:
- // removes a class of the current target anchor based on "before" status
- if(!this.targetAnchor){ return; }
- this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
- this.targetAnchor = null;
- this.targetBox = null;
- this.before = true;
- },
- _markDndStatus: function(copy){
- // summary:
- // changes source's state based on "copy" status
- this._changeState("Source", copy ? "Copied" : "Moved");
- },
- _legalMouseDown: function(e){
- // summary:
- // checks if user clicked on "approved" items
- // e: Event
- // mouse event
- // accept only the left mouse button
- if(!dojo.mouseButtons.isLeft(e)){ return false; }
- if(!this.withHandles){ return true; }
- // check for handles
- for(var node = e.target; node && node !== this.node; node = node.parentNode){
- if(dojo.hasClass(node, "dojoDndHandle")){ return true; }
- if(dojo.hasClass(node, "dojoDndItem") || dojo.hasClass(node, "dojoDndIgnore")){ break; }
- }
- return false; // Boolean
- }
- });
- });
- },
- 'dojo/data/ItemFileReadStore':function(){
- define("dojo/data/ItemFileReadStore", ["../_base/kernel", "../_base/lang", "../_base/declare", "../_base/array", "../_base/xhr",
- "../Evented", "../_base/window", "./util/filter", "./util/simpleFetch", "../date/stamp"
- ], function(kernel, lang, declare, array, xhr, Evented, window, filterUtil, simpleFetch, dateStamp) {
- // module:
- // dojo/data/ItemFileReadStore
- // summary:
- // TODOC
- var ItemFileReadStore = declare("dojo.data.ItemFileReadStore", [Evented],{
- // summary:
- // The ItemFileReadStore implements the dojo.data.api.Read API and reads
- // data from JSON files that have contents in this format --
- // { items: [
- // { name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]},
- // { name:'Fozzie Bear', wears:['hat', 'tie']},
- // { name:'Miss Piggy', pets:'Foo-Foo'}
- // ]}
- // Note that it can also contain an 'identifer' property that specified which attribute on the items
- // in the array of items that acts as the unique identifier for that item.
- //
- constructor: function(/* Object */ keywordParameters){
- // summary: constructor
- // keywordParameters: {url: String}
- // keywordParameters: {data: jsonObject}
- // keywordParameters: {typeMap: object)
- // The structure of the typeMap object is as follows:
- // {
- // type0: function || object,
- // type1: function || object,
- // ...
- // typeN: function || object
- // }
- // Where if it is a function, it is assumed to be an object constructor that takes the
- // value of _value as the initialization parameters. If it is an object, then it is assumed
- // to be an object of general form:
- // {
- // type: function, //constructor.
- // deserialize: function(value) //The function that parses the value and constructs the object defined by type appropriately.
- // }
- this._arrayOfAllItems = [];
- this._arrayOfTopLevelItems = [];
- this._loadFinished = false;
- this._jsonFileUrl = keywordParameters.url;
- this._ccUrl = keywordParameters.url;
- this.url = keywordParameters.url;
- this._jsonData = keywordParameters.data;
- this.data = null;
- this._datatypeMap = keywordParameters.typeMap || {};
- if(!this._datatypeMap['Date']){
- //If no default mapping for dates, then set this as default.
- //We use the dojo.date.stamp here because the ISO format is the 'dojo way'
- //of generically representing dates.
- this._datatypeMap['Date'] = {
- type: Date,
- deserialize: function(value){
- return dateStamp.fromISOString(value);
- }
- };
- }
- this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true};
- this._itemsByIdentity = null;
- this._storeRefPropName = "_S"; // Default name for the store reference to attach to every item.
- this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item.
- this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item.
- this._reverseRefMap = "_RRM"; // Default attribute for constructing a reverse reference map for use with reference integrity
- this._loadInProgress = false; //Got to track the initial load to prevent duelling loads of the dataset.
- this._queuedFetches = [];
- if(keywordParameters.urlPreventCache !== undefined){
- this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
- }
- if(keywordParameters.hierarchical !== undefined){
- this.hierarchical = keywordParameters.hierarchical?true:false;
- }
- if(keywordParameters.clearOnClose){
- this.clearOnClose = true;
- }
- if("failOk" in keywordParameters){
- this.failOk = keywordParameters.failOk?true:false;
- }
- },
- url: "", // use "" rather than undefined for the benefit of the parser (#3539)
- //Internal var, crossCheckUrl. Used so that setting either url or _jsonFileUrl, can still trigger a reload
- //when clearOnClose and close is used.
- _ccUrl: "",
- data: null, // define this so that the parser can populate it
- typeMap: null, //Define so parser can populate.
- //Parameter to allow users to specify if a close call should force a reload or not.
- //By default, it retains the old behavior of not clearing if close is called. But
- //if set true, the store will be reset to default state. Note that by doing this,
- //all item handles will become invalid and a new fetch must be issued.
- clearOnClose: false,
- //Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url.
- //Note this does not mean the store calls the server on each fetch, only that the data load has preventCache set as an option.
- //Added for tracker: #6072
- urlPreventCache: false,
- //Parameter for specifying that it is OK for the xhrGet call to fail silently.
- failOk: false,
- //Parameter to indicate to process data from the url as hierarchical
- //(data items can contain other data items in js form). Default is true
- //for backwards compatibility. False means only root items are processed
- //as items, all child objects outside of type-mapped objects and those in
- //specific reference format, are left straight JS data objects.
- hierarchical: true,
- _assertIsItem: function(/* item */ item){
- // summary:
- // This function tests whether the item passed in is indeed an item in the store.
- // item:
- // The item to test for being contained by the store.
- if(!this.isItem(item)){
- throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");
- }
- },
- _assertIsAttribute: function(/* attribute-name-string */ attribute){
- // summary:
- // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
- // attribute:
- // The attribute to test for being contained by the store.
- if(typeof attribute !== "string"){
- throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");
- }
- },
- getValue: function( /* item */ item,
- /* attribute-name-string */ attribute,
- /* value? */ defaultValue){
- // summary:
- // See dojo.data.api.Read.getValue()
- var values = this.getValues(item, attribute);
- return (values.length > 0)?values[0]:defaultValue; // mixed
- },
- getValues: function(/* item */ item,
- /* attribute-name-string */ attribute){
- // summary:
- // See dojo.data.api.Read.getValues()
- this._assertIsItem(item);
- this._assertIsAttribute(attribute);
- // Clone it before returning. refs: #10474
- return (item[attribute] || []).slice(0); // Array
- },
- getAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getAttributes()
- this._assertIsItem(item);
- var attributes = [];
- for(var key in item){
- // Save off only the real item attributes, not the special id marks for O(1) isItem.
- if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName) && (key !== this._reverseRefMap)){
- attributes.push(key);
- }
- }
- return attributes; // Array
- },
- hasAttribute: function( /* item */ item,
- /* attribute-name-string */ attribute){
- // summary:
- // See dojo.data.api.Read.hasAttribute()
- this._assertIsItem(item);
- this._assertIsAttribute(attribute);
- return (attribute in item);
- },
- containsValue: function(/* item */ item,
- /* attribute-name-string */ attribute,
- /* anything */ value){
- // summary:
- // See dojo.data.api.Read.containsValue()
- var regexp = undefined;
- if(typeof value === "string"){
- regexp = filterUtil.patternToRegExp(value, false);
- }
- return this._containsValue(item, attribute, value, regexp); //boolean.
- },
- _containsValue: function( /* item */ item,
- /* attribute-name-string */ attribute,
- /* anything */ value,
- /* RegExp?*/ regexp){
- // summary:
- // Internal function for looking at the values contained by the item.
- // description:
- // Internal function for looking at the values contained by the item. This
- // function allows for denoting if the comparison should be case sensitive for
- // strings or not (for handling filtering cases where string case should not matter)
- //
- // item:
- // The data item to examine for attribute values.
- // attribute:
- // The attribute to inspect.
- // value:
- // The value to match.
- // regexp:
- // Optional regular expression generated off value if value was of string type to handle wildcarding.
- // If present and attribute values are string, then it can be used for comparison instead of 'value'
- return array.some(this.getValues(item, attribute), function(possibleValue){
- if(possibleValue !== null && !lang.isObject(possibleValue) && regexp){
- if(possibleValue.toString().match(regexp)){
- return true; // Boolean
- }
- }else if(value === possibleValue){
- return true; // Boolean
- }
- });
- },
- isItem: function(/* anything */ something){
- // summary:
- // See dojo.data.api.Read.isItem()
- if(something && something[this._storeRefPropName] === this){
- if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){
- return true;
- }
- }
- return false; // Boolean
- },
- isItemLoaded: function(/* anything */ something){
- // summary:
- // See dojo.data.api.Read.isItemLoaded()
- return this.isItem(something); //boolean
- },
- loadItem: function(/* object */ keywordArgs){
- // summary:
- // See dojo.data.api.Read.loadItem()
- this._assertIsItem(keywordArgs.item);
- },
- getFeatures: function(){
- // summary:
- // See dojo.data.api.Read.getFeatures()
- return this._features; //Object
- },
- getLabel: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getLabel()
- if(this._labelAttr && this.isItem(item)){
- return this.getValue(item,this._labelAttr); //String
- }
- return undefined; //undefined
- },
- getLabelAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getLabelAttributes()
- if(this._labelAttr){
- return [this._labelAttr]; //array
- }
- return null; //null
- },
- _fetchItems: function( /* Object */ keywordArgs,
- /* Function */ findCallback,
- /* Function */ errorCallback){
- // summary:
- // See dojo.data.util.simpleFetch.fetch()
- var self = this,
- filter = function(requestArgs, arrayOfItems){
- var items = [],
- i, key;
- if(requestArgs.query){
- var value,
- ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false;
- //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
- //same value for each item examined. Much more efficient.
- var regexpList = {};
- for(key in requestArgs.query){
- value = requestArgs.query[key];
- if(typeof value === "string"){
- regexpList[key] = filterUtil.patternToRegExp(value, ignoreCase);
- }else if(value instanceof RegExp){
- regexpList[key] = value;
- }
- }
- for(i = 0; i < arrayOfItems.length; ++i){
- var match = true;
- var candidateItem = arrayOfItems[i];
- if(candidateItem === null){
- match = false;
- }else{
- for(key in requestArgs.query){
- value = requestArgs.query[key];
- if(!self._containsValue(candidateItem, key, value, regexpList[key])){
- match = false;
- }
- }
- }
- if(match){
- items.push(candidateItem);
- }
- }
- findCallback(items, requestArgs);
- }else{
- // We want a copy to pass back in case the parent wishes to sort the array.
- // We shouldn't allow resort of the internal list, so that multiple callers
- // can get lists and sort without affecting each other. We also need to
- // filter out any null values that have been left as a result of deleteItem()
- // calls in ItemFileWriteStore.
- for(i = 0; i < arrayOfItems.length; ++i){
- var item = arrayOfItems[i];
- if(item !== null){
- items.push(item);
- }
- }
- findCallback(items, requestArgs);
- }
- };
- if(this._loadFinished){
- filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
- }else{
- //Do a check on the JsonFileUrl and crosscheck it.
- //If it doesn't match the cross-check, it needs to be updated
- //This allows for either url or _jsonFileUrl to he changed to
- //reset the store load location. Done this way for backwards
- //compatibility. People use _jsonFileUrl (even though officially
- //private.
- if(this._jsonFileUrl !== this._ccUrl){
- kernel.deprecated("dojo.data.ItemFileReadStore: ",
- "To change the url, set the url property of the store," +
- " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0");
- this._ccUrl = this._jsonFileUrl;
- this.url = this._jsonFileUrl;
- }else if(this.url !== this._ccUrl){
- this._jsonFileUrl = this.url;
- this._ccUrl = this.url;
- }
- //See if there was any forced reset of data.
- if(this.data != null){
- this._jsonData = this.data;
- this.data = null;
- }
- if(this._jsonFileUrl){
- //If fetches come in before the loading has finished, but while
- //a load is in progress, we have to defer the fetching to be
- //invoked in the callback.
- if(this._loadInProgress){
- this._queuedFetches.push({args: keywordArgs, filter: filter});
- }else{
- this._loadInProgress = true;
- var getArgs = {
- url: self._jsonFileUrl,
- handleAs: "json-comment-optional",
- preventCache: this.urlPreventCache,
- failOk: this.failOk
- };
- var getHandler = xhr.get(getArgs);
- getHandler.addCallback(function(data){
- try{
- self._getItemsFromLoadedData(data);
- self._loadFinished = true;
- self._loadInProgress = false;
- filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions));
- self._handleQueuedFetches();
- }catch(e){
- self._loadFinished = true;
- self._loadInProgress = false;
- errorCallback(e, keywordArgs);
- }
- });
- getHandler.addErrback(function(error){
- self._loadInProgress = false;
- errorCallback(error, keywordArgs);
- });
- //Wire up the cancel to abort of the request
- //This call cancel on the deferred if it hasn't been called
- //yet and then will chain to the simple abort of the
- //simpleFetch keywordArgs
- var oldAbort = null;
- if(keywordArgs.abort){
- oldAbort = keywordArgs.abort;
- }
- keywordArgs.abort = function(){
- var df = getHandler;
- if(df && df.fired === -1){
- df.cancel();
- df = null;
- }
- if(oldAbort){
- oldAbort.call(keywordArgs);
- }
- };
- }
- }else if(this._jsonData){
- try{
- this._loadFinished = true;
- this._getItemsFromLoadedData(this._jsonData);
- this._jsonData = null;
- filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
- }catch(e){
- errorCallback(e, keywordArgs);
- }
- }else{
- errorCallback(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs);
- }
- }
- },
- _handleQueuedFetches: function(){
- // summary:
- // Internal function to execute delayed request in the store.
- //Execute any deferred fetches now.
- if(this._queuedFetches.length > 0){
- for(var i = 0; i < this._queuedFetches.length; i++){
- var fData = this._queuedFetches[i],
- delayedQuery = fData.args,
- delayedFilter = fData.filter;
- if(delayedFilter){
- delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions));
- }else{
- this.fetchItemByIdentity(delayedQuery);
- }
- }
- this._queuedFetches = [];
- }
- },
- _getItemsArray: function(/*object?*/queryOptions){
- // summary:
- // Internal function to determine which list of items to search over.
- // queryOptions: The query options parameter, if any.
- if(queryOptions && queryOptions.deep){
- return this._arrayOfAllItems;
- }
- return this._arrayOfTopLevelItems;
- },
- close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
- // summary:
- // See dojo.data.api.Read.close()
- if(this.clearOnClose &&
- this._loadFinished &&
- !this._loadInProgress){
- //Reset all internalsback to default state. This will force a reload
- //on next fetch. This also checks that the data or url param was set
- //so that the store knows it can get data. Without one of those being set,
- //the next fetch will trigger an error.
- if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) &&
- (this.url == "" || this.url == null)
- ) && this.data == null){
- console.debug("dojo.data.ItemFileReadStore: WARNING! Data reload " +
- " information has not been provided." +
- " Please set 'url' or 'data' to the appropriate value before" +
- " the next fetch");
- }
- this._arrayOfAllItems = [];
- this._arrayOfTopLevelItems = [];
- this._loadFinished = false;
- this._itemsByIdentity = null;
- this._loadInProgress = false;
- this._queuedFetches = [];
- }
- },
- _getItemsFromLoadedData: function(/* Object */ dataObject){
- // summary:
- // Function to parse the loaded data into item format and build the internal items array.
- // description:
- // Function to parse the loaded data into item format and build the internal items array.
- //
- // dataObject:
- // The JS data object containing the raw data to convery into item format.
- //
- // returns: array
- // Array of items in store item format.
- // First, we define a couple little utility functions...
- var addingArrays = false,
- self = this;
- function valueIsAnItem(/* anything */ aValue){
- // summary:
- // Given any sort of value that could be in the raw json data,
- // return true if we should interpret the value as being an
- // item itself, rather than a literal value or a reference.
- // example:
- // | false == valueIsAnItem("Kermit");
- // | false == valueIsAnItem(42);
- // | false == valueIsAnItem(new Date());
- // | false == valueIsAnItem({_type:'Date', _value:'1802-05-14'});
- // | false == valueIsAnItem({_reference:'Kermit'});
- // | true == valueIsAnItem({name:'Kermit', color:'green'});
- // | true == valueIsAnItem({iggy:'pop'});
- // | true == valueIsAnItem({foo:42});
- return (aValue !== null) &&
- (typeof aValue === "object") &&
- (!lang.isArray(aValue) || addingArrays) &&
- (!lang.isFunction(aValue)) &&
- (aValue.constructor == Object || lang.isArray(aValue)) &&
- (typeof aValue._reference === "undefined") &&
- (typeof aValue._type === "undefined") &&
- (typeof aValue._value === "undefined") &&
- self.hierarchical;
- }
- function addItemAndSubItemsToArrayOfAllItems(/* Item */ anItem){
- self._arrayOfAllItems.push(anItem);
- for(var attribute in anItem){
- var valueForAttribute = anItem[attribute];
- if(valueForAttribute){
- if(lang.isArray(valueForAttribute)){
- var valueArray = valueForAttribute;
- for(var k = 0; k < valueArray.length; ++k){
- var singleValue = valueArray[k];
- if(valueIsAnItem(singleValue)){
- addItemAndSubItemsToArrayOfAllItems(singleValue);
- }
- }
- }else{
- if(valueIsAnItem(valueForAttribute)){
- addItemAndSubItemsToArrayOfAllItems(valueForAttribute);
- }
- }
- }
- }
- }
- this._labelAttr = dataObject.label;
- // We need to do some transformations to convert the data structure
- // that we read from the file into a format that will be convenient
- // to work with in memory.
- // Step 1: Walk through the object hierarchy and build a list of all items
- var i,
- item;
- this._arrayOfAllItems = [];
- this._arrayOfTopLevelItems = dataObject.items;
- for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){
- item = this._arrayOfTopLevelItems[i];
- if(lang.isArray(item)){
- addingArrays = true;
- }
- addItemAndSubItemsToArrayOfAllItems(item);
- item[this._rootItemPropName]=true;
- }
- // Step 2: Walk through all the attribute values of all the items,
- // and replace single values with arrays. For example, we change this:
- // { name:'Miss Piggy', pets:'Foo-Foo'}
- // into this:
- // { name:['Miss Piggy'], pets:['Foo-Foo']}
- //
- // We also store the attribute names so we can validate our store
- // reference and item id special properties for the O(1) isItem
- var allAttributeNames = {},
- key;
- for(i = 0; i < this._arrayOfAllItems.length; ++i){
- item = this._arrayOfAllItems[i];
- for(key in item){
- if(key !== this._rootItemPropName){
- var value = item[key];
- if(value !== null){
- if(!lang.isArray(value)){
- item[key] = [value];
- }
- }else{
- item[key] = [null];
- }
- }
- allAttributeNames[key]=key;
- }
- }
- // Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName
- // This should go really fast, it will generally never even run the loop.
- while(allAttributeNames[this._storeRefPropName]){
- this._storeRefPropName += "_";
- }
- while(allAttributeNames[this._itemNumPropName]){
- this._itemNumPropName += "_";
- }
- while(allAttributeNames[this._reverseRefMap]){
- this._reverseRefMap += "_";
- }
- // Step 4: Some data files specify an optional 'identifier', which is
- // the name of an attribute that holds the identity of each item.
- // If this data file specified an identifier attribute, then build a
- // hash table of items keyed by the identity of the items.
- var arrayOfValues;
- var identifier = dataObject.identifier;
- if(identifier){
- this._itemsByIdentity = {};
- this._features['dojo.data.api.Identity'] = identifier;
- for(i = 0; i < this._arrayOfAllItems.length; ++i){
- item = this._arrayOfAllItems[i];
- arrayOfValues = item[identifier];
- var identity = arrayOfValues[0];
- if(!Object.hasOwnProperty.call(this._itemsByIdentity, identity)){
- this._itemsByIdentity[identity] = item;
- }else{
- if(this._jsonFileUrl){
- throw new Error("dojo.data.ItemFileReadStore: The json data as specified by: [" + this._jsonFileUrl + "] is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]");
- }else if(this._jsonData){
- throw new Error("dojo.data.ItemFileReadStore: The json data provided by the creation arguments is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]");
- }
- }
- }
- }else{
- this._features['dojo.data.api.Identity'] = Number;
- }
- // Step 5: Walk through all the items, and set each item's properties
- // for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true.
- for(i = 0; i < this._arrayOfAllItems.length; ++i){
- item = this._arrayOfAllItems[i];
- item[this._storeRefPropName] = this;
- item[this._itemNumPropName] = i;
- }
- // Step 6: We walk through all the attribute values of all the items,
- // looking for type/value literals and item-references.
- //
- // We replace item-references with pointers to items. For example, we change:
- // { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
- // into this:
- // { name:['Kermit'], friends:[miss_piggy] }
- // (where miss_piggy is the object representing the 'Miss Piggy' item).
- //
- // We replace type/value pairs with typed-literals. For example, we change:
- // { name:['Nelson Mandela'], born:[{_type:'Date', _value:'1918-07-18'}] }
- // into this:
- // { name:['Kermit'], born:(new Date(1918, 6, 18)) }
- //
- // We also generate the associate map for all items for the O(1) isItem function.
- for(i = 0; i < this._arrayOfAllItems.length; ++i){
- item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
- for(key in item){
- arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}]
- for(var j = 0; j < arrayOfValues.length; ++j){
- value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}}
- if(value !== null && typeof value == "object"){
- if(("_type" in value) && ("_value" in value)){
- var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber'
- var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}}
- if(!mappingObj){
- throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'");
- }else if(lang.isFunction(mappingObj)){
- arrayOfValues[j] = new mappingObj(value._value);
- }else if(lang.isFunction(mappingObj.deserialize)){
- arrayOfValues[j] = mappingObj.deserialize(value._value);
- }else{
- throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function");
- }
- }
- if(value._reference){
- var referenceDescription = value._reference; // example: {name:'Miss Piggy'}
- if(!lang.isObject(referenceDescription)){
- // example: 'Miss Piggy'
- // from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]}
- arrayOfValues[j] = this._getItemByIdentity(referenceDescription);
- }else{
- // example: {name:'Miss Piggy'}
- // from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
- for(var k = 0; k < this._arrayOfAllItems.length; ++k){
- var candidateItem = this._arrayOfAllItems[k],
- found = true;
- for(var refKey in referenceDescription){
- if(candidateItem[refKey] != referenceDescription[refKey]){
- found = false;
- }
- }
- if(found){
- arrayOfValues[j] = candidateItem;
- }
- }
- }
- if(this.referenceIntegrity){
- var refItem = arrayOfValues[j];
- if(this.isItem(refItem)){
- this._addReferenceToMap(refItem, item, key);
- }
- }
- }else if(this.isItem(value)){
- //It's a child item (not one referenced through _reference).
- //We need to treat this as a referenced item, so it can be cleaned up
- //in a write store easily.
- if(this.referenceIntegrity){
- this._addReferenceToMap(value, item, key);
- }
- }
- }
- }
- }
- }
- },
- _addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){
- // summary:
- // Method to add an reference map entry for an item and attribute.
- // description:
- // Method to add an reference map entry for an item and attribute. //
- // refItem:
- // The item that is referenced.
- // parentItem:
- // The item that holds the new reference to refItem.
- // attribute:
- // The attribute on parentItem that contains the new reference.
- //Stub function, does nothing. Real processing is in ItemFileWriteStore.
- },
- getIdentity: function(/* item */ item){
- // summary:
- // See dojo.data.api.Identity.getIdentity()
- var identifier = this._features['dojo.data.api.Identity'];
- if(identifier === Number){
- return item[this._itemNumPropName]; // Number
- }else{
- var arrayOfValues = item[identifier];
- if(arrayOfValues){
- return arrayOfValues[0]; // Object || String
- }
- }
- return null; // null
- },
- fetchItemByIdentity: function(/* Object */ keywordArgs){
- // summary:
- // See dojo.data.api.Identity.fetchItemByIdentity()
- // Hasn't loaded yet, we have to trigger the load.
- var item,
- scope;
- if(!this._loadFinished){
- var self = this;
- //Do a check on the JsonFileUrl and crosscheck it.
- //If it doesn't match the cross-check, it needs to be updated
- //This allows for either url or _jsonFileUrl to he changed to
- //reset the store load location. Done this way for backwards
- //compatibility. People use _jsonFileUrl (even though officially
- //private.
- if(this._jsonFileUrl !== this._ccUrl){
- kernel.deprecated("dojo.data.ItemFileReadStore: ",
- "To change the url, set the url property of the store," +
- " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0");
- this._ccUrl = this._jsonFileUrl;
- this.url = this._jsonFileUrl;
- }else if(this.url !== this._ccUrl){
- this._jsonFileUrl = this.url;
- this._ccUrl = this.url;
- }
- //See if there was any forced reset of data.
- if(this.data != null && this._jsonData == null){
- this._jsonData = this.data;
- this.data = null;
- }
- if(this._jsonFileUrl){
- if(this._loadInProgress){
- this._queuedFetches.push({args: keywordArgs});
- }else{
- this._loadInProgress = true;
- var getArgs = {
- url: self._jsonFileUrl,
- handleAs: "json-comment-optional",
- preventCache: this.urlPreventCache,
- failOk: this.failOk
- };
- var getHandler = xhr.get(getArgs);
- getHandler.addCallback(function(data){
- var scope = keywordArgs.scope?keywordArgs.scope:window.global;
- try{
- self._getItemsFromLoadedData(data);
- self._loadFinished = true;
- self._loadInProgress = false;
- item = self._getItemByIdentity(keywordArgs.identity);
- if(keywordArgs.onItem){
- keywordArgs.onItem.call(scope, item);
- }
- self._handleQueuedFetches();
- }catch(error){
- self._loadInProgress = false;
- if(keywordArgs.onError){
- keywordArgs.onError.call(scope, error);
- }
- }
- });
- getHandler.addErrback(function(error){
- self._loadInProgress = false;
- if(keywordArgs.onError){
- var scope = keywordArgs.scope?keywordArgs.scope:window.global;
- keywordArgs.onError.call(scope, error);
- }
- });
- }
- }else if(this._jsonData){
- // Passed in data, no need to xhr.
- self._getItemsFromLoadedData(self._jsonData);
- self._jsonData = null;
- self._loadFinished = true;
- item = self._getItemByIdentity(keywordArgs.identity);
- if(keywordArgs.onItem){
- scope = keywordArgs.scope?keywordArgs.scope:window.global;
- keywordArgs.onItem.call(scope, item);
- }
- }
- }else{
- // Already loaded. We can just look it up and call back.
- item = this._getItemByIdentity(keywordArgs.identity);
- if(keywordArgs.onItem){
- scope = keywordArgs.scope?keywordArgs.scope:window.global;
- keywordArgs.onItem.call(scope, item);
- }
- }
- },
- _getItemByIdentity: function(/* Object */ identity){
- // summary:
- // Internal function to look an item up by its identity map.
- var item = null;
- if(this._itemsByIdentity){
- // If this map is defined, we need to just try to get it. If it fails
- // the item does not exist.
- if(Object.hasOwnProperty.call(this._itemsByIdentity, identity)){
- item = this._itemsByIdentity[identity];
- }
- }else if (Object.hasOwnProperty.call(this._arrayOfAllItems, identity)){
- item = this._arrayOfAllItems[identity];
- }
- if(item === undefined){
- item = null;
- }
- return item; // Object
- },
- getIdentityAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Identity.getIdentityAttributes()
- var identifier = this._features['dojo.data.api.Identity'];
- if(identifier === Number){
- // If (identifier === Number) it means getIdentity() just returns
- // an integer item-number for each item. The dojo.data.api.Identity
- // spec says we need to return null if the identity is not composed
- // of attributes
- return null; // null
- }else{
- return [identifier]; // Array
- }
- },
- _forceLoad: function(){
- // summary:
- // Internal function to force a load of the store if it hasn't occurred yet. This is required
- // for specific functions to work properly.
- var self = this;
- //Do a check on the JsonFileUrl and crosscheck it.
- //If it doesn't match the cross-check, it needs to be updated
- //This allows for either url or _jsonFileUrl to he changed to
- //reset the store load location. Done this way for backwards
- //compatibility. People use _jsonFileUrl (even though officially
- //private.
- if(this._jsonFileUrl !== this._ccUrl){
- kernel.deprecated("dojo.data.ItemFileReadStore: ",
- "To change the url, set the url property of the store," +
- " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0");
- this._ccUrl = this._jsonFileUrl;
- this.url = this._jsonFileUrl;
- }else if(this.url !== this._ccUrl){
- this._jsonFileUrl = this.url;
- this._ccUrl = this.url;
- }
- //See if there was any forced reset of data.
- if(this.data != null){
- this._jsonData = this.data;
- this.data = null;
- }
- if(this._jsonFileUrl){
- var getArgs = {
- url: this._jsonFileUrl,
- handleAs: "json-comment-optional",
- preventCache: this.urlPreventCache,
- failOk: this.failOk,
- sync: true
- };
- var getHandler = xhr.get(getArgs);
- getHandler.addCallback(function(data){
- try{
- //Check to be sure there wasn't another load going on concurrently
- //So we don't clobber data that comes in on it. If there is a load going on
- //then do not save this data. It will potentially clobber current data.
- //We mainly wanted to sync/wait here.
- //TODO: Revisit the loading scheme of this store to improve multi-initial
- //request handling.
- if(self._loadInProgress !== true && !self._loadFinished){
- self._getItemsFromLoadedData(data);
- self._loadFinished = true;
- }else if(self._loadInProgress){
- //Okay, we hit an error state we can't recover from. A forced load occurred
- //while an async load was occurring. Since we cannot block at this point, the best
- //that can be managed is to throw an error.
- throw new Error("dojo.data.ItemFileReadStore: Unable to perform a synchronous load, an async load is in progress.");
- }
- }catch(e){
- console.log(e);
- throw e;
- }
- });
- getHandler.addErrback(function(error){
- throw error;
- });
- }else if(this._jsonData){
- self._getItemsFromLoadedData(self._jsonData);
- self._jsonData = null;
- self._loadFinished = true;
- }
- }
- });
- //Mix in the simple fetch implementation to this class.
- lang.extend(ItemFileReadStore,simpleFetch);
- return ItemFileReadStore;
- });
- },
- 'dojo/html':function(){
- define("dojo/html", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/declare", "./dom", "./dom-construct", "./parser"], function(dojo, lang, darray, declare, dom, domConstruct, parser) {
- // module:
- // dojo/html
- // summary:
- // TODOC
- lang.getObject("html", true, dojo);
- // the parser might be needed..
- // idCounter is incremented with each instantiation to allow asignment of a unique id for tracking, logging purposes
- var idCounter = 0;
- dojo.html._secureForInnerHtml = function(/*String*/ cont){
- // summary:
- // removes !DOCTYPE and title elements from the html string.
- //
- // khtml is picky about dom faults, you can't attach a style or <title> node as child of body
- // must go into head, so we need to cut out those tags
- // cont:
- // An html string for insertion into the dom
- //
- return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
- };
- /*====
- dojo.html._emptyNode = function(node){
- // summary:
- // removes all child nodes from the given node
- // node: DOMNode
- // the parent element
- };
- =====*/
- dojo.html._emptyNode = domConstruct.empty;
- dojo.html._setNodeContent = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont){
- // summary:
- // inserts the given content into the given node
- // node:
- // the parent element
- // content:
- // the content to be set on the parent element.
- // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
- // always empty
- domConstruct.empty(node);
- if(cont) {
- if(typeof cont == "string") {
- cont = domConstruct.toDom(cont, node.ownerDocument);
- }
- if(!cont.nodeType && lang.isArrayLike(cont)) {
- // handle as enumerable, but it may shrink as we enumerate it
- for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0) {
- domConstruct.place( cont[i], node, "last");
- }
- } else {
- // pass nodes, documentFragments and unknowns through to dojo.place
- domConstruct.place(cont, node, "last");
- }
- }
- // return DomNode
- return node;
- };
- // we wrap up the content-setting operation in a object
- declare("dojo.html._ContentSetter", null,
- {
- // node: DomNode|String
- // An node which will be the parent element that we set content into
- node: "",
- // content: String|DomNode|DomNode[]
- // The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
- content: "",
- // id: String?
- // Usually only used internally, and auto-generated with each instance
- id: "",
- // cleanContent: Boolean
- // Should the content be treated as a full html document,
- // and the real content stripped of <html>, <body> wrapper before injection
- cleanContent: false,
- // extractContent: Boolean
- // Should the content be treated as a full html document, and the real content stripped of <html>, <body> wrapper before injection
- extractContent: false,
- // parseContent: Boolean
- // Should the node by passed to the parser after the new content is set
- parseContent: false,
- // parserScope: String
- // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo,
- // will search for data-dojo-type (or dojoType). For backwards compatibility
- // reasons defaults to dojo._scopeName (which is "dojo" except when
- // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
- parserScope: dojo._scopeName,
- // startup: Boolean
- // Start the child widgets after parsing them. Only obeyed if parseContent is true.
- startup: true,
- // lifecyle methods
- constructor: function(/* Object */params, /* String|DomNode */node){
- // summary:
- // Provides a configurable, extensible object to wrap the setting on content on a node
- // call the set() method to actually set the content..
- // the original params are mixed directly into the instance "this"
- lang.mixin(this, params || {});
- // give precedence to params.node vs. the node argument
- // and ensure its a node, not an id string
- node = this.node = dom.byId( this.node || node );
- if(!this.id){
- this.id = [
- "Setter",
- (node) ? node.id || node.tagName : "",
- idCounter++
- ].join("_");
- }
- },
- set: function(/* String|DomNode|NodeList? */ cont, /* Object? */ params){
- // summary:
- // front-end to the set-content sequence
- // cont:
- // An html string, node or enumerable list of nodes for insertion into the dom
- // If not provided, the object's content property will be used
- if(undefined !== cont){
- this.content = cont;
- }
- // in the re-use scenario, set needs to be able to mixin new configuration
- if(params){
- this._mixin(params);
- }
- this.onBegin();
- this.setContent();
- this.onEnd();
- return this.node;
- },
- setContent: function(){
- // summary:
- // sets the content on the node
- var node = this.node;
- if(!node) {
- // can't proceed
- throw new Error(this.declaredClass + ": setContent given no node");
- }
- try{
- node = dojo.html._setNodeContent(node, this.content);
- }catch(e){
- // check if a domfault occurs when we are appending this.errorMessage
- // like for instance if domNode is a UL and we try append a DIV
- // FIXME: need to allow the user to provide a content error message string
- var errMess = this.onContentError(e);
- try{
- node.innerHTML = errMess;
- }catch(e){
- console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e);
- }
- }
- // always put back the node for the next method
- this.node = node; // DomNode
- },
- empty: function() {
- // summary
- // cleanly empty out existing content
- // destroy any widgets from a previous run
- // NOTE: if you dont want this you'll need to empty
- // the parseResults array property yourself to avoid bad things happenning
- if(this.parseResults && this.parseResults.length) {
- darray.forEach(this.parseResults, function(w) {
- if(w.destroy){
- w.destroy();
- }
- });
- delete this.parseResults;
- }
- // this is fast, but if you know its already empty or safe, you could
- // override empty to skip this step
- dojo.html._emptyNode(this.node);
- },
- onBegin: function(){
- // summary
- // Called after instantiation, but before set();
- // It allows modification of any of the object properties
- // - including the node and content provided - before the set operation actually takes place
- // This default implementation checks for cleanContent and extractContent flags to
- // optionally pre-process html string content
- var cont = this.content;
- if(lang.isString(cont)){
- if(this.cleanContent){
- cont = dojo.html._secureForInnerHtml(cont);
- }
- if(this.extractContent){
- var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
- if(match){ cont = match[1]; }
- }
- }
- // clean out the node and any cruft associated with it - like widgets
- this.empty();
- this.content = cont;
- return this.node; /* DomNode */
- },
- onEnd: function(){
- // summary
- // Called after set(), when the new content has been pushed into the node
- // It provides an opportunity for post-processing before handing back the node to the caller
- // This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
- if(this.parseContent){
- // populates this.parseResults if you need those..
- this._parse();
- }
- return this.node; /* DomNode */
- },
- tearDown: function(){
- // summary
- // manually reset the Setter instance if its being re-used for example for another set()
- // description
- // tearDown() is not called automatically.
- // In normal use, the Setter instance properties are simply allowed to fall out of scope
- // but the tearDown method can be called to explicitly reset this instance.
- delete this.parseResults;
- delete this.node;
- delete this.content;
- },
- onContentError: function(err){
- return "Error occured setting content: " + err;
- },
- _mixin: function(params){
- // mix properties/methods into the instance
- // TODO: the intention with tearDown is to put the Setter's state
- // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
- // so we could do something here to move the original properties aside for later restoration
- var empty = {}, key;
- for(key in params){
- if(key in empty){ continue; }
- // TODO: here's our opportunity to mask the properties we dont consider configurable/overridable
- // .. but history shows we'll almost always guess wrong
- this[key] = params[key];
- }
- },
- _parse: function(){
- // summary:
- // runs the dojo parser over the node contents, storing any results in this.parseResults
- // Any errors resulting from parsing are passed to _onError for handling
- var rootNode = this.node;
- try{
- // store the results (widgets, whatever) for potential retrieval
- var inherited = {};
- darray.forEach(["dir", "lang", "textDir"], function(name){
- if(this[name]){
- inherited[name] = this[name];
- }
- }, this);
- this.parseResults = parser.parse({
- rootNode: rootNode,
- noStart: !this.startup,
- inherited: inherited,
- scope: this.parserScope
- });
- }catch(e){
- this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id);
- }
- },
- _onError: function(type, err, consoleText){
- // summary:
- // shows user the string that is returned by on[type]Error
- // overide/implement on[type]Error and return your own string to customize
- var errText = this['on' + type + 'Error'].call(this, err);
- if(consoleText){
- console.error(consoleText, err);
- }else if(errText){ // a empty string won't change current content
- dojo.html._setNodeContent(this.node, errText, true);
- }
- }
- }); // end dojo.declare()
- dojo.html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
- // summary:
- // inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
- // may be a better choice for simple HTML insertion.
- // description:
- // Unless you need to use the params capabilities of this method, you should use
- // dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
- // an HTML string into the DOM, but it only handles inserting an HTML string as DOM
- // elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
- // or the other capabilities as defined by the params object for this method.
- // node:
- // the parent element that will receive the content
- // cont:
- // the content to be set on the parent element.
- // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
- // params:
- // Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
- // example:
- // A safe string/node/nodelist content replacement/injection with hooks for extension
- // Example Usage:
- // dojo.html.set(node, "some string");
- // dojo.html.set(node, contentNode, {options});
- // dojo.html.set(node, myNode.childNodes, {options});
- if(undefined == cont){
- console.warn("dojo.html.set: no cont argument provided, using empty string");
- cont = "";
- }
- if(!params){
- // simple and fast
- return dojo.html._setNodeContent(node, cont, true);
- }else{
- // more options but slower
- // note the arguments are reversed in order, to match the convention for instantiation via the parser
- var op = new dojo.html._ContentSetter(lang.mixin(
- params,
- { content: cont, node: node }
- ));
- return op.set();
- }
- };
- return dojo.html;
- });
- },
- 'url:dijit/templates/TitlePane.html':"<div>\r\n\t<div data-dojo-attach-event=\"onclick:_onTitleClick, onkeypress:_onTitleKey\"\r\n\t\t\tclass=\"dijitTitlePaneTitle\" data-dojo-attach-point=\"titleBarNode\">\r\n\t\t<div class=\"dijitTitlePaneTitleFocus\" data-dojo-attach-point=\"focusNode\">\r\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"arrowNode\" class=\"dijitArrowNode\" role=\"presentation\"\r\n\t\t\t/><span data-dojo-attach-point=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span\r\n\t\t\t><span data-dojo-attach-point=\"titleNode\" class=\"dijitTitlePaneTextNode\"></span>\r\n\t\t</div>\r\n\t</div>\r\n\t<div class=\"dijitTitlePaneContentOuter\" data-dojo-attach-point=\"hideNode\" role=\"presentation\">\r\n\t\t<div class=\"dijitReset\" data-dojo-attach-point=\"wipeNode\" role=\"presentation\">\r\n\t\t\t<div class=\"dijitTitlePaneContentInner\" data-dojo-attach-point=\"containerNode\" role=\"region\" id=\"${id}_pane\">\r\n\t\t\t\t<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc. Put padding on inner div. -->\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t</div>\r\n</div>\r\n",
- 'dijit/form/ValidationTextBox':function(){
- require({cache:{
- 'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\" role=\"presentation\"\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\r\n\t\t\t${!nameAttrSetting} type='${type}'\r\n\t/></div\r\n></div>\r\n"}});
- define("dijit/form/ValidationTextBox", [
- "dojo/_base/declare", // declare
- "dojo/i18n", // i18n.getLocalization
- "./TextBox",
- "../Tooltip",
- "dojo/text!./templates/ValidationTextBox.html",
- "dojo/i18n!./nls/validate"
- ], function(declare, i18n, TextBox, Tooltip, template){
- /*=====
- var Tooltip = dijit.Tooltip;
- var TextBox = dijit.form.TextBox;
- =====*/
- // module:
- // dijit/form/ValidationTextBox
- // summary:
- // Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
- /*=====
- dijit.form.ValidationTextBox.__Constraints = function(){
- // locale: String
- // locale used for validation, picks up value from this widget's lang attribute
- // _flags_: anything
- // various flags passed to regExpGen function
- this.locale = "";
- this._flags_ = "";
- }
- =====*/
- return declare("dijit.form.ValidationTextBox", TextBox, {
- // summary:
- // Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
- // tags:
- // protected
- templateString: template,
- baseClass: "dijitTextBox dijitValidationTextBox",
- // required: Boolean
- // User is required to enter data into this field.
- required: false,
- // promptMessage: String
- // If defined, display this hint string immediately on focus to the textbox, if empty.
- // Also displays if the textbox value is Incomplete (not yet valid but will be with additional input).
- // Think of this like a tooltip that tells the user what to do, not an error message
- // that tells the user what they've done wrong.
- //
- // Message disappears when user starts typing.
- promptMessage: "",
- // invalidMessage: String
- // The message to display if value is invalid.
- // The translated string value is read from the message file by default.
- // Set to "" to use the promptMessage instead.
- invalidMessage: "$_unset_$",
- // missingMessage: String
- // The message to display if value is empty and the field is required.
- // The translated string value is read from the message file by default.
- // Set to "" to use the invalidMessage instead.
- missingMessage: "$_unset_$",
- // message: String
- // Currently error/prompt message.
- // When using the default tooltip implementation, this will only be
- // displayed when the field is focused.
- message: "",
- // constraints: dijit.form.ValidationTextBox.__Constraints
- // user-defined object needed to pass parameters to the validator functions
- constraints: {},
- // regExp: [extension protected] String
- // regular expression string used to validate the input
- // Do not specify both regExp and regExpGen
- regExp: ".*",
- regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/ /*===== constraints =====*/){
- // summary:
- // Overridable function used to generate regExp when dependent on constraints.
- // Do not specify both regExp and regExpGen.
- // tags:
- // extension protected
- return this.regExp; // String
- },
- // state: [readonly] String
- // Shows current state (ie, validation result) of input (""=Normal, Incomplete, or Error)
- state: "",
- // tooltipPosition: String[]
- // See description of `dijit.Tooltip.defaultPosition` for details on this parameter.
- tooltipPosition: [],
- _setValueAttr: function(){
- // summary:
- // Hook so set('value', ...) works.
- this.inherited(arguments);
- this.validate(this.focused);
- },
- validator: function(/*anything*/ value, /*dijit.form.ValidationTextBox.__Constraints*/ constraints){
- // summary:
- // Overridable function used to validate the text input against the regular expression.
- // tags:
- // protected
- return (new RegExp("^(?:" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
- (!this.required || !this._isEmpty(value)) &&
- (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
- },
- _isValidSubset: function(){
- // summary:
- // Returns true if the value is either already valid or could be made valid by appending characters.
- // This is used for validation while the user [may be] still typing.
- return this.textbox.value.search(this._partialre) == 0;
- },
- isValid: function(/*Boolean*/ /*===== isFocused =====*/){
- // summary:
- // Tests if value is valid.
- // Can override with your own routine in a subclass.
- // tags:
- // protected
- return this.validator(this.textbox.value, this.constraints);
- },
- _isEmpty: function(value){
- // summary:
- // Checks for whitespace
- return (this.trim ? /^\s*$/ : /^$/).test(value); // Boolean
- },
- getErrorMessage: function(/*Boolean*/ /*===== isFocused =====*/){
- // summary:
- // Return an error message to show if appropriate
- // tags:
- // protected
- return (this.required && this._isEmpty(this.textbox.value)) ? this.missingMessage : this.invalidMessage; // String
- },
- getPromptMessage: function(/*Boolean*/ /*===== isFocused =====*/){
- // summary:
- // Return a hint message to show when widget is first focused
- // tags:
- // protected
- return this.promptMessage; // String
- },
- _maskValidSubsetError: true,
- validate: function(/*Boolean*/ isFocused){
- // summary:
- // Called by oninit, onblur, and onkeypress.
- // description:
- // Show missing or invalid messages if appropriate, and highlight textbox field.
- // tags:
- // protected
- var message = "";
- var isValid = this.disabled || this.isValid(isFocused);
- if(isValid){ this._maskValidSubsetError = true; }
- var isEmpty = this._isEmpty(this.textbox.value);
- var isValidSubset = !isValid && isFocused && this._isValidSubset();
- this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && this._maskValidSubsetError) ? "Incomplete" : "Error"));
- this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");
- if(this.state == "Error"){
- this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus
- message = this.getErrorMessage(isFocused);
- }else if(this.state == "Incomplete"){
- message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete
- this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused
- }else if(isEmpty){
- message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text
- }
- this.set("message", message);
- return isValid;
- },
- displayMessage: function(/*String*/ message){
- // summary:
- // Overridable method to display validation errors/hints.
- // By default uses a tooltip.
- // tags:
- // extension
- if(message && this.focused){
- Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
- }else{
- Tooltip.hide(this.domNode);
- }
- },
- _refreshState: function(){
- // Overrides TextBox._refreshState()
- this.validate(this.focused);
- this.inherited(arguments);
- },
- //////////// INITIALIZATION METHODS ///////////////////////////////////////
- constructor: function(){
- this.constraints = {};
- },
- _setConstraintsAttr: function(/*Object*/ constraints){
- if(!constraints.locale && this.lang){
- constraints.locale = this.lang;
- }
- this._set("constraints", constraints);
- this._computePartialRE();
- },
- _computePartialRE: function(){
- var p = this.regExpGen(this.constraints);
- this.regExp = p;
- var partialre = "";
- // parse the regexp and produce a new regexp that matches valid subsets
- // if the regexp is .* then there's no use in matching subsets since everything is valid
- if(p != ".*"){ this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
- function(re){
- switch(re.charAt(0)){
- case '{':
- case '+':
- case '?':
- case '*':
- case '^':
- case '$':
- case '|':
- case '(':
- partialre += re;
- break;
- case ")":
- partialre += "|$)";
- break;
- default:
- partialre += "(?:"+re+"|$)";
- break;
- }
- }
- );}
- try{ // this is needed for now since the above regexp parsing needs more test verification
- "".search(partialre);
- }catch(e){ // should never be here unless the original RE is bad or the parsing is bad
- partialre = this.regExp;
- console.warn('RegExp error in ' + this.declaredClass + ': ' + this.regExp);
- } // should never be here unless the original RE is bad or the parsing is bad
- this._partialre = "^(?:" + partialre + ")$";
- },
- postMixInProperties: function(){
- this.inherited(arguments);
- this.messages = i18n.getLocalization("dijit.form", "validate", this.lang);
- if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
- if(!this.invalidMessage){ this.invalidMessage = this.promptMessage; }
- if(this.missingMessage == "$_unset_$"){ this.missingMessage = this.messages.missingMessage; }
- if(!this.missingMessage){ this.missingMessage = this.invalidMessage; }
- this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints
- },
- _setDisabledAttr: function(/*Boolean*/ value){
- this.inherited(arguments); // call FormValueWidget._setDisabledAttr()
- this._refreshState();
- },
- _setRequiredAttr: function(/*Boolean*/ value){
- this._set("required", value);
- this.focusNode.setAttribute("aria-required", value);
- this._refreshState();
- },
- _setMessageAttr: function(/*String*/ message){
- this._set("message", message);
- this.displayMessage(message);
- },
- reset:function(){
- // Overrides dijit.form.TextBox.reset() by also
- // hiding errors about partial matches
- this._maskValidSubsetError = true;
- this.inherited(arguments);
- },
- _onBlur: function(){
- // the message still exists but for back-compat, and to erase the tooltip
- // (if the message is being displayed as a tooltip), call displayMessage('')
- this.displayMessage('');
- this.inherited(arguments);
- }
- });
- });
- },
- 'dijit/layout/BorderContainer':function(){
- define("dijit/layout/BorderContainer", [
- "dojo/_base/array", // array.filter array.forEach array.map
- "dojo/cookie", // cookie
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.add domClass.remove domClass.toggle
- "dojo/dom-construct", // domConstruct.destroy domConstruct.place
- "dojo/dom-geometry", // domGeometry.marginBox
- "dojo/dom-style", // domStyle.style
- "dojo/_base/event", // event.stop
- "dojo/keys",
- "dojo/_base/lang", // lang.getObject lang.hitch
- "dojo/on",
- "dojo/touch",
- "dojo/_base/window", // win.body win.doc win.doc.createElement
- "../_WidgetBase",
- "../_Widget",
- "../_TemplatedMixin",
- "./_LayoutWidget",
- "./utils" // layoutUtils.layoutChildren
- ], function(array, cookie, declare, domClass, domConstruct, domGeometry, domStyle, event, keys, lang, on, touch, win,
- _WidgetBase, _Widget, _TemplatedMixin, _LayoutWidget, layoutUtils){
- /*=====
- var _WidgetBase = dijit._WidgetBase;
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var _LayoutWidget = dijit.layout._LayoutWidget;
- =====*/
- // module:
- // dijit/layout/BorderContainer
- // summary:
- // Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
- var _Splitter = declare("dijit.layout._Splitter", [_Widget, _TemplatedMixin ],
- {
- // summary:
- // A draggable spacer between two items in a `dijit.layout.BorderContainer`.
- // description:
- // This is instantiated by `dijit.layout.BorderContainer`. Users should not
- // create it directly.
- // tags:
- // private
- /*=====
- // container: [const] dijit.layout.BorderContainer
- // Pointer to the parent BorderContainer
- container: null,
- // child: [const] dijit.layout._LayoutWidget
- // Pointer to the pane associated with this splitter
- child: null,
- // region: [const] String
- // Region of pane associated with this splitter.
- // "top", "bottom", "left", "right".
- region: null,
- =====*/
- // live: [const] Boolean
- // If true, the child's size changes and the child widget is redrawn as you drag the splitter;
- // otherwise, the size doesn't change until you drop the splitter (by mouse-up)
- live: true,
- 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>',
- constructor: function(){
- this._handlers = [];
- },
- postMixInProperties: function(){
- this.inherited(arguments);
- this.horizontal = /top|bottom/.test(this.region);
- this._factor = /top|left/.test(this.region) ? 1 : -1;
- this._cookieName = this.container.id + "_" + this.region;
- },
- buildRendering: function(){
- this.inherited(arguments);
- domClass.add(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V"));
- if(this.container.persist){
- // restore old size
- var persistSize = cookie(this._cookieName);
- if(persistSize){
- this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize;
- }
- }
- },
- _computeMaxSize: function(){
- // summary:
- // Return the maximum size that my corresponding pane can be set to
- var dim = this.horizontal ? 'h' : 'w',
- childSize = domGeometry.getMarginBox(this.child.domNode)[dim],
- center = array.filter(this.container.getChildren(), function(child){ return child.region == "center";})[0],
- spaceAvailable = domGeometry.getMarginBox(center.domNode)[dim]; // can expand until center is crushed to 0
- return Math.min(this.child.maxSize, childSize + spaceAvailable);
- },
- _startDrag: function(e){
- if(!this.cover){
- this.cover = win.doc.createElement('div');
- domClass.add(this.cover, "dijitSplitterCover");
- domConstruct.place(this.cover, this.child.domNode, "after");
- }
- domClass.add(this.cover, "dijitSplitterCoverActive");
- // Safeguard in case the stop event was missed. Shouldn't be necessary if we always get the mouse up.
- if(this.fake){ domConstruct.destroy(this.fake); }
- if(!(this._resize = this.live)){ //TODO: disable live for IE6?
- // create fake splitter to display at old position while we drag
- (this.fake = this.domNode.cloneNode(true)).removeAttribute("id");
- domClass.add(this.domNode, "dijitSplitterShadow");
- domConstruct.place(this.fake, this.domNode, "after");
- }
- domClass.add(this.domNode, "dijitSplitterActive dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
- if(this.fake){
- domClass.remove(this.fake, "dijitSplitterHover dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover");
- }
- //Performance: load data info local vars for onmousevent function closure
- var factor = this._factor,
- isHorizontal = this.horizontal,
- axis = isHorizontal ? "pageY" : "pageX",
- pageStart = e[axis],
- splitterStyle = this.domNode.style,
- dim = isHorizontal ? 'h' : 'w',
- childStart = domGeometry.getMarginBox(this.child.domNode)[dim],
- max = this._computeMaxSize(),
- min = this.child.minSize || 20,
- region = this.region,
- splitterAttr = region == "top" || region == "bottom" ? "top" : "left", // style attribute of splitter to adjust
- splitterStart = parseInt(splitterStyle[splitterAttr], 10),
- resize = this._resize,
- layoutFunc = lang.hitch(this.container, "_layoutChildren", this.child.id),
- de = win.doc;
- this._handlers = this._handlers.concat([
- on(de, touch.move, this._drag = function(e, forceResize){
- var delta = e[axis] - pageStart,
- childSize = factor * delta + childStart,
- boundChildSize = Math.max(Math.min(childSize, max), min);
- if(resize || forceResize){
- layoutFunc(boundChildSize);
- }
- // TODO: setting style directly (usually) sets content box size, need to set margin box size
- splitterStyle[splitterAttr] = delta + splitterStart + factor*(boundChildSize - childSize) + "px";
- }),
- on(de, "dragstart", event.stop),
- on(win.body(), "selectstart", event.stop),
- on(de, touch.release, lang.hitch(this, "_stopDrag"))
- ]);
- event.stop(e);
- },
- _onMouse: function(e){
- // summary:
- // Handler for onmouseenter / onmouseleave events
- var o = (e.type == "mouseover" || e.type == "mouseenter");
- domClass.toggle(this.domNode, "dijitSplitterHover", o);
- domClass.toggle(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o);
- },
- _stopDrag: function(e){
- try{
- if(this.cover){
- domClass.remove(this.cover, "dijitSplitterCoverActive");
- }
- if(this.fake){ domConstruct.destroy(this.fake); }
- domClass.remove(this.domNode, "dijitSplitterActive dijitSplitter"
- + (this.horizontal ? "H" : "V") + "Active dijitSplitterShadow");
- this._drag(e); //TODO: redundant with onmousemove?
- this._drag(e, true);
- }finally{
- this._cleanupHandlers();
- delete this._drag;
- }
- if(this.container.persist){
- cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365});
- }
- },
- _cleanupHandlers: function(){
- var h;
- while(h = this._handlers.pop()){ h.remove(); }
- },
- _onKeyPress: function(/*Event*/ e){
- // should we apply typematic to this?
- this._resize = true;
- var horizontal = this.horizontal;
- var tick = 1;
- switch(e.charOrCode){
- case horizontal ? keys.UP_ARROW : keys.LEFT_ARROW:
- tick *= -1;
- // break;
- case horizontal ? keys.DOWN_ARROW : keys.RIGHT_ARROW:
- break;
- default:
- // this.inherited(arguments);
- return;
- }
- var childSize = domGeometry.getMarginSize(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick;
- this.container._layoutChildren(this.child.id, Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize));
- event.stop(e);
- },
- destroy: function(){
- this._cleanupHandlers();
- delete this.child;
- delete this.container;
- delete this.cover;
- delete this.fake;
- this.inherited(arguments);
- }
- });
- var _Gutter = declare("dijit.layout._Gutter", [_Widget, _TemplatedMixin],
- {
- // summary:
- // Just a spacer div to separate side pane from center pane.
- // Basically a trick to lookup the gutter/splitter width from the theme.
- // description:
- // Instantiated by `dijit.layout.BorderContainer`. Users should not
- // create directly.
- // tags:
- // private
- templateString: '<div class="dijitGutter" role="presentation"></div>',
- postMixInProperties: function(){
- this.inherited(arguments);
- this.horizontal = /top|bottom/.test(this.region);
- },
- buildRendering: function(){
- this.inherited(arguments);
- domClass.add(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V"));
- }
- });
- var BorderContainer = declare("dijit.layout.BorderContainer", _LayoutWidget, {
- // summary:
- // Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
- //
- // description:
- // A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;",
- // that contains a child widget marked region="center" and optionally children widgets marked
- // region equal to "top", "bottom", "leading", "trailing", "left" or "right".
- // Children along the edges will be laid out according to width or height dimensions and may
- // include optional splitters (splitter="true") to make them resizable by the user. The remaining
- // space is designated for the center region.
- //
- // The outer size must be specified on the BorderContainer node. Width must be specified for the sides
- // and height for the top and bottom, respectively. No dimensions should be specified on the center;
- // it will fill the remaining space. Regions named "leading" and "trailing" may be used just like
- // "left" and "right" except that they will be reversed in right-to-left environments.
- //
- // For complex layouts, multiple children can be specified for a single region. In this case, the
- // layoutPriority flag on the children determines which child is closer to the edge (low layoutPriority)
- // and which child is closer to the center (high layoutPriority). layoutPriority can also be used
- // instead of the design attribute to control layout precedence of horizontal vs. vertical panes.
- // example:
- // | <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'sidebar', gutters: false"
- // | style="width: 400px; height: 300px;">
- // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'top'">header text</div>
- // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'right', splitter: true" style="width: 200px;">table of contents</div>
- // | <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'center'">client area</div>
- // | </div>
- // design: String
- // Which design is used for the layout:
- // - "headline" (default) where the top and bottom extend
- // the full width of the container
- // - "sidebar" where the left and right sides extend from top to bottom.
- design: "headline",
- // gutters: [const] Boolean
- // Give each pane a border and margin.
- // Margin determined by domNode.paddingLeft.
- // When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing.
- gutters: true,
- // liveSplitters: [const] Boolean
- // Specifies whether splitters resize as you drag (true) or only upon mouseup (false)
- liveSplitters: true,
- // persist: Boolean
- // Save splitter positions in a cookie.
- persist: false,
- baseClass: "dijitBorderContainer",
- // _splitterClass: Function||String
- // Optional hook to override the default Splitter widget used by BorderContainer
- _splitterClass: _Splitter,
- postMixInProperties: function(){
- // change class name to indicate that BorderContainer is being used purely for
- // layout (like LayoutContainer) rather than for pretty formatting.
- if(!this.gutters){
- this.baseClass += "NoGutter";
- }
- this.inherited(arguments);
- },
- startup: function(){
- if(this._started){ return; }
- array.forEach(this.getChildren(), this._setupChild, this);
- this.inherited(arguments);
- },
- _setupChild: function(/*dijit._Widget*/ child){
- // Override _LayoutWidget._setupChild().
- var region = child.region;
- if(region){
- this.inherited(arguments);
- domClass.add(child.domNode, this.baseClass+"Pane");
- var ltr = this.isLeftToRight();
- if(region == "leading"){ region = ltr ? "left" : "right"; }
- if(region == "trailing"){ region = ltr ? "right" : "left"; }
- // Create draggable splitter for resizing pane,
- // or alternately if splitter=false but BorderContainer.gutters=true then
- // insert dummy div just for spacing
- if(region != "center" && (child.splitter || this.gutters) && !child._splitterWidget){
- var _Splitter = child.splitter ? this._splitterClass : _Gutter;
- if(lang.isString(_Splitter)){
- _Splitter = lang.getObject(_Splitter); // for back-compat, remove in 2.0
- }
- var splitter = new _Splitter({
- id: child.id + "_splitter",
- container: this,
- child: child,
- region: region,
- live: this.liveSplitters
- });
- splitter.isSplitter = true;
- child._splitterWidget = splitter;
- domConstruct.place(splitter.domNode, child.domNode, "after");
- // Splitters aren't added as Contained children, so we need to call startup explicitly
- splitter.startup();
- }
- child.region = region; // TODO: technically wrong since it overwrites "trailing" with "left" etc.
- }
- },
- layout: function(){
- // Implement _LayoutWidget.layout() virtual method.
- this._layoutChildren();
- },
- addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
- // Override _LayoutWidget.addChild().
- this.inherited(arguments);
- if(this._started){
- this.layout(); //OPT
- }
- },
- removeChild: function(/*dijit._Widget*/ child){
- // Override _LayoutWidget.removeChild().
- var region = child.region;
- var splitter = child._splitterWidget;
- if(splitter){
- splitter.destroy();
- delete child._splitterWidget;
- }
- this.inherited(arguments);
- if(this._started){
- this._layoutChildren();
- }
- // Clean up whatever style changes we made to the child pane.
- // Unclear how height and width should be handled.
- domClass.remove(child.domNode, this.baseClass+"Pane");
- domStyle.set(child.domNode, {
- top: "auto",
- bottom: "auto",
- left: "auto",
- right: "auto",
- position: "static"
- });
- domStyle.set(child.domNode, region == "top" || region == "bottom" ? "width" : "height", "auto");
- },
- getChildren: function(){
- // Override _LayoutWidget.getChildren() to only return real children, not the splitters.
- return array.filter(this.inherited(arguments), function(widget){
- return !widget.isSplitter;
- });
- },
- // TODO: remove in 2.0
- getSplitter: function(/*String*/region){
- // summary:
- // Returns the widget responsible for rendering the splitter associated with region
- // tags:
- // deprecated
- return array.filter(this.getChildren(), function(child){
- return child.region == region;
- })[0]._splitterWidget;
- },
- resize: function(newSize, currentSize){
- // Overrides _LayoutWidget.resize().
- // resetting potential padding to 0px to provide support for 100% width/height + padding
- // TODO: this hack doesn't respect the box model and is a temporary fix
- if(!this.cs || !this.pe){
- var node = this.domNode;
- this.cs = domStyle.getComputedStyle(node);
- this.pe = domGeometry.getPadExtents(node, this.cs);
- this.pe.r = domStyle.toPixelValue(node, this.cs.paddingRight);
- this.pe.b = domStyle.toPixelValue(node, this.cs.paddingBottom);
- domStyle.set(node, "padding", "0px");
- }
- this.inherited(arguments);
- },
- _layoutChildren: function(/*String?*/ changedChildId, /*Number?*/ changedChildSize){
- // summary:
- // This is the main routine for setting size/position of each child.
- // description:
- // With no arguments, measures the height of top/bottom panes, the width
- // of left/right panes, and then sizes all panes accordingly.
- //
- // With changedRegion specified (as "left", "top", "bottom", or "right"),
- // it changes that region's width/height to changedRegionSize and
- // then resizes other regions that were affected.
- // changedChildId:
- // Id of the child which should be resized because splitter was dragged.
- // changedChildSize:
- // The new width/height (in pixels) to make specified child
- if(!this._borderBox || !this._borderBox.h){
- // We are currently hidden, or we haven't been sized by our parent yet.
- // Abort. Someone will resize us later.
- return;
- }
- // Generate list of wrappers of my children in the order that I want layoutChildren()
- // to process them (i.e. from the outside to the inside)
- var wrappers = array.map(this.getChildren(), function(child, idx){
- return {
- pane: child,
- weight: [
- child.region == "center" ? Infinity : 0,
- child.layoutPriority,
- (this.design == "sidebar" ? 1 : -1) * (/top|bottom/.test(child.region) ? 1 : -1),
- idx
- ]
- };
- }, this);
- wrappers.sort(function(a, b){
- var aw = a.weight, bw = b.weight;
- for(var i=0; i<aw.length; i++){
- if(aw[i] != bw[i]){
- return aw[i] - bw[i];
- }
- }
- return 0;
- });
- // Make new list, combining the externally specified children with splitters and gutters
- var childrenAndSplitters = [];
- array.forEach(wrappers, function(wrapper){
- var pane = wrapper.pane;
- childrenAndSplitters.push(pane);
- if(pane._splitterWidget){
- childrenAndSplitters.push(pane._splitterWidget);
- }
- });
- // Compute the box in which to lay out my children
- var dim = {
- l: this.pe.l,
- t: this.pe.t,
- w: this._borderBox.w - this.pe.w,
- h: this._borderBox.h - this.pe.h
- };
- // Layout the children, possibly changing size due to a splitter drag
- layoutUtils.layoutChildren(this.domNode, dim, childrenAndSplitters,
- changedChildId, changedChildSize);
- },
- destroyRecursive: function(){
- // Destroy splitters first, while getChildren() still works
- array.forEach(this.getChildren(), function(child){
- var splitter = child._splitterWidget;
- if(splitter){
- splitter.destroy();
- }
- delete child._splitterWidget;
- });
- // Then destroy the real children, and myself
- this.inherited(arguments);
- }
- });
- // This argument can be specified for the children of a BorderContainer.
- // Since any widget can be specified as a LayoutContainer child, mix it
- // into the base widget class. (This is a hack, but it's effective.)
- lang.extend(_WidgetBase, {
- // region: [const] String
- // Parameter for children of `dijit.layout.BorderContainer`.
- // Values: "top", "bottom", "leading", "trailing", "left", "right", "center".
- // See the `dijit.layout.BorderContainer` description for details.
- region: '',
- // layoutPriority: [const] Number
- // Parameter for children of `dijit.layout.BorderContainer`.
- // Children with a higher layoutPriority will be placed closer to the BorderContainer center,
- // between children with a lower layoutPriority.
- layoutPriority: 0,
- // splitter: [const] Boolean
- // Parameter for child of `dijit.layout.BorderContainer` where region != "center".
- // If true, enables user to resize the widget by putting a draggable splitter between
- // this widget and the region=center widget.
- splitter: false,
- // minSize: [const] Number
- // Parameter for children of `dijit.layout.BorderContainer`.
- // Specifies a minimum size (in pixels) for this widget when resized by a splitter.
- minSize: 0,
- // maxSize: [const] Number
- // Parameter for children of `dijit.layout.BorderContainer`.
- // Specifies a maximum size (in pixels) for this widget when resized by a splitter.
- maxSize: Infinity
- });
- // For monkey patching
- BorderContainer._Splitter = _Splitter;
- BorderContainer._Gutter = _Gutter;
- return BorderContainer;
- });
- },
- 'dojo/window':function(){
- define("dojo/window", ["./_base/lang", "./_base/sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style"],
- function(lang, has, baseWindow, dom, geom, style) {
- // module:
- // dojo/window
- // summary:
- // TODOC
- var window = lang.getObject("dojo.window", true);
- /*=====
- dojo.window = {
- // summary:
- // TODO
- };
- window = dojo.window;
- =====*/
- window.getBox = function(){
- // summary:
- // Returns the dimensions and scroll position of the viewable area of a browser window
- var
- scrollRoot = (baseWindow.doc.compatMode == 'BackCompat') ? baseWindow.body() : baseWindow.doc.documentElement,
- // get scroll position
- scroll = geom.docScroll(), // scrollRoot.scrollTop/Left should work
- w, h;
- if(has("touch")){ // if(scrollbars not supported)
- 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
- // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight
- w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated
- h = uiWindow.innerHeight || scrollRoot.clientHeight;
- }else{
- // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight
- // uiWindow.innerWidth/Height includes the scrollbar and cannot be used
- w = scrollRoot.clientWidth;
- h = scrollRoot.clientHeight;
- }
- return {
- l: scroll.x,
- t: scroll.y,
- w: w,
- h: h
- };
- };
- window.get = function(doc){
- // summary:
- // Get window object associated with document doc
- // In some IE versions (at least 6.0), document.parentWindow does not return a
- // reference to the real window object (maybe a copy), so we must fix it as well
- // We use IE specific execScript to attach the real window reference to
- // document._parentWindow for later use
- if(has("ie") && window !== document.parentWindow){
- /*
- In IE 6, only the variable "window" can be used to connect events (others
- may be only copies).
- */
- doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
- //to prevent memory leak, unset it after use
- //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
- var win = doc._parentWindow;
- doc._parentWindow = null;
- return win; // Window
- }
- return doc.parentWindow || doc.defaultView; // Window
- };
- window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
- // summary:
- // Scroll the passed node into view, if it is not already.
- // don't rely on node.scrollIntoView working just because the function is there
- try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
- node = dom.byId(node);
- var doc = node.ownerDocument || baseWindow.doc,
- body = doc.body || baseWindow.body(),
- html = doc.documentElement || body.parentNode,
- isIE = has("ie"), isWK = has("webkit");
- // if an untested browser, then use the native method
- if((!(has("mozilla") || isIE || isWK || has("opera")) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
- node.scrollIntoView(false); // short-circuit to native if possible
- return;
- }
- var backCompat = doc.compatMode == 'BackCompat',
- clientAreaRoot = (isIE >= 9 && node.ownerDocument.parentWindow.frameElement)
- ? ((html.clientHeight > 0 && html.clientWidth > 0 && (body.clientHeight == 0 || body.clientWidth == 0 || body.clientHeight > html.clientHeight || body.clientWidth > html.clientWidth)) ? html : body)
- : (backCompat ? body : html),
- scrollRoot = isWK ? body : clientAreaRoot,
- rootWidth = clientAreaRoot.clientWidth,
- rootHeight = clientAreaRoot.clientHeight,
- rtl = !geom.isBodyLtr(),
- nodePos = pos || geom.position(node),
- el = node.parentNode,
- isFixed = function(el){
- return ((isIE <= 6 || (isIE && backCompat))? false : (style.get(el, 'position').toLowerCase() == "fixed"));
- };
- if(isFixed(node)){ return; } // nothing to do
- while(el){
- if(el == body){ el = scrollRoot; }
- var elPos = geom.position(el),
- fixedPos = isFixed(el);
- if(el == scrollRoot){
- elPos.w = rootWidth; elPos.h = rootHeight;
- if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
- if(elPos.x < 0 || !isIE){ elPos.x = 0; } // IE can have values > 0
- if(elPos.y < 0 || !isIE){ elPos.y = 0; }
- }else{
- var pb = geom.getPadBorderExtents(el);
- elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
- var clientSize = el.clientWidth,
- scrollBarSize = elPos.w - clientSize;
- if(clientSize > 0 && scrollBarSize > 0){
- elPos.w = clientSize;
- elPos.x += (rtl && (isIE || el.clientLeft > pb.l/*Chrome*/)) ? scrollBarSize : 0;
- }
- clientSize = el.clientHeight;
- scrollBarSize = elPos.h - clientSize;
- if(clientSize > 0 && scrollBarSize > 0){
- elPos.h = clientSize;
- }
- }
- if(fixedPos){ // bounded by viewport, not parents
- if(elPos.y < 0){
- elPos.h += elPos.y; elPos.y = 0;
- }
- if(elPos.x < 0){
- elPos.w += elPos.x; elPos.x = 0;
- }
- if(elPos.y + elPos.h > rootHeight){
- elPos.h = rootHeight - elPos.y;
- }
- if(elPos.x + elPos.w > rootWidth){
- elPos.w = rootWidth - elPos.x;
- }
- }
- // calculate overflow in all 4 directions
- var l = nodePos.x - elPos.x, // beyond left: < 0
- t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
- r = l + nodePos.w - elPos.w, // beyond right: > 0
- bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
- if(r * l > 0){
- var s = Math[l < 0? "max" : "min"](l, r);
- if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; }
- nodePos.x += el.scrollLeft;
- el.scrollLeft += s;
- nodePos.x -= el.scrollLeft;
- }
- if(bot * t > 0){
- nodePos.y += el.scrollTop;
- el.scrollTop += Math[t < 0? "max" : "min"](t, bot);
- nodePos.y -= el.scrollTop;
- }
- el = (el != scrollRoot) && !fixedPos && el.parentNode;
- }
- }catch(error){
- console.error('scrollIntoView: ' + error);
- node.scrollIntoView(false);
- }
- };
- return window;
- });
- },
- 'dojo/number':function(){
- define("dojo/number", ["./_base/kernel", "./_base/lang", "./i18n", "./i18n!./cldr/nls/number", "./string", "./regexp"],
- function(dojo, lang, i18n, nlsNumber, dstring, dregexp) {
- // module:
- // dojo/number
- // summary:
- // TODOC
- lang.getObject("number", true, dojo);
- /*=====
- dojo.number = {
- // summary: localized formatting and parsing routines for Number
- }
- dojo.number.__FormatOptions = function(){
- // pattern: String?
- // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
- // with this string. Default value is based on locale. Overriding this property will defeat
- // localization. Literal characters in patterns are not supported.
- // type: String?
- // choose a format type based on the locale from the following:
- // decimal, scientific (not yet supported), percent, currency. decimal by default.
- // places: Number?
- // fixed number of decimal places to show. This overrides any
- // information in the provided pattern.
- // round: Number?
- // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
- // means do not round.
- // locale: String?
- // override the locale used to determine formatting rules
- // fractional: Boolean?
- // If false, show no decimal places, overriding places and pattern settings.
- this.pattern = pattern;
- this.type = type;
- this.places = places;
- this.round = round;
- this.locale = locale;
- this.fractional = fractional;
- }
- =====*/
- dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){
- // summary:
- // Format a Number as a String, using locale-specific settings
- // description:
- // Create a string from a Number using a known localized pattern.
- // Formatting patterns appropriate to the locale are chosen from the
- // [Common Locale Data Repository](http://unicode.org/cldr) as well as the appropriate symbols and
- // delimiters.
- // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null.
- // value:
- // the number to be formatted
- options = lang.mixin({}, options || {});
- var locale = i18n.normalizeLocale(options.locale),
- bundle = i18n.getLocalization("dojo.cldr", "number", locale);
- options.customs = bundle;
- var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];
- if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null
- return dojo.number._applyPattern(value, pattern, options); // String
- };
- //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough
- dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough
- dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){
- // summary:
- // Apply pattern to format value as a string using options. Gives no
- // consideration to local customs.
- // value:
- // the number to be formatted.
- // pattern:
- // a pattern string as described by
- // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
- // options: dojo.number.__FormatOptions?
- // _applyPattern is usually called via `dojo.number.format()` which
- // populates an extra property in the options parameter, "customs".
- // The customs object specifies group and decimal parameters if set.
- //TODO: support escapes
- options = options || {};
- var group = options.customs.group,
- decimal = options.customs.decimal,
- patternList = pattern.split(';'),
- positivePattern = patternList[0];
- pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern);
- //TODO: only test against unescaped
- if(pattern.indexOf('%') != -1){
- value *= 100;
- }else if(pattern.indexOf('\u2030') != -1){
- value *= 1000; // per mille
- }else if(pattern.indexOf('\u00a4') != -1){
- group = options.customs.currencyGroup || group;//mixins instead?
- decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead?
- pattern = pattern.replace(/\u00a4{1,3}/, function(match){
- var prop = ["symbol", "currency", "displayName"][match.length-1];
- return options[prop] || options.currency || "";
- });
- }else if(pattern.indexOf('E') != -1){
- throw new Error("exponential notation not supported");
- }
- //TODO: support @ sig figs?
- var numberPatternRE = dojo.number._numberPatternRE;
- var numberPattern = positivePattern.match(numberPatternRE);
- if(!numberPattern){
- throw new Error("unable to find a number expression in pattern: "+pattern);
- }
- if(options.fractional === false){ options.places = 0; }
- return pattern.replace(numberPatternRE,
- dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round}));
- };
- dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){
- // summary:
- // Rounds to the nearest value with the given number of decimal places, away from zero
- // description:
- // Rounds to the nearest value with the given number of decimal places, away from zero if equal.
- // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by
- // fractional increments also, such as the nearest quarter.
- // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround.
- // value:
- // The number to round
- // places:
- // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding.
- // Must be non-negative.
- // increment:
- // Rounds next place to nearest value of increment/10. 10 by default.
- // example:
- // >>> dojo.number.round(-0.5)
- // -1
- // >>> dojo.number.round(162.295, 2)
- // 162.29 // note floating point error. Should be 162.3
- // >>> dojo.number.round(10.71, 0, 2.5)
- // 10.75
- var factor = 10 / (increment || 10);
- return (factor * +value).toFixed(places) / factor; // Number
- };
- if((0.9).toFixed() == 0){
- // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit
- // is just after the rounding place and is >=5
- var round = dojo.number.round;
- dojo.number.round = function(v, p, m){
- var d = Math.pow(10, -p || 0), a = Math.abs(v);
- if(!v || a >= d || a * Math.pow(10, p + 1) < 5){
- d = 0;
- }
- return round(v, p, m) + (v > 0 ? d : -d);
- };
- }
- /*=====
- dojo.number.__FormatAbsoluteOptions = function(){
- // decimal: String?
- // the decimal separator
- // group: String?
- // the group separator
- // places: Number?|String?
- // number of decimal places. the range "n,m" will format to m places.
- // round: Number?
- // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
- // means don't round.
- this.decimal = decimal;
- this.group = group;
- this.places = places;
- this.round = round;
- }
- =====*/
- dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){
- // summary:
- // Apply numeric pattern to absolute value using options. Gives no
- // consideration to local customs.
- // value:
- // the number to be formatted, ignores sign
- // pattern:
- // the number portion of a pattern (e.g. `#,##0.00`)
- options = options || {};
- if(options.places === true){options.places=0;}
- if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit
- var patternParts = pattern.split("."),
- comma = typeof options.places == "string" && options.places.indexOf(","),
- maxPlaces = options.places;
- if(comma){
- maxPlaces = options.places.substring(comma + 1);
- }else if(!(maxPlaces >= 0)){
- maxPlaces = (patternParts[1] || []).length;
- }
- if(!(options.round < 0)){
- value = dojo.number.round(value, maxPlaces, options.round);
- }
- var valueParts = String(Math.abs(value)).split("."),
- fractional = valueParts[1] || "";
- if(patternParts[1] || options.places){
- if(comma){
- options.places = options.places.substring(0, comma);
- }
- // Pad fractional with trailing zeros
- var pad = options.places !== undefined ? options.places : (patternParts[1] && patternParts[1].lastIndexOf("0") + 1);
- if(pad > fractional.length){
- valueParts[1] = dstring.pad(fractional, pad, '0', true);
- }
- // Truncate fractional
- if(maxPlaces < fractional.length){
- valueParts[1] = fractional.substr(0, maxPlaces);
- }
- }else{
- if(valueParts[1]){ valueParts.pop(); }
- }
- // Pad whole with leading zeros
- var patternDigits = patternParts[0].replace(',', '');
- pad = patternDigits.indexOf("0");
- if(pad != -1){
- pad = patternDigits.length - pad;
- if(pad > valueParts[0].length){
- valueParts[0] = dstring.pad(valueParts[0], pad);
- }
- // Truncate whole
- if(patternDigits.indexOf("#") == -1){
- valueParts[0] = valueParts[0].substr(valueParts[0].length - pad);
- }
- }
- // Add group separators
- var index = patternParts[0].lastIndexOf(','),
- groupSize, groupSize2;
- if(index != -1){
- groupSize = patternParts[0].length - index - 1;
- var remainder = patternParts[0].substr(0, index);
- index = remainder.lastIndexOf(',');
- if(index != -1){
- groupSize2 = remainder.length - index - 1;
- }
- }
- var pieces = [];
- for(var whole = valueParts[0]; whole;){
- var off = whole.length - groupSize;
- pieces.push((off > 0) ? whole.substr(off) : whole);
- whole = (off > 0) ? whole.slice(0, off) : "";
- if(groupSize2){
- groupSize = groupSize2;
- delete groupSize2;
- }
- }
- valueParts[0] = pieces.reverse().join(options.group || ",");
- return valueParts.join(options.decimal || ".");
- };
- /*=====
- dojo.number.__RegexpOptions = function(){
- // pattern: String?
- // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
- // with this string. Default value is based on locale. Overriding this property will defeat
- // localization.
- // type: String?
- // choose a format type based on the locale from the following:
- // decimal, scientific (not yet supported), percent, currency. decimal by default.
- // locale: String?
- // override the locale used to determine formatting rules
- // strict: Boolean?
- // strict parsing, false by default. Strict parsing requires input as produced by the format() method.
- // Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
- // places: Number|String?
- // number of decimal places to accept: Infinity, a positive number, or
- // a range "n,m". Defined by pattern or Infinity if pattern not provided.
- this.pattern = pattern;
- this.type = type;
- this.locale = locale;
- this.strict = strict;
- this.places = places;
- }
- =====*/
- dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){
- // summary:
- // Builds the regular needed to parse a number
- // description:
- // Returns regular expression with positive and negative match, group
- // and decimal separators
- return dojo.number._parseInfo(options).regexp; // String
- };
- dojo.number._parseInfo = function(/*Object?*/options){
- options = options || {};
- var locale = i18n.normalizeLocale(options.locale),
- bundle = i18n.getLocalization("dojo.cldr", "number", locale),
- pattern = options.pattern || bundle[(options.type || "decimal") + "Format"],
- //TODO: memoize?
- group = bundle.group,
- decimal = bundle.decimal,
- factor = 1;
- if(pattern.indexOf('%') != -1){
- factor /= 100;
- }else if(pattern.indexOf('\u2030') != -1){
- factor /= 1000; // per mille
- }else{
- var isCurrency = pattern.indexOf('\u00a4') != -1;
- if(isCurrency){
- group = bundle.currencyGroup || group;
- decimal = bundle.currencyDecimal || decimal;
- }
- }
- //TODO: handle quoted escapes
- var patternList = pattern.split(';');
- if(patternList.length == 1){
- patternList.push("-" + patternList[0]);
- }
- var re = dregexp.buildGroupRE(patternList, function(pattern){
- pattern = "(?:"+dregexp.escapeString(pattern, '.')+")";
- return pattern.replace(dojo.number._numberPatternRE, function(format){
- var flags = {
- signed: false,
- separator: options.strict ? group : [group,""],
- fractional: options.fractional,
- decimal: decimal,
- exponent: false
- },
- parts = format.split('.'),
- places = options.places;
- // special condition for percent (factor != 1)
- // allow decimal places even if not specified in pattern
- if(parts.length == 1 && factor != 1){
- parts[1] = "###";
- }
- if(parts.length == 1 || places === 0){
- flags.fractional = false;
- }else{
- if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0') + 1 : Infinity; }
- if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified
- if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; }
- flags.places = places;
- }
- var groups = parts[0].split(',');
- if(groups.length > 1){
- flags.groupSize = groups.pop().length;
- if(groups.length > 1){
- flags.groupSize2 = groups.pop().length;
- }
- }
- return "("+dojo.number._realNumberRegexp(flags)+")";
- });
- }, true);
- if(isCurrency){
- // substitute the currency symbol for the placeholder in the pattern
- re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){
- var prop = ["symbol", "currency", "displayName"][target.length-1],
- symbol = dregexp.escapeString(options[prop] || options.currency || "");
- before = before ? "[\\s\\xa0]" : "";
- after = after ? "[\\s\\xa0]" : "";
- if(!options.strict){
- if(before){before += "*";}
- if(after){after += "*";}
- return "(?:"+before+symbol+after+")?";
- }
- return before+symbol+after;
- });
- }
- //TODO: substitute localized sign/percent/permille/etc.?
- // normalize whitespace and return
- return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object
- };
- /*=====
- dojo.number.__ParseOptions = function(){
- // pattern: String?
- // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
- // with this string. Default value is based on locale. Overriding this property will defeat
- // localization. Literal characters in patterns are not supported.
- // type: String?
- // choose a format type based on the locale from the following:
- // decimal, scientific (not yet supported), percent, currency. decimal by default.
- // locale: String?
- // override the locale used to determine formatting rules
- // strict: Boolean?
- // strict parsing, false by default. Strict parsing requires input as produced by the format() method.
- // Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
- // fractional: Boolean?|Array?
- // Whether to include the fractional portion, where the number of decimal places are implied by pattern
- // or explicit 'places' parameter. The value [true,false] makes the fractional portion optional.
- this.pattern = pattern;
- this.type = type;
- this.locale = locale;
- this.strict = strict;
- this.fractional = fractional;
- }
- =====*/
- dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){
- // summary:
- // Convert a properly formatted string to a primitive Number, using
- // locale-specific settings.
- // description:
- // Create a Number from a string using a known localized pattern.
- // Formatting patterns are chosen appropriate to the locale
- // and follow the syntax described by
- // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
- // Note that literal characters in patterns are not supported.
- // expression:
- // A string representation of a Number
- var info = dojo.number._parseInfo(options),
- results = (new RegExp("^"+info.regexp+"$")).exec(expression);
- if(!results){
- return NaN; //NaN
- }
- var absoluteMatch = results[1]; // match for the positive expression
- if(!results[1]){
- if(!results[2]){
- return NaN; //NaN
- }
- // matched the negative pattern
- absoluteMatch =results[2];
- info.factor *= -1;
- }
- // Transform it to something Javascript can parse as a number. Normalize
- // decimal point and strip out group separators or alternate forms of whitespace
- absoluteMatch = absoluteMatch.
- replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), "").
- replace(info.decimal, ".");
- // Adjust for negative sign, percent, etc. as necessary
- return absoluteMatch * info.factor; //Number
- };
- /*=====
- dojo.number.__RealNumberRegexpFlags = function(){
- // places: Number?
- // The integer number of decimal places or a range given as "n,m". If
- // not given, the decimal part is optional and the number of places is
- // unlimited.
- // decimal: String?
- // A string for the character used as the decimal point. Default
- // is ".".
- // fractional: Boolean?|Array?
- // Whether decimal places are used. Can be true, false, or [true,
- // false]. Default is [true, false] which means optional.
- // exponent: Boolean?|Array?
- // Express in exponential notation. Can be true, false, or [true,
- // false]. Default is [true, false], (i.e. will match if the
- // exponential part is present are not).
- // eSigned: Boolean?|Array?
- // The leading plus-or-minus sign on the exponent. Can be true,
- // false, or [true, false]. Default is [true, false], (i.e. will
- // match if it is signed or unsigned). flags in regexp.integer can be
- // applied.
- this.places = places;
- this.decimal = decimal;
- this.fractional = fractional;
- this.exponent = exponent;
- this.eSigned = eSigned;
- }
- =====*/
- dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){
- // summary:
- // Builds a regular expression to match a real number in exponential
- // notation
- // assign default values to missing parameters
- flags = flags || {};
- //TODO: use mixin instead?
- if(!("places" in flags)){ flags.places = Infinity; }
- if(typeof flags.decimal != "string"){ flags.decimal = "."; }
- if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; }
- if(!("exponent" in flags)){ flags.exponent = [true, false]; }
- if(!("eSigned" in flags)){ flags.eSigned = [true, false]; }
- var integerRE = dojo.number._integerRegexp(flags),
- decimalRE = dregexp.buildGroupRE(flags.fractional,
- function(q){
- var re = "";
- if(q && (flags.places!==0)){
- re = "\\" + flags.decimal;
- if(flags.places == Infinity){
- re = "(?:" + re + "\\d+)?";
- }else{
- re += "\\d{" + flags.places + "}";
- }
- }
- return re;
- },
- true
- );
- var exponentRE = dregexp.buildGroupRE(flags.exponent,
- function(q){
- if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }
- return "";
- }
- );
- var realRE = integerRE + decimalRE;
- // allow for decimals without integers, e.g. .25
- if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";}
- return realRE + exponentRE; // String
- };
- /*=====
- dojo.number.__IntegerRegexpFlags = function(){
- // signed: Boolean?
- // The leading plus-or-minus sign. Can be true, false, or `[true,false]`.
- // Default is `[true, false]`, (i.e. will match if it is signed
- // or unsigned).
- // separator: String?
- // The character used as the thousands separator. Default is no
- // separator. For more than one symbol use an array, e.g. `[",", ""]`,
- // makes ',' optional.
- // groupSize: Number?
- // group size between separators
- // groupSize2: Number?
- // second grouping, where separators 2..n have a different interval than the first separator (for India)
- this.signed = signed;
- this.separator = separator;
- this.groupSize = groupSize;
- this.groupSize2 = groupSize2;
- }
- =====*/
- dojo.number._integerRegexp = function(/*dojo.number.__IntegerRegexpFlags?*/flags){
- // summary:
- // Builds a regular expression that matches an integer
- // assign default values to missing parameters
- flags = flags || {};
- if(!("signed" in flags)){ flags.signed = [true, false]; }
- if(!("separator" in flags)){
- flags.separator = "";
- }else if(!("groupSize" in flags)){
- flags.groupSize = 3;
- }
- var signRE = dregexp.buildGroupRE(flags.signed,
- function(q){ return q ? "[-+]" : ""; },
- true
- );
- var numberRE = dregexp.buildGroupRE(flags.separator,
- function(sep){
- if(!sep){
- return "(?:\\d+)";
- }
- sep = dregexp.escapeString(sep);
- if(sep == " "){ sep = "\\s"; }
- else if(sep == "\xa0"){ sep = "\\s\\xa0"; }
- var grp = flags.groupSize, grp2 = flags.groupSize2;
- //TODO: should we continue to enforce that numbers with separators begin with 1-9? See #6933
- if(grp2){
- var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";
- return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;
- }
- return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)";
- },
- true
- );
- return signRE + numberRE; // String
- };
- return dojo.number;
- });
- },
- 'dojox/timing':function(){
- define("dojox/timing", ["./timing/_base"], function(timing){
- return timing;
- });
- },
- 'dijit/_FocusMixin':function(){
- define("dijit/_FocusMixin", [
- "./focus",
- "./_WidgetBase",
- "dojo/_base/declare", // declare
- "dojo/_base/lang" // lang.extend
- ], function(focus, _WidgetBase, declare, lang){
- /*=====
- var _WidgetBase = dijit._WidgetBase;
- =====*/
- // module:
- // dijit/_FocusMixin
- // summary:
- // Mixin to widget to provide _onFocus() and _onBlur() methods that
- // fire when a widget or it's descendants get/lose focus
- // We don't know where _FocusMixin will occur in the inheritance chain, but we need the _onFocus()/_onBlur() below
- // to be last in the inheritance chain, so mixin to _WidgetBase.
- lang.extend(_WidgetBase, {
- // focused: [readonly] Boolean
- // This widget or a widget it contains has focus, or is "active" because
- // it was recently clicked.
- focused: false,
- onFocus: function(){
- // summary:
- // Called when the widget becomes "active" because
- // it or a widget inside of it either has focus, or has recently
- // been clicked.
- // tags:
- // callback
- },
- onBlur: function(){
- // summary:
- // Called when the widget stops being "active" because
- // focus moved to something outside of it, or the user
- // clicked somewhere outside of it, or the widget was
- // hidden.
- // tags:
- // callback
- },
- _onFocus: function(){
- // summary:
- // This is where widgets do processing for when they are active,
- // such as changing CSS classes. See onFocus() for more details.
- // tags:
- // protected
- this.onFocus();
- },
- _onBlur: function(){
- // summary:
- // This is where widgets do processing for when they stop being active,
- // such as changing CSS classes. See onBlur() for more details.
- // tags:
- // protected
- this.onBlur();
- }
- });
- return declare("dijit._FocusMixin", null, {
- // summary:
- // Mixin to widget to provide _onFocus() and _onBlur() methods that
- // fire when a widget or it's descendants get/lose focus
- // flag that I want _onFocus()/_onBlur() notifications from focus manager
- _focusManager: focus
- });
- });
- },
- 'dojo/data/util/filter':function(){
- define("dojo/data/util/filter", ["dojo/_base/lang"], function(lang) {
- // module:
- // dojo/data/util/filter
- // summary:
- // TODOC
- var filter = lang.getObject("dojo.data.util.filter", true);
- filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){
- // summary:
- // Helper function to convert a simple pattern to a regular expression for matching.
- // description:
- // Returns a regular expression object that conforms to the defined conversion rules.
- // For example:
- // ca* -> /^ca.*$/
- // *ca* -> /^.*ca.*$/
- // *c\*a* -> /^.*c\*a.*$/
- // *c\*a?* -> /^.*c\*a..*$/
- // and so on.
- //
- // pattern: string
- // A simple matching pattern to convert that follows basic rules:
- // * Means match anything, so ca* means match anything starting with ca
- // ? Means match single character. So, b?b will match to bob and bab, and so on.
- // \ is an escape character. So for example, \* means do not treat * as a match, but literal character *.
- // To use a \ as a character in the string, it must be escaped. So in the pattern it should be
- // represented by \\ to be treated as an ordinary \ character instead of an escape.
- //
- // ignoreCase:
- // An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing
- // By default, it is assumed case sensitive.
- var rxp = "^";
- var c = null;
- for(var i = 0; i < pattern.length; i++){
- c = pattern.charAt(i);
- switch(c){
- case '\\':
- rxp += c;
- i++;
- rxp += pattern.charAt(i);
- break;
- case '*':
- rxp += ".*"; break;
- case '?':
- rxp += "."; break;
- case '$':
- case '^':
- case '/':
- case '+':
- case '.':
- case '|':
- case '(':
- case ')':
- case '{':
- case '}':
- case '[':
- case ']':
- rxp += "\\"; //fallthrough
- default:
- rxp += c;
- }
- }
- rxp += "$";
- if(ignoreCase){
- return new RegExp(rxp,"mi"); //RegExp
- }else{
- return new RegExp(rxp,"m"); //RegExp
- }
- };
- return filter;
- });
- },
- 'dijit/_WidgetsInTemplateMixin':function(){
- define("dijit/_WidgetsInTemplateMixin", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/parser", // parser.parse
- "dijit/registry" // registry.findWidgets
- ], function(array, declare, parser, registry){
- // module:
- // dijit/_WidgetsInTemplateMixin
- // summary:
- // Mixin to supplement _TemplatedMixin when template contains widgets
- return declare("dijit._WidgetsInTemplateMixin", null, {
- // summary:
- // Mixin to supplement _TemplatedMixin when template contains widgets
- // _earlyTemplatedStartup: Boolean
- // A fallback to preserve the 1.0 - 1.3 behavior of children in
- // templates having their startup called before the parent widget
- // fires postCreate. Defaults to 'false', causing child widgets to
- // have their .startup() called immediately before a parent widget
- // .startup(), but always after the parent .postCreate(). Set to
- // 'true' to re-enable to previous, arguably broken, behavior.
- _earlyTemplatedStartup: false,
- // widgetsInTemplate: [protected] Boolean
- // Should we parse the template to find widgets that might be
- // declared in markup inside it? (Remove for 2.0 and assume true)
- widgetsInTemplate: true,
- _beforeFillContent: function(){
- if(this.widgetsInTemplate){
- // Before copying over content, instantiate widgets in template
- var node = this.domNode;
- var cw = (this._startupWidgets = parser.parse(node, {
- noStart: !this._earlyTemplatedStartup,
- template: true,
- inherited: {dir: this.dir, lang: this.lang, textDir: this.textDir},
- propsThis: this, // so data-dojo-props of widgets in the template can reference "this" to refer to me
- scope: "dojo" // even in multi-version mode templates use dojoType/data-dojo-type
- }));
- this._supportingWidgets = registry.findWidgets(node);
- this._attachTemplateNodes(cw, function(n,p){
- return n[p];
- });
- }
- },
- startup: function(){
- array.forEach(this._startupWidgets, function(w){
- if(w && !w._started && w.startup){
- w.startup();
- }
- });
- this.inherited(arguments);
- }
- });
- });
- },
- 'dojox/grid/_Builder':function(){
- define("dojox/grid/_Builder", [
- "../main",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/window",
- "dojo/_base/event",
- "dojo/_base/sniff",
- "dojo/_base/connect",
- "dojo/dnd/Moveable",
- "dojox/html/metrics",
- "./util",
- "dojo/_base/html"
- ], function(dojox, array, lang, win, event, has, connect, Moveable, metrics, util, html){
- var dg = dojox.grid;
- var getTdIndex = function(td){
- return td.cellIndex >=0 ? td.cellIndex : array.indexOf(td.parentNode.cells, td);
- };
-
- var getTrIndex = function(tr){
- return tr.rowIndex >=0 ? tr.rowIndex : array.indexOf(tr.parentNode.childNodes, tr);
- };
-
- var getTr = function(rowOwner, index){
- return rowOwner && ((rowOwner.rows||0)[index] || rowOwner.childNodes[index]);
- };
- var findTable = function(node){
- for(var n=node; n && n.tagName!='TABLE'; n=n.parentNode){}
- return n;
- };
-
- var ascendDom = function(inNode, inWhile){
- for(var n=inNode; n && inWhile(n); n=n.parentNode){}
- return n;
- };
-
- var makeNotTagName = function(inTagName){
- var name = inTagName.toUpperCase();
- return function(node){ return node.tagName != name; };
- };
- var rowIndexTag = util.rowIndexTag;
- var gridViewTag = util.gridViewTag;
- // base class for generating markup for the views
- var _Builder = dg._Builder = lang.extend(function(view){
- if(view){
- this.view = view;
- this.grid = view.grid;
- }
- },{
- view: null,
- // boilerplate HTML
- _table: '<table class="dojoxGridRowTable" border="0" cellspacing="0" cellpadding="0" role="presentation"',
- // Returns the table variable as an array - and with the view width, if specified
- getTableArray: function(){
- var html = [this._table];
- if(this.view.viewWidth){
- html.push([' style="width:', this.view.viewWidth, ';"'].join(''));
- }
- html.push('>');
- return html;
- },
-
- // generate starting tags for a cell
- generateCellMarkup: function(inCell, inMoreStyles, inMoreClasses, isHeader){
- var result = [], html;
- if(isHeader){
- var sortInfo = inCell.index != inCell.grid.getSortIndex() ? "" : inCell.grid.sortInfo > 0 ? 'aria-sort="ascending"' : 'aria-sort="descending"';
- if (!inCell.id){
- inCell.id = this.grid.id + "Hdr" + inCell.index;
- }
- // column headers are not editable, mark as aria-readonly=true
- html = ['<th tabIndex="-1" aria-readonly="true" role="columnheader"', sortInfo, 'id="', inCell.id, '"'];
- }else{
- // cells inherit grid aria-readonly property; default value for aria-readonly is false(grid is editable)
- // if grid is editable (had any editable cells), mark non editable cells as aria-readonly=true
- // if no editable cells, grid's aria-readonly value will have been set to true and cells will inherit
- var editInfo = this.grid.editable && !inCell.editable ? 'aria-readonly="true"' : "";
- html = ['<td tabIndex="-1" role="gridcell"', editInfo];
- }
- if(inCell.colSpan){
- html.push(' colspan="', inCell.colSpan, '"');
- }
- if(inCell.rowSpan){
- html.push(' rowspan="', inCell.rowSpan, '"');
- }
- html.push(' class="dojoxGridCell ');
- if(inCell.classes){
- html.push(inCell.classes, ' ');
- }
- if(inMoreClasses){
- html.push(inMoreClasses, ' ');
- }
- // result[0] => td opener, style
- result.push(html.join(''));
- // SLOT: result[1] => td classes
- result.push('');
- html = ['" idx="', inCell.index, '" style="'];
- if(inMoreStyles && inMoreStyles[inMoreStyles.length-1] != ';'){
- inMoreStyles += ';';
- }
- html.push(inCell.styles, inMoreStyles||'', inCell.hidden?'display:none;':'');
- if(inCell.unitWidth){
- html.push('width:', inCell.unitWidth, ';');
- }
- // result[2] => markup
- result.push(html.join(''));
- // SLOT: result[3] => td style
- result.push('');
- html = [ '"' ];
- if(inCell.attrs){
- html.push(" ", inCell.attrs);
- }
- html.push('>');
- // result[4] => td postfix
- result.push(html.join(''));
- // SLOT: result[5] => content
- result.push('');
- // result[6] => td closes
- result.push(isHeader?'</th>':'</td>');
- return result; // Array
- },
- // cell finding
- isCellNode: function(inNode){
- return Boolean(inNode && inNode!=win.doc && html.attr(inNode, "idx"));
- },
-
- getCellNodeIndex: function(inCellNode){
- return inCellNode ? Number(html.attr(inCellNode, "idx")) : -1;
- },
-
- getCellNode: function(inRowNode, inCellIndex){
- for(var i=0, row; ((row = getTr(inRowNode.firstChild, i)) && row.cells); i++){
- for(var j=0, cell; (cell = row.cells[j]); j++){
- if(this.getCellNodeIndex(cell) == inCellIndex){
- return cell;
- }
- }
- }
- return null;
- },
-
- findCellTarget: function(inSourceNode, inTopNode){
- var n = inSourceNode;
- while(n && (!this.isCellNode(n) || (n.offsetParent && gridViewTag in n.offsetParent.parentNode && n.offsetParent.parentNode[gridViewTag] != this.view.id)) && (n!=inTopNode)){
- n = n.parentNode;
- }
- return n!=inTopNode ? n : null;
- },
-
- // event decoration
- baseDecorateEvent: function(e){
- e.dispatch = 'do' + e.type;
- e.grid = this.grid;
- e.sourceView = this.view;
- e.cellNode = this.findCellTarget(e.target, e.rowNode);
- e.cellIndex = this.getCellNodeIndex(e.cellNode);
- e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
- },
-
- // event dispatch
- findTarget: function(inSource, inTag){
- var n = inSource;
- while(n && (n!=this.domNode) && (!(inTag in n) || (gridViewTag in n && n[gridViewTag] != this.view.id))){
- n = n.parentNode;
- }
- return (n != this.domNode) ? n : null;
- },
- findRowTarget: function(inSource){
- return this.findTarget(inSource, rowIndexTag);
- },
- isIntraNodeEvent: function(e){
- try{
- return (e.cellNode && e.relatedTarget && html.isDescendant(e.relatedTarget, e.cellNode));
- }catch(x){
- // e.relatedTarget has permission problem in FF if it's an input: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
- return false;
- }
- },
- isIntraRowEvent: function(e){
- try{
- var row = e.relatedTarget && this.findRowTarget(e.relatedTarget);
- return !row && (e.rowIndex==-1) || row && (e.rowIndex==row.gridRowIndex);
- }catch(x){
- // e.relatedTarget on INPUT has permission problem in FF: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
- return false;
- }
- },
- dispatchEvent: function(e){
- if(e.dispatch in this){
- return this[e.dispatch](e);
- }
- return false;
- },
- // dispatched event handlers
- domouseover: function(e){
- if(e.cellNode && (e.cellNode!=this.lastOverCellNode)){
- this.lastOverCellNode = e.cellNode;
- this.grid.onMouseOver(e);
- }
- this.grid.onMouseOverRow(e);
- },
- domouseout: function(e){
- if(e.cellNode && (e.cellNode==this.lastOverCellNode) && !this.isIntraNodeEvent(e, this.lastOverCellNode)){
- this.lastOverCellNode = null;
- this.grid.onMouseOut(e);
- if(!this.isIntraRowEvent(e)){
- this.grid.onMouseOutRow(e);
- }
- }
- },
-
- domousedown: function(e){
- if (e.cellNode)
- this.grid.onMouseDown(e);
- this.grid.onMouseDownRow(e);
- }
- });
- // Produces html for grid data content. Owned by grid and used internally
- // for rendering data. Override to implement custom rendering.
- var _ContentBuilder = dg._ContentBuilder = lang.extend(function(view){
- _Builder.call(this, view);
- },_Builder.prototype,{
- update: function(){
- this.prepareHtml();
- },
- // cache html for rendering data rows
- prepareHtml: function(){
- var defaultGet=this.grid.get, cells=this.view.structure.cells;
- for(var j=0, row; (row=cells[j]); j++){
- for(var i=0, cell; (cell=row[i]); i++){
- cell.get = cell.get || (cell.value == undefined) && defaultGet;
- cell.markup = this.generateCellMarkup(cell, cell.cellStyles, cell.cellClasses, false);
- if (!this.grid.editable && cell.editable){
- this.grid.editable = true;
- }
- }
- }
- },
- // time critical: generate html using cache and data source
- generateHtml: function(inDataIndex, inRowIndex){
- var
- html = this.getTableArray(),
- v = this.view,
- cells = v.structure.cells,
- item = this.grid.getItem(inRowIndex);
- util.fire(this.view, "onBeforeRow", [inRowIndex, cells]);
- for(var j=0, row; (row=cells[j]); j++){
- if(row.hidden || row.header){
- continue;
- }
- html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
- for(var i=0, cell, m, cc, cs; (cell=row[i]); i++){
- m = cell.markup; cc = cell.customClasses = []; cs = cell.customStyles = [];
- // content (format can fill in cc and cs as side-effects)
- m[5] = cell.format(inRowIndex, item);
- if(has("ie") < 8 && (m[5] === null || m[5] === '' || /^\s+$/.test(m[5]))){
- //fix IE 6/7 quirks - border style not effective for empty td
- m[5] = ' '
- }
- // classes
- m[1] = cc.join(' ');
- // styles
- m[3] = cs.join(';');
- // in-place concat
- html.push.apply(html, m);
- }
- html.push('</tr>');
- }
- html.push('</table>');
- return html.join(''); // String
- },
- decorateEvent: function(e){
- e.rowNode = this.findRowTarget(e.target);
- if(!e.rowNode){return false;}
- e.rowIndex = e.rowNode[rowIndexTag];
- this.baseDecorateEvent(e);
- e.cell = this.grid.getCell(e.cellIndex);
- return true; // Boolean
- }
- });
- // Produces html for grid header content. Owned by grid and used internally
- // for rendering data. Override to implement custom rendering.
- var _HeaderBuilder = dg._HeaderBuilder = lang.extend(function(view){
- this.moveable = null;
- _Builder.call(this, view);
- },_Builder.prototype,{
- _skipBogusClicks: false,
- overResizeWidth: 4,
- minColWidth: 1,
-
- update: function(){
- if(this.tableMap){
- this.tableMap.mapRows(this.view.structure.cells);
- }else{
- this.tableMap = new dg._TableMap(this.view.structure.cells);
- }
- },
- generateHtml: function(inGetValue, inValue){
- var html = this.getTableArray(), cells = this.view.structure.cells;
-
- util.fire(this.view, "onBeforeRow", [-1, cells]);
- for(var j=0, row; (row=cells[j]); j++){
- if(row.hidden){
- continue;
- }
- html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
- for(var i=0, cell, markup; (cell=row[i]); i++){
- cell.customClasses = [];
- cell.customStyles = [];
- if(this.view.simpleStructure){
- if(cell.draggable){
- if(cell.headerClasses){
- if(cell.headerClasses.indexOf('dojoDndItem') == -1){
- cell.headerClasses += ' dojoDndItem';
- }
- }else{
- cell.headerClasses = 'dojoDndItem';
- }
- }
- if(cell.attrs){
- if(cell.attrs.indexOf("dndType='gridColumn_") == -1){
- cell.attrs += " dndType='gridColumn_" + this.grid.id + "'";
- }
- }else{
- cell.attrs = "dndType='gridColumn_" + this.grid.id + "'";
- }
- }
- markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
- // content
- markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
- // styles
- markup[3] = cell.customStyles.join(';');
- // classes
- markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
- html.push(markup.join(''));
- }
- html.push('</tr>');
- }
- html.push('</table>');
- return html.join('');
- },
- // event helpers
- getCellX: function(e){
- var n, x = e.layerX;
- if(has("mozilla") || has("ie") >= 9){
- n = ascendDom(e.target, makeNotTagName("th"));
- x -= (n && n.offsetLeft) || 0;
- var t = e.sourceView.getScrollbarWidth();
- if(!this.grid.isLeftToRight()/*&& e.sourceView.headerNode.scrollLeft < t*/){
- //fix #11253
- table = ascendDom(n,makeNotTagName("table"));
- x -= (table && table.offsetLeft) || 0;
- }
- //x -= getProp(ascendDom(e.target, mkNotTagName("td")), "offsetLeft") || 0;
- }
- n = ascendDom(e.target, function(){
- if(!n || n == e.cellNode){
- return false;
- }
- // Mozilla 1.8 (FF 1.5) has a bug that makes offsetLeft = -parent border width
- // when parent has border, overflow: hidden, and is positioned
- // handle this problem here ... not a general solution!
- x += (n.offsetLeft < 0 ? 0 : n.offsetLeft);
- return true;
- });
- return x;
- },
- // event decoration
- decorateEvent: function(e){
- this.baseDecorateEvent(e);
- e.rowIndex = -1;
- e.cellX = this.getCellX(e);
- return true;
- },
- // event handlers
- // resizing
- prepareResize: function(e, mod){
- do{
- var i = e.cellIndex;
- e.cellNode = (i ? e.cellNode.parentNode.cells[i+mod] : null);
- e.cellIndex = (e.cellNode ? this.getCellNodeIndex(e.cellNode) : -1);
- }while(e.cellNode && e.cellNode.style.display == "none");
- return Boolean(e.cellNode);
- },
- canResize: function(e){
- if(!e.cellNode || e.cellNode.colSpan > 1){
- return false;
- }
- var cell = this.grid.getCell(e.cellIndex);
- return !cell.noresize && cell.canResize();
- },
- overLeftResizeArea: function(e){
- // We are never over a resize area if we are in the process of moving
- if(html.hasClass(win.body(), "dojoDndMove")){
- return false;
- }
- //Bugfix for crazy IE problem (#8807). IE returns position information for the icon and text arrow divs
- //as if they were still on the left instead of returning the position they were 'float: right' to.
- //So, the resize check ends up checking the wrong adjacent cell. This checks to see if the hover was over
- //the image or text nodes, then just ignored them/treat them not in scale range.
- if(has("ie")){
- var tN = e.target;
- if(html.hasClass(tN, "dojoxGridArrowButtonNode") ||
- html.hasClass(tN, "dojoxGridArrowButtonChar") ||
- html.hasClass(tN, "dojoxGridColCaption")){
- return false;
- }
- }
- if(this.grid.isLeftToRight()){
- return (e.cellIndex>0) && (e.cellX > 0 && e.cellX < this.overResizeWidth) && this.prepareResize(e, -1);
- }
- var t = e.cellNode && (e.cellX > 0 && e.cellX < this.overResizeWidth);
- return t;
- },
- overRightResizeArea: function(e){
- // We are never over a resize area if we are in the process of moving
- if(html.hasClass(win.body(), "dojoDndMove")){
- return false;
- }
- //Bugfix for crazy IE problem (#8807). IE returns position information for the icon and text arrow divs
- //as if they were still on the left instead of returning the position they were 'float: right' to.
- //So, the resize check ends up checking the wrong adjacent cell. This checks to see if the hover was over
- //the image or text nodes, then just ignored them/treat them not in scale range.
- if(has("ie")){
- var tN = e.target;
- if(html.hasClass(tN, "dojoxGridArrowButtonNode") ||
- html.hasClass(tN, "dojoxGridArrowButtonChar") ||
- html.hasClass(tN, "dojoxGridColCaption")){
- return false;
- }
- }
- if(this.grid.isLeftToRight()){
- return e.cellNode && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth);
- }
- return (e.cellIndex>0) && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth) && this.prepareResize(e, -1);
- },
- domousemove: function(e){
- //console.log(e.cellIndex, e.cellX, e.cellNode.offsetWidth);
- if(!this.moveable){
- var c = (this.overRightResizeArea(e) ? 'dojoxGridColResize' : (this.overLeftResizeArea(e) ? 'dojoxGridColResize' : ''));
- if(c && !this.canResize(e)){
- c = 'dojoxGridColNoResize';
- }
- html.toggleClass(e.sourceView.headerNode, "dojoxGridColNoResize", (c == "dojoxGridColNoResize"));
- html.toggleClass(e.sourceView.headerNode, "dojoxGridColResize", (c == "dojoxGridColResize"));
- if(c){
- event.stop(e);
- }
- }
- },
- domousedown: function(e){
- if(!this.moveable){
- if((this.overRightResizeArea(e) || this.overLeftResizeArea(e)) && this.canResize(e)){
- this.beginColumnResize(e);
- }else{
- this.grid.onMouseDown(e);
- this.grid.onMouseOverRow(e);
- }
- //else{
- // this.beginMoveColumn(e);
- //}
- }
- },
- doclick: function(e) {
- if(this._skipBogusClicks){
- event.stop(e);
- return true;
- }
- return false;
- },
- // column resizing
- colResizeSetup: function(/*Event Object*/e, /*boolean*/ isMouse ){
- //Set up the drag object for column resizing
- // Called with mouse event in case of drag and drop,
- // Also called from keyboard shift-arrow event when focus is on a header
- var headContentBox = html.contentBox(e.sourceView.headerNode);
-
- if(isMouse){ //IE draws line even with no mouse down so separate from keyboard
- this.lineDiv = document.createElement('div');
- var vw = html.position(e.sourceView.headerNode, true);
- var bodyContentBox = html.contentBox(e.sourceView.domNode);
- //fix #11340
- var l = e.pageX;
- if(!this.grid.isLeftToRight() && has("ie") < 8){
- l -= metrics.getScrollbar().w;
- }
- html.style(this.lineDiv, {
- top: vw.y + "px",
- left: l + "px",
- height: (bodyContentBox.h + headContentBox.h) + "px"
- });
- html.addClass(this.lineDiv, "dojoxGridResizeColLine");
- this.lineDiv._origLeft = l;
- win.body().appendChild(this.lineDiv);
- }
- var spanners = [], nodes = this.tableMap.findOverlappingNodes(e.cellNode);
- for(var i=0, cell; (cell=nodes[i]); i++){
- spanners.push({ node: cell, index: this.getCellNodeIndex(cell), width: cell.offsetWidth });
- //console.log("spanner: " + this.getCellNodeIndex(cell));
- }
- var view = e.sourceView;
- var adj = this.grid.isLeftToRight() ? 1 : -1;
- var views = e.grid.views.views;
- var followers = [];
- for(var j=view.idx+adj, cView; (cView=views[j]); j=j+adj){
- followers.push({ node: cView.headerNode, left: window.parseInt(cView.headerNode.style.left) });
- }
- var table = view.headerContentNode.firstChild;
- var drag = {
- scrollLeft: e.sourceView.headerNode.scrollLeft,
- view: view,
- node: e.cellNode,
- index: e.cellIndex,
- w: html.contentBox(e.cellNode).w,
- vw: headContentBox.w,
- table: table,
- tw: html.contentBox(table).w,
- spanners: spanners,
- followers: followers
- };
- return drag;
- },
- beginColumnResize: function(e){
- this.moverDiv = document.createElement("div");
- html.style(this.moverDiv,{position: "absolute", left:0}); // to make DnD work with dir=rtl
- win.body().appendChild(this.moverDiv);
- html.addClass(this.grid.domNode, "dojoxGridColumnResizing");
- var m = (this.moveable = new Moveable(this.moverDiv));
- var drag = this.colResizeSetup(e,true);
- m.onMove = lang.hitch(this, "doResizeColumn", drag);
- connect.connect(m, "onMoveStop", lang.hitch(this, function(){
- this.endResizeColumn(drag);
- if(drag.node.releaseCapture){
- drag.node.releaseCapture();
- }
- this.moveable.destroy();
- delete this.moveable;
- this.moveable = null;
- html.removeClass(this.grid.domNode, "dojoxGridColumnResizing");
- }));
- if(e.cellNode.setCapture){
- e.cellNode.setCapture();
- }
- m.onMouseDown(e);
- },
- doResizeColumn: function(inDrag, mover, leftTop){
- var changeX = leftTop.l;
- var data = {
- deltaX: changeX,
- w: inDrag.w + (this.grid.isLeftToRight() ? changeX : -changeX),//fix #11341
- vw: inDrag.vw + changeX,
- tw: inDrag.tw + changeX
- };
-
- this.dragRecord = {inDrag: inDrag, mover: mover, leftTop:leftTop};
-
- if(data.w >= this.minColWidth){
- if (!mover) { // we are using keyboard do immediate resize
- this.doResizeNow(inDrag, data);
- }
- else{
- html.style(this.lineDiv, "left", (this.lineDiv._origLeft + data.deltaX) + "px");
- }
- }
- },
- endResizeColumn: function(inDrag){
- if(this.dragRecord){
- var leftTop = this.dragRecord.leftTop;
- var changeX = this.grid.isLeftToRight() ? leftTop.l : -leftTop.l;
- // Make sure we are not under our minimum
- // http://bugs.dojotoolkit.org/ticket/9390
- changeX += Math.max(inDrag.w + changeX, this.minColWidth) - (inDrag.w + changeX);
- if(has("webkit") && inDrag.spanners.length){
- // Webkit needs the pad border extents back in
- changeX += html._getPadBorderExtents(inDrag.spanners[0].node).w;
- }
- var data = {
- deltaX: changeX,
- w: inDrag.w + changeX,
- vw: inDrag.vw + changeX,
- tw: inDrag.tw + changeX
- };
- // Only resize the columns when the drag has finished
- this.doResizeNow(inDrag, data);
- delete this.dragRecord;
- }
-
- html.destroy(this.lineDiv);
- html.destroy(this.moverDiv);
- html.destroy(this.moverDiv);
- delete this.moverDiv;
- this._skipBogusClicks = true;
- inDrag.view.update();
- this._skipBogusClicks = false;
- this.grid.onResizeColumn(inDrag.index);
- },
- doResizeNow: function(inDrag, data){
- inDrag.view.convertColPctToFixed();
- if(inDrag.view.flexCells && !inDrag.view.testFlexCells()){
- var t = findTable(inDrag.node);
- if(t){
- (t.style.width = '');
- }
- }
- var i, s, sw, f, fl;
- for(i=0; (s=inDrag.spanners[i]); i++){
- sw = s.width + data.deltaX;
- if(sw > 0){
- s.node.style.width = sw + 'px';
- inDrag.view.setColWidth(s.index, sw);
- }
- }
- if(this.grid.isLeftToRight() || !has("ie")){//fix #11339
- for(i=0; (f=inDrag.followers[i]); i++){
- fl = f.left + data.deltaX;
- f.node.style.left = fl + 'px';
- }
- }
- inDrag.node.style.width = data.w + 'px';
- inDrag.view.setColWidth(inDrag.index, data.w);
- inDrag.view.headerNode.style.width = data.vw + 'px';
- inDrag.view.setColumnsWidth(data.tw);
- if(!this.grid.isLeftToRight()){
- inDrag.view.headerNode.scrollLeft = inDrag.scrollLeft + data.deltaX;
- }
- }
- });
- // Maps an html table into a structure parsable for information about cell row and col spanning.
- // Used by HeaderBuilder.
- dg._TableMap = lang.extend(function(rows){
- this.mapRows(rows);
- },{
- map: null,
- mapRows: function(inRows){
- // summary: Map table topography
- //console.log('mapRows');
- // # of rows
- var rowCount = inRows.length;
- if(!rowCount){
- return;
- }
- // map which columns and rows fill which cells
- this.map = [];
- var row;
- for(var k=0; (row=inRows[k]); k++){
- this.map[k] = [];
- }
- for(var j=0; (row=inRows[j]); j++){
- for(var i=0, x=0, cell, colSpan, rowSpan; (cell=row[i]); i++){
- while(this.map[j][x]){x++;}
- this.map[j][x] = { c: i, r: j };
- rowSpan = cell.rowSpan || 1;
- colSpan = cell.colSpan || 1;
- for(var y=0; y<rowSpan; y++){
- for(var s=0; s<colSpan; s++){
- this.map[j+y][x+s] = this.map[j][x];
- }
- }
- x += colSpan;
- }
- }
- //this.dumMap();
- },
- dumpMap: function(){
- for(var j=0, row, h=''; (row=this.map[j]); j++,h=''){
- for(var i=0, cell; (cell=row[i]); i++){
- h += cell.r + ',' + cell.c + ' ';
- }
- }
- },
- getMapCoords: function(inRow, inCol){
- // summary: Find node's map coords by it's structure coords
- for(var j=0, row; (row=this.map[j]); j++){
- for(var i=0, cell; (cell=row[i]); i++){
- if(cell.c==inCol && cell.r == inRow){
- return { j: j, i: i };
- }
- //else{console.log(inRow, inCol, ' : ', i, j, " : ", cell.r, cell.c); };
- }
- }
- return { j: -1, i: -1 };
- },
-
- getNode: function(inTable, inRow, inCol){
- // summary: Find a node in inNode's table with the given structure coords
- var row = inTable && inTable.rows[inRow];
- return row && row.cells[inCol];
- },
-
- _findOverlappingNodes: function(inTable, inRow, inCol){
- var nodes = [];
- var m = this.getMapCoords(inRow, inCol);
- //console.log("node j: %d, i: %d", m.j, m.i);
- for(var j=0, row; (row=this.map[j]); j++){
- if(j == m.j){ continue; }
- var rw = row[m.i];
- //console.log("overlaps: r: %d, c: %d", rw.r, rw.c);
- var n = (rw?this.getNode(inTable, rw.r, rw.c):null);
- if(n){ nodes.push(n); }
- }
- //console.log(nodes);
- return nodes;
- },
-
- findOverlappingNodes: function(inNode){
- return this._findOverlappingNodes(findTable(inNode), getTrIndex(inNode.parentNode), getTdIndex(inNode));
- }
- });
- return {
- _Builder: _Builder,
- _HeaderBuilder: _HeaderBuilder,
- _ContentBuilder: _ContentBuilder
- };
- });
- },
- 'dojox/grid/_EditManager':function(){
- define("dojox/grid/_EditManager", [
- "dojo/_base/lang",
- "dojo/_base/array",
- "dojo/_base/declare",
- "dojo/_base/connect",
- "dojo/_base/sniff",
- "./util"
- ], function(lang, array, declare, connect, has, util){
- return declare("dojox.grid._EditManager", null, {
- // summary:
- // Controls grid cell editing process. Owned by grid and used internally for editing.
- constructor: function(inGrid){
- // inGrid: dojox.Grid
- // The dojox.Grid this editor should be attached to
- this.grid = inGrid;
- if(has("ie")){
- this.connections = [connect.connect(document.body, "onfocus", lang.hitch(this, "_boomerangFocus"))];
- }else{
- this.connections = [connect.connect(this.grid, 'onBlur', this, 'apply')];
- }
- },
-
- info: {},
- destroy: function(){
- array.forEach(this.connections, connect.disconnect);
- },
- cellFocus: function(inCell, inRowIndex){
- // summary:
- // Invoke editing when cell is focused
- // inCell: cell object
- // Grid cell object
- // inRowIndex: Integer
- // Grid row index
- if(this.grid.singleClickEdit || this.isEditRow(inRowIndex)){
- // if same row or quick editing, edit
- this.setEditCell(inCell, inRowIndex);
- }else{
- // otherwise, apply any pending row edits
- this.apply();
- }
- // if dynamic or static editing...
- if(this.isEditing() || (inCell && inCell.editable && inCell.alwaysEditing)){
- // let the editor focus itself as needed
- this._focusEditor(inCell, inRowIndex);
- }
- },
- rowClick: function(e){
- if(this.isEditing() && !this.isEditRow(e.rowIndex)){
- this.apply();
- }
- },
- styleRow: function(inRow){
- if(inRow.index == this.info.rowIndex){
- inRow.customClasses += ' dojoxGridRowEditing';
- }
- },
- dispatchEvent: function(e){
- var c = e.cell, ed = (c && c["editable"]) ? c : 0;
- return ed && ed.dispatchEvent(e.dispatch, e);
- },
- // Editing
- isEditing: function(){
- // summary:
- // Indicates editing state of the grid.
- // returns: Boolean
- // True if grid is actively editing
- return this.info.rowIndex !== undefined;
- },
- isEditCell: function(inRowIndex, inCellIndex){
- // summary:
- // Indicates if the given cell is being edited.
- // inRowIndex: Integer
- // Grid row index
- // inCellIndex: Integer
- // Grid cell index
- // returns: Boolean
- // True if given cell is being edited
- return (this.info.rowIndex === inRowIndex) && (this.info.cell.index == inCellIndex);
- },
- isEditRow: function(inRowIndex){
- // summary:
- // Indicates if the given row is being edited.
- // inRowIndex: Integer
- // Grid row index
- // returns: Boolean
- // True if given row is being edited
- return this.info.rowIndex === inRowIndex;
- },
- setEditCell: function(inCell, inRowIndex){
- // summary:
- // Set the given cell to be edited
- // inRowIndex: Integer
- // Grid row index
- // inCell: Object
- // Grid cell object
- if(!this.isEditCell(inRowIndex, inCell.index) && this.grid.canEdit && this.grid.canEdit(inCell, inRowIndex)){
- this.start(inCell, inRowIndex, this.isEditRow(inRowIndex) || inCell.editable);
- }
- },
- _focusEditor: function(inCell, inRowIndex){
- util.fire(inCell, "focus", [inRowIndex]);
- },
- focusEditor: function(){
- if(this.isEditing()){
- this._focusEditor(this.info.cell, this.info.rowIndex);
- }
- },
- // implement fix for focus boomerang effect on IE
- _boomerangWindow: 500,
- _shouldCatchBoomerang: function(){
- return this._catchBoomerang > new Date().getTime();
- },
- _boomerangFocus: function(){
- //console.log("_boomerangFocus");
- if(this._shouldCatchBoomerang()){
- // make sure we don't utterly lose focus
- this.grid.focus.focusGrid();
- // let the editor focus itself as needed
- this.focusEditor();
- // only catch once
- this._catchBoomerang = 0;
- }
- },
- _doCatchBoomerang: function(){
- // give ourselves a few ms to boomerang IE focus effects
- if(has("ie")){this._catchBoomerang = new Date().getTime() + this._boomerangWindow;}
- },
- // end boomerang fix API
- start: function(inCell, inRowIndex, inEditing){
- if(!this._isValidInput()){
- return;
- }
- this.grid.beginUpdate();
- this.editorApply();
- if(this.isEditing() && !this.isEditRow(inRowIndex)){
- this.applyRowEdit();
- this.grid.updateRow(inRowIndex);
- }
- if(inEditing){
- this.info = { cell: inCell, rowIndex: inRowIndex };
- this.grid.doStartEdit(inCell, inRowIndex);
- this.grid.updateRow(inRowIndex);
- }else{
- this.info = {};
- }
- this.grid.endUpdate();
- // make sure we don't utterly lose focus
- this.grid.focus.focusGrid();
- // let the editor focus itself as needed
- this._focusEditor(inCell, inRowIndex);
- // give ourselves a few ms to boomerang IE focus effects
- this._doCatchBoomerang();
- },
- _editorDo: function(inMethod){
- var c = this.info.cell;
- //c && c.editor && c.editor[inMethod](c, this.info.rowIndex);
- if(c && c.editable){
- c[inMethod](this.info.rowIndex);
- }
- },
- editorApply: function(){
- this._editorDo("apply");
- },
- editorCancel: function(){
- this._editorDo("cancel");
- },
- applyCellEdit: function(inValue, inCell, inRowIndex){
- if(this.grid.canEdit(inCell, inRowIndex)){
- this.grid.doApplyCellEdit(inValue, inRowIndex, inCell.field);
- }
- },
- applyRowEdit: function(){
- this.grid.doApplyEdit(this.info.rowIndex, this.info.cell.field);
- },
- apply: function(){
- // summary:
- // Apply a grid edit
- if(this.isEditing() && this._isValidInput()){
- this.grid.beginUpdate();
- this.editorApply();
- this.applyRowEdit();
- this.info = {};
- this.grid.endUpdate();
- this.grid.focus.focusGrid();
- this._doCatchBoomerang();
- }
- },
- cancel: function(){
- // summary:
- // Cancel a grid edit
- if(this.isEditing()){
- this.grid.beginUpdate();
- this.editorCancel();
- this.info = {};
- this.grid.endUpdate();
- this.grid.focus.focusGrid();
- this._doCatchBoomerang();
- }
- },
- save: function(inRowIndex, inView){
- // summary:
- // Save the grid editing state
- // inRowIndex: Integer
- // Grid row index
- // inView: Object
- // Grid view
- var c = this.info.cell;
- if(this.isEditRow(inRowIndex) && (!inView || c.view==inView) && c.editable){
- c.save(c, this.info.rowIndex);
- }
- },
- restore: function(inView, inRowIndex){
- // summary:
- // Restores the grid editing state
- // inRowIndex: Integer
- // Grid row index
- // inView: Object
- // Grid view
- var c = this.info.cell;
- if(this.isEditRow(inRowIndex) && c.view == inView && c.editable){
- c.restore(this.info.rowIndex);
- }
- },
-
- _isValidInput: function(){
- var w = (this.info.cell || {}).widget;
- if(!w || !w.isValid){
- //no validation needed
- return true;
- }
- w.focused = true;
- return w.isValid(true);
- }
- });
- });
- },
- 'dojo/data/util/sorter':function(){
- define("dojo/data/util/sorter", ["dojo/_base/lang"], function(lang) {
- // module:
- // dojo/data/util/sorter
- // summary:
- // TODOC
- var sorter = lang.getObject("dojo.data.util.sorter", true);
- sorter.basicComparator = function( /*anything*/ a,
- /*anything*/ b){
- // summary:
- // Basic comparision function that compares if an item is greater or less than another item
- // description:
- // returns 1 if a > b, -1 if a < b, 0 if equal.
- // 'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list.
- // And compared to each other, null is equivalent to undefined.
- //null is a problematic compare, so if null, we set to undefined.
- //Makes the check logic simple, compact, and consistent
- //And (null == undefined) === true, so the check later against null
- //works for undefined and is less bytes.
- var r = -1;
- if(a === null){
- a = undefined;
- }
- if(b === null){
- b = undefined;
- }
- if(a == b){
- r = 0;
- }else if(a > b || a == null){
- r = 1;
- }
- return r; //int {-1,0,1}
- };
- sorter.createSortFunction = function( /* attributes array */sortSpec, /*dojo.data.core.Read*/ store){
- // summary:
- // Helper function to generate the sorting function based off the list of sort attributes.
- // description:
- // The sort function creation will look for a property on the store called 'comparatorMap'. If it exists
- // it will look in the mapping for comparisons function for the attributes. If one is found, it will
- // use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates.
- // Returns the sorting function for this particular list of attributes and sorting directions.
- //
- // sortSpec: array
- // A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending.
- // The objects should be formatted as follows:
- // {
- // attribute: "attributeName-string" || attribute,
- // descending: true|false; // Default is false.
- // }
- // store: object
- // The datastore object to look up item values from.
- //
- var sortFunctions=[];
- function createSortFunction(attr, dir, comp, s){
- //Passing in comp and s (comparator and store), makes this
- //function much faster.
- return function(itemA, itemB){
- var a = s.getValue(itemA, attr);
- var b = s.getValue(itemB, attr);
- return dir * comp(a,b); //int
- };
- }
- var sortAttribute;
- var map = store.comparatorMap;
- var bc = sorter.basicComparator;
- for(var i = 0; i < sortSpec.length; i++){
- sortAttribute = sortSpec[i];
- var attr = sortAttribute.attribute;
- if(attr){
- var dir = (sortAttribute.descending) ? -1 : 1;
- var comp = bc;
- if(map){
- if(typeof attr !== "string" && ("toString" in attr)){
- attr = attr.toString();
- }
- comp = map[attr] || bc;
- }
- sortFunctions.push(createSortFunction(attr,
- dir, comp, store));
- }
- }
- return function(rowA, rowB){
- var i=0;
- while(i < sortFunctions.length){
- var ret = sortFunctions[i++](rowA, rowB);
- if(ret !== 0){
- return ret;//int
- }
- }
- return 0; //int
- }; // Function
- };
- return sorter;
- });
- },
- 'dijit/form/_ButtonMixin':function(){
- define("dijit/form/_ButtonMixin", [
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.setSelectable
- "dojo/_base/event", // event.stop
- "../registry" // registry.byNode
- ], function(declare, dom, event, registry){
- // module:
- // dijit/form/_ButtonMixin
- // summary:
- // A mixin to add a thin standard API wrapper to a normal HTML button
- return declare("dijit.form._ButtonMixin", null, {
- // summary:
- // A mixin to add a thin standard API wrapper to a normal HTML button
- // description:
- // A label should always be specified (through innerHTML) or the label attribute.
- // Attach points:
- // focusNode (required): this node receives focus
- // valueNode (optional): this node's value gets submitted with FORM elements
- // containerNode (optional): this node gets the innerHTML assignment for label
- // example:
- // | <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
- //
- // example:
- // | var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
- // | dojo.body().appendChild(button1.domNode);
- // label: HTML String
- // Content to display in button.
- label: "",
- // type: [const] String
- // Type of button (submit, reset, button, checkbox, radio)
- type: "button",
- _onClick: function(/*Event*/ e){
- // summary:
- // Internal function to handle click actions
- if(this.disabled){
- event.stop(e);
- return false;
- }
- var preventDefault = this.onClick(e) === false; // user click actions
- if(!preventDefault && this.type == "submit" && !(this.valueNode||this.focusNode).form){ // see if a non-form widget needs to be signalled
- for(var node=this.domNode; node.parentNode; node=node.parentNode){
- var widget=registry.byNode(node);
- if(widget && typeof widget._onSubmit == "function"){
- widget._onSubmit(e);
- preventDefault = true;
- break;
- }
- }
- }
- if(preventDefault){
- e.preventDefault();
- }
- return !preventDefault;
- },
- postCreate: function(){
- this.inherited(arguments);
- dom.setSelectable(this.focusNode, false);
- },
- onClick: function(/*Event*/ /*===== e =====*/){
- // summary:
- // Callback for when button is clicked.
- // If type="submit", return true to perform submit, or false to cancel it.
- // type:
- // callback
- return true; // Boolean
- },
- _setLabelAttr: function(/*String*/ content){
- // summary:
- // Hook for set('label', ...) to work.
- // description:
- // Set the label (text) of the button; takes an HTML string.
- this._set("label", content);
- (this.containerNode||this.focusNode).innerHTML = content;
- }
- });
- });
- },
- 'url:dijit/form/templates/Spinner.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\" role=\"presentation\"\r\n\t><div class=\"dijitReset dijitButtonNode dijitSpinnerButtonContainer\"\r\n\t\t><input class=\"dijitReset dijitInputField dijitSpinnerButtonInner\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t/><div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton\"\r\n\t\t\tdata-dojo-attach-point=\"upArrowNode\"\r\n\t\t\t><div class=\"dijitArrowButtonInner\"\r\n\t\t\t\t><input class=\"dijitReset dijitInputField\" value=\"▲\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t\t\t${_buttonInputDisabled}\r\n\t\t\t/></div\r\n\t\t></div\r\n\t\t><div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton\"\r\n\t\t\tdata-dojo-attach-point=\"downArrowNode\"\r\n\t\t\t><div class=\"dijitArrowButtonInner\"\r\n\t\t\t\t><input class=\"dijitReset dijitInputField\" value=\"▼\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t\t\t${_buttonInputDisabled}\r\n\t\t\t/></div\r\n\t\t></div\r\n\t></div\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ\" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class='dijitReset dijitInputInner' data-dojo-attach-point=\"textbox,focusNode\" type=\"${type}\" data-dojo-attach-event=\"onkeypress:_onKeyPress\"\r\n\t\t\trole=\"spinbutton\" autocomplete=\"off\" ${!nameAttrSetting}\r\n\t/></div\r\n></div>\r\n",
- 'dijit/registry':function(){
- define("dijit/registry", [
- "dojo/_base/array", // array.forEach array.map
- "dojo/_base/sniff", // has("ie")
- "dojo/_base/unload", // unload.addOnWindowUnload
- "dojo/_base/window", // win.body
- "." // dijit._scopeName
- ], function(array, has, unload, win, dijit){
- // module:
- // dijit/registry
- // summary:
- // Registry of existing widget on page, plus some utility methods.
- // Must be accessed through AMD api, ex:
- // require(["dijit/registry"], function(registry){ registry.byId("foo"); })
- var _widgetTypeCtr = {}, hash = {};
- var registry = {
- // summary:
- // A set of widgets indexed by id
- length: 0,
- add: function(/*dijit._Widget*/ widget){
- // summary:
- // Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
- //
- // widget: dijit._Widget
- // Any dijit._Widget subclass.
- if(hash[widget.id]){
- throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
- }
- hash[widget.id] = widget;
- this.length++;
- },
- remove: function(/*String*/ id){
- // summary:
- // Remove a widget from the registry. Does not destroy the widget; simply
- // removes the reference.
- if(hash[id]){
- delete hash[id];
- this.length--;
- }
- },
- byId: function(/*String|Widget*/ id){
- // summary:
- // Find a widget by it's id.
- // If passed a widget then just returns the widget.
- return typeof id == "string" ? hash[id] : id; // dijit._Widget
- },
- byNode: function(/*DOMNode*/ node){
- // summary:
- // Returns the widget corresponding to the given DOMNode
- return hash[node.getAttribute("widgetId")]; // dijit._Widget
- },
- toArray: function(){
- // summary:
- // Convert registry into a true Array
- //
- // example:
- // Work with the widget .domNodes in a real Array
- // | array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
- var ar = [];
- for(var id in hash){
- ar.push(hash[id]);
- }
- return ar; // dijit._Widget[]
- },
- getUniqueId: function(/*String*/widgetType){
- // summary:
- // Generates a unique id for a given widgetType
- var id;
- do{
- id = widgetType + "_" +
- (widgetType in _widgetTypeCtr ?
- ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
- }while(hash[id]);
- return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
- },
- findWidgets: function(/*DomNode*/ root){
- // summary:
- // Search subtree under root returning widgets found.
- // Doesn't search for nested widgets (ie, widgets inside other widgets).
- var outAry = [];
- function getChildrenHelper(root){
- for(var node = root.firstChild; node; node = node.nextSibling){
- if(node.nodeType == 1){
- var widgetId = node.getAttribute("widgetId");
- if(widgetId){
- var widget = hash[widgetId];
- if(widget){ // may be null on page w/multiple dojo's loaded
- outAry.push(widget);
- }
- }else{
- getChildrenHelper(node);
- }
- }
- }
- }
- getChildrenHelper(root);
- return outAry;
- },
- _destroyAll: function(){
- // summary:
- // Code to destroy all widgets and do other cleanup on page unload
- // Clean up focus manager lingering references to widgets and nodes
- dijit._curFocus = null;
- dijit._prevFocus = null;
- dijit._activeStack = [];
- // Destroy all the widgets, top down
- array.forEach(registry.findWidgets(win.body()), function(widget){
- // Avoid double destroy of widgets like Menu that are attached to <body>
- // even though they are logically children of other widgets.
- if(!widget._destroyed){
- if(widget.destroyRecursive){
- widget.destroyRecursive();
- }else if(widget.destroy){
- widget.destroy();
- }
- }
- });
- },
- getEnclosingWidget: function(/*DOMNode*/ node){
- // summary:
- // Returns the widget whose DOM tree contains the specified DOMNode, or null if
- // the node is not contained within the DOM tree of any widget
- while(node){
- var id = node.getAttribute && node.getAttribute("widgetId");
- if(id){
- return hash[id];
- }
- node = node.parentNode;
- }
- return null;
- },
- // In case someone needs to access hash.
- // Actually, this is accessed from WidgetSet back-compatibility code
- _hash: hash
- };
- /*=====
- dijit.registry = {
- // summary:
- // A list of widgets on a page.
- };
- =====*/
- dijit.registry = registry;
- return registry;
- });
- },
- 'dojo/date/locale':function(){
- define("dojo/date/locale", [
- "../_base/kernel",
- "../_base/lang",
- "../_base/array",
- "../date",
- "../cldr/supplemental",
- "../regexp",
- "../string",
- "../i18n!../cldr/nls/gregorian"
- ], function(dojo, lang, array, date, cldr, regexp, string, gregorian) {
- // module:
- // dojo/date/locale
- // summary:
- // This modules defines dojo.date.locale, localization methods for Date.
- lang.getObject("date.locale", true, dojo);
- // Localization methods for Date. Honor local customs using locale-dependent dojo.cldr data.
- // Load the bundles containing localization information for
- // names and formats
- //NOTE: Everything in this module assumes Gregorian calendars.
- // Other calendars will be implemented in separate modules.
- // Format a pattern without literals
- function formatPattern(dateObject, bundle, options, pattern){
- return pattern.replace(/([a-z])\1*/ig, function(match){
- var s, pad,
- c = match.charAt(0),
- l = match.length,
- widthList = ["abbr", "wide", "narrow"];
- switch(c){
- case 'G':
- s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1];
- break;
- case 'y':
- s = dateObject.getFullYear();
- switch(l){
- case 1:
- break;
- case 2:
- if(!options.fullYear){
- s = String(s); s = s.substr(s.length - 2);
- break;
- }
- // fallthrough
- default:
- pad = true;
- }
- break;
- case 'Q':
- case 'q':
- s = Math.ceil((dateObject.getMonth()+1)/3);
- // switch(l){
- // case 1: case 2:
- pad = true;
- // break;
- // case 3: case 4: // unimplemented
- // }
- break;
- case 'M':
- var m = dateObject.getMonth();
- if(l<3){
- s = m+1; pad = true;
- }else{
- var propM = ["months", "format", widthList[l-3]].join("-");
- s = bundle[propM][m];
- }
- break;
- case 'w':
- var firstDay = 0;
- s = dojo.date.locale._getWeekOfYear(dateObject, firstDay); pad = true;
- break;
- case 'd':
- s = dateObject.getDate(); pad = true;
- break;
- case 'D':
- s = dojo.date.locale._getDayOfYear(dateObject); pad = true;
- break;
- case 'E':
- var d = dateObject.getDay();
- if(l<3){
- s = d+1; pad = true;
- }else{
- var propD = ["days", "format", widthList[l-3]].join("-");
- s = bundle[propD][d];
- }
- break;
- case 'a':
- var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm';
- s = options[timePeriod] || bundle['dayPeriods-format-wide-' + timePeriod];
- break;
- case 'h':
- case 'H':
- case 'K':
- case 'k':
- var h = dateObject.getHours();
- // strange choices in the date format make it impossible to write this succinctly
- switch (c){
- case 'h': // 1-12
- s = (h % 12) || 12;
- break;
- case 'H': // 0-23
- s = h;
- break;
- case 'K': // 0-11
- s = (h % 12);
- break;
- case 'k': // 1-24
- s = h || 24;
- break;
- }
- pad = true;
- break;
- case 'm':
- s = dateObject.getMinutes(); pad = true;
- break;
- case 's':
- s = dateObject.getSeconds(); pad = true;
- break;
- case 'S':
- s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true;
- break;
- case 'v': // FIXME: don't know what this is. seems to be same as z?
- case 'z':
- // We only have one timezone to offer; the one from the browser
- s = dojo.date.locale._getZone(dateObject, true, options);
- if(s){break;}
- l=4;
- // fallthrough... use GMT if tz not available
- case 'Z':
- var offset = dojo.date.locale._getZone(dateObject, false, options);
- var tz = [
- (offset<=0 ? "+" : "-"),
- string.pad(Math.floor(Math.abs(offset)/60), 2),
- string.pad(Math.abs(offset)% 60, 2)
- ];
- if(l==4){
- tz.splice(0, 0, "GMT");
- tz.splice(3, 0, ":");
- }
- s = tz.join("");
- break;
- // case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A': case 'e':
- // console.log(match+" modifier unimplemented");
- default:
- throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern);
- }
- if(pad){ s = string.pad(s, l); }
- return s;
- });
- }
- /*=====
- dojo.date.locale.__FormatOptions = function(){
- // selector: String
- // choice of 'time','date' (default: date and time)
- // formatLength: String
- // choice of long, short, medium or full (plus any custom additions). Defaults to 'short'
- // datePattern:String
- // override pattern with this string
- // timePattern:String
- // override pattern with this string
- // am: String
- // override strings for am in times
- // pm: String
- // override strings for pm in times
- // locale: String
- // override the locale used to determine formatting rules
- // fullYear: Boolean
- // (format only) use 4 digit years whenever 2 digit years are called for
- // strict: Boolean
- // (parse only) strict parsing, off by default
- this.selector = selector;
- this.formatLength = formatLength;
- this.datePattern = datePattern;
- this.timePattern = timePattern;
- this.am = am;
- this.pm = pm;
- this.locale = locale;
- this.fullYear = fullYear;
- this.strict = strict;
- }
- =====*/
- dojo.date.locale._getZone = function(/*Date*/dateObject, /*boolean*/getName, /*dojo.date.locale.__FormatOptions?*/options){
- // summary:
- // Returns the zone (or offset) for the given date and options. This
- // is broken out into a separate function so that it can be overridden
- // by timezone-aware code.
- //
- // dateObject:
- // the date and/or time being formatted.
- //
- // getName:
- // Whether to return the timezone string (if true), or the offset (if false)
- //
- // options:
- // The options being used for formatting
- if(getName){
- return date.getTimezoneName(dateObject);
- }else{
- return dateObject.getTimezoneOffset();
- }
- };
- dojo.date.locale.format = function(/*Date*/dateObject, /*dojo.date.locale.__FormatOptions?*/options){
- // summary:
- // Format a Date object as a String, using locale-specific settings.
- //
- // description:
- // Create a string from a Date object using a known localized pattern.
- // By default, this method formats both date and time from dateObject.
- // Formatting patterns are chosen appropriate to the locale. Different
- // formatting lengths may be chosen, with "full" used by default.
- // Custom patterns may be used or registered with translations using
- // the dojo.date.locale.addCustomFormats method.
- // Formatting patterns are implemented using [the syntax described at
- // unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
- //
- // dateObject:
- // the date and/or time to be formatted. If a time only is formatted,
- // the values in the year, month, and day fields are irrelevant. The
- // opposite is true when formatting only dates.
- options = options || {};
- var locale = dojo.i18n.normalizeLocale(options.locale),
- formatLength = options.formatLength || 'short',
- bundle = dojo.date.locale._getGregorianBundle(locale),
- str = [],
- sauce = lang.hitch(this, formatPattern, dateObject, bundle, options);
- if(options.selector == "year"){
- return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce);
- }
- var pattern;
- if(options.selector != "date"){
- pattern = options.timePattern || bundle["timeFormat-"+formatLength];
- if(pattern){str.push(_processPattern(pattern, sauce));}
- }
- if(options.selector != "time"){
- pattern = options.datePattern || bundle["dateFormat-"+formatLength];
- if(pattern){str.push(_processPattern(pattern, sauce));}
- }
- return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
- function(match, key){ return str[key]; }); // String
- };
- dojo.date.locale.regexp = function(/*dojo.date.locale.__FormatOptions?*/options){
- // summary:
- // Builds the regular needed to parse a localized date
- return dojo.date.locale._parseInfo(options).regexp; // String
- };
- dojo.date.locale._parseInfo = function(/*dojo.date.locale.__FormatOptions?*/options){
- options = options || {};
- var locale = dojo.i18n.normalizeLocale(options.locale),
- bundle = dojo.date.locale._getGregorianBundle(locale),
- formatLength = options.formatLength || 'short',
- datePattern = options.datePattern || bundle["dateFormat-" + formatLength],
- timePattern = options.timePattern || bundle["timeFormat-" + formatLength],
- pattern;
- if(options.selector == 'date'){
- pattern = datePattern;
- }else if(options.selector == 'time'){
- pattern = timePattern;
- }else{
- pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
- function(match, key){ return [timePattern, datePattern][key]; });
- }
- var tokens = [],
- re = _processPattern(pattern, lang.hitch(this, _buildDateTimeRE, tokens, bundle, options));
- return {regexp: re, tokens: tokens, bundle: bundle};
- };
- dojo.date.locale.parse = function(/*String*/value, /*dojo.date.locale.__FormatOptions?*/options){
- // summary:
- // Convert a properly formatted string to a primitive Date object,
- // using locale-specific settings.
- //
- // description:
- // Create a Date object from a string using a known localized pattern.
- // By default, this method parses looking for both date and time in the string.
- // Formatting patterns are chosen appropriate to the locale. Different
- // formatting lengths may be chosen, with "full" used by default.
- // Custom patterns may be used or registered with translations using
- // the dojo.date.locale.addCustomFormats method.
- //
- // Formatting patterns are implemented using [the syntax described at
- // unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
- // When two digit years are used, a century is chosen according to a sliding
- // window of 80 years before and 20 years after present year, for both `yy` and `yyyy` patterns.
- // year < 100CE requires strict mode.
- //
- // value:
- // A string representation of a date
- // remove non-printing bidi control chars from input and pattern
- var controlChars = /[\u200E\u200F\u202A\u202E]/g,
- info = dojo.date.locale._parseInfo(options),
- tokens = info.tokens, bundle = info.bundle,
- re = new RegExp("^" + info.regexp.replace(controlChars, "") + "$",
- info.strict ? "" : "i"),
- match = re.exec(value && value.replace(controlChars, ""));
- if(!match){ return null; } // null
- var widthList = ['abbr', 'wide', 'narrow'],
- result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end
- amPm = "",
- valid = dojo.every(match, function(v, i){
- if(!i){return true;}
- var token=tokens[i-1];
- var l=token.length;
- switch(token.charAt(0)){
- case 'y':
- if(l != 2 && options.strict){
- //interpret year literally, so '5' would be 5 A.D.
- result[0] = v;
- }else{
- if(v<100){
- v = Number(v);
- //choose century to apply, according to a sliding window
- //of 80 years before and 20 years after present year
- var year = '' + new Date().getFullYear(),
- century = year.substring(0, 2) * 100,
- cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99);
- result[0] = (v < cutoff) ? century + v : century - 100 + v;
- }else{
- //we expected 2 digits and got more...
- if(options.strict){
- return false;
- }
- //interpret literally, so '150' would be 150 A.D.
- //also tolerate '1950', if 'yyyy' input passed to 'yy' format
- result[0] = v;
- }
- }
- break;
- case 'M':
- if(l>2){
- var months = bundle['months-format-' + widthList[l-3]].concat();
- if(!options.strict){
- //Tolerate abbreviating period in month part
- //Case-insensitive comparison
- v = v.replace(".","").toLowerCase();
- months = dojo.map(months, function(s){ return s.replace(".","").toLowerCase(); } );
- }
- v = dojo.indexOf(months, v);
- if(v == -1){
- // console.log("dojo.date.locale.parse: Could not parse month name: '" + v + "'.");
- return false;
- }
- }else{
- v--;
- }
- result[1] = v;
- break;
- case 'E':
- case 'e':
- var days = bundle['days-format-' + widthList[l-3]].concat();
- if(!options.strict){
- //Case-insensitive comparison
- v = v.toLowerCase();
- days = dojo.map(days, function(d){return d.toLowerCase();});
- }
- v = dojo.indexOf(days, v);
- if(v == -1){
- // console.log("dojo.date.locale.parse: Could not parse weekday name: '" + v + "'.");
- return false;
- }
- //TODO: not sure what to actually do with this input,
- //in terms of setting something on the Date obj...?
- //without more context, can't affect the actual date
- //TODO: just validate?
- break;
- case 'D':
- result[1] = 0;
- // fallthrough...
- case 'd':
- result[2] = v;
- break;
- case 'a': //am/pm
- var am = options.am || bundle['dayPeriods-format-wide-am'],
- pm = options.pm || bundle['dayPeriods-format-wide-pm'];
- if(!options.strict){
- var period = /\./g;
- v = v.replace(period,'').toLowerCase();
- am = am.replace(period,'').toLowerCase();
- pm = pm.replace(period,'').toLowerCase();
- }
- if(options.strict && v != am && v != pm){
- // console.log("dojo.date.locale.parse: Could not parse am/pm part.");
- return false;
- }
- // we might not have seen the hours field yet, so store the state and apply hour change later
- amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';
- break;
- case 'K': //hour (1-24)
- if(v == 24){ v = 0; }
- // fallthrough...
- case 'h': //hour (1-12)
- case 'H': //hour (0-23)
- case 'k': //hour (0-11)
- //TODO: strict bounds checking, padding
- if(v > 23){
- // console.log("dojo.date.locale.parse: Illegal hours value");
- return false;
- }
- //in the 12-hour case, adjusting for am/pm requires the 'a' part
- //which could come before or after the hour, so we will adjust later
- result[3] = v;
- break;
- case 'm': //minutes
- result[4] = v;
- break;
- case 's': //seconds
- result[5] = v;
- break;
- case 'S': //milliseconds
- result[6] = v;
- // break;
- // case 'w':
- //TODO var firstDay = 0;
- // default:
- //TODO: throw?
- // console.log("dojo.date.locale.parse: unsupported pattern char=" + token.charAt(0));
- }
- return true;
- });
- var hours = +result[3];
- if(amPm === 'p' && hours < 12){
- result[3] = hours + 12; //e.g., 3pm -> 15
- }else if(amPm === 'a' && hours == 12){
- result[3] = 0; //12am -> 0
- }
- //TODO: implement a getWeekday() method in order to test
- //validity of input strings containing 'EEE' or 'EEEE'...
- var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date
- if(options.strict){
- dateObject.setFullYear(result[0]);
- }
- // Check for overflow. The Date() constructor normalizes things like April 32nd...
- //TODO: why isn't this done for times as well?
- var allTokens = tokens.join(""),
- dateToken = allTokens.indexOf('d') != -1,
- monthToken = allTokens.indexOf('M') != -1;
- if(!valid ||
- (monthToken && dateObject.getMonth() > result[1]) ||
- (dateToken && dateObject.getDate() > result[2])){
- return null;
- }
- // Check for underflow, due to DST shifts. See #9366
- // This assumes a 1 hour dst shift correction at midnight
- // We could compare the timezone offset after the shift and add the difference instead.
- if((monthToken && dateObject.getMonth() < result[1]) ||
- (dateToken && dateObject.getDate() < result[2])){
- dateObject = date.add(dateObject, "hour", 1);
- }
- return dateObject; // Date
- };
- function _processPattern(pattern, applyPattern, applyLiteral, applyAll){
- //summary: Process a pattern with literals in it
- // Break up on single quotes, treat every other one as a literal, except '' which becomes '
- var identity = function(x){return x;};
- applyPattern = applyPattern || identity;
- applyLiteral = applyLiteral || identity;
- applyAll = applyAll || identity;
- //split on single quotes (which escape literals in date format strings)
- //but preserve escaped single quotes (e.g., o''clock)
- var chunks = pattern.match(/(''|[^'])+/g),
- literal = pattern.charAt(0) == "'";
- dojo.forEach(chunks, function(chunk, i){
- if(!chunk){
- chunks[i]='';
- }else{
- chunks[i]=(literal ? applyLiteral : applyPattern)(chunk.replace(/''/g, "'"));
- literal = !literal;
- }
- });
- return applyAll(chunks.join(''));
- }
- function _buildDateTimeRE(tokens, bundle, options, pattern){
- pattern = regexp.escapeString(pattern);
- if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pm
- return pattern.replace(/([a-z])\1*/ig, function(match){
- // Build a simple regexp. Avoid captures, which would ruin the tokens list
- var s,
- c = match.charAt(0),
- l = match.length,
- p2 = '', p3 = '';
- if(options.strict){
- if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }
- if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }
- }else{
- p2 = '0?'; p3 = '0{0,2}';
- }
- switch(c){
- case 'y':
- s = '\\d{2,4}';
- break;
- case 'M':
- s = (l>2) ? '\\S+?' : '1[0-2]|'+p2+'[1-9]';
- break;
- case 'D':
- s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|'+p2+'[1-9][0-9]|'+p3+'[1-9]';
- break;
- case 'd':
- s = '3[01]|[12]\\d|'+p2+'[1-9]';
- break;
- case 'w':
- s = '[1-4][0-9]|5[0-3]|'+p2+'[1-9]';
- break;
- case 'E':
- s = '\\S+';
- break;
- case 'h': //hour (1-12)
- s = '1[0-2]|'+p2+'[1-9]';
- break;
- case 'k': //hour (0-11)
- s = '1[01]|'+p2+'\\d';
- break;
- case 'H': //hour (0-23)
- s = '1\\d|2[0-3]|'+p2+'\\d';
- break;
- case 'K': //hour (1-24)
- s = '1\\d|2[0-4]|'+p2+'[1-9]';
- break;
- case 'm':
- case 's':
- s = '[0-5]\\d';
- break;
- case 'S':
- s = '\\d{'+l+'}';
- break;
- case 'a':
- var am = options.am || bundle['dayPeriods-format-wide-am'],
- pm = options.pm || bundle['dayPeriods-format-wide-pm'];
- s = am + '|' + pm;
- if(!options.strict){
- if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }
- if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }
- if(s.indexOf('.') != -1){ s += '|' + s.replace(/\./g, ""); }
- }
- s = s.replace(/\./g, "\\.");
- break;
- default:
- // case 'v':
- // case 'z':
- // case 'Z':
- s = ".*";
- // console.log("parse of date format, pattern=" + pattern);
- }
- if(tokens){ tokens.push(match); }
- return "(" + s + ")"; // add capture
- }).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace. Need explicit handling of \xa0 for IE.
- }
- var _customFormats = [];
- dojo.date.locale.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){
- // summary:
- // Add a reference to a bundle containing localized custom formats to be
- // used by date/time formatting and parsing routines.
- //
- // description:
- // The user may add custom localized formats where the bundle has properties following the
- // same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx`
- // The pattern string should match the format used by the CLDR.
- // See dojo.date.locale.format() for details.
- // The resources must be loaded by dojo.requireLocalization() prior to use
- _customFormats.push({pkg:packageName,name:bundleName});
- };
- dojo.date.locale._getGregorianBundle = function(/*String*/locale){
- var gregorian = {};
- dojo.forEach(_customFormats, function(desc){
- var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
- gregorian = lang.mixin(gregorian, bundle);
- }, this);
- return gregorian; /*Object*/
- };
- dojo.date.locale.addCustomFormats("dojo.cldr","gregorian");
- dojo.date.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale){
- // summary:
- // Used to get localized strings from dojo.cldr for day or month names.
- //
- // item:
- // 'months' || 'days'
- // type:
- // 'wide' || 'abbr' || 'narrow' (e.g. "Monday", "Mon", or "M" respectively, in English)
- // context:
- // 'standAlone' || 'format' (default)
- // locale:
- // override locale used to find the names
- var label,
- lookup = dojo.date.locale._getGregorianBundle(locale),
- props = [item, context, type];
- if(context == 'standAlone'){
- var key = props.join('-');
- label = lookup[key];
- // Fall back to 'format' flavor of name
- if(label[0] == 1){ label = undefined; } // kludge, in the absence of real aliasing support in dojo.cldr
- }
- props[1] = 'format';
- // return by copy so changes won't be made accidentally to the in-memory model
- return (label || lookup[props.join('-')]).concat(); /*Array*/
- };
- dojo.date.locale.isWeekend = function(/*Date?*/dateObject, /*String?*/locale){
- // summary:
- // Determines if the date falls on a weekend, according to local custom.
- var weekend = cldr.getWeekend(locale),
- day = (dateObject || new Date()).getDay();
- if(weekend.end < weekend.start){
- weekend.end += 7;
- if(day < weekend.start){ day += 7; }
- }
- return day >= weekend.start && day <= weekend.end; // Boolean
- };
- // These are used only by format and strftime. Do they need to be public? Which module should they go in?
- dojo.date.locale._getDayOfYear = function(/*Date*/dateObject){
- // summary: gets the day of the year as represented by dateObject
- return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject) + 1; // Number
- };
- dojo.date.locale._getWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDayOfWeek){
- if(arguments.length == 1){ firstDayOfWeek = 0; } // Sunday
- var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay(),
- adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
- week = Math.floor((dojo.date.locale._getDayOfYear(dateObject) + adj - 1) / 7);
- // if year starts on the specified day, start counting weeks at 1
- if(firstDayOfYear == firstDayOfWeek){ week++; }
- return week; // Number
- };
- return dojo.date.locale;
- });
- },
- 'url:dojox/grid/resources/View.html':"<div class=\"dojoxGridView\" role=\"presentation\">\r\n\t<div class=\"dojoxGridHeader\" dojoAttachPoint=\"headerNode\" role=\"presentation\">\r\n\t\t<div dojoAttachPoint=\"headerNodeContainer\" style=\"width:9000em\" role=\"presentation\">\r\n\t\t\t<div dojoAttachPoint=\"headerContentNode\" role=\"row\"></div>\r\n\t\t</div>\r\n\t</div>\r\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" dojoAttachPoint=\"hiddenFocusNode\" role=\"presentation\" />\r\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" role=\"presentation\" />\r\n\t<div class=\"dojoxGridScrollbox\" dojoAttachPoint=\"scrollboxNode\" role=\"presentation\">\r\n\t\t<div class=\"dojoxGridContent\" dojoAttachPoint=\"contentNode\" hidefocus=\"hidefocus\" role=\"presentation\"></div>\r\n\t</div>\r\n</div>\r\n",
- 'dojox/grid/enhanced/_Plugin':function(){
- define("dojox/grid/enhanced/_Plugin", [
- "dojo/_base/kernel",
- "dojo/_base/lang",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/connect",
- "../EnhancedGrid"
- ], function(dojo, lang, declare, array, connect){
-
- return declare("dojox.grid.enhanced._Plugin", null, {
- // summary:
- // Base class for all plugins.
- //
- // description:
- // Provides common plugin functionality and basic life cycle management.
- //
- // Each concrete plugin must have a name field and is responsible for registering itself to the global plugin registry
- // e.g. for dnd plugin:
- // | dojox.grid.EnhancedGrid.registerPlugin("dnd" /*plugin name*/,
- // | dojox.grid.enhanced.plugins.DnD /*full class name of a plugin*/
- // | {"preInit": false, "dependency": ["nestedSorting"]} /*properties*/);
- //
- // [Keywords] of plugin properties(case sensitive)
- // - "preInit": boolean, whether a plugin should be created before EnhancedGrid.postCreate(),
- // false by default(plugins are created after EnhancedGrid.postCreate()).
- // - "dependency": array or string, plugin(s) indicated by "dependency" will be created before the current one.
- // Note: recursive cycle dependencies are not supported e.g. following dependency is invalid:
- // pluginA -> pluginB -> pluginA
- //
- // example:
- // 1. Customize default DnD plugin
- // | dojo.declare("mygrid.MyDnD", dojox.grid.enhanced.plugins.DnD, {
- // | name:"dnd" //still reuse the plugin name
- // | constructor: function(inGrid, option){ ... }
- // | });
- // | dojox.grid.EnhancedGrid.registerPlugin("dnd", mygrid.MyDnD);
- //
- // 2. Add new plugin - PluginA
- // | dojo.declare("mygrid.PluginA", dojox.grid.enhanced._Plugin, {
- // | name: "pA",
- // | constructor: function(inGrid, option){ ... }
- // | });
- // | dojox.grid.EnhancedGrid.registerPlugin("pA",mygrid.PluginA);
- //
- // 3. Use plugins
- // | dojo.require("mygrid.MyDnD");
- // | dojo.require("mygrid.PluginA");
-
- // | <script type="text/javascript">
- // | var grid = new dojox.grid.EnhancedGrid(
- // | {plugins: {dnd:true, pA:true}, ... }, dojo.byId("gridDiv"));
- // | grid.startup();
- // | </script>
- //name: String
- // Plugin name, e.g. 'nestedSorting', 'dnd'...
- name: 'plugin',
-
- //grid: Object
- // Grid that the plugin belongs to
- grid: null,
- //option: Object
- // Plugin properties - leveraged with default and user specified properties.
- // e.g. for dnd plugin, it may look like {"class": dojox.grid.enhanced.plugins.DnD, "dependency": ["nestedSorting"], ...}
- option: {},
- //_connects: Array
- // List of all connections.
- _connects: [],
-
- //_subscribes: Array
- // List of all subscribes.
- _subscribes: [],
- //privates: Object
- // Private properties/methods shouldn't be mixin-ed anytime.
- privates: {},
-
- constructor: function(inGrid, option){
- this.grid = inGrid;
- this.option = option;
- this._connects = [];
- this._subscribes = [];
- this.privates = lang.mixin({},dojox.grid.enhanced._Plugin.prototype);
- this.init();
- },
-
- init: function(){},
-
- onPreInit: function(){},
-
- onPostInit: function(){},
-
- onStartUp: function(){},
-
- connect: function(obj, event, method){
- // summary:
- // Connects specified obj/event to specified method of this object.
- // example:
- // | var plugin = new dojox.grid.enhanced._Plugin(grid,"myPlugin",{...});
- // | // when foo.bar() is called, call the listener in the scope of plugin
- // | plugin.connect(foo, "bar", function(){
- // | console.debug(this.xxx());//"this" - plugin scope
- // | });
- var conn = connect.connect(obj, event, this, method);
- this._connects.push(conn);
- return conn;
- },
- disconnect: function(handle){
- // summary:
- // Disconnects handle and removes it from connection list.
- array.some(this._connects, function(conn, i, conns){
- if(conn == handle){
- connect.disconnect(handle);
- conns.splice(i, 1);
- return true;
- }
- return false;
- });
- },
- subscribe: function(topic, method){
- // summary:
- // Subscribes to the specified topic and calls the specified method
- // of this object.
- // example:
- // | var plugin = new dojox.grid.enhanced._Plugin(grid,"myPlugin",{...});
- // | // when /my/topic is published, call the subscriber in the scope of plugin
- // | // with passed parameter - "v"
- // | plugin.subscribe("/my/topic", function(v){
- // | console.debug(this.xxx(v));//"this" - plugin scope
- // | });
- var subscribe = connect.subscribe(topic, this, method);
- this._subscribes.push(subscribe);
- return subscribe;
- },
- unsubscribe: function(handle){
- // summary:
- // Un-subscribes handle and removes it from subscriptions list.
- array.some(this._subscribes, function(subscribe, i, subscribes){
- if(subscribe == handle){
- connect.unsubscribe(handle);
- subscribes.splice(i, 1);
- return true;
- }
- return false;
- });
- },
- onSetStore: function(store){
- // summary:
- // Called when store is changed.
- },
- destroy: function(){
- // summary:
- // Destroy all resources.
- array.forEach(this._connects, connect.disconnect);
- array.forEach(this._subscribes, connect.unsubscribe);
- delete this._connects;
- delete this._subscribes;
- delete this.option;
- delete this.privates;
- //console.log('Plugin [', this.name, '].destroy() executed!');
- }
- });
- //Each plugin is responsible for registering itself
- // e.g. for DnD plugin(name:'dnd'):
- // | dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.DnD/*class*/,
- // | {"dependency": ["nestedSorting"]}/*Optional - properties*/);
- });
- },
- 'dojox/html/entities':function(){
- define("dojox/html/entities", ["dojo/_base/lang"], function(lang) {
- // dojox.html.entities.html [public] Array
- // Entity characters for HTML, represented as an array of
- // character code, entity name (minus & and ; wrapping.
- // The function wrapper is to fix global leking with the build tools.
- var dhe = lang.getObject("dojox.html.entities",true);
-
- var _applyEncodingMap = function(str, map){
- // summary:
- // Private internal function for performing encoding of entity characters.
- // tags:
- // private
-
- // Check to see if we have genned and cached a regexp for this map yet
- // If we have, use it, if not, gen it, cache, then use.
- var mapper, regexp;
- if(map._encCache &&
- map._encCache.regexp &&
- map._encCache.mapper &&
- map.length == map._encCache.length){
- mapper = map._encCache.mapper;
- regexp = map._encCache.regexp;
- }else{
- mapper = {};
- regexp = ["["];
- var i;
- for(i = 0; i < map.length; i++){
- mapper[map[i][0]] = "&" + map[i][1] + ";";
- regexp.push(map[i][0]);
- }
- regexp.push("]");
- regexp = new RegExp(regexp.join(""), "g");
- map._encCache = {
- mapper: mapper,
- regexp: regexp,
- length: map.length
- };
- }
- str = str.replace(regexp, function(c){
- return mapper[c];
- });
- return str;
- };
-
- var _applyDecodingMap = function(str, map){
- // summary:
- // Private internal function for performing decoding of entity characters.
- // tags:
- // private
- var mapper, regexp;
- if(map._decCache &&
- map._decCache.regexp &&
- map._decCache.mapper &&
- map.length == map._decCache.length){
- mapper = map._decCache.mapper;
- regexp = map._decCache.regexp;
- }else{
- mapper = {};
- regexp = ["("];
- var i;
- for(i = 0; i < map.length; i++){
- var e = "&" + map[i][1] + ";";
- if(i){regexp.push("|");}
- mapper[e] = map[i][0];
- regexp.push(e);
- }
- regexp.push(")");
- regexp = new RegExp(regexp.join(""), "g");
- map._decCache = {
- mapper: mapper,
- regexp: regexp,
- length: map.length
- };
- }
- str = str.replace(regexp, function(c){
- return mapper[c];
- });
- return str;
- };
- dhe.html = [
- ["\u0026","amp"], ["\u0022","quot"],["\u003C","lt"], ["\u003E","gt"],
- ["\u00A0","nbsp"]
- ];
-
- // dojox.html.entities.latin [public] Array
- // Entity characters for Latin characters and similar, represented as an array of
- // character code, entity name (minus & and ; wrapping.
- dhe.latin = [
- ["\u00A1","iexcl"],["\u00A2","cent"],["\u00A3","pound"],["\u20AC","euro"],
- ["\u00A4","curren"],["\u00A5","yen"],["\u00A6","brvbar"],["\u00A7","sect"],
- ["\u00A8","uml"],["\u00A9","copy"],["\u00AA","ordf"],["\u00AB","laquo"],
- ["\u00AC","not"],["\u00AD","shy"],["\u00AE","reg"],["\u00AF","macr"],
- ["\u00B0","deg"],["\u00B1","plusmn"],["\u00B2","sup2"],["\u00B3","sup3"],
- ["\u00B4","acute"],["\u00B5","micro"],["\u00B6","para"],["\u00B7","middot"],
- ["\u00B8","cedil"],["\u00B9","sup1"],["\u00BA","ordm"],["\u00BB","raquo"],
- ["\u00BC","frac14"],["\u00BD","frac12"],["\u00BE","frac34"],["\u00BF","iquest"],
- ["\u00C0","Agrave"],["\u00C1","Aacute"],["\u00C2","Acirc"],["\u00C3","Atilde"],
- ["\u00C4","Auml"],["\u00C5","Aring"],["\u00C6","AElig"],["\u00C7","Ccedil"],
- ["\u00C8","Egrave"],["\u00C9","Eacute"],["\u00CA","Ecirc"],["\u00CB","Euml"],
- ["\u00CC","Igrave"],["\u00CD","Iacute"],["\u00CE","Icirc"],["\u00CF","Iuml"],
- ["\u00D0","ETH"],["\u00D1","Ntilde"],["\u00D2","Ograve"],["\u00D3","Oacute"],
- ["\u00D4","Ocirc"],["\u00D5","Otilde"],["\u00D6","Ouml"],["\u00D7","times"],
- ["\u00D8","Oslash"],["\u00D9","Ugrave"],["\u00DA","Uacute"],["\u00DB","Ucirc"],
- ["\u00DC","Uuml"],["\u00DD","Yacute"],["\u00DE","THORN"],["\u00DF","szlig"],
- ["\u00E0","agrave"],["\u00E1","aacute"],["\u00E2","acirc"],["\u00E3","atilde"],
- ["\u00E4","auml"],["\u00E5","aring"],["\u00E6","aelig"],["\u00E7","ccedil"],
- ["\u00E8","egrave"],["\u00E9","eacute"],["\u00EA","ecirc"],["\u00EB","euml"],
- ["\u00EC","igrave"],["\u00ED","iacute"],["\u00EE","icirc"],["\u00EF","iuml"],
- ["\u00F0","eth"],["\u00F1","ntilde"],["\u00F2","ograve"],["\u00F3","oacute"],
- ["\u00F4","ocirc"],["\u00F5","otilde"],["\u00F6","ouml"],["\u00F7","divide"],
- ["\u00F8","oslash"],["\u00F9","ugrave"],["\u00FA","uacute"],["\u00FB","ucirc"],
- ["\u00FC","uuml"],["\u00FD","yacute"],["\u00FE","thorn"],["\u00FF","yuml"],
- ["\u0192","fnof"],["\u0391","Alpha"],["\u0392","Beta"],["\u0393","Gamma"],
- ["\u0394","Delta"],["\u0395","Epsilon"],["\u0396","Zeta"],["\u0397","Eta"],
- ["\u0398","Theta"], ["\u0399","Iota"],["\u039A","Kappa"],["\u039B","Lambda"],
- ["\u039C","Mu"],["\u039D","Nu"],["\u039E","Xi"],["\u039F","Omicron"],
- ["\u03A0","Pi"],["\u03A1","Rho"],["\u03A3","Sigma"],["\u03A4","Tau"],
- ["\u03A5","Upsilon"],["\u03A6","Phi"],["\u03A7","Chi"],["\u03A8","Psi"],
- ["\u03A9","Omega"],["\u03B1","alpha"],["\u03B2","beta"],["\u03B3","gamma"],
- ["\u03B4","delta"],["\u03B5","epsilon"],["\u03B6","zeta"],["\u03B7","eta"],
- ["\u03B8","theta"],["\u03B9","iota"],["\u03BA","kappa"],["\u03BB","lambda"],
- ["\u03BC","mu"],["\u03BD","nu"],["\u03BE","xi"],["\u03BF","omicron"],
- ["\u03C0","pi"],["\u03C1","rho"],["\u03C2","sigmaf"],["\u03C3","sigma"],
- ["\u03C4","tau"],["\u03C5","upsilon"],["\u03C6","phi"],["\u03C7","chi"],
- ["\u03C8","psi"],["\u03C9","omega"],["\u03D1","thetasym"],["\u03D2","upsih"],
- ["\u03D6","piv"],["\u2022","bull"],["\u2026","hellip"],["\u2032","prime"],
- ["\u2033","Prime"],["\u203E","oline"],["\u2044","frasl"],["\u2118","weierp"],
- ["\u2111","image"],["\u211C","real"],["\u2122","trade"],["\u2135","alefsym"],
- ["\u2190","larr"],["\u2191","uarr"],["\u2192","rarr"],["\u2193","darr"],
- ["\u2194","harr"],["\u21B5","crarr"],["\u21D0","lArr"],["\u21D1","uArr"],
- ["\u21D2","rArr"],["\u21D3","dArr"],["\u21D4","hArr"],["\u2200","forall"],
- ["\u2202","part"],["\u2203","exist"],["\u2205","empty"],["\u2207","nabla"],
- ["\u2208","isin"],["\u2209","notin"],["\u220B","ni"],["\u220F","prod"],
- ["\u2211","sum"],["\u2212","minus"],["\u2217","lowast"],["\u221A","radic"],
- ["\u221D","prop"],["\u221E","infin"],["\u2220","ang"],["\u2227","and"],
- ["\u2228","or"],["\u2229","cap"],["\u222A","cup"],["\u222B","int"],
- ["\u2234","there4"],["\u223C","sim"],["\u2245","cong"],["\u2248","asymp"],
- ["\u2260","ne"],["\u2261","equiv"],["\u2264","le"],["\u2265","ge"],
- ["\u2282","sub"],["\u2283","sup"],["\u2284","nsub"],["\u2286","sube"],
- ["\u2287","supe"],["\u2295","oplus"],["\u2297","otimes"],["\u22A5","perp"],
- ["\u22C5","sdot"],["\u2308","lceil"],["\u2309","rceil"],["\u230A","lfloor"],
- ["\u230B","rfloor"],["\u2329","lang"],["\u232A","rang"],["\u25CA","loz"],
- ["\u2660","spades"],["\u2663","clubs"],["\u2665","hearts"],["\u2666","diams"],
- ["\u0152","Elig"],["\u0153","oelig"],["\u0160","Scaron"],["\u0161","scaron"],
- ["\u0178","Yuml"],["\u02C6","circ"],["\u02DC","tilde"],["\u2002","ensp"],
- ["\u2003","emsp"],["\u2009","thinsp"],["\u200C","zwnj"],["\u200D","zwj"],
- ["\u200E","lrm"],["\u200F","rlm"],["\u2013","ndash"],["\u2014","mdash"],
- ["\u2018","lsquo"],["\u2019","rsquo"],["\u201A","sbquo"],["\u201C","ldquo"],
- ["\u201D","rdquo"],["\u201E","bdquo"],["\u2020","dagger"],["\u2021","Dagger"],
- ["\u2030","permil"],["\u2039","lsaquo"],["\u203A","rsaquo"]
- ];
-
- dhe.encode = function(str/*string*/, m /*array?*/){
- // summary:
- // Function to obtain an entity encoding for a specified character
- // str:
- // The string to process for possible entity encoding.
- // m:
- // An optional list of character to entity name mappings (array of
- // arrays). If not provided, it uses the and Latin entities as the
- // set to map and escape.
- // tags:
- // public
- if(str){
- if(!m){
- // Apply the basic mappings. HTML should always come first when decoding
- // as well.
- str = _applyEncodingMap(str, dhe.html);
- str = _applyEncodingMap(str, dhe.latin);
-
- }else{
- str = _applyEncodingMap(str, m);
- }
- }
- return str;
- };
-
- dhe.decode = function(str/*string*/, m /*array?*/){
- // summary:
- // Function to obtain an entity encoding for a specified character
- // str:
- // The string to process for possible entity encoding to decode.
- // m:
- // An optional list of character to entity name mappings (array of
- // arrays). If not provided, it uses the HTML and Latin entities as the
- // set to map and decode.
- // tags:
- // public
- if(str){
- if(!m){
- // Apply the basic mappings. HTML should always come first when decoding
- // as well.
- str = _applyDecodingMap(str, dhe.html);
- str = _applyDecodingMap(str, dhe.latin);
-
- }else{
- str = _applyDecodingMap(str, m);
- }
- }
- return str;
- };
- return dhe;
- });
- },
- 'dijit/_editor/range':function(){
- define("dijit/_editor/range", [
- "dojo/_base/array", // array.every
- "dojo/_base/declare", // declare
- "dojo/_base/lang", // lang.isArray
- "dojo/_base/window", // win.global
- ".." // for exporting symbols to dijit, TODO: remove in 2.0
- ], function(array, declare, lang, win, dijit){
- // module:
- // dijit/_editor/range
- // summary:
- // W3C range API
- dijit.range={};
- dijit.range.getIndex = function(/*DomNode*/node, /*DomNode*/parent){
- // dojo.profile.start("dijit.range.getIndex");
- var ret = [], retR = [];
- var onode = node;
- var pnode, n;
- while(node != parent){
- var i = 0;
- pnode = node.parentNode;
- while((n = pnode.childNodes[i++])){
- if(n === node){
- --i;
- break;
- }
- }
- //if(i>=pnode.childNodes.length){
- //dojo.debug("Error finding index of a node in dijit.range.getIndex");
- //}
- ret.unshift(i);
- retR.unshift(i - pnode.childNodes.length);
- node = pnode;
- }
- //normalized() can not be called so often to prevent
- //invalidating selection/range, so we have to detect
- //here that any text nodes in a row
- if(ret.length > 0 && onode.nodeType == 3){
- n = onode.previousSibling;
- while(n && n.nodeType == 3){
- ret[ret.length - 1]--;
- n = n.previousSibling;
- }
- n = onode.nextSibling;
- while(n && n.nodeType == 3){
- retR[retR.length - 1]++;
- n = n.nextSibling;
- }
- }
- // dojo.profile.end("dijit.range.getIndex");
- return {o: ret, r:retR};
- };
- dijit.range.getNode = function(/*Array*/index, /*DomNode*/parent){
- if(!lang.isArray(index) || index.length == 0){
- return parent;
- }
- var node = parent;
- // if(!node)debugger
- array.every(index, function(i){
- if(i >= 0 && i < node.childNodes.length){
- node = node.childNodes[i];
- }else{
- node = null;
- //console.debug('Error: can not find node with index',index,'under parent node',parent );
- return false; //terminate array.every
- }
- return true; //carry on the every loop
- });
- return node;
- };
- dijit.range.getCommonAncestor = function(n1, n2, root){
- root = root || n1.ownerDocument.body;
- var getAncestors = function(n){
- var as = [];
- while(n){
- as.unshift(n);
- if(n !== root){
- n = n.parentNode;
- }else{
- break;
- }
- }
- return as;
- };
- var n1as = getAncestors(n1);
- var n2as = getAncestors(n2);
- var m = Math.min(n1as.length, n2as.length);
- var com = n1as[0]; //at least, one element should be in the array: the root (BODY by default)
- for(var i = 1; i < m; i++){
- if(n1as[i] === n2as[i]){
- com = n1as[i]
- }else{
- break;
- }
- }
- return com;
- };
- dijit.range.getAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
- root = root || node.ownerDocument.body;
- while(node && node !== root){
- var name = node.nodeName.toUpperCase();
- if(regex.test(name)){
- return node;
- }
- node = node.parentNode;
- }
- return null;
- };
- dijit.range.BlockTagNames = /^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/;
- dijit.range.getBlockAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
- root = root || node.ownerDocument.body;
- regex = regex || dijit.range.BlockTagNames;
- var block = null, blockContainer;
- while(node && node !== root){
- var name = node.nodeName.toUpperCase();
- if(!block && regex.test(name)){
- block = node;
- }
- if(!blockContainer && (/^(?:BODY|TD|TH|CAPTION)$/).test(name)){
- blockContainer = node;
- }
- node = node.parentNode;
- }
- return {blockNode:block, blockContainer:blockContainer || node.ownerDocument.body};
- };
- dijit.range.atBeginningOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
- var atBeginning = false;
- var offsetAtBeginning = (offset == 0);
- if(!offsetAtBeginning && node.nodeType == 3){ //if this is a text node, check whether the left part is all space
- if(/^[\s\xA0]+$/.test(node.nodeValue.substr(0, offset))){
- offsetAtBeginning = true;
- }
- }
- if(offsetAtBeginning){
- var cnode = node;
- atBeginning = true;
- while(cnode && cnode !== container){
- if(cnode.previousSibling){
- atBeginning = false;
- break;
- }
- cnode = cnode.parentNode;
- }
- }
- return atBeginning;
- };
- dijit.range.atEndOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
- var atEnd = false;
- var offsetAtEnd = (offset == (node.length || node.childNodes.length));
- if(!offsetAtEnd && node.nodeType == 3){ //if this is a text node, check whether the right part is all space
- if(/^[\s\xA0]+$/.test(node.nodeValue.substr(offset))){
- offsetAtEnd = true;
- }
- }
- if(offsetAtEnd){
- var cnode = node;
- atEnd = true;
- while(cnode && cnode !== container){
- if(cnode.nextSibling){
- atEnd = false;
- break;
- }
- cnode = cnode.parentNode;
- }
- }
- return atEnd;
- };
- dijit.range.adjacentNoneTextNode = function(startnode, next){
- var node = startnode;
- var len = (0 - startnode.length) || 0;
- var prop = next ? 'nextSibling' : 'previousSibling';
- while(node){
- if(node.nodeType != 3){
- break;
- }
- len += node.length;
- node = node[prop];
- }
- return [node,len];
- };
- dijit.range._w3c = Boolean(window['getSelection']);
- dijit.range.create = function(/*Window?*/window){
- if(dijit.range._w3c){
- return (window || win.global).document.createRange();
- }else{//IE
- return new dijit.range.W3CRange;
- }
- };
- dijit.range.getSelection = function(/*Window*/win, /*Boolean?*/ignoreUpdate){
- if(dijit.range._w3c){
- return win.getSelection();
- }else{//IE
- var s = new dijit.range.ie.selection(win);
- if(!ignoreUpdate){
- s._getCurrentSelection();
- }
- return s;
- }
- };
- if(!dijit.range._w3c){
- dijit.range.ie = {
- cachedSelection: {},
- selection: function(win){
- this._ranges = [];
- this.addRange = function(r, /*boolean*/internal){
- this._ranges.push(r);
- if(!internal){
- r._select();
- }
- this.rangeCount = this._ranges.length;
- };
- this.removeAllRanges = function(){
- //don't detach, the range may be used later
- // for(var i=0;i<this._ranges.length;i++){
- // this._ranges[i].detach();
- // }
- this._ranges = [];
- this.rangeCount = 0;
- };
- var _initCurrentRange = function(){
- var r = win.document.selection.createRange();
- var type = win.document.selection.type.toUpperCase();
- if(type == "CONTROL"){
- //TODO: multiple range selection(?)
- return new dijit.range.W3CRange(dijit.range.ie.decomposeControlRange(r));
- }else{
- return new dijit.range.W3CRange(dijit.range.ie.decomposeTextRange(r));
- }
- };
- this.getRangeAt = function(i){
- return this._ranges[i];
- };
- this._getCurrentSelection = function(){
- this.removeAllRanges();
- var r = _initCurrentRange();
- if(r){
- this.addRange(r, true);
- this.isCollapsed = r.collapsed;
- }else{
- this.isCollapsed = true;
- }
- };
- },
- decomposeControlRange: function(range){
- var firstnode = range.item(0), lastnode = range.item(range.length - 1);
- var startContainer = firstnode.parentNode, endContainer = lastnode.parentNode;
- var startOffset = dijit.range.getIndex(firstnode, startContainer).o[0];
- var endOffset = dijit.range.getIndex(lastnode, endContainer).o[0] + 1;
- return [startContainer, startOffset,endContainer, endOffset];
- },
- getEndPoint: function(range, end){
- var atmrange = range.duplicate();
- atmrange.collapse(!end);
- var cmpstr = 'EndTo' + (end ? 'End' : 'Start');
- var parentNode = atmrange.parentElement();
- var startnode, startOffset, lastNode;
- if(parentNode.childNodes.length > 0){
- array.every(parentNode.childNodes, function(node, i){
- var calOffset;
- if(node.nodeType != 3){
- atmrange.moveToElementText(node);
- if(atmrange.compareEndPoints(cmpstr, range) > 0){
- //startnode = node.previousSibling;
- if(lastNode && lastNode.nodeType == 3){
- //where shall we put the start? in the text node or after?
- startnode = lastNode;
- calOffset = true;
- }else{
- startnode = parentNode;
- startOffset = i;
- return false;
- }
- }else{
- if(i == parentNode.childNodes.length - 1){
- startnode = parentNode;
- startOffset = parentNode.childNodes.length;
- return false;
- }
- }
- }else{
- if(i == parentNode.childNodes.length - 1){//at the end of this node
- startnode = node;
- calOffset = true;
- }
- }
- // try{
- if(calOffset && startnode){
- var prevnode = dijit.range.adjacentNoneTextNode(startnode)[0];
- if(prevnode){
- startnode = prevnode.nextSibling;
- }else{
- startnode = parentNode.firstChild; //firstChild must be a text node
- }
- var prevnodeobj = dijit.range.adjacentNoneTextNode(startnode);
- prevnode = prevnodeobj[0];
- var lenoffset = prevnodeobj[1];
- if(prevnode){
- atmrange.moveToElementText(prevnode);
- atmrange.collapse(false);
- }else{
- atmrange.moveToElementText(parentNode);
- }
- atmrange.setEndPoint(cmpstr, range);
- startOffset = atmrange.text.length - lenoffset;
- return false;
- }
- // }catch(e){ debugger }
- lastNode = node;
- return true;
- });
- }else{
- startnode = parentNode;
- startOffset = 0;
- }
- //if at the end of startnode and we are dealing with start container, then
- //move the startnode to nextSibling if it is a text node
- //TODO: do this for end container?
- if(!end && startnode.nodeType == 1 && startOffset == startnode.childNodes.length){
- var nextnode = startnode.nextSibling;
- if(nextnode && nextnode.nodeType == 3){
- startnode = nextnode;
- startOffset = 0;
- }
- }
- return [startnode, startOffset];
- },
- setEndPoint: function(range, container, offset){
- //text node
- var atmrange = range.duplicate(), node, len;
- if(container.nodeType != 3){ //normal node
- if(offset > 0){
- node = container.childNodes[offset - 1];
- if(node){
- if(node.nodeType == 3){
- container = node;
- offset = node.length;
- //pass through
- }else{
- if(node.nextSibling && node.nextSibling.nodeType == 3){
- container = node.nextSibling;
- offset = 0;
- //pass through
- }else{
- atmrange.moveToElementText(node.nextSibling ? node : container);
- var parent = node.parentNode;
- var tempNode = parent.insertBefore(node.ownerDocument.createTextNode(' '), node.nextSibling);
- atmrange.collapse(false);
- parent.removeChild(tempNode);
- }
- }
- }
- }else{
- atmrange.moveToElementText(container);
- atmrange.collapse(true);
- }
- }
- if(container.nodeType == 3){
- var prevnodeobj = dijit.range.adjacentNoneTextNode(container);
- var prevnode = prevnodeobj[0];
- len = prevnodeobj[1];
- if(prevnode){
- atmrange.moveToElementText(prevnode);
- atmrange.collapse(false);
- //if contentEditable is not inherit, the above collapse won't make the end point
- //in the correctly position: it always has a -1 offset, so compensate it
- if(prevnode.contentEditable != 'inherit'){
- len++;
- }
- }else{
- atmrange.moveToElementText(container.parentNode);
- atmrange.collapse(true);
- }
- offset += len;
- if(offset > 0){
- if(atmrange.move('character', offset) != offset){
- console.error('Error when moving!');
- }
- }
- }
- return atmrange;
- },
- decomposeTextRange: function(range){
- var tmpary = dijit.range.ie.getEndPoint(range);
- var startContainer = tmpary[0], startOffset = tmpary[1];
- var endContainer = tmpary[0], endOffset = tmpary[1];
- if(range.htmlText.length){
- if(range.htmlText == range.text){ //in the same text node
- endOffset = startOffset + range.text.length;
- }else{
- tmpary = dijit.range.ie.getEndPoint(range, true);
- endContainer = tmpary[0],endOffset = tmpary[1];
- // if(startContainer.tagName == "BODY"){
- // startContainer = startContainer.firstChild;
- // }
- }
- }
- return [startContainer, startOffset, endContainer, endOffset];
- },
- setRange: function(range, startContainer, startOffset, endContainer, endOffset, collapsed){
- var start = dijit.range.ie.setEndPoint(range, startContainer, startOffset);
- range.setEndPoint('StartToStart', start);
- if(!collapsed){
- var end = dijit.range.ie.setEndPoint(range, endContainer, endOffset);
- }
- range.setEndPoint('EndToEnd', end || start);
- return range;
- }
- };
- declare("dijit.range.W3CRange",null, {
- constructor: function(){
- if(arguments.length>0){
- this.setStart(arguments[0][0],arguments[0][1]);
- this.setEnd(arguments[0][2],arguments[0][3]);
- }else{
- this.commonAncestorContainer = null;
- this.startContainer = null;
- this.startOffset = 0;
- this.endContainer = null;
- this.endOffset = 0;
- this.collapsed = true;
- }
- },
- _updateInternal: function(){
- if(this.startContainer !== this.endContainer){
- this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer);
- }else{
- this.commonAncestorContainer = this.startContainer;
- }
- this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset);
- },
- setStart: function(node, offset){
- offset=parseInt(offset);
- if(this.startContainer === node && this.startOffset == offset){
- return;
- }
- delete this._cachedBookmark;
- this.startContainer = node;
- this.startOffset = offset;
- if(!this.endContainer){
- this.setEnd(node, offset);
- }else{
- this._updateInternal();
- }
- },
- setEnd: function(node, offset){
- offset=parseInt(offset);
- if(this.endContainer === node && this.endOffset == offset){
- return;
- }
- delete this._cachedBookmark;
- this.endContainer = node;
- this.endOffset = offset;
- if(!this.startContainer){
- this.setStart(node, offset);
- }else{
- this._updateInternal();
- }
- },
- setStartAfter: function(node, offset){
- this._setPoint('setStart', node, offset, 1);
- },
- setStartBefore: function(node, offset){
- this._setPoint('setStart', node, offset, 0);
- },
- setEndAfter: function(node, offset){
- this._setPoint('setEnd', node, offset, 1);
- },
- setEndBefore: function(node, offset){
- this._setPoint('setEnd', node, offset, 0);
- },
- _setPoint: function(what, node, offset, ext){
- var index = dijit.range.getIndex(node, node.parentNode).o;
- this[what](node.parentNode, index.pop()+ext);
- },
- _getIERange: function(){
- var r = (this._body || this.endContainer.ownerDocument.body).createTextRange();
- dijit.range.ie.setRange(r, this.startContainer, this.startOffset, this.endContainer, this.endOffset, this.collapsed);
- return r;
- },
- getBookmark: function(){
- this._getIERange();
- return this._cachedBookmark;
- },
- _select: function(){
- var r = this._getIERange();
- r.select();
- },
- deleteContents: function(){
- var s = this.startContainer, r = this._getIERange();
- if(s.nodeType === 3 && !this.startOffset){
- //if the range starts at the beginning of a
- //text node, move it to before the textnode
- //to make sure the range is still valid
- //after deleteContents() finishes
- this.setStartBefore(s);
- }
- r.pasteHTML('');
- this.endContainer = this.startContainer;
- this.endOffset = this.startOffset;
- this.collapsed = true;
- },
- cloneRange: function(){
- var r = new dijit.range.W3CRange([this.startContainer,this.startOffset,
- this.endContainer,this.endOffset]);
- r._body = this._body;
- return r;
- },
- detach: function(){
- this._body = null;
- this.commonAncestorContainer = null;
- this.startContainer = null;
- this.startOffset = 0;
- this.endContainer = null;
- this.endOffset = 0;
- this.collapsed = true;
- }
- });
- } //if(!dijit.range._w3c)
- return dijit.range;
- });
- },
- 'dojo/store/util/QueryResults':function(){
- define("dojo/store/util/QueryResults", ["../../_base/array", "../../_base/lang", "../../_base/Deferred"
- ], function(array, lang, Deferred) {
- // module:
- // dojo/store/util/QueryResults
- // summary:
- // The module defines a query results wrapper
- var util = lang.getObject("dojo.store.util", true);
- util.QueryResults = function(results){
- // summary:
- // A function that wraps the results of a store query with additional
- // methods.
- //
- // description:
- // QueryResults is a basic wrapper that allows for array-like iteration
- // over any kind of returned data from a query. While the simplest store
- // will return a plain array of data, other stores may return deferreds or
- // promises; this wrapper makes sure that *all* results can be treated
- // the same.
- //
- // Additional methods include `forEach`, `filter` and `map`.
- //
- // returns: Object
- // An array-like object that can be used for iterating over.
- //
- // example:
- // Query a store and iterate over the results.
- //
- // | store.query({ prime: true }).forEach(function(item){
- // | // do something
- // | });
- if(!results){
- return results;
- }
- // if it is a promise it may be frozen
- if(results.then){
- results = lang.delegate(results);
- }
- function addIterativeMethod(method){
- if(!results[method]){
- results[method] = function(){
- var args = arguments;
- return Deferred.when(results, function(results){
- Array.prototype.unshift.call(args, results);
- return util.QueryResults(array[method].apply(array, args));
- });
- };
- }
- }
- addIterativeMethod("forEach");
- addIterativeMethod("filter");
- addIterativeMethod("map");
- if(!results.total){
- results.total = Deferred.when(results, function(results){
- return results.length;
- });
- }
- return results;
- };
- return util.QueryResults;
- });
- },
- 'dijit/form/_ListBase':function(){
- define("dijit/form/_ListBase", [
- "dojo/_base/declare", // declare
- "dojo/window" // winUtils.scrollIntoView
- ], function(declare, winUtils){
- // module:
- // dijit/form/_ListBase
- // summary:
- // Focus-less menu to handle UI events consistently
- return declare( "dijit.form._ListBase", null, {
- // summary:
- // Focus-less menu to handle UI events consistently
- // Abstract methods that must be defined externally:
- // onSelect: item is active (mousedown but not yet mouseup, or keyboard arrow selected but no Enter)
- // onDeselect: cancels onSelect
- // tags:
- // private
- // selected: DOMnode
- // currently selected node
- selected: null,
- _getTarget: function(/*Event*/ evt){
- var tgt = evt.target;
- var container = this.containerNode;
- if(tgt == container || tgt == this.domNode){ return null; }
- while(tgt && tgt.parentNode != container){
- // recurse to the top
- tgt = tgt.parentNode;
- }
- return tgt;
- },
- selectFirstNode: function(){
- // summary:
- // Select the first displayed item in the list.
- var first = this.containerNode.firstChild;
- while(first && first.style.display == "none"){
- first = first.nextSibling;
- }
- this._setSelectedAttr(first);
- },
- selectLastNode: function(){
- // summary:
- // Select the last displayed item in the list
- var last = this.containerNode.lastChild;
- while(last && last.style.display == "none"){
- last = last.previousSibling;
- }
- this._setSelectedAttr(last);
- },
- selectNextNode: function(){
- // summary:
- // Select the item just below the current selection.
- // If nothing selected, select first node.
- var selectedNode = this._getSelectedAttr();
- if(!selectedNode){
- this.selectFirstNode();
- }else{
- var next = selectedNode.nextSibling;
- while(next && next.style.display == "none"){
- next = next.nextSibling;
- }
- if(!next){
- this.selectFirstNode();
- }else{
- this._setSelectedAttr(next);
- }
- }
- },
- selectPreviousNode: function(){
- // summary:
- // Select the item just above the current selection.
- // If nothing selected, select last node (if
- // you select Previous and try to keep scrolling up the list).
- var selectedNode = this._getSelectedAttr();
- if(!selectedNode){
- this.selectLastNode();
- }else{
- var prev = selectedNode.previousSibling;
- while(prev && prev.style.display == "none"){
- prev = prev.previousSibling;
- }
- if(!prev){
- this.selectLastNode();
- }else{
- this._setSelectedAttr(prev);
- }
- }
- },
- _setSelectedAttr: function(/*DomNode*/ node){
- // summary:
- // Does the actual select.
- if(this.selected != node){
- var selectedNode = this._getSelectedAttr();
- if(selectedNode){
- this.onDeselect(selectedNode);
- this.selected = null;
- }
- if(node && node.parentNode == this.containerNode){
- this.selected = node;
- winUtils.scrollIntoView(node);
- this.onSelect(node);
- }
- }else if(node){
- this.onSelect(node);
- }
- },
- _getSelectedAttr: function(){
- // summary:
- // Returns the selected node.
- var v = this.selected;
- return (v && v.parentNode == this.containerNode) ? v : (this.selected = null);
- }
- });
- });
- },
- 'dijit/form/_FormWidget':function(){
- define("dijit/form/_FormWidget", [
- "dojo/_base/declare", // declare
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/ready",
- "../_Widget",
- "../_CssStateMixin",
- "../_TemplatedMixin",
- "./_FormWidgetMixin"
- ], function(declare, kernel, ready, _Widget, _CssStateMixin, _TemplatedMixin, _FormWidgetMixin){
- /*=====
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var _CssStateMixin = dijit._CssStateMixin;
- var _FormWidgetMixin = dijit.form._FormWidgetMixin;
- =====*/
- // module:
- // dijit/form/_FormWidget
- // summary:
- // FormWidget
- // Back compat w/1.6, remove for 2.0
- if(!kernel.isAsync){
- ready(0, function(){
- var requires = ["dijit/form/_FormValueWidget"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- return declare("dijit.form._FormWidget", [_Widget, _TemplatedMixin, _CssStateMixin, _FormWidgetMixin], {
- // summary:
- // Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>,
- // which can be children of a <form> node or a `dijit.form.Form` widget.
- //
- // description:
- // Represents a single HTML element.
- // All these widgets should have these attributes just like native HTML input elements.
- // You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
- //
- // They also share some common methods.
- setDisabled: function(/*Boolean*/ disabled){
- // summary:
- // Deprecated. Use set('disabled', ...) instead.
- kernel.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0");
- this.set('disabled', disabled);
- },
- setValue: function(/*String*/ value){
- // summary:
- // Deprecated. Use set('value', ...) instead.
- kernel.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated. Use set('value',"+value+") instead.", "", "2.0");
- this.set('value', value);
- },
- getValue: function(){
- // summary:
- // Deprecated. Use get('value') instead.
- kernel.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0");
- return this.get('value');
- },
- postMixInProperties: function(){
- // Setup name=foo string to be referenced from the template (but only if a name has been specified)
- // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8484, #8660.
- // Regarding escaping, see heading "Attribute values" in
- // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
- this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, """) + '"') : '';
- this.inherited(arguments);
- },
- // Override automatic assigning type --> focusNode, it causes exception on IE.
- // Instead, type must be specified as ${type} in the template, as part of the original DOM
- _setTypeAttr: null
- });
- });
- },
- 'dojo/dnd/common':function(){
- define("dojo/dnd/common", ["../main"], function(dojo) {
- // module:
- // dojo/dnd/common
- // summary:
- // TODOC
- dojo.getObject("dnd", true, dojo);
- dojo.dnd.getCopyKeyState = dojo.isCopyKey;
- dojo.dnd._uniqueId = 0;
- dojo.dnd.getUniqueId = function(){
- // summary:
- // returns a unique string for use with any DOM element
- var id;
- do{
- id = dojo._scopeName + "Unique" + (++dojo.dnd._uniqueId);
- }while(dojo.byId(id));
- return id;
- };
- dojo.dnd._empty = {};
- dojo.dnd.isFormElement = function(/*Event*/ e){
- // summary:
- // returns true if user clicked on a form element
- var t = e.target;
- if(t.nodeType == 3 /*TEXT_NODE*/){
- t = t.parentNode;
- }
- return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0; // Boolean
- };
- return dojo.dnd;
- });
- },
- 'dijit/CalendarLite':function(){
- require({cache:{
- 'url:dijit/templates/Calendar.html':"<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\" role=\"grid\" aria-labelledby=\"${id}_mddb ${id}_year\">\r\n\t<thead>\r\n\t\t<tr class=\"dijitReset dijitCalendarMonthContainer\" valign=\"top\">\r\n\t\t\t<th class='dijitReset dijitCalendarArrow' data-dojo-attach-point=\"decrementMonth\">\r\n\t\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitCalendarIncrementControl dijitCalendarDecrease\" role=\"presentation\"/>\r\n\t\t\t\t<span data-dojo-attach-point=\"decreaseArrowNode\" class=\"dijitA11ySideArrow\">-</span>\r\n\t\t\t</th>\r\n\t\t\t<th class='dijitReset' colspan=\"5\">\r\n\t\t\t\t<div data-dojo-attach-point=\"monthNode\">\r\n\t\t\t\t</div>\r\n\t\t\t</th>\r\n\t\t\t<th class='dijitReset dijitCalendarArrow' data-dojo-attach-point=\"incrementMonth\">\r\n\t\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitCalendarIncrementControl dijitCalendarIncrease\" role=\"presentation\"/>\r\n\t\t\t\t<span data-dojo-attach-point=\"increaseArrowNode\" class=\"dijitA11ySideArrow\">+</span>\r\n\t\t\t</th>\r\n\t\t</tr>\r\n\t\t<tr>\r\n\t\t\t${!dayCellsHtml}\r\n\t\t</tr>\r\n\t</thead>\r\n\t<tbody data-dojo-attach-point=\"dateRowsNode\" data-dojo-attach-event=\"onclick: _onDayClick\" class=\"dijitReset dijitCalendarBodyContainer\">\r\n\t\t\t${!dateRowsHtml}\r\n\t</tbody>\r\n\t<tfoot class=\"dijitReset dijitCalendarYearContainer\">\r\n\t\t<tr>\r\n\t\t\t<td class='dijitReset' valign=\"top\" colspan=\"7\" role=\"presentation\">\r\n\t\t\t\t<div class=\"dijitCalendarYearLabel\">\r\n\t\t\t\t\t<span data-dojo-attach-point=\"previousYearLabelNode\" class=\"dijitInline dijitCalendarPreviousYear\" role=\"button\"></span>\r\n\t\t\t\t\t<span data-dojo-attach-point=\"currentYearLabelNode\" class=\"dijitInline dijitCalendarSelectedYear\" role=\"button\" id=\"${id}_year\"></span>\r\n\t\t\t\t\t<span data-dojo-attach-point=\"nextYearLabelNode\" class=\"dijitInline dijitCalendarNextYear\" role=\"button\"></span>\r\n\t\t\t\t</div>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t</tfoot>\r\n</table>\r\n"}});
- define("dijit/CalendarLite", [
- "dojo/_base/array", // array.forEach array.map
- "dojo/_base/declare", // declare
- "dojo/cldr/supplemental", // cldrSupplemental.getFirstDayOfWeek
- "dojo/date", // date
- "dojo/date/locale",
- "dojo/dom", // dom.setSelectable
- "dojo/dom-class", // domClass.contains
- "dojo/_base/event", // event.stop
- "dojo/_base/lang", // lang.getObject, lang.hitch
- "dojo/_base/sniff", // has("ie") has("webkit")
- "dojo/string", // string.substitute
- "dojo/_base/window", // win.doc.createTextNode
- "./_WidgetBase",
- "./_TemplatedMixin",
- "dojo/text!./templates/Calendar.html"
- ], function(array, declare, cldrSupplemental, date, local, dom, domClass, event, lang, has, string, win,
- _WidgetBase, _TemplatedMixin, template){
- /*=====
- var _WidgetBase = dijit._WidgetBase;
- var _TemplatedMixin = dijit._TemplatedMixin;
- =====*/
- // module:
- // dijit/CalendarLite
- // summary:
- // Lightweight version of Calendar widget aimed towards mobile use
- var CalendarLite = declare("dijit.CalendarLite", [_WidgetBase, _TemplatedMixin], {
- // summary:
- // Lightweight version of Calendar widget aimed towards mobile use
- //
- // description:
- // A simple GUI for choosing a date in the context of a monthly calendar.
- // This widget can't be used in a form because it doesn't serialize the date to an
- // `<input>` field. For a form element, use dijit.form.DateTextBox instead.
- //
- // Note that the parser takes all dates attributes passed in the
- // [RFC 3339 format](http://www.faqs.org/rfcs/rfc3339.html), e.g. `2005-06-30T08:05:00-07:00`
- // so that they are serializable and locale-independent.
- //
- // Also note that this widget isn't keyboard accessible; use dijit.Calendar for that
- // example:
- // | var calendar = new dijit.CalendarLite({}, dojo.byId("calendarNode"));
- //
- // example:
- // | <div data-dojo-type="dijit.CalendarLite"></div>
- // Template for main calendar
- templateString: template,
- // Template for cell for a day of the week (ex: M)
- dowTemplateString: '<th class="dijitReset dijitCalendarDayLabelTemplate" role="columnheader"><span class="dijitCalendarDayLabel">${d}</span></th>',
- // Templates for a single date (ex: 13), and for a row for a week (ex: 20 21 22 23 24 25 26)
- dateTemplateString: '<td class="dijitReset" role="gridcell" data-dojo-attach-point="dateCells"><span class="dijitCalendarDateLabel" data-dojo-attach-point="dateLabels"></span></td>',
- weekTemplateString: '<tr class="dijitReset dijitCalendarWeekTemplate" role="row">${d}${d}${d}${d}${d}${d}${d}</tr>',
- // value: Date
- // The currently selected Date, initially set to invalid date to indicate no selection.
- value: new Date(""),
- // TODO: for 2.0 make this a string (ISO format) rather than a Date
- // datePackage: String
- // JavaScript object containing Calendar functions. Uses Gregorian Calendar routines
- // from dojo.date by default.
- datePackage: date,
- // dayWidth: String
- // How to represent the days of the week in the calendar header. See locale
- dayWidth: "narrow",
- // tabIndex: Integer
- // Order fields are traversed when user hits the tab key
- tabIndex: "0",
- // currentFocus: Date
- // Date object containing the currently focused date, or the date which would be focused
- // if the calendar itself was focused. Also indicates which year and month to display,
- // i.e. the current "page" the calendar is on.
- currentFocus: new Date(),
- baseClass:"dijitCalendar",
- _isValidDate: function(/*Date*/ value){
- // summary:
- // Runs various tests on the value, checking that it's a valid date, rather
- // than blank or NaN.
- // tags:
- // private
- return value && !isNaN(value) && typeof value == "object" &&
- value.toString() != this.constructor.prototype.value.toString();
- },
- _getValueAttr: function(){
- // summary:
- // Support get('value')
- // this.value is set to 1AM, but return midnight, local time for back-compat
- if(this.value && !isNaN(this.value)){
- var value = new this.dateClassObj(this.value);
- value.setHours(0, 0, 0, 0);
- // If daylight savings pushes midnight to the previous date, fix the Date
- // object to point at 1am so it will represent the correct day. See #9366
- if(value.getDate() < this.value.getDate()){
- value = this.dateFuncObj.add(value, "hour", 1);
- }
- return value;
- }else{
- return null;
- }
- },
- _setValueAttr: function(/*Date|Number*/ value, /*Boolean*/ priorityChange){
- // summary:
- // Support set("value", ...)
- // description:
- // Set the current date and update the UI. If the date is disabled, the value will
- // not change, but the display will change to the corresponding month.
- // value:
- // Either a Date or the number of seconds since 1970.
- // tags:
- // protected
- if(value){
- // convert from Number to Date, or make copy of Date object so that setHours() call below
- // doesn't affect original value
- value = new this.dateClassObj(value);
- }
- if(this._isValidDate(value)){
- if(!this._isValidDate(this.value) || this.dateFuncObj.compare(value, this.value)){
- value.setHours(1, 0, 0, 0); // round to nearest day (1am to avoid issues when DST shift occurs at midnight, see #8521, #9366)
- if(!this.isDisabledDate(value, this.lang)){
- this._set("value", value);
- // Set focus cell to the new value. Arguably this should only happen when there isn't a current
- // focus point. This will also repopulate the grid, showing the new selected value (and possibly
- // new month/year).
- this.set("currentFocus", value);
- if(priorityChange || typeof priorityChange == "undefined"){
- this.onChange(this.get('value'));
- }
- }
- }
- }else{
- // clear value, and repopulate grid (to deselect the previously selected day) without changing currentFocus
- this._set("value", null);
- this.set("currentFocus", this.currentFocus);
- }
- },
- _setText: function(node, text){
- // summary:
- // This just sets the content of node to the specified text.
- // Can't do "node.innerHTML=text" because of an IE bug w/tables, see #3434.
- // tags:
- // private
- while(node.firstChild){
- node.removeChild(node.firstChild);
- }
- node.appendChild(win.doc.createTextNode(text));
- },
- _populateGrid: function(){
- // summary:
- // Fills in the calendar grid with each day (1-31)
- // tags:
- // private
- var month = new this.dateClassObj(this.currentFocus);
- month.setDate(1);
- var firstDay = month.getDay(),
- daysInMonth = this.dateFuncObj.getDaysInMonth(month),
- daysInPreviousMonth = this.dateFuncObj.getDaysInMonth(this.dateFuncObj.add(month, "month", -1)),
- today = new this.dateClassObj(),
- dayOffset = cldrSupplemental.getFirstDayOfWeek(this.lang);
- if(dayOffset > firstDay){ dayOffset -= 7; }
- // Mapping from date (as specified by number returned from Date.valueOf()) to corresponding <td>
- this._date2cell = {};
- // Iterate through dates in the calendar and fill in date numbers and style info
- array.forEach(this.dateCells, function(template, idx){
- var i = idx + dayOffset;
- var date = new this.dateClassObj(month),
- number, clazz = "dijitCalendar", adj = 0;
- if(i < firstDay){
- number = daysInPreviousMonth - firstDay + i + 1;
- adj = -1;
- clazz += "Previous";
- }else if(i >= (firstDay + daysInMonth)){
- number = i - firstDay - daysInMonth + 1;
- adj = 1;
- clazz += "Next";
- }else{
- number = i - firstDay + 1;
- clazz += "Current";
- }
- if(adj){
- date = this.dateFuncObj.add(date, "month", adj);
- }
- date.setDate(number);
- if(!this.dateFuncObj.compare(date, today, "date")){
- clazz = "dijitCalendarCurrentDate " + clazz;
- }
- if(this._isSelectedDate(date, this.lang)){
- clazz = "dijitCalendarSelectedDate " + clazz;
- template.setAttribute("aria-selected", true);
- }else{
- template.setAttribute("aria-selected", false);
- }
- if(this.isDisabledDate(date, this.lang)){
- clazz = "dijitCalendarDisabledDate " + clazz;
- template.setAttribute("aria-disabled", true);
- }else{
- clazz = "dijitCalendarEnabledDate " + clazz;
- template.removeAttribute("aria-disabled");
- }
- var clazz2 = this.getClassForDate(date, this.lang);
- if(clazz2){
- clazz = clazz2 + " " + clazz;
- }
- template.className = clazz + "Month dijitCalendarDateTemplate";
- // Each cell has an associated integer value representing it's date
- var dateVal = date.valueOf();
- this._date2cell[dateVal] = template;
- template.dijitDateValue = dateVal;
- // Set Date string (ex: "13").
- this._setText(this.dateLabels[idx], date.getDateLocalized ? date.getDateLocalized(this.lang) : date.getDate());
- }, this);
- // set name of this month
- this.monthWidget.set("month", month);
- // Fill in localized prev/current/next years
- var y = month.getFullYear() - 1;
- var d = new this.dateClassObj();
- array.forEach(["previous", "current", "next"], function(name){
- d.setFullYear(y++);
- this._setText(this[name+"YearLabelNode"],
- this.dateLocaleModule.format(d, {selector:'year', locale:this.lang}));
- }, this);
- },
- goToToday: function(){
- // summary:
- // Sets calendar's value to today's date
- this.set('value', new this.dateClassObj());
- },
- constructor: function(/*Object*/args){
- this.datePackage = args.datePackage || this.datePackage;
- this.dateFuncObj = typeof this.datePackage == "string" ?
- lang.getObject(this.datePackage, false) :// "string" part for back-compat, remove for 2.0
- this.datePackage;
- this.dateClassObj = this.dateFuncObj.Date || Date;
- this.dateLocaleModule = lang.getObject("locale", false, this.dateFuncObj);
- },
- _createMonthWidget: function(){
- // summary:
- // Creates the drop down button that displays the current month and lets user pick a new one
- return CalendarLite._MonthWidget({
- id: this.id + "_mw",
- lang: this.lang,
- dateLocaleModule: this.dateLocaleModule
- }, this.monthNode);
- },
- buildRendering: function(){
- // Markup for days of the week (referenced from template)
- var d = this.dowTemplateString,
- dayNames = this.dateLocaleModule.getNames('days', this.dayWidth, 'standAlone', this.lang),
- dayOffset = cldrSupplemental.getFirstDayOfWeek(this.lang);
- this.dayCellsHtml = string.substitute([d,d,d,d,d,d,d].join(""), {d: ""}, function(){
- return dayNames[dayOffset++ % 7]
- });
- // Markup for dates of the month (referenced from template), but without numbers filled in
- var r = string.substitute(this.weekTemplateString, {d: this.dateTemplateString});
- this.dateRowsHtml = [r,r,r,r,r,r].join("");
- // Instantiate from template.
- // dateCells and dateLabels arrays filled when _Templated parses my template.
- this.dateCells = [];
- this.dateLabels = [];
- this.inherited(arguments);
- dom.setSelectable(this.domNode, false);
- var dateObj = new this.dateClassObj(this.currentFocus);
- this._supportingWidgets.push(this.monthWidget = this._createMonthWidget());
- this.set('currentFocus', dateObj, false); // draw the grid to the month specified by currentFocus
- // Set up connects for increment/decrement of months/years
- var connect = lang.hitch(this, function(nodeProp, part, amount){
- this.connect(this[nodeProp], "onclick", function(){
- this._setCurrentFocusAttr(this.dateFuncObj.add(this.currentFocus, part, amount));
- });
- });
- connect("incrementMonth", "month", 1);
- connect("decrementMonth", "month", -1);
- connect("nextYearLabelNode", "year", 1);
- connect("previousYearLabelNode", "year", -1);
- },
- _setCurrentFocusAttr: function(/*Date*/ date, /*Boolean*/ forceFocus){
- // summary:
- // If the calendar currently has focus, then focuses specified date,
- // changing the currently displayed month/year if necessary.
- // If the calendar doesn't have focus, updates currently
- // displayed month/year, and sets the cell that will get focus.
- // forceFocus:
- // If true, will focus() the cell even if calendar itself doesn't have focus
- var oldFocus = this.currentFocus,
- oldCell = oldFocus && this._date2cell ? this._date2cell[oldFocus.valueOf()] : null;
- // round specified value to nearest day (1am to avoid issues when DST shift occurs at midnight, see #8521, #9366)
- date = new this.dateClassObj(date);
- date.setHours(1, 0, 0, 0);
- this._set("currentFocus", date);
- // TODO: only re-populate grid when month/year has changed
- this._populateGrid();
- // set tabIndex=0 on new cell, and focus it (but only if Calendar itself is focused)
- var newCell = this._date2cell[date.valueOf()];
- newCell.setAttribute("tabIndex", this.tabIndex);
- if(this.focused || forceFocus){
- newCell.focus();
- }
- // set tabIndex=-1 on old focusable cell
- if(oldCell && oldCell != newCell){
- if(has("webkit")){ // see #11064 about webkit bug
- oldCell.setAttribute("tabIndex", "-1");
- }else{
- oldCell.removeAttribute("tabIndex");
- }
- }
- },
- focus: function(){
- // summary:
- // Focus the calendar by focusing one of the calendar cells
- this._setCurrentFocusAttr(this.currentFocus, true);
- },
- _onDayClick: function(/*Event*/ evt){
- // summary:
- // Handler for day clicks, selects the date if appropriate
- // tags:
- // protected
- event.stop(evt);
- for(var node = evt.target; node && !node.dijitDateValue; node = node.parentNode);
- if(node && !domClass.contains(node, "dijitCalendarDisabledDate")){
- this.set('value', node.dijitDateValue);
- }
- },
- onChange: function(/*Date*/ /*===== date =====*/){
- // summary:
- // Called only when the selected date has changed
- },
- _isSelectedDate: function(dateObject /*===== , locale =====*/){
- // summary:
- // Extension point so developers can subclass Calendar to
- // support multiple (concurrently) selected dates
- // dateObject: Date
- // locale: String?
- // tags:
- // protected extension
- return this._isValidDate(this.value) && !this.dateFuncObj.compare(dateObject, this.value, "date")
- },
- isDisabledDate: function(/*===== dateObject, locale =====*/){
- // summary:
- // May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
- // dateObject: Date
- // locale: String?
- // tags:
- // extension
- /*=====
- return false; // Boolean
- =====*/
- },
- getClassForDate: function(/*===== dateObject, locale =====*/){
- // summary:
- // May be overridden to return CSS classes to associate with the date entry for the given dateObject,
- // for example to indicate a holiday in specified locale.
- // dateObject: Date
- // locale: String?
- // tags:
- // extension
- /*=====
- return ""; // String
- =====*/
- }
- });
- CalendarLite._MonthWidget = declare("dijit.CalendarLite._MonthWidget", _WidgetBase, {
- // summary:
- // Displays name of current month padded to the width of the month
- // w/the longest name, so that changing months doesn't change width.
- //
- // Create as new dijit.Calendar._MonthWidget({
- // lang: ...,
- // dateLocaleModule: ...
- // })
- _setMonthAttr: function(month){
- // summary:
- // Set the current month to display as a label
- var monthNames = this.dateLocaleModule.getNames('months', 'wide', 'standAlone', this.lang, month),
- spacer =
- (has("ie") == 6 ? "" : "<div class='dijitSpacer'>" +
- array.map(monthNames, function(s){ return "<div>" + s + "</div>"; }).join("") + "</div>");
- // Set name of current month and also fill in spacer element with all the month names
- // (invisible) so that the maximum width will affect layout. But not on IE6 because then
- // the center <TH> overlaps the right <TH> (due to a browser bug).
- this.domNode.innerHTML =
- spacer +
- "<div class='dijitCalendarMonthLabel dijitCalendarCurrentMonthLabel'>" +
- monthNames[month.getMonth()] + "</div>";
- }
- });
- return CalendarLite;
- });
- },
- 'dojox/grid/_Events':function(){
- define("dojox/grid/_Events", [
- "dojo/keys",
- "dojo/dom-class",
- "dojo/_base/declare",
- "dojo/_base/event",
- "dojo/_base/sniff"
- ], function(keys, domClass, declare, event, has){
- return declare("dojox.grid._Events", null, {
- // summary:
- // _Grid mixin that provides default implementations for grid events.
- // description:
- // Default synthetic events dispatched for _Grid. dojo.connect to events to
- // retain default implementation or override them for custom handling.
-
- // cellOverClass: String
- // css class to apply to grid cells over which the cursor is placed.
- cellOverClass: "dojoxGridCellOver",
-
- onKeyEvent: function(e){
- // summary: top level handler for Key Events
- this.dispatchKeyEvent(e);
- },
- onContentEvent: function(e){
- // summary: Top level handler for Content events
- this.dispatchContentEvent(e);
- },
- onHeaderEvent: function(e){
- // summary: Top level handler for header events
- this.dispatchHeaderEvent(e);
- },
- onStyleRow: function(inRow){
- // summary:
- // Perform row styling on a given row. Called whenever row styling is updated.
- //
- // inRow: Object
- // Object containing row state information: selected, true if the row is selcted; over:
- // true of the mouse is over the row; odd: true if the row is odd. Use customClasses and
- // customStyles to control row css classes and styles; both properties are strings.
- //
- // example: onStyleRow({ selected: true, over:true, odd:false })
- var i = inRow;
- i.customClasses += (i.odd?" dojoxGridRowOdd":"") + (i.selected?" dojoxGridRowSelected":"") + (i.over?" dojoxGridRowOver":"");
- this.focus.styleRow(inRow);
- this.edit.styleRow(inRow);
- },
-
- onKeyDown: function(e){
- // summary:
- // Grid key event handler. By default enter begins editing and applies edits, escape cancels an edit,
- // tab, shift-tab, and arrow keys move grid cell focus.
- if(e.altKey || e.metaKey){
- return;
- }
- var colIdx;
- switch(e.keyCode){
- case keys.ESCAPE:
- this.edit.cancel();
- break;
- case keys.ENTER:
- if(!this.edit.isEditing()){
- colIdx = this.focus.getHeaderIndex();
- if(colIdx >= 0) {
- this.setSortIndex(colIdx);
- break;
- }else {
- this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
- }
- event.stop(e);
- }
- if(!e.shiftKey){
- var isEditing = this.edit.isEditing();
- this.edit.apply();
- if(!isEditing){
- this.edit.setEditCell(this.focus.cell, this.focus.rowIndex);
- }
- }
- if (!this.edit.isEditing()){
- var curView = this.focus.focusView || this.views.views[0]; //if no focusView than only one view
- curView.content.decorateEvent(e);
- this.onRowClick(e);
- event.stop(e);
- }
- break;
- case keys.SPACE:
- if(!this.edit.isEditing()){
- colIdx = this.focus.getHeaderIndex();
- if(colIdx >= 0) {
- this.setSortIndex(colIdx);
- break;
- }else {
- this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
- }
- event.stop(e);
- }
- break;
- case keys.TAB:
- this.focus[e.shiftKey ? 'previousKey' : 'nextKey'](e);
- break;
- case keys.LEFT_ARROW:
- case keys.RIGHT_ARROW:
- if(!this.edit.isEditing()){
- var keyCode = e.keyCode; // IE seems to lose after stopEvent when modifier keys
- event.stop(e);
- colIdx = this.focus.getHeaderIndex();
- if (colIdx >= 0 && (e.shiftKey && e.ctrlKey)){
- this.focus.colSizeAdjust(e, colIdx, (keyCode == keys.LEFT_ARROW ? -1 : 1)*5);
- }
- else{
- var offset = (keyCode == keys.LEFT_ARROW) ? 1 : -1;
- if(this.isLeftToRight()){ offset *= -1; }
- this.focus.move(0, offset);
- }
- }
- break;
- case keys.UP_ARROW:
- if(!this.edit.isEditing() && this.focus.rowIndex !== 0){
- event.stop(e);
- this.focus.move(-1, 0);
- }
- break;
- case keys.DOWN_ARROW:
- if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.rowCount){
- event.stop(e);
- this.focus.move(1, 0);
- }
- break;
- case keys.PAGE_UP:
- if(!this.edit.isEditing() && this.focus.rowIndex !== 0){
- event.stop(e);
- if(this.focus.rowIndex != this.scroller.firstVisibleRow+1){
- this.focus.move(this.scroller.firstVisibleRow-this.focus.rowIndex, 0);
- }else{
- this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex-1));
- this.focus.move(this.scroller.firstVisibleRow-this.scroller.lastVisibleRow+1, 0);
- }
- }
- break;
- case keys.PAGE_DOWN:
- if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.rowCount){
- event.stop(e);
- if(this.focus.rowIndex != this.scroller.lastVisibleRow-1){
- this.focus.move(this.scroller.lastVisibleRow-this.focus.rowIndex-1, 0);
- }else{
- this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex+1));
- this.focus.move(this.scroller.lastVisibleRow-this.scroller.firstVisibleRow-1, 0);
- }
- }
- break;
- default:
- break;
- }
- },
-
- onMouseOver: function(e){
- // summary:
- // Event fired when mouse is over the grid.
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- e.rowIndex == -1 ? this.onHeaderCellMouseOver(e) : this.onCellMouseOver(e);
- },
-
- onMouseOut: function(e){
- // summary:
- // Event fired when mouse moves out of the grid.
- // e: Event
- // Decorated event object that contains reference to grid, cell, and rowIndex
- e.rowIndex == -1 ? this.onHeaderCellMouseOut(e) : this.onCellMouseOut(e);
- },
-
- onMouseDown: function(e){
- // summary:
- // Event fired when mouse is down inside grid.
- // e: Event
- // Decorated event object that contains reference to grid, cell, and rowIndex
- e.rowIndex == -1 ? this.onHeaderCellMouseDown(e) : this.onCellMouseDown(e);
- },
-
- onMouseOverRow: function(e){
- // summary:
- // Event fired when mouse is over any row (data or header).
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- if(!this.rows.isOver(e.rowIndex)){
- this.rows.setOverRow(e.rowIndex);
- e.rowIndex == -1 ? this.onHeaderMouseOver(e) : this.onRowMouseOver(e);
- }
- },
- onMouseOutRow: function(e){
- // summary:
- // Event fired when mouse moves out of any row (data or header).
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- if(this.rows.isOver(-1)){
- this.onHeaderMouseOut(e);
- }else if(!this.rows.isOver(-2)){
- this.rows.setOverRow(-2);
- this.onRowMouseOut(e);
- }
- },
-
- onMouseDownRow: function(e){
- // summary:
- // Event fired when mouse is down inside grid row
- // e: Event
- // Decorated event object that contains reference to grid, cell, and rowIndex
- if(e.rowIndex != -1)
- this.onRowMouseDown(e);
- },
- // cell events
- onCellMouseOver: function(e){
- // summary:
- // Event fired when mouse is over a cell.
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- if(e.cellNode){
- domClass.add(e.cellNode, this.cellOverClass);
- }
- },
-
- onCellMouseOut: function(e){
- // summary:
- // Event fired when mouse moves out of a cell.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- if(e.cellNode){
- domClass.remove(e.cellNode, this.cellOverClass);
- }
- },
-
- onCellMouseDown: function(e){
- // summary:
- // Event fired when mouse is down in a header cell.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onCellClick: function(e){
- // summary:
- // Event fired when a cell is clicked.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this._click[0] = this._click[1];
- this._click[1] = e;
- if(!this.edit.isEditCell(e.rowIndex, e.cellIndex)){
- this.focus.setFocusCell(e.cell, e.rowIndex);
- }
- // in some cases click[0] is null which causes false doubeClicks. Fixes #100703
- if(this._click.length > 1 && this._click[0] == null){
- this._click.shift();
- }
- this.onRowClick(e);
- },
- onCellDblClick: function(e){
- // summary:
- // Event fired when a cell is double-clicked.
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- var event;
- if(this._click.length > 1 && has("ie")){
- event = this._click[1];
- }else if(this._click.length > 1 && this._click[0].rowIndex != this._click[1].rowIndex){
- event = this._click[0];
- }else{
- event = e;
- }
- this.focus.setFocusCell(event.cell, event.rowIndex);
- this.onRowClick(event);
- this.edit.setEditCell(event.cell, event.rowIndex);
- this.onRowDblClick(e);
- },
- onCellContextMenu: function(e){
- // summary:
- // Event fired when a cell context menu is accessed via mouse right click.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this.onRowContextMenu(e);
- },
- onCellFocus: function(inCell, inRowIndex){
- // summary:
- // Event fired when a cell receives focus.
- // inCell: Object
- // Cell object containing properties of the grid column.
- // inRowIndex: Integer
- // Index of the grid row
- this.edit.cellFocus(inCell, inRowIndex);
- },
- // row events
- onRowClick: function(e){
- // summary:
- // Event fired when a row is clicked.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this.edit.rowClick(e);
- this.selection.clickSelectEvent(e);
- },
- onRowDblClick: function(e){
- // summary:
- // Event fired when a row is double clicked.
- // e: Event
- // decorated event object which contains reference to grid, cell, and rowIndex
- },
- onRowMouseOver: function(e){
- // summary:
- // Event fired when mouse moves over a data row.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onRowMouseOut: function(e){
- // summary:
- // Event fired when mouse moves out of a data row.
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- },
-
- onRowMouseDown: function(e){
- // summary:
- // Event fired when mouse is down in a row.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onRowContextMenu: function(e){
- // summary:
- // Event fired when a row context menu is accessed via mouse right click.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- event.stop(e);
- },
- // header events
- onHeaderMouseOver: function(e){
- // summary:
- // Event fired when mouse moves over the grid header.
- // e: Event
- // Decorated event object contains reference to grid, cell, and rowIndex
- },
- onHeaderMouseOut: function(e){
- // summary:
- // Event fired when mouse moves out of the grid header.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onHeaderCellMouseOver: function(e){
- // summary:
- // Event fired when mouse moves over a header cell.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- if(e.cellNode){
- domClass.add(e.cellNode, this.cellOverClass);
- }
- },
- onHeaderCellMouseOut: function(e){
- // summary:
- // Event fired when mouse moves out of a header cell.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- if(e.cellNode){
- domClass.remove(e.cellNode, this.cellOverClass);
- }
- },
-
- onHeaderCellMouseDown: function(e) {
- // summary:
- // Event fired when mouse is down in a header cell.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onHeaderClick: function(e){
- // summary:
- // Event fired when the grid header is clicked.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onHeaderCellClick: function(e){
- // summary:
- // Event fired when a header cell is clicked.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this.setSortIndex(e.cell.index);
- this.onHeaderClick(e);
- },
- onHeaderDblClick: function(e){
- // summary:
- // Event fired when the grid header is double clicked.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- },
- onHeaderCellDblClick: function(e){
- // summary:
- // Event fired when a header cell is double clicked.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this.onHeaderDblClick(e);
- },
- onHeaderCellContextMenu: function(e){
- // summary:
- // Event fired when a header cell context menu is accessed via mouse right click.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- this.onHeaderContextMenu(e);
- },
- onHeaderContextMenu: function(e){
- // summary:
- // Event fired when the grid header context menu is accessed via mouse right click.
- // e: Event
- // Decorated event object which contains reference to grid, cell, and rowIndex
- if(!this.headerMenu){
- event.stop(e);
- }
- },
- // editing
- onStartEdit: function(inCell, inRowIndex){
- // summary:
- // Event fired when editing is started for a given grid cell
- // inCell: Object
- // Cell object containing properties of the grid column.
- // inRowIndex: Integer
- // Index of the grid row
- },
- onApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
- // summary:
- // Event fired when editing is applied for a given grid cell
- // inValue: String
- // Value from cell editor
- // inRowIndex: Integer
- // Index of the grid row
- // inFieldIndex: Integer
- // Index in the grid's data store
- },
- onCancelEdit: function(inRowIndex){
- // summary:
- // Event fired when editing is cancelled for a given grid cell
- // inRowIndex: Integer
- // Index of the grid row
- },
- onApplyEdit: function(inRowIndex){
- // summary:
- // Event fired when editing is applied for a given grid row
- // inRowIndex: Integer
- // Index of the grid row
- },
- onCanSelect: function(inRowIndex){
- // summary:
- // Event to determine if a grid row may be selected
- // inRowIndex: Integer
- // Index of the grid row
- // returns: Boolean
- // true if the row can be selected
- return true;
- },
- onCanDeselect: function(inRowIndex){
- // summary:
- // Event to determine if a grid row may be deselected
- // inRowIndex: Integer
- // Index of the grid row
- // returns: Boolean
- // true if the row can be deselected
- return true;
- },
- onSelected: function(inRowIndex){
- // summary:
- // Event fired when a grid row is selected
- // inRowIndex: Integer
- // Index of the grid row
- this.updateRowStyles(inRowIndex);
- },
- onDeselected: function(inRowIndex){
- // summary:
- // Event fired when a grid row is deselected
- // inRowIndex: Integer
- // Index of the grid row
- this.updateRowStyles(inRowIndex);
- },
- onSelectionChanged: function(){
- }
- });
- });
- },
- 'dijit/CheckedMenuItem':function(){
- require({cache:{
- 'url:dijit/templates/CheckedMenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitemcheckbox\" tabIndex=\"-1\"\r\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\r\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\r\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\r\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">✓</span>\r\n\t</td>\r\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode,labelNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\r\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\"> </td>\r\n</tr>\r\n"}});
- define("dijit/CheckedMenuItem", [
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.toggle
- "./MenuItem",
- "dojo/text!./templates/CheckedMenuItem.html",
- "./hccss"
- ], function(declare, domClass, MenuItem, template){
- /*=====
- var MenuItem = dijit.MenuItem;
- =====*/
- // module:
- // dijit/CheckedMenuItem
- // summary:
- // A checkbox-like menu item for toggling on and off
- return declare("dijit.CheckedMenuItem", MenuItem, {
- // summary:
- // A checkbox-like menu item for toggling on and off
- templateString: template,
- // checked: Boolean
- // Our checked state
- checked: false,
- _setCheckedAttr: function(/*Boolean*/ checked){
- // summary:
- // Hook so attr('checked', bool) works.
- // Sets the class and state for the check box.
- domClass.toggle(this.domNode, "dijitCheckedMenuItemChecked", checked);
- this.domNode.setAttribute("aria-checked", checked);
- this._set("checked", checked);
- },
- iconClass: "", // override dijitNoIcon
- onChange: function(/*Boolean*/ /*===== checked =====*/){
- // summary:
- // User defined function to handle check/uncheck events
- // tags:
- // callback
- },
- _onClick: function(/*Event*/ e){
- // summary:
- // Clicking this item just toggles its state
- // tags:
- // private
- if(!this.disabled){
- this.set("checked", !this.checked);
- this.onChange(this.checked);
- }
- this.inherited(arguments);
- }
- });
- });
- },
- 'dojox/io/xhrMultiPart':function(){
- define("dojox/io/xhrMultiPart", [
- "dojo/_base/kernel",
- "dojo/_base/array",
- "dojo/_base/xhr",
- "dojo/query",
- "dojox/uuid/generateRandomUuid"
- ], function(dojo, array, xhr, query, generateRandomUuid){
- dojo.getObject("io.xhrMultiPart", true, dojox);
- /*=====
- dojox.io.__xhrContentArgs = function(){
- // name: String
- // Name of the form value.
- // content: String
- // The contents of the value.
- // filename: String?
- // An optional filename to pass to the server, as defined by the boundary.
- // contentType: String?
- // An optional content-type (MIME) to pass to the server, if value is being
- // treated as a file.
- // charset: String?
- // Optional charset to pass, for the server to interpret the file correctly.
- // contentTransferEncoding: String?
- // Optional transfer encoding header value.
- this.name = name;
- this.content = content;
- this.filename = filename;
- this.contentType = contentType;
- this.charset = charset;
- this.contentTransferEncoding = contentTransferEncoding;
- }
- =====*/
- function _createPart(/* dojox.io.__xhrContentArgs */args, /* String */boundary){
- // summary
- // Assemble an array of boundary parts based on the passed values in args.
- if(!args["name"] && !args["content"]){
- throw new Error("Each part of a multi-part request requires 'name' and 'content'.");
- }
- var tmp = [];
- tmp.push(
- "--" + boundary,
- "Content-Disposition: form-data; name=\"" + args.name + "\"" + (args["filename"] ? "; filename=\"" + args.filename + "\"" : "")
- );
- if(args["contentType"]){
- var ct = "Content-Type: " + args.contentType;
- if(args["charset"]){
- ct += "; Charset=" + args.charset;
- }
- tmp.push(ct);
- }
- if(args["contentTransferEncoding"]){
- tmp.push("Content-Transfer-Encoding: " + args.contentTransferEncoding);
- }
- tmp.push("", args.content);
- return tmp; // Array
- }
- function _partsFromNode(/* DOMNode */node, /* String */boundary){
- // summary
- // Assemble an array of boundary parts based on the passed FORM node.
- var o=dojo.formToObject(node), parts=[];
- for(var p in o){
- if(dojo.isArray(o[p])){
- dojo.forEach(o[p], function(item){
- parts = parts.concat(_createPart({ name: p, content: item }, boundary));
- });
- } else {
- parts = parts.concat(_createPart({ name: p, content: o[p] }, boundary));
- }
- }
- return parts; // Array
- }
- /*=====
- dojox.io.__xhrMultiArgs = function(){
- // url: String
- // URL to server endpoint.
- // content: Object?
- // Contains properties with string values. These
- // properties will be serialized using multi-part
- // boundaries.
- // file: Object?
- // Alias for "content". Provided for backwards compatibility.
- // timeout: Integer?
- // Milliseconds to wait for the response. If this time
- // passes, the then error callbacks are called.
- // form: DOMNode?
- // DOM node for a form. Used to extract the form values
- // and send to the server; each form value will be serialized
- // using multi-part boundaries.
- // preventCache: Boolean?
- // Default is false. If true, then a
- // "dojo.preventCache" parameter is sent in the request
- // with a value that changes with each request
- // (timestamp). Useful only with GET-type requests.
- // handleAs: String?
- // Acceptable values depend on the type of IO
- // transport (see specific IO calls for more information).
- // load: Function?
- // function(response, ioArgs){}. response is an Object, ioArgs
- // is of type dojo.__IoCallbackArgs. The load function will be
- // called on a successful response.
- // error: Function?
- // function(response, ioArgs){}. response is an Object, ioArgs
- // is of type dojo.__IoCallbackArgs. The error function will
- // be called in an error case.
- // handle: Function?
- // function(response, ioArgs){}. response is an Object, ioArgs
- // is of type dojo.__IoCallbackArgs. The handle function will
- // be called in either the successful or error case.
- this.url = url;
- this.content = content;
- this.file = file;
- this.timeout = timeout;
- this.form = form;
- this.preventCache = preventCache;
- this.handleAs = handleAs;
- this.load = load;
- this.error = error;
- this.handle = handle;
- }
- =====*/
- dojox.io.xhrMultiPart = function(/* dojox.io.__xhrMultiArgs */args){
- if(!args["file"] && !args["content"] && !args["form"]){
- throw new Error("content, file or form must be provided to dojox.io.xhrMultiPart's arguments");
- }
- // unique guid as a boundary value for multipart posts
- var boundary=generateRandomUuid(), tmp=[], out="";
- if(args["file"] || args["content"]){
- var v = args["file"] || args["content"];
- dojo.forEach((dojo.isArray(v) ? v : [v]), function(item){
- tmp = tmp.concat(_createPart(item, boundary));
- });
- }
- else if(args["form"]){
- if(query("input[type=file]", args["form"]).length){
- throw new Error("dojox.io.xhrMultiPart cannot post files that are values of an INPUT TYPE=FILE. Use dojo.io.iframe.send() instead.");
- }
- tmp = _partsFromNode(args["form"], boundary);
- }
- if(tmp.length){
- tmp.push("--"+boundary+"--", "");
- out = tmp.join("\r\n");
- }
- console.log(out);
- return dojo.rawXhrPost(dojo.mixin(args, {
- contentType: "multipart/form-data; boundary=" + boundary,
- postData: out
- })); // dojo.Deferred
- };
- return dojox.io.xhrMultiPart;
- });
- },
- 'dojo/io/iframe':function(){
- define("dojo/io/iframe", ["../main", "require"], function(dojo, require) {
- // module:
- // dojo/io/iframe
- // summary:
- // TODOC
- dojo.getObject("io", true, dojo);
- /*=====
- dojo.declare("dojo.io.iframe.__ioArgs", dojo.__IoArgs, {
- constructor: function(){
- // summary:
- // All the properties described in the dojo.__ioArgs type, apply
- // to this type. The following additional properties are allowed
- // for dojo.io.iframe.send():
- // method: String?
- // The HTTP method to use. "GET" or "POST" are the only supported
- // values. It will try to read the value from the form node's
- // method, then try this argument. If neither one exists, then it
- // defaults to POST.
- // handleAs: String?
- // Specifies what format the result data should be given to the
- // load/handle callback. Valid values are: text, html, xml, json,
- // javascript. IMPORTANT: For all values EXCEPT html and xml, The
- // server response should be an HTML file with a textarea element.
- // The response data should be inside the textarea element. Using an
- // HTML document the only reliable, cross-browser way this
- // transport can know when the response has loaded. For the html
- // handleAs value, just return a normal HTML document. NOTE: xml
- // is now supported with this transport (as of 1.1+); a known issue
- // is if the XML document in question is malformed, Internet Explorer
- // will throw an uncatchable error.
- // content: Object?
- // If "form" is one of the other args properties, then the content
- // object properties become hidden form form elements. For
- // instance, a content object of {name1 : "value1"} is converted
- // to a hidden form element with a name of "name1" and a value of
- // "value1". If there is not a "form" property, then the content
- // object is converted into a name=value&name=value string, by
- // using dojo.objectToQuery().
- this.method = method;
- this.handleAs = handleAs;
- this.content = content;
- }
- });
- =====*/
- dojo.io.iframe = {
- // summary:
- // Sends an Ajax I/O call using and Iframe (for instance, to upload files)
- create: function(/*String*/fname, /*String*/onloadstr, /*String?*/uri){
- // summary:
- // Creates a hidden iframe in the page. Used mostly for IO
- // transports. You do not need to call this to start a
- // dojo.io.iframe request. Just call send().
- // fname: String
- // The name of the iframe. Used for the name attribute on the
- // iframe.
- // onloadstr: String
- // A string of JavaScript that will be executed when the content
- // in the iframe loads.
- // uri: String
- // The value of the src attribute on the iframe element. If a
- // value is not given, then dojo/resources/blank.html will be
- // used.
- if(window[fname]){ return window[fname]; }
- if(window.frames[fname]){ return window.frames[fname]; }
- var turi = uri;
- if(!turi){
- if(dojo.config["useXDomain"] && !dojo.config["dojoBlankHtmlUrl"]){
- console.warn("dojo.io.iframe.create: When using cross-domain Dojo builds,"
- + " please save dojo/resources/blank.html to your domain and set djConfig.dojoBlankHtmlUrl"
- + " to the path on your domain to blank.html");
- }
- turi = (dojo.config["dojoBlankHtmlUrl"]||require.toUrl("../resources/blank.html"));
- }
- var cframe = dojo.place(
- '<iframe id="'+fname+'" name="'+fname+'" src="'+turi+'" onload="'+onloadstr+
- '" style="position: absolute; left: 1px; top: 1px; height: 1px; width: 1px; visibility: hidden">',
- dojo.body());
- window[fname] = cframe;
- return cframe;
- },
- setSrc: function(/*DOMNode*/iframe, /*String*/src, /*Boolean*/replace){
- //summary:
- // Sets the URL that is loaded in an IFrame. The replace parameter
- // indicates whether location.replace() should be used when
- // changing the location of the iframe.
- try{
- if(!replace){
- if(dojo.isWebKit){
- iframe.location = src;
- }else{
- frames[iframe.name].location = src;
- }
- }else{
- // Fun with DOM 0 incompatibilities!
- var idoc;
- if(dojo.isIE || dojo.isWebKit){
- idoc = iframe.contentWindow.document;
- }else{ // if(d.isMozilla){
- idoc = iframe.contentWindow;
- }
- //For Safari (at least 2.0.3) and Opera, if the iframe
- //has just been created but it doesn't have content
- //yet, then iframe.document may be null. In that case,
- //use iframe.location and return.
- if(!idoc){
- iframe.location = src;
- }else{
- idoc.location.replace(src);
- }
- }
- }catch(e){
- console.log("dojo.io.iframe.setSrc: ", e);
- }
- },
- doc: function(/*DOMNode*/iframeNode){
- //summary: Returns the document object associated with the iframe DOM Node argument.
- return iframeNode.contentDocument || // W3
- (
- (
- (iframeNode.name) && (iframeNode.document) &&
- (dojo.doc.getElementsByTagName("iframe")[iframeNode.name].contentWindow) &&
- (dojo.doc.getElementsByTagName("iframe")[iframeNode.name].contentWindow.document)
- )
- ) || // IE
- (
- (iframeNode.name)&&(dojo.doc.frames[iframeNode.name])&&
- (dojo.doc.frames[iframeNode.name].document)
- ) || null;
- },
- send: function(/*dojo.io.iframe.__ioArgs*/args){
- //summary:
- // Function that sends the request to the server.
- // This transport can only process one send() request at a time, so if send() is called
- //multiple times, it will queue up the calls and only process one at a time.
- if(!this["_frame"]){
- this._frame = this.create(this._iframeName, dojo._scopeName + ".io.iframe._iframeOnload();");
- }
- //Set up the deferred.
- var dfd = dojo._ioSetArgs(
- args,
- function(/*Deferred*/dfd){
- //summary: canceller function for dojo._ioSetArgs call.
- dfd.canceled = true;
- dfd.ioArgs._callNext();
- },
- function(/*Deferred*/dfd){
- //summary: okHandler function for dojo._ioSetArgs call.
- var value = null;
- try{
- var ioArgs = dfd.ioArgs;
- var dii = dojo.io.iframe;
- var ifd = dii.doc(dii._frame);
- var handleAs = ioArgs.handleAs;
- //Assign correct value based on handleAs value.
- value = ifd; //html
- if(handleAs != "html"){
- if(handleAs == "xml"){
- // FF, Saf 3+ and Opera all seem to be fine with ifd being xml. We have to
- // do it manually for IE6-8. Refs #6334.
- if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
- dojo.query("a", dii._frame.contentWindow.document.documentElement).orphan();
- var xmlText=(dii._frame.contentWindow.document).documentElement.innerText;
- xmlText=xmlText.replace(/>\s+</g, "><");
- xmlText=dojo.trim(xmlText);
- //Reusing some code in base dojo for handling XML content. Simpler and keeps
- //Core from duplicating the effort needed to locate the XML Parser on IE.
- var fauxXhr = { responseText: xmlText };
- value = dojo._contentHandlers["xml"](fauxXhr); // DOMDocument
- }
- }else{
- value = ifd.getElementsByTagName("textarea")[0].value; //text
- if(handleAs == "json"){
- value = dojo.fromJson(value); //json
- }else if(handleAs == "javascript"){
- value = dojo.eval(value); //javascript
- }
- }
- }
- }catch(e){
- value = e;
- }finally{
- ioArgs._callNext();
- }
- return value;
- },
- function(/*Error*/error, /*Deferred*/dfd){
- //summary: errHandler function for dojo._ioSetArgs call.
- dfd.ioArgs._hasError = true;
- dfd.ioArgs._callNext();
- return error;
- }
- );
- //Set up a function that will fire the next iframe request. Make sure it only
- //happens once per deferred.
- dfd.ioArgs._callNext = function(){
- if(!this["_calledNext"]){
- this._calledNext = true;
- dojo.io.iframe._currentDfd = null;
- dojo.io.iframe._fireNextRequest();
- }
- };
- this._dfdQueue.push(dfd);
- this._fireNextRequest();
- //Add it the IO watch queue, to get things like timeout support.
- dojo._ioWatch(
- dfd,
- function(/*Deferred*/dfd){
- //validCheck
- return !dfd.ioArgs["_hasError"];
- },
- function(dfd){
- //ioCheck
- return (!!dfd.ioArgs["_finished"]);
- },
- function(dfd){
- //resHandle
- if(dfd.ioArgs._finished){
- dfd.callback(dfd);
- }else{
- dfd.errback(new Error("Invalid dojo.io.iframe request state"));
- }
- }
- );
- return dfd;
- },
- _currentDfd: null,
- _dfdQueue: [],
- _iframeName: dojo._scopeName + "IoIframe",
- _fireNextRequest: function(){
- //summary: Internal method used to fire the next request in the bind queue.
- try{
- if((this._currentDfd)||(this._dfdQueue.length == 0)){ return; }
- //Find next deferred, skip the canceled ones.
- do{
- var dfd = this._currentDfd = this._dfdQueue.shift();
- } while(dfd && dfd.canceled && this._dfdQueue.length);
- //If no more dfds, cancel.
- if(!dfd || dfd.canceled){
- this._currentDfd = null;
- return;
- }
- var ioArgs = dfd.ioArgs;
- var args = ioArgs.args;
- ioArgs._contentToClean = [];
- var fn = dojo.byId(args["form"]);
- var content = args["content"] || {};
- if(fn){
- if(content){
- // if we have things in content, we need to add them to the form
- // before submission
- var pHandler = function(name, value) {
- dojo.create("input", {type: "hidden", name: name, value: value}, fn);
- ioArgs._contentToClean.push(name);
- };
- for(var x in content){
- var val = content[x];
- if(dojo.isArray(val) && val.length > 1){
- var i;
- for (i = 0; i < val.length; i++) {
- pHandler(x,val[i]);
- }
- }else{
- if(!fn[x]){
- pHandler(x,val);
- }else{
- fn[x].value = val;
- }
- }
- }
- }
- //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
- //so use it for all. See #2844
- var actnNode = fn.getAttributeNode("action");
- var mthdNode = fn.getAttributeNode("method");
- var trgtNode = fn.getAttributeNode("target");
- if(args["url"]){
- ioArgs._originalAction = actnNode ? actnNode.value : null;
- if(actnNode){
- actnNode.value = args.url;
- }else{
- fn.setAttribute("action",args.url);
- }
- }
- if(!mthdNode || !mthdNode.value){
- if(mthdNode){
- mthdNode.value= (args["method"]) ? args["method"] : "post";
- }else{
- fn.setAttribute("method", (args["method"]) ? args["method"] : "post");
- }
- }
- ioArgs._originalTarget = trgtNode ? trgtNode.value: null;
- if(trgtNode){
- trgtNode.value = this._iframeName;
- }else{
- fn.setAttribute("target", this._iframeName);
- }
- fn.target = this._iframeName;
- dojo._ioNotifyStart(dfd);
- fn.submit();
- }else{
- // otherwise we post a GET string by changing URL location for the
- // iframe
- var tmpUrl = args.url + (args.url.indexOf("?") > -1 ? "&" : "?") + ioArgs.query;
- dojo._ioNotifyStart(dfd);
- this.setSrc(this._frame, tmpUrl, true);
- }
- }catch(e){
- dfd.errback(e);
- }
- },
- _iframeOnload: function(){
- var dfd = this._currentDfd;
- if(!dfd){
- this._fireNextRequest();
- return;
- }
- var ioArgs = dfd.ioArgs;
- var args = ioArgs.args;
- var fNode = dojo.byId(args.form);
- if(fNode){
- // remove all the hidden content inputs
- var toClean = ioArgs._contentToClean;
- for(var i = 0; i < toClean.length; i++) {
- var key = toClean[i];
- //Need to cycle over all nodes since we may have added
- //an array value which means that more than one node could
- //have the same .name value.
- for(var j = 0; j < fNode.childNodes.length; j++){
- var chNode = fNode.childNodes[j];
- if(chNode.name == key){
- dojo.destroy(chNode);
- break;
- }
- }
- }
- // restore original action + target
- if(ioArgs["_originalAction"]){
- fNode.setAttribute("action", ioArgs._originalAction);
- }
- if(ioArgs["_originalTarget"]){
- fNode.setAttribute("target", ioArgs._originalTarget);
- fNode.target = ioArgs._originalTarget;
- }
- }
- ioArgs._finished = true;
- }
- };
- return dojo.io.iframe;
- });
- },
- 'dojox/form/uploader/plugins/IFrame':function(){
- define("dojox/form/uploader/plugins/IFrame", [
- "dojo/dom-construct",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/array",
- "dojo/io/iframe",
- "dojox/form/uploader/plugins/HTML5"
- ],function(domConstruct, declare, lang, array, ioIframe, formUploaderPluginsHTML5){
-
- var pluginsIFrame = declare("dojox.form.uploader.plugins.IFrame", [], {
- //
- // Version: 1.6
- //
- // summary:
- // A plugin for dojox.form.Uploader that adds Ajax upload capabilities.
- //
- // description:
- // Only supported by IE, due to the specifc iFrame hack used. The
- // formUploaderPluginsHTML5 plugin should be used along with this to add HTML5
- // capabilities to browsers that support them. Progress events are not supported.
- // Inherits all properties from dojox.form.Uploader and formUploaderPluginsHTML5.
- //
- force:"",
- postMixInProperties: function(){
- this.inherited(arguments);
- if(!this.supports("multiple") || this.force =="iframe"){
- this.uploadType = "iframe";
- this.upload = this.uploadIFrame;
- }
- },
- uploadIFrame: function(data){
- // summary:
- // Internal. You could use this, but you should use upload() or submit();
- // which can also handle the post data.
- //
- var form, destroyAfter = false;
- if(!this.getForm()){
- //enctype can't be changed once a form element is created
- form = domConstruct.place('<form enctype="multipart/form-data" method="post"></form>', this.domNode);
- array.forEach(this._inputs, function(n, i){
- if(n.value) form.appendChild(n);
- }, this);
- destroyAfter = true;
- }else{
- form = this.form;
- }
- var url = this.getUrl();
- var dfd = ioIframe.send({
- url: url,
- form: form,
- handleAs: "json",
- content: data,
- error: lang.hitch(this, function(err){
- if(destroyAfter){ domConstruct.destroy(form); }
- this.onError(err);
- }),
- load: lang.hitch(this, function(data, ioArgs, widgetRef){
- if(destroyAfter){ domConstruct.destroy(form); }
- if(data["ERROR"] || data["error"]){
- this.onError(data);
- }else{
- this.onComplete(data);
- }
- })
- });
- }
- });
- dojox.form.addUploaderPlugin(pluginsIFrame);
- return pluginsIFrame;
- });
- },
- 'dojox/grid/enhanced/plugins/AutoScroll':function(){
- define("dojox/grid/enhanced/plugins/AutoScroll", [
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/lang",
- "dojo/_base/html",
- "dojo/_base/window",
- "../_Plugin",
- "../../_RowSelector",
- "../../EnhancedGrid"
- ], function(declare, array, lang, html, win, _Plugin, _RowSelector, EnhancedGrid){
- var AutoScroll = declare("dojox.grid.enhanced.plugins.AutoScroll", _Plugin, {
- // summary:
- // Provides horizontal and vertical auto-scroll for grid.
-
- // name: String
- // Plugin name
- name: "autoScroll",
-
- // autoScrollInterval: Integer
- // The time interval (in miliseconds) between 2 scrolling.
- autoScrollInterval: 1000,
-
- // autoScrollMargin: Integer
- // The width (in pixel) of the margin area where autoscroll can be triggered.
- autoScrollMargin: 30,
-
- constructor: function(grid, args){
- this.grid = grid;
- this.readyForAutoScroll = false;
- this._scrolling = false;
- args = lang.isObject(args) ? args : {};
- if("interval" in args){
- this.autoScrollInterval = args.interval;
- }
- if("margin" in args){
- this.autoScrollMargin = args.margin;
- }
- this._initEvents();
- this._mixinGrid();
- },
- _initEvents: function(){
- var g = this.grid;
- this.connect(g, "onCellMouseDown", function(){
- this.readyForAutoScroll = true;
- });
- this.connect(g, "onHeaderCellMouseDown", function(){
- this.readyForAutoScroll = true;
- });
- this.connect(g, "onRowSelectorMouseDown", function(){
- this.readyForAutoScroll = true;
- });
- this.connect(win.doc, "onmouseup", function(evt){
- this._manageAutoScroll(true);
- this.readyForAutoScroll = false;
- });
- this.connect(win.doc, "onmousemove", function(evt){
- if(this.readyForAutoScroll){
- this._event = evt;
- var gridPos = html.position(g.domNode),
- hh = g._getHeaderHeight(),
- margin = this.autoScrollMargin,
- ey = evt.clientY, ex = evt.clientX,
- gy = gridPos.y, gx = gridPos.x,
- gh = gridPos.h, gw = gridPos.w;
- if(ex >= gx && ex <= gx + gw){
- if(ey >= gy + hh && ey < gy + hh + margin){
- this._manageAutoScroll(false, true, false);
- return;
- }else if(ey > gy + gh - margin && ey <= gy + gh){
- this._manageAutoScroll(false, true, true);
- return;
- }else if(ey >= gy && ey <= gy + gh){
- var withinSomeview = array.some(g.views.views, function(view, i){
- if(view instanceof _RowSelector){
- return false;
- }
- var viewPos = html.position(view.domNode);
- if(ex < viewPos.x + margin && ex >= viewPos.x){
- this._manageAutoScroll(false, false, false, view);
- return true;
- }else if(ex > viewPos.x + viewPos.w - margin && ex < viewPos.x + viewPos.w){
- this._manageAutoScroll(false, false, true, view);
- return true;
- }
- return false;
- }, this);
- if(withinSomeview){
- return;
- }
- }
- }
- //stop autoscroll.
- this._manageAutoScroll(true);
- }
- });
- },
- _mixinGrid: function(){
- var g = this.grid;
- g.onStartAutoScroll = function(/*isVertical, isForward*/){};
- g.onEndAutoScroll = function(/*isVertical, isForward, view, scrollToRowIndex, event*/){};
- },
- _fireEvent: function(eventName, args){
- var g = this.grid;
- switch(eventName){
- case "start":
- g.onStartAutoScroll.apply(g, args);
- break;
- case "end":
- g.onEndAutoScroll.apply(g, args);
- break;
- }
- },
- _manageAutoScroll: function(toStop, isVertical, isForward, view){
- if(toStop){
- this._scrolling = false;
- clearInterval(this._handler);
- }else if(!this._scrolling){
- this._scrolling = true;
- this._fireEvent("start", [isVertical, isForward, view]);
- this._autoScroll(isVertical, isForward, view);
- this._handler = setInterval(lang.hitch(this, "_autoScroll", isVertical, isForward, view), this.autoScrollInterval);
- }
- },
- _autoScroll: function(isVertical, isForward, view){
- var g = this.grid,
- target = null;
- if(isVertical){
- var targetRow = g.scroller.firstVisibleRow + (isForward ? 1 : -1);
- if(targetRow >= 0 && targetRow < g.rowCount){
- g.scrollToRow(targetRow);
- target = targetRow;
- }
- }else{
- target = this._scrollColumn(isForward, view);
- }
- if(target !== null){
- this._fireEvent("end", [isVertical, isForward, view, target, this._event]);
- }
- },
- _scrollColumn: function(isForward, view){
- var node = view.scrollboxNode,
- target = null;
- if(node.clientWidth < node.scrollWidth){
- var cells = array.filter(this.grid.layout.cells, function(cell){
- return !cell.hidden;
- });
- var viewPos = html.position(view.domNode);
- var limit, edge, headerPos, i;
- if(isForward){
- limit = node.clientWidth;
- for(i = 0; i < cells.length; ++i){
- headerPos = html.position(cells[i].getHeaderNode());
- edge = headerPos.x - viewPos.x + headerPos.w;
- if(edge > limit){
- target = cells[i].index;
- node.scrollLeft += edge - limit + 10;
- break;
- }
- }
- }else{
- limit = 0;
- for(i = cells.length - 1; i >= 0; --i){
- headerPos = html.position(cells[i].getHeaderNode());
- edge = headerPos.x - viewPos.x;
- if(edge < limit){
- target = cells[i].index;
- node.scrollLeft += edge - limit - 10;
- break;
- }
- }
- }
- }
- return target;
- }
- });
- EnhancedGrid.registerPlugin(AutoScroll);
- return AutoScroll;
- });
- },
- 'dojox/grid/util':function(){
- define("dojox/grid/util", [
- "../main",
- "dojo/_base/lang",
- "dojo/dom"
- ], function(dojox, lang, dom){
- // summary: grid utility library
- var dgu = lang.getObject("grid.util", true, dojox);
- dgu.na = '...';
- dgu.rowIndexTag = "gridRowIndex";
- dgu.gridViewTag = "gridView";
- dgu.fire = function(ob, ev, args){
- var fn = ob && ev && ob[ev];
- return fn && (args ? fn.apply(ob, args) : ob[ev]());
- };
-
- dgu.setStyleHeightPx = function(inElement, inHeight){
- if(inHeight >= 0){
- var s = inElement.style;
- var v = inHeight + 'px';
- if(inElement && s['height'] != v){
- s['height'] = v;
- }
- }
- };
-
- dgu.mouseEvents = [ 'mouseover', 'mouseout', /*'mousemove',*/ 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu' ];
- dgu.keyEvents = [ 'keyup', 'keydown', 'keypress' ];
- dgu.funnelEvents = function(inNode, inObject, inMethod, inEvents){
- var evts = (inEvents ? inEvents : dgu.mouseEvents.concat(dgu.keyEvents));
- for (var i=0, l=evts.length; i<l; i++){
- inObject.connect(inNode, 'on' + evts[i], inMethod);
- }
- };
- dgu.removeNode = function(inNode){
- inNode = dom.byId(inNode);
- inNode && inNode.parentNode && inNode.parentNode.removeChild(inNode);
- return inNode;
- };
-
- dgu.arrayCompare = function(inA, inB){
- for(var i=0,l=inA.length; i<l; i++){
- if(inA[i] != inB[i]){return false;}
- }
- return (inA.length == inB.length);
- };
-
- dgu.arrayInsert = function(inArray, inIndex, inValue){
- if(inArray.length <= inIndex){
- inArray[inIndex] = inValue;
- }else{
- inArray.splice(inIndex, 0, inValue);
- }
- };
-
- dgu.arrayRemove = function(inArray, inIndex){
- inArray.splice(inIndex, 1);
- };
-
- dgu.arraySwap = function(inArray, inI, inJ){
- var cache = inArray[inI];
- inArray[inI] = inArray[inJ];
- inArray[inJ] = cache;
- };
- return dojox.grid.util;
- });
- },
- 'dijit/form/_ComboBoxMenu':function(){
- define("dijit/form/_ComboBoxMenu", [
- "dojo/_base/declare", // declare
- "dojo/dom-class", // domClass.add domClass.remove
- "dojo/dom-construct", // domConstruct.create
- "dojo/dom-style", // domStyle.get
- "dojo/keys", // keys.DOWN_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.UP_ARROW
- "../_WidgetBase",
- "../_TemplatedMixin",
- "./_ComboBoxMenuMixin",
- "./_ListMouseMixin"
- ], function(declare, domClass, domConstruct, domStyle, keys,
- _WidgetBase, _TemplatedMixin, _ComboBoxMenuMixin, _ListMouseMixin){
- /*=====
- var _WidgetBase = dijit._WidgetBase;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var _ComboBoxMenuMixin = dijit.form._ComboBoxMenuMixin;
- var _ListMouseMixin = dijit.form._ListMouseMixin;
- =====*/
- // module:
- // dijit/form/_ComboBoxMenu
- // summary:
- // Focus-less menu for internal use in `dijit.form.ComboBox`
- return declare("dijit.form._ComboBoxMenu",[_WidgetBase, _TemplatedMixin, _ListMouseMixin, _ComboBoxMenuMixin], {
- // summary:
- // Focus-less menu for internal use in `dijit.form.ComboBox`
- // Abstract methods that must be defined externally:
- // onChange: item was explicitly chosen (mousedown somewhere on the menu and mouseup somewhere on the menu)
- // onPage: next(1) or previous(-1) button pressed
- // tags:
- // private
- templateString: "<div class='dijitReset dijitMenu' data-dojo-attach-point='containerNode' style='overflow: auto; overflow-x: hidden;'>"
- +"<div class='dijitMenuItem dijitMenuPreviousButton' data-dojo-attach-point='previousButton' role='option'></div>"
- +"<div class='dijitMenuItem dijitMenuNextButton' data-dojo-attach-point='nextButton' role='option'></div>"
- +"</div>",
- baseClass: "dijitComboBoxMenu",
- postCreate: function(){
- this.inherited(arguments);
- if(!this.isLeftToRight()){
- domClass.add(this.previousButton, "dijitMenuItemRtl");
- domClass.add(this.nextButton, "dijitMenuItemRtl");
- }
- },
- _createMenuItem: function(){
- return domConstruct.create("div", {
- "class": "dijitReset dijitMenuItem" +(this.isLeftToRight() ? "" : " dijitMenuItemRtl"),
- role: "option"
- });
- },
- onHover: function(/*DomNode*/ node){
- // summary:
- // Add hover CSS
- domClass.add(node, "dijitMenuItemHover");
- },
- onUnhover: function(/*DomNode*/ node){
- // summary:
- // Remove hover CSS
- domClass.remove(node, "dijitMenuItemHover");
- },
- onSelect: function(/*DomNode*/ node){
- // summary:
- // Add selected CSS
- domClass.add(node, "dijitMenuItemSelected");
- },
- onDeselect: function(/*DomNode*/ node){
- // summary:
- // Remove selected CSS
- domClass.remove(node, "dijitMenuItemSelected");
- },
- _page: function(/*Boolean*/ up){
- // summary:
- // Handles page-up and page-down keypresses
- var scrollamount = 0;
- var oldscroll = this.domNode.scrollTop;
- var height = domStyle.get(this.domNode, "height");
- // if no item is highlighted, highlight the first option
- if(!this.getHighlightedOption()){
- this.selectNextNode();
- }
- while(scrollamount<height){
- var highlighted_option = this.getHighlightedOption();
- if(up){
- // stop at option 1
- if(!highlighted_option.previousSibling ||
- highlighted_option.previousSibling.style.display == "none"){
- break;
- }
- this.selectPreviousNode();
- }else{
- // stop at last option
- if(!highlighted_option.nextSibling ||
- highlighted_option.nextSibling.style.display == "none"){
- break;
- }
- this.selectNextNode();
- }
- // going backwards
- var newscroll = this.domNode.scrollTop;
- scrollamount += (newscroll-oldscroll)*(up ? -1:1);
- oldscroll = newscroll;
- }
- },
- handleKey: function(evt){
- // summary:
- // Handle keystroke event forwarded from ComboBox, returning false if it's
- // a keystroke I recognize and process, true otherwise.
- switch(evt.charOrCode){
- case keys.DOWN_ARROW:
- this.selectNextNode();
- return false;
- case keys.PAGE_DOWN:
- this._page(false);
- return false;
- case keys.UP_ARROW:
- this.selectPreviousNode();
- return false;
- case keys.PAGE_UP:
- this._page(true);
- return false;
- default:
- return true;
- }
- }
- });
- });
- },
- 'dojox/grid/cells/_base':function(){
- define("dojox/grid/cells/_base", [
- "dojo/_base/kernel",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/event",
- "dojo/_base/connect",
- "dojo/_base/array",
- "dojo/_base/sniff",
- "dojo/dom",
- "dojo/dom-attr",
- "dojo/dom-construct",
- "dijit/_Widget",
- "../util"
- ], function(dojo, declare, lang, event, connect, array, has, dom, domAttr, domConstruct, _Widget, util){
- var _DeferredTextWidget = declare("dojox.grid._DeferredTextWidget", _Widget, {
- deferred: null,
- _destroyOnRemove: true,
- postCreate: function(){
- if(this.deferred){
- this.deferred.addBoth(lang.hitch(this, function(text){
- if(this.domNode){
- this.domNode.innerHTML = text;
- }
- }));
- }
- }
- });
- var focusSelectNode = function(inNode){
- try{
- util.fire(inNode, "focus");
- util.fire(inNode, "select");
- }catch(e){// IE sux bad
- }
- };
-
- var whenIdle = function(/*inContext, inMethod, args ...*/){
- setTimeout(lang.hitch.apply(dojo, arguments), 0);
- };
- var BaseCell = declare("dojox.grid.cells._Base", null, {
- // summary:
- // Respresents a grid cell and contains information about column options and methods
- // for retrieving cell related information.
- // Each column in a grid layout has a cell object and most events and many methods
- // provide access to these objects.
- styles: '',
- classes: '',
- editable: false,
- alwaysEditing: false,
- formatter: null,
- defaultValue: '...',
- value: null,
- hidden: false,
- noresize: false,
- draggable: true,
- //private
- _valueProp: "value",
- _formatPending: false,
- constructor: function(inProps){
- this._props = inProps || {};
- lang.mixin(this, inProps);
- if(this.draggable === undefined){
- this.draggable = true;
- }
- },
- _defaultFormat: function(inValue, callArgs){
- var s = this.grid.formatterScope || this;
- var f = this.formatter;
- if(f && s && typeof f == "string"){
- f = this.formatter = s[f];
- }
- var v = (inValue != this.defaultValue && f) ? f.apply(s, callArgs) : inValue;
- if(typeof v == "undefined"){
- return this.defaultValue;
- }
- if(v && v.addBoth){
- // Check if it's a deferred
- v = new _DeferredTextWidget({deferred: v},
- domConstruct.create("span", {innerHTML: this.defaultValue}));
- }
- if(v && v.declaredClass && v.startup){
- return "<div class='dojoxGridStubNode' linkWidget='" +
- v.id +
- "' cellIdx='" +
- this.index +
- "'>" +
- this.defaultValue +
- "</div>";
- }
- return v;
- },
-
- // data source
- format: function(inRowIndex, inItem){
- // summary:
- // provides the html for a given grid cell.
- // inRowIndex: int
- // grid row index
- // returns: html for a given grid cell
- var f, i=this.grid.edit.info, d=this.get ? this.get(inRowIndex, inItem) : (this.value || this.defaultValue);
- d = (d && d.replace && this.grid.escapeHTMLInData) ? d.replace(/&/g, '&').replace(/</g, '<') : d;
- if (this.editable && (this.alwaysEditing || (i.rowIndex==inRowIndex && i.cell==this))) {
- return this.formatEditing(i.value ? i.value : d, inRowIndex);
- } else {
- return this._defaultFormat(d, [d, inRowIndex, this]);
- }
- },
- formatEditing: function(inDatum, inRowIndex){
- // summary:
- // formats the cell for editing
- // inDatum: anything
- // cell data to edit
- // inRowIndex: int
- // grid row index
- // returns: string of html to place in grid cell
- },
- // utility
- getNode: function(inRowIndex){
- // summary:
- // gets the dom node for a given grid cell.
- // inRowIndex: int
- // grid row index
- // returns: dom node for a given grid cell
- return this.view.getCellNode(inRowIndex, this.index);
- },
- getHeaderNode: function(){
- return this.view.getHeaderCellNode(this.index);
- },
- getEditNode: function(inRowIndex){
- return (this.getNode(inRowIndex) || 0).firstChild || 0;
- },
- canResize: function(){
- var uw = this.unitWidth;
- return uw && (uw!=='auto');
- },
- isFlex: function(){
- var uw = this.unitWidth;
- return uw && lang.isString(uw) && (uw=='auto' || uw.slice(-1)=='%');
- },
- // edit support
- applyEdit: function(inValue, inRowIndex){
- if(this.getNode(inRowIndex)){
- this.grid.edit.applyCellEdit(inValue, this, inRowIndex);
- }
- },
- cancelEdit: function(inRowIndex){
- this.grid.doCancelEdit(inRowIndex);
- },
- _onEditBlur: function(inRowIndex){
- if(this.grid.edit.isEditCell(inRowIndex, this.index)){
- //console.log('editor onblur', e);
- this.grid.edit.apply();
- }
- },
- registerOnBlur: function(inNode, inRowIndex){
- if(this.commitOnBlur){
- connect.connect(inNode, "onblur", function(e){
- // hack: if editor still thinks this editor is current some ms after it blurs, assume we've focused away from grid
- setTimeout(lang.hitch(this, "_onEditBlur", inRowIndex), 250);
- });
- }
- },
- //protected
- needFormatNode: function(inDatum, inRowIndex){
- this._formatPending = true;
- whenIdle(this, "_formatNode", inDatum, inRowIndex);
- },
- cancelFormatNode: function(){
- this._formatPending = false;
- },
- //private
- _formatNode: function(inDatum, inRowIndex){
- if(this._formatPending){
- this._formatPending = false;
- // make cell selectable
- if(!has("ie")){
- dom.setSelectable(this.grid.domNode, true);
- }
- this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
- }
- },
- //protected
- formatNode: function(inNode, inDatum, inRowIndex){
- // summary:
- // format the editing dom node. Use when editor is a widget.
- // inNode: dom node
- // dom node for the editor
- // inDatum: anything
- // cell data to edit
- // inRowIndex: int
- // grid row index
- if(has("ie")){
- // IE sux bad
- whenIdle(this, "focus", inRowIndex, inNode);
- }else{
- this.focus(inRowIndex, inNode);
- }
- },
- dispatchEvent: function(m, e){
- if(m in this){
- return this[m](e);
- }
- },
- //public
- getValue: function(inRowIndex){
- // summary:
- // returns value entered into editor
- // inRowIndex: int
- // grid row index
- // returns:
- // value of editor
- return this.getEditNode(inRowIndex)[this._valueProp];
- },
- setValue: function(inRowIndex, inValue){
- // summary:
- // set the value of the grid editor
- // inRowIndex: int
- // grid row index
- // inValue: anything
- // value of editor
- var n = this.getEditNode(inRowIndex);
- if(n){
- n[this._valueProp] = inValue;
- }
- },
- focus: function(inRowIndex, inNode){
- // summary:
- // focus the grid editor
- // inRowIndex: int
- // grid row index
- // inNode: dom node
- // editor node
- focusSelectNode(inNode || this.getEditNode(inRowIndex));
- },
- save: function(inRowIndex){
- // summary:
- // save editor state
- // inRowIndex: int
- // grid row index
- this.value = this.value || this.getValue(inRowIndex);
- //console.log("save", this.value, inCell.index, inRowIndex);
- },
- restore: function(inRowIndex){
- // summary:
- // restore editor state
- // inRowIndex: int
- // grid row index
- this.setValue(inRowIndex, this.value);
- //console.log("restore", this.value, inCell.index, inRowIndex);
- },
- //protected
- _finish: function(inRowIndex){
- // summary:
- // called when editing is completed to clean up editor
- // inRowIndex: int
- // grid row index
- dom.setSelectable(this.grid.domNode, false);
- this.cancelFormatNode();
- },
- //public
- apply: function(inRowIndex){
- // summary:
- // apply edit from cell editor
- // inRowIndex: int
- // grid row index
- this.applyEdit(this.getValue(inRowIndex), inRowIndex);
- this._finish(inRowIndex);
- },
- cancel: function(inRowIndex){
- // summary:
- // cancel cell edit
- // inRowIndex: int
- // grid row index
- this.cancelEdit(inRowIndex);
- this._finish(inRowIndex);
- }
- });
- BaseCell.markupFactory = function(node, cellDef){
- var formatter = lang.trim(domAttr.get(node, "formatter")||"");
- if(formatter){
- cellDef.formatter = lang.getObject(formatter)||formatter;
- }
- var get = lang.trim(domAttr.get(node, "get")||"");
- if(get){
- cellDef.get = lang.getObject(get);
- }
- var getBoolAttr = function(attr, cell, cellAttr){
- var value = lang.trim(domAttr.get(node, attr)||"");
- if(value){ cell[cellAttr||attr] = !(value.toLowerCase()=="false"); }
- };
- getBoolAttr("sortDesc", cellDef);
- getBoolAttr("editable", cellDef);
- getBoolAttr("alwaysEditing", cellDef);
- getBoolAttr("noresize", cellDef);
- getBoolAttr("draggable", cellDef);
- var value = lang.trim(domAttr.get(node, "loadingText")||domAttr.get(node, "defaultValue")||"");
- if(value){
- cellDef.defaultValue = value;
- }
- var getStrAttr = function(attr, cell, cellAttr){
- var value = lang.trim(domAttr.get(node, attr)||"")||undefined;
- if(value){ cell[cellAttr||attr] = value; }
- };
- getStrAttr("styles", cellDef);
- getStrAttr("headerStyles", cellDef);
- getStrAttr("cellStyles", cellDef);
- getStrAttr("classes", cellDef);
- getStrAttr("headerClasses", cellDef);
- getStrAttr("cellClasses", cellDef);
- };
- var Cell = declare("dojox.grid.cells.Cell", BaseCell, {
- // summary
- // grid cell that provides a standard text input box upon editing
- constructor: function(){
- this.keyFilter = this.keyFilter;
- },
- // keyFilter: RegExp
- // optional regex for disallowing keypresses
- keyFilter: null,
- formatEditing: function(inDatum, inRowIndex){
- this.needFormatNode(inDatum, inRowIndex);
- if (inDatum && inDatum.replace) {
- // escape quotes to avoid XSS
- inDatum = inDatum.replace(/"/g, '"')
- }
- return '<input class="dojoxGridInput" type="text" value="' + inDatum + '">';
- },
- formatNode: function(inNode, inDatum, inRowIndex){
- this.inherited(arguments);
- // FIXME: feels too specific for this interface
- this.registerOnBlur(inNode, inRowIndex);
- },
- doKey: function(e){
- if(this.keyFilter){
- var key = String.fromCharCode(e.charCode);
- if(key.search(this.keyFilter) == -1){
- event.stop(e);
- }
- }
- },
- _finish: function(inRowIndex){
- this.inherited(arguments);
- var n = this.getEditNode(inRowIndex);
- try{
- util.fire(n, "blur");
- }catch(e){}
- }
- });
- Cell.markupFactory = function(node, cellDef){
- BaseCell.markupFactory(node, cellDef);
- var keyFilter = lang.trim(domAttr.get(node, "keyFilter")||"");
- if(keyFilter){
- cellDef.keyFilter = new RegExp(keyFilter);
- }
- };
- var RowIndex = declare("dojox.grid.cells.RowIndex", Cell, {
- name: 'Row',
- postscript: function(){
- this.editable = false;
- },
- get: function(inRowIndex){
- return inRowIndex + 1;
- }
- });
- RowIndex.markupFactory = function(node, cellDef){
- Cell.markupFactory(node, cellDef);
- };
- var Select = declare("dojox.grid.cells.Select", Cell, {
- // summary:
- // grid cell that provides a standard select for editing
- // options: Array
- // text of each item
- options: null,
- // values: Array
- // value for each item
- values: null,
- // returnIndex: Integer
- // editor returns only the index of the selected option and not the value
- returnIndex: -1,
- constructor: function(inCell){
- this.values = this.values || this.options;
- },
- formatEditing: function(inDatum, inRowIndex){
- this.needFormatNode(inDatum, inRowIndex);
- var h = [ '<select class="dojoxGridSelect">' ];
- for (var i=0, o, v; ((o=this.options[i]) !== undefined)&&((v=this.values[i]) !== undefined); i++){
- v = v.replace ? v.replace(/&/g, '&').replace(/</g, '<') : v;
- o = o.replace ? o.replace(/&/g, '&').replace(/</g, '<') : o;
- h.push("<option", (inDatum==v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
- }
- h.push('</select>');
- return h.join('');
- },
- _defaultFormat: function(inValue, callArgs){
- var v = this.inherited(arguments);
- // when 'values' and 'options' both provided and there is no cutomized formatter,
- // then we use 'options' as label in order to be consistent
- if(!this.formatter && this.values && this.options){
- var i = array.indexOf(this.values, v);
- if(i >= 0){
- v = this.options[i];
- }
- }
- return v;
- },
- getValue: function(inRowIndex){
- var n = this.getEditNode(inRowIndex);
- if(n){
- var i = n.selectedIndex, o = n.options[i];
- return this.returnIndex > -1 ? i : o.value || o.innerHTML;
- }
- }
- });
- Select.markupFactory = function(node, cell){
- Cell.markupFactory(node, cell);
- var options = lang.trim(domAttr.get(node, "options")||"");
- if(options){
- var o = options.split(',');
- if(o[0] != options){
- cell.options = o;
- }
- }
- var values = lang.trim(domAttr.get(node, "values")||"");
- if(values){
- var v = values.split(',');
- if(v[0] != values){
- cell.values = v;
- }
- }
- };
- var AlwaysEdit = declare("dojox.grid.cells.AlwaysEdit", Cell, {
- // summary:
- // grid cell that is always in an editable state, regardless of grid editing state
- alwaysEditing: true,
- _formatNode: function(inDatum, inRowIndex){
- this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
- },
- applyStaticValue: function(inRowIndex){
- var e = this.grid.edit;
- e.applyCellEdit(this.getValue(inRowIndex), this, inRowIndex);
- e.start(this, inRowIndex, true);
- }
- });
- AlwaysEdit.markupFactory = function(node, cell){
- Cell.markupFactory(node, cell);
- };
- var Bool = declare("dojox.grid.cells.Bool", AlwaysEdit, {
- // summary:
- // grid cell that provides a standard checkbox that is always on for editing
- _valueProp: "checked",
- formatEditing: function(inDatum, inRowIndex){
- return '<input class="dojoxGridInput" type="checkbox"' + (inDatum ? ' checked="checked"' : '') + ' style="width: auto" />';
- },
- doclick: function(e){
- if(e.target.tagName == 'INPUT'){
- this.applyStaticValue(e.rowIndex);
- }
- }
- });
- Bool.markupFactory = function(node, cell){
- AlwaysEdit.markupFactory(node, cell);
- };
- return BaseCell;
- });
- },
- 'dijit/form/_DateTimeTextBox':function(){
- require({cache:{
- 'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\r\n\tid=\"widget_${id}\"\r\n\trole=\"combobox\"\r\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\r\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\r\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t\t\t${_buttonInputDisabled}\r\n\t/></div\r\n\t><div class='dijitReset dijitValidationContainer'\r\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\r\n\t/></div\r\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\r\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\r\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\r\n\t/></div\r\n></div>\r\n"}});
- define("dijit/form/_DateTimeTextBox", [
- "dojo/date", // date date.compare
- "dojo/date/locale", // locale.regexp
- "dojo/date/stamp", // stamp.fromISOString stamp.toISOString
- "dojo/_base/declare", // declare
- "dojo/_base/lang", // lang.getObject
- "./RangeBoundTextBox",
- "../_HasDropDown",
- "dojo/text!./templates/DropDownBox.html"
- ], function(date, locale, stamp, declare, lang, RangeBoundTextBox, _HasDropDown, template){
- /*=====
- var _HasDropDown = dijit._HasDropDown;
- var RangeBoundTextBox = dijit.form.RangeBoundTextBox;
- =====*/
- // module:
- // dijit/form/_DateTimeTextBox
- // summary:
- // Base class for validating, serializable, range-bound date or time text box.
- new Date("X"); // workaround for #11279, new Date("") == NaN
- /*=====
- declare(
- "dijit.form._DateTimeTextBox.__Constraints",
- [RangeBoundTextBox.__Constraints, locale.__FormatOptions], {
- // summary:
- // Specifies both the rules on valid/invalid values (first/last date/time allowed),
- // and also formatting options for how the date/time is displayed.
- // example:
- // To restrict to dates within 2004, displayed in a long format like "December 25, 2005":
- // | {min:'2004-01-01',max:'2004-12-31', formatLength:'long'}
- });
- =====*/
- var _DateTimeTextBox = declare("dijit.form._DateTimeTextBox", [RangeBoundTextBox, _HasDropDown], {
- // summary:
- // Base class for validating, serializable, range-bound date or time text box.
- templateString: template,
- // hasDownArrow: [const] Boolean
- // Set this textbox to display a down arrow button, to open the drop down list.
- hasDownArrow: true,
- // openOnClick: [const] Boolean
- // Set to true to open drop down upon clicking anywhere on the textbox.
- openOnClick: true,
- /*=====
- // constraints: dijit.form._DateTimeTextBox.__Constraints
- // Despite the name, this parameter specifies both constraints on the input
- // (including starting/ending dates/times allowed) as well as
- // formatting options like whether the date is displayed in long (ex: December 25, 2005)
- // or short (ex: 12/25/2005) format. See `dijit.form._DateTimeTextBox.__Constraints` for details.
- constraints: {},
- ======*/
- // Override ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
- // than a straight regexp to deal with locale (plus formatting options too?)
- regExpGen: locale.regexp,
- // datePackage: String
- // JavaScript namespace to find calendar routines. Uses Gregorian calendar routines
- // at dojo.date, by default.
- datePackage: date,
- postMixInProperties: function(){
- this.inherited(arguments);
- this._set("type", "text"); // in case type="date"|"time" was specified which messes up parse/format
- },
- // Override _FormWidget.compare() to work for dates/times
- compare: function(/*Date*/ val1, /*Date*/ val2){
- var isInvalid1 = this._isInvalidDate(val1);
- var isInvalid2 = this._isInvalidDate(val2);
- return isInvalid1 ? (isInvalid2 ? 0 : -1) : (isInvalid2 ? 1 : date.compare(val1, val2, this._selector));
- },
- // flag to _HasDropDown to make drop down Calendar width == <input> width
- forceWidth: true,
- format: function(/*Date*/ value, /*dojo.date.locale.__FormatOptions*/ constraints){
- // summary:
- // Formats the value as a Date, according to specified locale (second argument)
- // tags:
- // protected
- if(!value){ return ''; }
- return this.dateLocaleModule.format(value, constraints);
- },
- "parse": function(/*String*/ value, /*dojo.date.locale.__FormatOptions*/ constraints){
- // summary:
- // Parses as string as a Date, according to constraints
- // tags:
- // protected
- return this.dateLocaleModule.parse(value, constraints) || (this._isEmpty(value) ? null : undefined); // Date
- },
- // Overrides ValidationTextBox.serialize() to serialize a date in canonical ISO format.
- serialize: function(/*anything*/ val, /*Object?*/ options){
- if(val.toGregorian){
- val = val.toGregorian();
- }
- return stamp.toISOString(val, options);
- },
- // dropDownDefaultValue: Date
- // The default value to focus in the popupClass widget when the textbox value is empty.
- dropDownDefaultValue : new Date(),
- // value: Date
- // The value of this widget as a JavaScript Date object. Use get("value") / set("value", val) to manipulate.
- // When passed to the parser in markup, must be specified according to `dojo.date.stamp.fromISOString`
- value: new Date(""), // value.toString()="NaN"
- _blankValue: null, // used by filter() when the textbox is blank
- // popupClass: [protected extension] String
- // Name of the popup widget class used to select a date/time.
- // Subclasses should specify this.
- popupClass: "", // default is no popup = text only
- // _selector: [protected extension] String
- // Specifies constraints.selector passed to dojo.date functions, should be either
- // "date" or "time".
- // Subclass must specify this.
- _selector: "",
- constructor: function(/*Object*/ args){
- this.datePackage = args.datePackage || this.datePackage;
- this.dateFuncObj = typeof this.datePackage == "string" ?
- lang.getObject(this.datePackage, false) :// "string" part for back-compat, remove for 2.0
- this.datePackage;
- this.dateClassObj = this.dateFuncObj.Date || Date;
- this.dateLocaleModule = lang.getObject("locale", false, this.dateFuncObj);
- this.regExpGen = this.dateLocaleModule.regexp;
- this._invalidDate = this.constructor.prototype.value.toString();
- },
- buildRendering: function(){
- this.inherited(arguments);
- if(!this.hasDownArrow){
- this._buttonNode.style.display = "none";
- }
- // If openOnClick is true, we basically just want to treat the whole widget as the
- // button. We need to do that also if the actual drop down button will be hidden,
- // so that there's a mouse method for opening the drop down.
- if(this.openOnClick || !this.hasDownArrow){
- this._buttonNode = this.domNode;
- this.baseClass += " dijitComboBoxOpenOnClick";
- }
- },
- _setConstraintsAttr: function(/*Object*/ constraints){
- constraints.selector = this._selector;
- constraints.fullYear = true; // see #5465 - always format with 4-digit years
- var fromISO = stamp.fromISOString;
- if(typeof constraints.min == "string"){ constraints.min = fromISO(constraints.min); }
- if(typeof constraints.max == "string"){ constraints.max = fromISO(constraints.max); }
- this.inherited(arguments);
- },
- _isInvalidDate: function(/*Date*/ value){
- // summary:
- // Runs various tests on the value, checking for invalid conditions
- // tags:
- // private
- return !value || isNaN(value) || typeof value != "object" || value.toString() == this._invalidDate;
- },
- _setValueAttr: function(/*Date|String*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
- // summary:
- // Sets the date on this textbox. Note: value can be a JavaScript Date literal or a string to be parsed.
- if(value !== undefined){
- if(typeof value == "string"){
- value = stamp.fromISOString(value);
- }
- if(this._isInvalidDate(value)){
- value = null;
- }
- if(value instanceof Date && !(this.dateClassObj instanceof Date)){
- value = new this.dateClassObj(value);
- }
- }
- this.inherited(arguments);
- if(this.value instanceof Date){
- this.filterString = "";
- }
- if(this.dropDown){
- this.dropDown.set('value', value, false);
- }
- },
- _set: function(attr, value){
- // Avoid spurious watch() notifications when value is changed to new Date object w/the same value
- if(attr == "value" && this.value instanceof Date && this.compare(value, this.value) == 0){
- return;
- }
- this.inherited(arguments);
- },
- _setDropDownDefaultValueAttr: function(/*Date*/ val){
- if(this._isInvalidDate(val)){
- // convert null setting into today's date, since there needs to be *some* default at all times.
- val = new this.dateClassObj();
- }
- this.dropDownDefaultValue = val;
- },
- openDropDown: function(/*Function*/ callback){
- // rebuild drop down every time, so that constraints get copied (#6002)
- if(this.dropDown){
- this.dropDown.destroy();
- }
- var PopupProto = lang.isString(this.popupClass) ? lang.getObject(this.popupClass, false) : this.popupClass,
- textBox = this,
- value = this.get("value");
- this.dropDown = new PopupProto({
- onChange: function(value){
- // this will cause InlineEditBox and other handlers to do stuff so make sure it's last
- textBox.set('value', value, true);
- },
- id: this.id + "_popup",
- dir: textBox.dir,
- lang: textBox.lang,
- value: value,
- currentFocus: !this._isInvalidDate(value) ? value : this.dropDownDefaultValue,
- constraints: textBox.constraints,
- filterString: textBox.filterString, // for TimeTextBox, to filter times shown
- datePackage: textBox.datePackage,
- isDisabledDate: function(/*Date*/ date){
- // summary:
- // disables dates outside of the min/max of the _DateTimeTextBox
- return !textBox.rangeCheck(date, textBox.constraints);
- }
- });
- this.inherited(arguments);
- },
- _getDisplayedValueAttr: function(){
- return this.textbox.value;
- },
- _setDisplayedValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange){
- this._setValueAttr(this.parse(value, this.constraints), priorityChange, value);
- }
- });
- return _DateTimeTextBox;
- });
- },
- 'dijit/_base/focus':function(){
- define("dijit/_base/focus", [
- "dojo/_base/array", // array.forEach
- "dojo/dom", // dom.isDescendant
- "dojo/_base/lang", // lang.isArray
- "dojo/topic", // publish
- "dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal
- "../focus",
- ".." // for exporting symbols to dijit
- ], function(array, dom, lang, topic, win, focus, dijit){
- // module:
- // dijit/_base/focus
- // summary:
- // Deprecated module to monitor currently focused node and stack of currently focused widgets.
- // New code should access dijit/focus directly.
- lang.mixin(dijit, {
- // _curFocus: DomNode
- // Currently focused item on screen
- _curFocus: null,
- // _prevFocus: DomNode
- // Previously focused item on screen
- _prevFocus: null,
- isCollapsed: function(){
- // summary:
- // Returns true if there is no text selected
- return dijit.getBookmark().isCollapsed;
- },
- getBookmark: function(){
- // summary:
- // Retrieves a bookmark that can be used with moveToBookmark to return to the same range
- var bm, rg, tg, sel = win.doc.selection, cf = focus.curNode;
- if(win.global.getSelection){
- //W3C Range API for selections.
- sel = win.global.getSelection();
- if(sel){
- if(sel.isCollapsed){
- tg = cf? cf.tagName : "";
- if(tg){
- //Create a fake rangelike item to restore selections.
- tg = tg.toLowerCase();
- if(tg == "textarea" ||
- (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
- sel = {
- start: cf.selectionStart,
- end: cf.selectionEnd,
- node: cf,
- pRange: true
- };
- return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
- }
- }
- bm = {isCollapsed:true};
- if(sel.rangeCount){
- bm.mark = sel.getRangeAt(0).cloneRange();
- }
- }else{
- rg = sel.getRangeAt(0);
- bm = {isCollapsed: false, mark: rg.cloneRange()};
- }
- }
- }else if(sel){
- // If the current focus was a input of some sort and no selection, don't bother saving
- // a native bookmark. This is because it causes issues with dialog/page selection restore.
- // So, we need to create psuedo bookmarks to work with.
- tg = cf ? cf.tagName : "";
- tg = tg.toLowerCase();
- if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
- if(sel.type && sel.type.toLowerCase() == "none"){
- return {
- isCollapsed: true,
- mark: null
- }
- }else{
- rg = sel.createRange();
- return {
- isCollapsed: rg.text && rg.text.length?false:true,
- mark: {
- range: rg,
- pRange: true
- }
- };
- }
- }
- bm = {};
- //'IE' way for selections.
- try{
- // createRange() throws exception when dojo in iframe
- //and nothing selected, see #9632
- rg = sel.createRange();
- bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
- }catch(e){
- bm.isCollapsed = true;
- return bm;
- }
- if(sel.type.toUpperCase() == 'CONTROL'){
- if(rg.length){
- bm.mark=[];
- var i=0,len=rg.length;
- while(i<len){
- bm.mark.push(rg.item(i++));
- }
- }else{
- bm.isCollapsed = true;
- bm.mark = null;
- }
- }else{
- bm.mark = rg.getBookmark();
- }
- }else{
- console.warn("No idea how to store the current selection for this browser!");
- }
- return bm; // Object
- },
- moveToBookmark: function(/*Object*/ bookmark){
- // summary:
- // Moves current selection to a bookmark
- // bookmark:
- // This should be a returned object from dijit.getBookmark()
- var _doc = win.doc,
- mark = bookmark.mark;
- if(mark){
- if(win.global.getSelection){
- //W3C Rangi API (FF, WebKit, Opera, etc)
- var sel = win.global.getSelection();
- if(sel && sel.removeAllRanges){
- if(mark.pRange){
- var n = mark.node;
- n.selectionStart = mark.start;
- n.selectionEnd = mark.end;
- }else{
- sel.removeAllRanges();
- sel.addRange(mark);
- }
- }else{
- console.warn("No idea how to restore selection for this browser!");
- }
- }else if(_doc.selection && mark){
- //'IE' way.
- var rg;
- if(mark.pRange){
- rg = mark.range;
- }else if(lang.isArray(mark)){
- rg = _doc.body.createControlRange();
- //rg.addElement does not have call/apply method, so can not call it directly
- //rg is not available in "range.addElement(item)", so can't use that either
- array.forEach(mark, function(n){
- rg.addElement(n);
- });
- }else{
- rg = _doc.body.createTextRange();
- rg.moveToBookmark(mark);
- }
- rg.select();
- }
- }
- },
- getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
- // summary:
- // Called as getFocus(), this returns an Object showing the current focus
- // and selected text.
- //
- // Called as getFocus(widget), where widget is a (widget representing) a button
- // that was just pressed, it returns where focus was before that button
- // was pressed. (Pressing the button may have either shifted focus to the button,
- // or removed focus altogether.) In this case the selected text is not returned,
- // since it can't be accurately determined.
- //
- // menu: dijit._Widget or {domNode: DomNode} structure
- // The button that was just pressed. If focus has disappeared or moved
- // to this button, returns the previous focus. In this case the bookmark
- // information is already lost, and null is returned.
- //
- // openedForWindow:
- // iframe in which menu was opened
- //
- // returns:
- // A handle to restore focus/selection, to be passed to `dijit.focus`
- var node = !focus.curNode || (menu && dom.isDescendant(focus.curNode, menu.domNode)) ? dijit._prevFocus : focus.curNode;
- return {
- node: node,
- bookmark: node && (node == focus.curNode) && win.withGlobal(openedForWindow || win.global, dijit.getBookmark),
- openedForWindow: openedForWindow
- }; // Object
- },
- // _activeStack: dijit._Widget[]
- // List of currently active widgets (focused widget and it's ancestors)
- _activeStack: [],
- registerIframe: function(/*DomNode*/ iframe){
- // summary:
- // Registers listeners on the specified iframe so that any click
- // or focus event on that iframe (or anything in it) is reported
- // as a focus/click event on the <iframe> itself.
- // description:
- // Currently only used by editor.
- // returns:
- // Handle to pass to unregisterIframe()
- return focus.registerIframe(iframe);
- },
- unregisterIframe: function(/*Object*/ handle){
- // summary:
- // Unregisters listeners on the specified iframe created by registerIframe.
- // After calling be sure to delete or null out the handle itself.
- // handle:
- // Handle returned by registerIframe()
- handle && handle.remove();
- },
- registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
- // summary:
- // Registers listeners on the specified window (either the main
- // window or an iframe's window) to detect when the user has clicked somewhere
- // or focused somewhere.
- // description:
- // Users should call registerIframe() instead of this method.
- // targetWindow:
- // If specified this is the window associated with the iframe,
- // i.e. iframe.contentWindow.
- // effectiveNode:
- // If specified, report any focus events inside targetWindow as
- // an event on effectiveNode, rather than on evt.target.
- // returns:
- // Handle to pass to unregisterWin()
- return focus.registerWin(targetWindow, effectiveNode);
- },
- unregisterWin: function(/*Handle*/ handle){
- // summary:
- // Unregisters listeners on the specified window (either the main
- // window or an iframe's window) according to handle returned from registerWin().
- // After calling be sure to delete or null out the handle itself.
- handle && handle.remove();
- }
- });
- // Override focus singleton's focus function so that dijit.focus()
- // has backwards compatible behavior of restoring selection (although
- // probably no one is using that).
- focus.focus = function(/*Object || DomNode */ handle){
- // summary:
- // Sets the focused node and the selection according to argument.
- // To set focus to an iframe's content, pass in the iframe itself.
- // handle:
- // object returned by get(), or a DomNode
- if(!handle){ return; }
- var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object
- bookmark = handle.bookmark,
- openedForWindow = handle.openedForWindow,
- collapsed = bookmark ? bookmark.isCollapsed : false;
- // Set the focus
- // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
- // but we need to set focus to iframe.contentWindow
- if(node){
- var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node;
- if(focusNode && focusNode.focus){
- try{
- // Gecko throws sometimes if setting focus is impossible,
- // node not displayed or something like that
- focusNode.focus();
- }catch(e){/*quiet*/}
- }
- focus._onFocusNode(node);
- }
- // set the selection
- // do not need to restore if current selection is not empty
- // (use keyboard to select a menu item) or if previous selection was collapsed
- // as it may cause focus shift (Esp in IE).
- if(bookmark && win.withGlobal(openedForWindow || win.global, dijit.isCollapsed) && !collapsed){
- if(openedForWindow){
- openedForWindow.focus();
- }
- try{
- win.withGlobal(openedForWindow || win.global, dijit.moveToBookmark, null, [bookmark]);
- }catch(e2){
- /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
- }
- }
- };
- // For back compatibility, monitor changes to focused node and active widget stack,
- // publishing events and copying changes from focus manager variables into dijit (top level) variables
- focus.watch("curNode", function(name, oldVal, newVal){
- dijit._curFocus = newVal;
- dijit._prevFocus = oldVal;
- if(newVal){
- topic.publish("focusNode", newVal); // publish
- }
- });
- focus.watch("activeStack", function(name, oldVal, newVal){
- dijit._activeStack = newVal;
- });
- focus.on("widget-blur", function(widget, by){
- topic.publish("widgetBlur", widget, by); // publish
- });
- focus.on("widget-focus", function(widget, by){
- topic.publish("widgetFocus", widget, by); // publish
- });
- return dijit;
- });
- },
- 'dijit/a11y':function(){
- define("dijit/a11y", [
- "dojo/_base/array", // array.forEach array.map
- "dojo/_base/config", // defaultDuration
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.byId
- "dojo/dom-attr", // domAttr.attr domAttr.has
- "dojo/dom-style", // style.style
- "dojo/_base/sniff", // has("ie")
- "./_base/manager", // manager._isElementShown
- "." // for exporting methods to dijit namespace
- ], function(array, config, declare, dom, domAttr, domStyle, has, manager, dijit){
- // module:
- // dijit/a11y
- // summary:
- // Accessibility utility functions (keyboard, tab stops, etc.)
- var shown = (dijit._isElementShown = function(/*Element*/ elem){
- var s = domStyle.get(elem);
- return (s.visibility != "hidden")
- && (s.visibility != "collapsed")
- && (s.display != "none")
- && (domAttr.get(elem, "type") != "hidden");
- });
- dijit.hasDefaultTabStop = function(/*Element*/ elem){
- // summary:
- // Tests if element is tab-navigable even without an explicit tabIndex setting
- // No explicit tabIndex setting, need to investigate node type
- switch(elem.nodeName.toLowerCase()){
- case "a":
- // An <a> w/out a tabindex is only navigable if it has an href
- return domAttr.has(elem, "href");
- case "area":
- case "button":
- case "input":
- case "object":
- case "select":
- case "textarea":
- // These are navigable by default
- return true;
- case "iframe":
- // If it's an editor <iframe> then it's tab navigable.
- var body;
- try{
- // non-IE
- var contentDocument = elem.contentDocument;
- if("designMode" in contentDocument && contentDocument.designMode == "on"){
- return true;
- }
- body = contentDocument.body;
- }catch(e1){
- // contentWindow.document isn't accessible within IE7/8
- // if the iframe.src points to a foreign url and this
- // page contains an element, that could get focus
- try{
- body = elem.contentWindow.document.body;
- }catch(e2){
- return false;
- }
- }
- return body && (body.contentEditable == 'true' ||
- (body.firstChild && body.firstChild.contentEditable == 'true'));
- default:
- return elem.contentEditable == 'true';
- }
- };
- var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){
- // summary:
- // Tests if an element is tab-navigable
- // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable()
- if(domAttr.get(elem, "disabled")){
- return false;
- }else if(domAttr.has(elem, "tabIndex")){
- // Explicit tab index setting
- return domAttr.get(elem, "tabIndex") >= 0; // boolean
- }else{
- // No explicit tabIndex setting, so depends on node type
- return dijit.hasDefaultTabStop(elem);
- }
- });
- dijit._getTabNavigable = function(/*DOMNode*/ root){
- // summary:
- // Finds descendants of the specified root node.
- //
- // description:
- // Finds the following descendants of the specified root node:
- // * the first tab-navigable element in document order
- // without a tabIndex or with tabIndex="0"
- // * the last tab-navigable element in document order
- // without a tabIndex or with tabIndex="0"
- // * the first element in document order with the lowest
- // positive tabIndex value
- // * the last element in document order with the highest
- // positive tabIndex value
- var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {};
- function radioName(node){
- // If this element is part of a radio button group, return the name for that group.
- return node && node.tagName.toLowerCase() == "input" &&
- node.type && node.type.toLowerCase() == "radio" &&
- node.name && node.name.toLowerCase();
- }
- var walkTree = function(/*DOMNode*/parent){
- for(var child = parent.firstChild; child; child = child.nextSibling){
- // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
- // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
- if(child.nodeType != 1 || (has("ie") && child.scopeName !== "HTML") || !shown(child)){
- continue;
- }
- if(isTabNavigable(child)){
- var tabindex = domAttr.get(child, "tabIndex");
- if(!domAttr.has(child, "tabIndex") || tabindex == 0){
- if(!first){
- first = child;
- }
- last = child;
- }else if(tabindex > 0){
- if(!lowest || tabindex < lowestTabindex){
- lowestTabindex = tabindex;
- lowest = child;
- }
- if(!highest || tabindex >= highestTabindex){
- highestTabindex = tabindex;
- highest = child;
- }
- }
- var rn = radioName(child);
- if(domAttr.get(child, "checked") && rn){
- radioSelected[rn] = child;
- }
- }
- if(child.nodeName.toUpperCase() != 'SELECT'){
- walkTree(child);
- }
- }
- };
- if(shown(root)){
- walkTree(root);
- }
- function rs(node){
- // substitute checked radio button for unchecked one, if there is a checked one with the same name.
- return radioSelected[radioName(node)] || node;
- }
- return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) };
- };
- dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root){
- // summary:
- // Finds the descendant of the specified root node
- // that is first in the tabbing order
- var elems = dijit._getTabNavigable(dom.byId(root));
- return elems.lowest ? elems.lowest : elems.first; // DomNode
- };
- dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root){
- // summary:
- // Finds the descendant of the specified root node
- // that is last in the tabbing order
- var elems = dijit._getTabNavigable(dom.byId(root));
- return elems.last ? elems.last : elems.highest; // DomNode
- };
- return {
- hasDefaultTabStop: dijit.hasDefaultTabStop,
- isTabNavigable: dijit.isTabNavigable,
- _getTabNavigable: dijit._getTabNavigable,
- getFirstInTabbingOrder: dijit.getFirstInTabbingOrder,
- getLastInTabbingOrder: dijit.getLastInTabbingOrder
- };
- });
- },
- 'dojox/grid/_Scroller':function(){
- define("dojox/grid/_Scroller", [
- "dijit/registry",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "./util",
- "dojo/_base/html"
- ], function(dijitRegistry, declare, lang, util, html){
- var indexInParent = function(inNode){
- var i=0, n, p=inNode.parentNode;
- while((n = p.childNodes[i++])){
- if(n == inNode){
- return i - 1;
- }
- }
- return -1;
- };
-
- var cleanNode = function(inNode){
- if(!inNode){
- return;
- }
- dojo.forEach(dijitRegistry.toArray(), function(w){
- if(w.domNode && html.isDescendant(w.domNode, inNode, true)){
- w.destroy();
- }
- });
- };
- var getTagName = function(inNodeOrId){
- var node = html.byId(inNodeOrId);
- return (node && node.tagName ? node.tagName.toLowerCase() : '');
- };
-
- var nodeKids = function(inNode, inTag){
- var result = [];
- var i=0, n;
- while((n = inNode.childNodes[i])){
- i++;
- if(getTagName(n) == inTag){
- result.push(n);
- }
- }
- return result;
- };
-
- var divkids = function(inNode){
- return nodeKids(inNode, 'div');
- };
- return declare("dojox.grid._Scroller", null, {
- constructor: function(inContentNodes){
- this.setContentNodes(inContentNodes);
- this.pageHeights = [];
- this.pageNodes = [];
- this.stack = [];
- },
- // specified
- rowCount: 0, // total number of rows to manage
- defaultRowHeight: 32, // default height of a row
- keepRows: 100, // maximum number of rows that should exist at one time
- contentNode: null, // node to contain pages
- scrollboxNode: null, // node that controls scrolling
- // calculated
- defaultPageHeight: 0, // default height of a page
- keepPages: 10, // maximum number of pages that should exists at one time
- pageCount: 0,
- windowHeight: 0,
- firstVisibleRow: 0,
- lastVisibleRow: 0,
- averageRowHeight: 0, // the average height of a row
- // private
- page: 0,
- pageTop: 0,
- // init
- init: function(inRowCount, inKeepRows, inRowsPerPage){
- switch(arguments.length){
- case 3: this.rowsPerPage = inRowsPerPage;
- case 2: this.keepRows = inKeepRows;
- case 1: this.rowCount = inRowCount;
- default: break;
- }
- this.defaultPageHeight = this.defaultRowHeight * this.rowsPerPage;
- this.pageCount = this._getPageCount(this.rowCount, this.rowsPerPage);
- this.setKeepInfo(this.keepRows);
- this.invalidate();
- if(this.scrollboxNode){
- this.scrollboxNode.scrollTop = 0;
- this.scroll(0);
- this.scrollboxNode.onscroll = lang.hitch(this, 'onscroll');
- }
- },
- _getPageCount: function(rowCount, rowsPerPage){
- return rowCount ? (Math.ceil(rowCount / rowsPerPage) || 1) : 0;
- },
- destroy: function(){
- this.invalidateNodes();
- delete this.contentNodes;
- delete this.contentNode;
- delete this.scrollboxNode;
- },
- setKeepInfo: function(inKeepRows){
- this.keepRows = inKeepRows;
- this.keepPages = !this.keepRows ? this.keepPages : Math.max(Math.ceil(this.keepRows / this.rowsPerPage), 2);
- },
- // nodes
- setContentNodes: function(inNodes){
- this.contentNodes = inNodes;
- this.colCount = (this.contentNodes ? this.contentNodes.length : 0);
- this.pageNodes = [];
- for(var i=0; i<this.colCount; i++){
- this.pageNodes[i] = [];
- }
- },
- getDefaultNodes: function(){
- return this.pageNodes[0] || [];
- },
- // updating
- invalidate: function(){
- this._invalidating = true;
- this.invalidateNodes();
- this.pageHeights = [];
- this.height = (this.pageCount ? (this.pageCount - 1)* this.defaultPageHeight + this.calcLastPageHeight() : 0);
- this.resize();
- this._invalidating = false;
- },
- updateRowCount: function(inRowCount){
- this.invalidateNodes();
- this.rowCount = inRowCount;
- // update page count, adjust document height
- var oldPageCount = this.pageCount;
- if(oldPageCount === 0){
- //We want to have at least 1px in height to keep scroller. Otherwise with an
- //empty grid you can't scroll to see the header.
- this.height = 1;
- }
- this.pageCount = this._getPageCount(this.rowCount, this.rowsPerPage);
- if(this.pageCount < oldPageCount){
- for(var i=oldPageCount-1; i>=this.pageCount; i--){
- this.height -= this.getPageHeight(i);
- delete this.pageHeights[i];
- }
- }else if(this.pageCount > oldPageCount){
- this.height += this.defaultPageHeight * (this.pageCount - oldPageCount - 1) + this.calcLastPageHeight();
- }
- this.resize();
- },
- // implementation for page manager
- pageExists: function(inPageIndex){
- return Boolean(this.getDefaultPageNode(inPageIndex));
- },
- measurePage: function(inPageIndex){
- if(this.grid.rowHeight){
- var height = this.grid.rowHeight + 1;
- return ((inPageIndex + 1) * this.rowsPerPage > this.rowCount ?
- this.rowCount - inPageIndex * this.rowsPerPage :
- this.rowsPerPage) * height;
-
- }
- var n = this.getDefaultPageNode(inPageIndex);
- return (n && n.innerHTML) ? n.offsetHeight : undefined;
- },
- positionPage: function(inPageIndex, inPos){
- for(var i=0; i<this.colCount; i++){
- this.pageNodes[i][inPageIndex].style.top = inPos + 'px';
- }
- },
- repositionPages: function(inPageIndex){
- var nodes = this.getDefaultNodes();
- var last = 0;
- for(var i=0; i<this.stack.length; i++){
- last = Math.max(this.stack[i], last);
- }
- //
- var n = nodes[inPageIndex];
- var y = (n ? this.getPageNodePosition(n) + this.getPageHeight(inPageIndex) : 0);
- for(var p=inPageIndex+1; p<=last; p++){
- n = nodes[p];
- if(n){
- if(this.getPageNodePosition(n) == y){
- return;
- }
- this.positionPage(p, y);
- }
- y += this.getPageHeight(p);
- }
- },
- installPage: function(inPageIndex){
- for(var i=0; i<this.colCount; i++){
- this.contentNodes[i].appendChild(this.pageNodes[i][inPageIndex]);
- }
- },
- preparePage: function(inPageIndex, inReuseNode){
- var p = (inReuseNode ? this.popPage() : null);
- for(var i=0; i<this.colCount; i++){
- var nodes = this.pageNodes[i];
- var new_p = (p === null ? this.createPageNode() : this.invalidatePageNode(p, nodes));
- new_p.pageIndex = inPageIndex;
- nodes[inPageIndex] = new_p;
- }
- },
- // rendering implementation
- renderPage: function(inPageIndex){
- var nodes = [];
- var i, j;
- for(i=0; i<this.colCount; i++){
- nodes[i] = this.pageNodes[i][inPageIndex];
- }
- for(i=0, j=inPageIndex*this.rowsPerPage; (i<this.rowsPerPage)&&(j<this.rowCount); i++, j++){
- this.renderRow(j, nodes);
- }
- },
- removePage: function(inPageIndex){
- for(var i=0, j=inPageIndex*this.rowsPerPage; i<this.rowsPerPage; i++, j++){
- this.removeRow(j);
- }
- },
- destroyPage: function(inPageIndex){
- for(var i=0; i<this.colCount; i++){
- var n = this.invalidatePageNode(inPageIndex, this.pageNodes[i]);
- if(n){
- html.destroy(n);
- }
- }
- },
- pacify: function(inShouldPacify){
- },
- // pacification
- pacifying: false,
- pacifyTicks: 200,
- setPacifying: function(inPacifying){
- if(this.pacifying != inPacifying){
- this.pacifying = inPacifying;
- this.pacify(this.pacifying);
- }
- },
- startPacify: function(){
- this.startPacifyTicks = new Date().getTime();
- },
- doPacify: function(){
- var result = (new Date().getTime() - this.startPacifyTicks) > this.pacifyTicks;
- this.setPacifying(true);
- this.startPacify();
- return result;
- },
- endPacify: function(){
- this.setPacifying(false);
- },
- // default sizing implementation
- resize: function(){
- if(this.scrollboxNode){
- this.windowHeight = this.scrollboxNode.clientHeight;
- }
- for(var i=0; i<this.colCount; i++){
- //We want to have 1px in height min to keep scroller. Otherwise can't scroll
- //and see header in empty grid.
- util.setStyleHeightPx(this.contentNodes[i], Math.max(1,this.height));
- }
-
- // Calculate the average row height and update the defaults (row and page).
- var needPage = (!this._invalidating);
- if(!needPage){
- var ah = this.grid.get("autoHeight");
- if(typeof ah == "number" && ah <= Math.min(this.rowsPerPage, this.rowCount)){
- needPage = true;
- }
- }
- if(needPage){
- this.needPage(this.page, this.pageTop);
- }
- var rowsOnPage = (this.page < this.pageCount - 1) ? this.rowsPerPage : ((this.rowCount % this.rowsPerPage) || this.rowsPerPage);
- var pageHeight = this.getPageHeight(this.page);
- this.averageRowHeight = (pageHeight > 0 && rowsOnPage > 0) ? (pageHeight / rowsOnPage) : 0;
- },
- calcLastPageHeight: function(){
- if(!this.pageCount){
- return 0;
- }
- var lastPage = this.pageCount - 1;
- var lastPageHeight = ((this.rowCount % this.rowsPerPage)||(this.rowsPerPage)) * this.defaultRowHeight;
- this.pageHeights[lastPage] = lastPageHeight;
- return lastPageHeight;
- },
- updateContentHeight: function(inDh){
- this.height += inDh;
- this.resize();
- },
- updatePageHeight: function(inPageIndex, fromBuild, fromAsynRendering){
- if(this.pageExists(inPageIndex)){
- var oh = this.getPageHeight(inPageIndex);
- var h = (this.measurePage(inPageIndex));
- if(h === undefined){
- h = oh;
- }
- this.pageHeights[inPageIndex] = h;
- if(oh != h){
- this.updateContentHeight(h - oh);
- var ah = this.grid.get("autoHeight");
- if((typeof ah == "number" && ah > this.rowCount)||(ah === true && !fromBuild)){
- if(!fromAsynRendering){
- this.grid.sizeChange();
- }else{//fix #11101 by using fromAsynRendering to avoid deadlock
- var ns = this.grid.viewsNode.style;
- ns.height = parseInt(ns.height) + h - oh + 'px';
- this.repositionPages(inPageIndex);
- }
- }else{
- this.repositionPages(inPageIndex);
- }
- }
- return h;
- }
- return 0;
- },
- rowHeightChanged: function(inRowIndex, fromAsynRendering){
- this.updatePageHeight(Math.floor(inRowIndex / this.rowsPerPage), false, fromAsynRendering);
- },
- // scroller core
- invalidateNodes: function(){
- while(this.stack.length){
- this.destroyPage(this.popPage());
- }
- },
- createPageNode: function(){
- var p = document.createElement('div');
- html.attr(p,"role","presentation");
- p.style.position = 'absolute';
- //p.style.width = '100%';
- p.style[this.grid.isLeftToRight() ? "left" : "right"] = '0';
- return p;
- },
- getPageHeight: function(inPageIndex){
- var ph = this.pageHeights[inPageIndex];
- return (ph !== undefined ? ph : this.defaultPageHeight);
- },
- // FIXME: this is not a stack, it's a FIFO list
- pushPage: function(inPageIndex){
- return this.stack.push(inPageIndex);
- },
- popPage: function(){
- return this.stack.shift();
- },
- findPage: function(inTop){
- var i = 0, h = 0;
- for(var ph = 0; i<this.pageCount; i++, h += ph){
- ph = this.getPageHeight(i);
- if(h + ph >= inTop){
- break;
- }
- }
- this.page = i;
- this.pageTop = h;
- },
- buildPage: function(inPageIndex, inReuseNode, inPos){
- this.preparePage(inPageIndex, inReuseNode);
- this.positionPage(inPageIndex, inPos);
- // order of operations is key below
- this.installPage(inPageIndex);
- this.renderPage(inPageIndex);
- // order of operations is key above
- this.pushPage(inPageIndex);
- },
- needPage: function(inPageIndex, inPos){
- var h = this.getPageHeight(inPageIndex), oh = h;
- if(!this.pageExists(inPageIndex)){
- this.buildPage(inPageIndex, (!this.grid._autoHeight/*fix #10543*/ && this.keepPages&&(this.stack.length >= this.keepPages)), inPos);
- h = this.updatePageHeight(inPageIndex, true);
- }else{
- this.positionPage(inPageIndex, inPos);
- }
- return h;
- },
- onscroll: function(){
- this.scroll(this.scrollboxNode.scrollTop);
- },
- scroll: function(inTop){
- this.grid.scrollTop = inTop;
- if(this.colCount){
- this.startPacify();
- this.findPage(inTop);
- var h = this.height;
- var b = this.getScrollBottom(inTop);
- for(var p=this.page, y=this.pageTop; (p<this.pageCount)&&((b<0)||(y<b)); p++){
- y += this.needPage(p, y);
- }
- this.firstVisibleRow = this.getFirstVisibleRow(this.page, this.pageTop, inTop);
- this.lastVisibleRow = this.getLastVisibleRow(p - 1, y, b);
- // indicates some page size has been updated
- if(h != this.height){
- this.repositionPages(p-1);
- }
- this.endPacify();
- }
- },
- getScrollBottom: function(inTop){
- return (this.windowHeight >= 0 ? inTop + this.windowHeight : -1);
- },
- // events
- processNodeEvent: function(e, inNode){
- var t = e.target;
- while(t && (t != inNode) && t.parentNode && (t.parentNode.parentNode != inNode)){
- t = t.parentNode;
- }
- if(!t || !t.parentNode || (t.parentNode.parentNode != inNode)){
- return false;
- }
- var page = t.parentNode;
- e.topRowIndex = page.pageIndex * this.rowsPerPage;
- e.rowIndex = e.topRowIndex + indexInParent(t);
- e.rowTarget = t;
- return true;
- },
- processEvent: function(e){
- return this.processNodeEvent(e, this.contentNode);
- },
- // virtual rendering interface
- renderRow: function(inRowIndex, inPageNode){
- },
- removeRow: function(inRowIndex){
- },
- // page node operations
- getDefaultPageNode: function(inPageIndex){
- return this.getDefaultNodes()[inPageIndex];
- },
- positionPageNode: function(inNode, inPos){
- },
- getPageNodePosition: function(inNode){
- return inNode.offsetTop;
- },
- invalidatePageNode: function(inPageIndex, inNodes){
- var p = inNodes[inPageIndex];
- if(p){
- delete inNodes[inPageIndex];
- this.removePage(inPageIndex, p);
- cleanNode(p);
- p.innerHTML = '';
- }
- return p;
- },
- // scroll control
- getPageRow: function(inPage){
- return inPage * this.rowsPerPage;
- },
- getLastPageRow: function(inPage){
- return Math.min(this.rowCount, this.getPageRow(inPage + 1)) - 1;
- },
- getFirstVisibleRow: function(inPage, inPageTop, inScrollTop){
- if(!this.pageExists(inPage)){
- return 0;
- }
- var row = this.getPageRow(inPage);
- var nodes = this.getDefaultNodes();
- var rows = divkids(nodes[inPage]);
- for(var i=0,l=rows.length; i<l && inPageTop<inScrollTop; i++, row++){
- inPageTop += rows[i].offsetHeight;
- }
- return (row ? row - 1 : row);
- },
- getLastVisibleRow: function(inPage, inBottom, inScrollBottom){
- if(!this.pageExists(inPage)){
- return 0;
- }
- var nodes = this.getDefaultNodes();
- var row = this.getLastPageRow(inPage);
- var rows = divkids(nodes[inPage]);
- for(var i=rows.length-1; i>=0 && inBottom>inScrollBottom; i--, row--){
- inBottom -= rows[i].offsetHeight;
- }
- return row + 1;
- },
- findTopRow: function(inScrollTop){
- var nodes = this.getDefaultNodes();
- var rows = divkids(nodes[this.page]);
- for(var i=0,l=rows.length,t=this.pageTop,h; i<l; i++){
- h = rows[i].offsetHeight;
- t += h;
- if(t >= inScrollTop){
- this.offset = h - (t - inScrollTop);
- return i + this.page * this.rowsPerPage;
- }
- }
- return -1;
- },
- findScrollTop: function(inRow){
- var rowPage = Math.floor(inRow / this.rowsPerPage);
- var t = 0;
- var i, l;
- for(i=0; i<rowPage; i++){
- t += this.getPageHeight(i);
- }
- this.pageTop = t;
- this.page = rowPage;//fix #10543
- this.needPage(rowPage, this.pageTop);
- var nodes = this.getDefaultNodes();
- var rows = divkids(nodes[rowPage]);
- var r = inRow - this.rowsPerPage * rowPage;
- for(i=0,l=rows.length; i<l && i<r; i++){
- t += rows[i].offsetHeight;
- }
- return t;
- },
- dummy: 0
- });
- });
- },
- 'dijit/Calendar':function(){
- define("dijit/Calendar", [
- "dojo/_base/array", // array.map
- "dojo/date",
- "dojo/date/locale",
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.get
- "dojo/dom-class", // domClass.add domClass.contains domClass.remove domClass.toggle
- "dojo/_base/event", // event.stop
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/keys", // keys
- "dojo/_base/lang", // lang.hitch
- "dojo/_base/sniff", // has("ie")
- "./CalendarLite",
- "./_Widget",
- "./_CssStateMixin",
- "./_TemplatedMixin",
- "./form/DropDownButton",
- "./hccss" // not used directly, but sets CSS class on <body>
- ], function(array, date, local, declare, domAttr, domClass, event, kernel, keys, lang, has,
- CalendarLite, _Widget, _CssStateMixin, _TemplatedMixin, DropDownButton){
- /*=====
- var CalendarLite = dijit.CalendarLite;
- var _CssStateMixin = dijit._CssStateMixin;
- var _Widget = dijit._Widget;
- var _TemplatedMixin = dijit._TemplatedMixin;
- var DropDownButton = dijit.form.DropDownButton;
- =====*/
- // module:
- // dijit/Calendar
- // summary:
- // A simple GUI for choosing a date in the context of a monthly calendar.
- var Calendar = declare("dijit.Calendar",
- [CalendarLite, _Widget, _CssStateMixin], // _Widget for deprecated methods like setAttribute()
- {
- // summary:
- // A simple GUI for choosing a date in the context of a monthly calendar.
- //
- // description:
- // See CalendarLite for general description. Calendar extends CalendarLite, adding:
- // - month drop down list
- // - keyboard navigation
- // - CSS classes for hover/mousepress on date, month, and year nodes
- // - support of deprecated methods (will be removed in 2.0)
- // Set node classes for various mouse events, see dijit._CssStateMixin for more details
- cssStateNodes: {
- "decrementMonth": "dijitCalendarArrow",
- "incrementMonth": "dijitCalendarArrow",
- "previousYearLabelNode": "dijitCalendarPreviousYear",
- "nextYearLabelNode": "dijitCalendarNextYear"
- },
- setValue: function(/*Date*/ value){
- // summary:
- // Deprecated. Use set('value', ...) instead.
- // tags:
- // deprecated
- kernel.deprecated("dijit.Calendar:setValue() is deprecated. Use set('value', ...) instead.", "", "2.0");
- this.set('value', value);
- },
- _createMonthWidget: function(){
- // summary:
- // Creates the drop down button that displays the current month and lets user pick a new one
- return new Calendar._MonthDropDownButton({
- id: this.id + "_mddb",
- tabIndex: -1,
- onMonthSelect: lang.hitch(this, "_onMonthSelect"),
- lang: this.lang,
- dateLocaleModule: this.dateLocaleModule
- }, this.monthNode);
- },
- buildRendering: function(){
- this.inherited(arguments);
- // Events specific to Calendar, not used in CalendarLite
- this.connect(this.domNode, "onkeypress", "_onKeyPress");
- this.connect(this.dateRowsNode, "onmouseover", "_onDayMouseOver");
- this.connect(this.dateRowsNode, "onmouseout", "_onDayMouseOut");
- this.connect(this.dateRowsNode, "onmousedown", "_onDayMouseDown");
- this.connect(this.dateRowsNode, "onmouseup", "_onDayMouseUp");
- },
- _onMonthSelect: function(/*Number*/ newMonth){
- // summary:
- // Handler for when user selects a month from the drop down list
- // tags:
- // protected
- // move to selected month, bounding by the number of days in the month
- // (ex: dec 31 --> jan 28, not jan 31)
- this._setCurrentFocusAttr(this.dateFuncObj.add(this.currentFocus, "month",
- newMonth - this.currentFocus.getMonth()));
- },
- _onDayMouseOver: function(/*Event*/ evt){
- // summary:
- // Handler for mouse over events on days, sets hovered style
- // tags:
- // protected
- // event can occur on <td> or the <span> inside the td,
- // set node to the <td>.
- var node =
- domClass.contains(evt.target, "dijitCalendarDateLabel") ?
- evt.target.parentNode :
- evt.target;
- if(node && (
- (node.dijitDateValue && !domClass.contains(node, "dijitCalendarDisabledDate"))
- || node == this.previousYearLabelNode || node == this.nextYearLabelNode
- )){
- domClass.add(node, "dijitCalendarHoveredDate");
- this._currentNode = node;
- }
- },
- _onDayMouseOut: function(/*Event*/ evt){
- // summary:
- // Handler for mouse out events on days, clears hovered style
- // tags:
- // protected
- if(!this._currentNode){ return; }
- // if mouse out occurs moving from <td> to <span> inside <td>, ignore it
- if(evt.relatedTarget && evt.relatedTarget.parentNode == this._currentNode){ return; }
- var cls = "dijitCalendarHoveredDate";
- if(domClass.contains(this._currentNode, "dijitCalendarActiveDate")){
- cls += " dijitCalendarActiveDate";
- }
- domClass.remove(this._currentNode, cls);
- this._currentNode = null;
- },
- _onDayMouseDown: function(/*Event*/ evt){
- var node = evt.target.parentNode;
- if(node && node.dijitDateValue && !domClass.contains(node, "dijitCalendarDisabledDate")){
- domClass.add(node, "dijitCalendarActiveDate");
- this._currentNode = node;
- }
- },
- _onDayMouseUp: function(/*Event*/ evt){
- var node = evt.target.parentNode;
- if(node && node.dijitDateValue){
- domClass.remove(node, "dijitCalendarActiveDate");
- }
- },
- handleKey: function(/*Event*/ evt){
- // summary:
- // Provides keyboard navigation of calendar.
- // description:
- // Called from _onKeyPress() to handle keypress on a stand alone Calendar,
- // and also from `dijit.form._DateTimeTextBox` to pass a keypress event
- // from the `dijit.form.DateTextBox` to be handled in this widget
- // returns:
- // False if the key was recognized as a navigation key,
- // to indicate that the event was handled by Calendar and shouldn't be propogated
- // tags:
- // protected
- var increment = -1,
- interval,
- newValue = this.currentFocus;
- switch(evt.charOrCode){
- case keys.RIGHT_ARROW:
- increment = 1;
- //fallthrough...
- case keys.LEFT_ARROW:
- interval = "day";
- if(!this.isLeftToRight()){ increment *= -1; }
- break;
- case keys.DOWN_ARROW:
- increment = 1;
- //fallthrough...
- case keys.UP_ARROW:
- interval = "week";
- break;
- case keys.PAGE_DOWN:
- increment = 1;
- //fallthrough...
- case keys.PAGE_UP:
- interval = evt.ctrlKey || evt.altKey ? "year" : "month";
- break;
- case keys.END:
- // go to the next month
- newValue = this.dateFuncObj.add(newValue, "month", 1);
- // subtract a day from the result when we're done
- interval = "day";
- //fallthrough...
- case keys.HOME:
- newValue = new this.dateClassObj(newValue);
- newValue.setDate(1);
- break;
- case keys.ENTER:
- case " ":
- this.set("value", this.currentFocus);
- break;
- default:
- return true;
- }
- if(interval){
- newValue = this.dateFuncObj.add(newValue, interval, increment);
- }
- this._setCurrentFocusAttr(newValue);
- return false;
- },
- _onKeyPress: function(/*Event*/ evt){
- // summary:
- // For handling keypress events on a stand alone calendar
- if(!this.handleKey(evt)){
- event.stop(evt);
- }
- },
- onValueSelected: function(/*Date*/ /*===== date =====*/){
- // summary:
- // Deprecated. Notification that a date cell was selected. It may be the same as the previous value.
- // description:
- // Formerly used by `dijit.form._DateTimeTextBox` (and thus `dijit.form.DateTextBox`)
- // to get notification when the user has clicked a date. Now onExecute() (above) is used.
- // tags:
- // protected
- },
- onChange: function(value){
- this.onValueSelected(value); // remove in 2.0
- },
- getClassForDate: function(/*===== dateObject, locale =====*/){
- // summary:
- // May be overridden to return CSS classes to associate with the date entry for the given dateObject,
- // for example to indicate a holiday in specified locale.
- // dateObject: Date
- // locale: String?
- // tags:
- // extension
- /*=====
- return ""; // String
- =====*/
- }
- });
- Calendar._MonthDropDownButton = declare("dijit.Calendar._MonthDropDownButton", DropDownButton, {
- // summary:
- // DropDownButton for the current month. Displays name of current month
- // and a list of month names in the drop down
- onMonthSelect: function(){ },
- postCreate: function(){
- this.inherited(arguments);
- this.dropDown = new Calendar._MonthDropDown({
- id: this.id + "_mdd", //do not change this id because it is referenced in the template
- onChange: this.onMonthSelect
- });
- },
- _setMonthAttr: function(month){
- // summary:
- // Set the current month to display as a label
- var monthNames = this.dateLocaleModule.getNames('months', 'wide', 'standAlone', this.lang, month);
- this.dropDown.set("months", monthNames);
- // Set name of current month and also fill in spacer element with all the month names
- // (invisible) so that the maximum width will affect layout. But not on IE6 because then
- // the center <TH> overlaps the right <TH> (due to a browser bug).
- this.containerNode.innerHTML =
- (has("ie") == 6 ? "" : "<div class='dijitSpacer'>" + this.dropDown.domNode.innerHTML + "</div>") +
- "<div class='dijitCalendarMonthLabel dijitCalendarCurrentMonthLabel'>" + monthNames[month.getMonth()] + "</div>";
- }
- });
- Calendar._MonthDropDown = declare("dijit.Calendar._MonthDropDown", [_Widget, _TemplatedMixin], {
- // summary:
- // The list-of-months drop down from the MonthDropDownButton
- // months: String[]
- // List of names of months, possibly w/some undefined entries for Hebrew leap months
- // (ex: ["January", "February", undefined, "April", ...])
- months: [],
- templateString: "<div class='dijitCalendarMonthMenu dijitMenu' " +
- "data-dojo-attach-event='onclick:_onClick,onmouseover:_onMenuHover,onmouseout:_onMenuHover'></div>",
- _setMonthsAttr: function(/*String[]*/ months){
- this.domNode.innerHTML = array.map(months, function(month, idx){
- return month ? "<div class='dijitCalendarMonthLabel' month='" + idx +"'>" + month + "</div>" : "";
- }).join("");
- },
- _onClick: function(/*Event*/ evt){
- this.onChange(domAttr.get(evt.target, "month"));
- },
- onChange: function(/*Number*/ /*===== month =====*/){
- // summary:
- // Callback when month is selected from drop down
- },
- _onMenuHover: function(evt){
- domClass.toggle(evt.target, "dijitCalendarMonthLabelHover", evt.type == "mouseover");
- }
- });
- return Calendar;
- });
- },
- 'dijit/form/_ToggleButtonMixin':function(){
- define("dijit/form/_ToggleButtonMixin", [
- "dojo/_base/declare", // declare
- "dojo/dom-attr" // domAttr.set
- ], function(declare, domAttr){
- // module:
- // dijit/form/_ToggleButtonMixin
- // summary:
- // A mixin to provide functionality to allow a button that can be in two states (checked or not).
- return declare("dijit.form._ToggleButtonMixin", null, {
- // summary:
- // A mixin to provide functionality to allow a button that can be in two states (checked or not).
- // checked: Boolean
- // Corresponds to the native HTML <input> element's attribute.
- // In markup, specified as "checked='checked'" or just "checked".
- // True if the button is depressed, or the checkbox is checked,
- // or the radio button is selected, etc.
- checked: false,
- // aria-pressed for toggle buttons, and aria-checked for checkboxes
- _aria_attr: "aria-pressed",
- _onClick: function(/*Event*/ evt){
- var original = this.checked;
- this._set('checked', !original); // partially set the toggled value, assuming the toggle will work, so it can be overridden in the onclick handler
- var ret = this.inherited(arguments); // the user could reset the value here
- this.set('checked', ret ? this.checked : original); // officially set the toggled or user value, or reset it back
- return ret;
- },
- _setCheckedAttr: function(/*Boolean*/ value, /*Boolean?*/ priorityChange){
- this._set("checked", value);
- domAttr.set(this.focusNode || this.domNode, "checked", value);
- (this.focusNode || this.domNode).setAttribute(this._aria_attr, value ? "true" : "false"); // aria values should be strings
- this._handleOnChange(value, priorityChange);
- },
- reset: function(){
- // summary:
- // Reset the widget's value to what it was at initialization time
- this._hasBeenBlurred = false;
- // set checked state to original setting
- this.set('checked', this.params.checked || false);
- }
- });
- });
- },
- 'dojox/grid/enhanced/plugins/Selector':function(){
- define("dojox/grid/enhanced/plugins/Selector", [
- "dojo/_base/kernel",
- "dojo/_base/lang",
- "dojo/_base/declare",
- "dojo/_base/array",
- "dojo/_base/event",
- "dojo/keys",
- "dojo/query",
- "dojo/_base/html",
- "dojo/_base/window",
- "dijit/focus",
- "../../_RowSelector",
- "../_Plugin",
- "../../EnhancedGrid",
- "../../cells/_base",
- "./AutoScroll"
- ], function(dojo, lang, declare, array, event, keys, query, html, win, dijitFocus, _RowSelector, _Plugin, EnhancedGrid){
- /*=====
- dojo.declare("__SelectItem", null,{
- // summary:
- // An abstract representation of an item.
- });
- dojo.declare("__SelectCellItem", __SelectItem,{
- // summary:
- // An abstract representation of a cell.
-
- // row: Integer
- // Row index of this cell
- row: 0,
-
- // col: Integer
- // Column index of this cell
- col: 0
- });
- dojo.declare("__SelectRowItem", __SelectItem,{
- // summary:
- // An abstract representation of a row.
-
- // row: Integer
- // Row index of this row
- row: 0,
-
- // except: Integer[]
- // An array of column indexes of all the unselected cells in this row.
- except: []
- });
- dojo.declare("__SelectColItem", __SelectItem,{
- // summary:
- // An abstract representation of a column.
-
- // col: Integer
- // Column index of this column
- col: 0,
-
- // except: Integer[]
- // An array of row indexes of all the unselected cells in this column.
- except: []
- });
- =====*/
- var DISABLED = 0, SINGLE = 1, MULTI = 2,
- _theOther = { col: "row", row: "col" },
- _inRange = function(type, value, start, end, halfClose){
- if(type !== "cell"){
- value = value[type];
- start = start[type];
- end = end[type];
- if(typeof value !== "number" || typeof start !== "number" || typeof end !== "number"){
- return false;
- }
- return halfClose ? ((value >= start && value < end) || (value > end && value <= start))
- : ((value >= start && value <= end) || (value >= end && value <= start));
- }else{
- return _inRange("col", value, start, end, halfClose) && _inRange("row", value, start, end, halfClose);
- }
- },
- _isEqual = function(type, v1, v2){
- try{
- if(v1 && v2){
- switch(type){
- case "col": case "row":
- return v1[type] == v2[type] && typeof v1[type] == "number" &&
- !(_theOther[type] in v1) && !(_theOther[type] in v2);
- case "cell":
- return v1.col == v2.col && v1.row == v2.row && typeof v1.col == "number" && typeof v1.row == "number";
- }
- }
- }catch(e){}
- return false;
- },
- _stopEvent = function(evt){
- try{
- if(evt && evt.preventDefault){
- event.stop(evt);
- }
- }catch(e){}
- },
- _createItem = function(type, rowIndex, colIndex){
- switch(type){
- case "col":
- return {
- "col": typeof colIndex == "undefined" ? rowIndex : colIndex,
- "except": []
- };
- case "row":
- return {
- "row": rowIndex,
- "except": []
- };
- case "cell":
- return {
- "row": rowIndex,
- "col": colIndex
- };
- }
- return null;
- };
- var Selector = declare("dojox.grid.enhanced.plugins.Selector", _Plugin, {
- // summary:
- // Provides standard extended selection for grid.
- // Supports mouse/keyboard selection, multi-selection, and de-selection.
- // Acceptable plugin parameters:
- // The whole plugin parameter object is a config object passed to the setupConfig function.
- //
- // Acceptable cell parameters defined in layout:
- // 1. notselectable: boolean
- // Whether this column is (and all the cells in it are) selectable.
-
- // name: String
- // plugin name
- name: "selector",
- // noClear: Boolean
- // Not to clear rows selected by IndirectSelection.
- /*
- // _config: null,
- // _enabled: true,
- // _selecting: {
- // row: false,
- // col: false,
- // cell: false
- // },
- // _selected: {
- // row: [],
- // col: [],
- // cell: []
- // },
- // _startPoint: {},
- // _currentPoint: {},
- // _lastAnchorPoint: {},
- // _lastEndPoint: {},
- // _lastSelectedAnchorPoint: {},
- // _lastSelectedEndPoint: {},
- // _keyboardSelect: {
- // row: 0,
- // col: 0,
- // cell: 0
- // },
- // _curType: null,
- // _lastType: null,
- // _usingKeyboard: false,
- // _toSelect: true,
- */
- constructor: function(grid, args){
- this.grid = grid;
- this._config = {
- row: MULTI,
- col: MULTI,
- cell: MULTI
- };
- this.noClear = args && args.noClear;
- this.setupConfig(args);
- if(grid.selectionMode === "single"){
- this._config.row = SINGLE;
- }
- this._enabled = true;
- this._selecting = {};
- this._selected = {
- "col": [],
- "row": [],
- "cell": []
- };
- this._startPoint = {};
- this._currentPoint = {};
- this._lastAnchorPoint = {};
- this._lastEndPoint = {};
- this._lastSelectedAnchorPoint = {};
- this._lastSelectedEndPoint = {};
- this._keyboardSelect = {};
- this._lastType = null;
- this._selectedRowModified = {};
- this._hacks();
- this._initEvents();
- this._initAreas();
- this._mixinGrid();
- },
- destroy: function(){
- this.inherited(arguments);
- },
- //------------public--------------------
- setupConfig: function(config){
- // summary:
- // Set selection mode for row/col/cell.
- // config: Object
- // An object with the following structure (all properties are optional):
- // {
- // //Default is "multi", all other values are same as "multi".
- // row: false|"disabled"|"single",
- // col: false|"disabled"|"single",
- // cell: false|"disabled"|"single"
- // }
- if(!config || !lang.isObject(config)){
- return;
- }
- var types = ["row", "col", "cell"];
- for(var type in config){
- if(array.indexOf(types, type) >= 0){
- if(!config[type] || config[type] == "disabled"){
- this._config[type] = DISABLED;
- }else if(config[type] == "single"){
- this._config[type] = SINGLE;
- }else{
- this._config[type] = MULTI;
- }
- }
- }
-
- //Have to set mode to default grid selection.
- var mode = ["none","single","extended"][this._config.row];
- this.grid.selection.setMode(mode);
- },
- isSelected: function(type, rowIndex, colIndex){
- // summary:
- // Check whether a location (a cell, a column or a row) is selected.
- // tag:
- // public
- // type: String
- // "row" or "col" or "cell"
- // rowIndex: Integer
- // If type is "row" or "cell", this is the row index.
- // If type if "col", this is the column index.
- // colIndex: Integer?
- // Only valid when type is "cell"
- // return: Boolean
- // true if selected, false if not. If cell is covered by a selected column, it's selected.
- return this._isSelected(type, _createItem(type, rowIndex, colIndex));
- },
- toggleSelect: function(type, rowIndex, colIndex){
- this._startSelect(type, _createItem(type, rowIndex, colIndex), this._config[type] === MULTI, false, false, !this.isSelected(type, rowIndex, colIndex));
- this._endSelect(type);
- },
- select: function(type, rowIndex, colIndex){
- // summary:
- // Select a location (a cell, a column or a row).
- // tag:
- // public
- // type: String
- // "row" or "col" or "cell"
- // rowIndex: Integer
- // If type is "row" or "cell", this is the row index.
- // If type if "col", this is the column index.
- // colIndex: Integer?
- // Only valid when type is "cell"
- if(!this.isSelected(type, rowIndex, colIndex)){
- this.toggleSelect(type, rowIndex, colIndex);
- }
- },
- deselect: function(type, rowIndex, colIndex){
- if(this.isSelected(type, rowIndex, colIndex)){
- this.toggleSelect(type, rowIndex, colIndex);
- }
- },
- selectRange: function(type, start, end, toSelect){
- // summary:
- // Select a continuous range (a block of cells, a set of continuous columns or rows)
- // tag:
- // public
- // type: String
- // "row" or "col" or "cell"
- // start: Integer | Object
- // If type is "row" or "col", this is the index of the starting row or column.
- // If type if "cell", this is the left-top cell of the range.
- // end: Integer | Object
- // If type is "row" or "col", this is the index of the ending row or column.
- // If type if "cell", this is the right-bottom cell of the range.
- this.grid._selectingRange = true;
- var startPoint = type == "cell" ? _createItem(type, start.row, start.col) : _createItem(type, start),
- endPoint = type == "cell" ? _createItem(type, end.row, end.col) : _createItem(type, end);
- this._startSelect(type, startPoint, false, false, false, toSelect);
- this._highlight(type, endPoint, toSelect === undefined ? true : toSelect);
- this._endSelect(type);
- this.grid._selectingRange = false;
- },
- clear: function(type){
- // summary:
- // Clear all selections.
- // tag:
- // public
- // type: String?
- // "row" or "col" or "cell". If omitted, clear all.
- this._clearSelection(type || "all");
- },
- isSelecting: function(type){
- // summary:
- // Check whether the user is currently selecting something.
- // tag:
- // public
- // type: String
- // "row" or "col" or "cell"
- // return: Boolean
- // true if is selection, false otherwise.
- if(typeof type == "undefined"){
- return this._selecting.col || this._selecting.row || this._selecting.cell;
- }
- return this._selecting[type];
- },
- selectEnabled: function(toEnable){
- // summary:
- // Turn on/off this selection functionality if *toEnable* is provided.
- // Check whether this selection functionality is enabled if nothing is passed in.
- // tag:
- // public
- // toEnable: Boolean?
- // To enable or not. Optional.
- // return: Boolean | undefined
- // Enabled or not.
- if(typeof toEnable != "undefined" && !this.isSelecting()){
- this._enabled = !!toEnable;
- }
- return this._enabled;
- },
- getSelected: function(type, includeExceptions){
- // summary:
- // Get an array of selected locations.
- // tag:
- // public
- // type: String
- // "row" or "col" or "cell"
- // includeExceptions: Boolean
- // Only meaningful for rows/columns. If true, all selected rows/cols, even they are partly selected, are all returned.
- // return: __SelectItem[]
- switch(type){
- case "cell":
- return array.map(this._selected[type], function(item){ return item; });
- case "col": case "row":
- return array.map(includeExceptions ? this._selected[type]
- : array.filter(this._selected[type], function(item){
- return item.except.length === 0;
- }), function(item){
- return includeExceptions ? item : item[type];
- });
- }
- return [];
- },
- getSelectedCount: function(type, includeExceptions){
- // summary:
- // Get the number of selected items.
- // tag:
- // public
- // type: String
- // "row" or "col" or "cell"
- // includeExceptions: Boolean
- // Only meaningful for rows/columns. If true, all selected rows/cols, even they are partly selected, are all returned.
- // return: Integer
- // The number of selected items.
- switch(type){
- case "cell":
- return this._selected[type].length;
- case "col": case "row":
- return (includeExceptions ? this._selected[type]
- : array.filter(this._selected[type], function(item){
- return item.except.length === 0;
- })).length;
- }
- return 0;
- },
- getSelectedType: function(){
- // summary:
- // Get the type of selected items.
- // tag:
- // public
- // return: String
- // "row" or "col" or "cell", or any mix of these (separator is | ).
- var s = this._selected;
- return ["", "cell", "row", "row|cell",
- "col", "col|cell", "col|row", "col|row|cell"
- ][(!!s.cell.length) | (!!s.row.length << 1) | (!!s.col.length << 2)];
- },
- getLastSelectedRange: function(type){
- // summary:
- // Get last selected range of the given type.
- // tag:
- // public
- // return: Object
- // {start: __SelectItem, end: __SelectItem}
- // return null if nothing is selected.
- return this._lastAnchorPoint[type] ? {
- "start": this._lastAnchorPoint[type],
- "end": this._lastEndPoint[type]
- } : null;
- },
-
- //--------------------------private----------------------------
- _hacks: function(){
- // summary:
- // Complete the event system of grid, hack some grid functions to prevent default behavior.
- var g = this.grid;
- var doContentMouseUp = function(e){
- if(e.cellNode){
- g.onMouseUp(e);
- }
- g.onMouseUpRow(e);
- };
- var mouseUp = lang.hitch(g, "onMouseUp");
- var mouseDown = lang.hitch(g, "onMouseDown");
- var doRowSelectorFocus = function(e){
- e.cellNode.style.border = "solid 1px";
- };
- array.forEach(g.views.views, function(view){
- view.content.domouseup = doContentMouseUp;
- view.header.domouseup = mouseUp;
- if(view.declaredClass == "dojox.grid._RowSelector"){
- view.domousedown = mouseDown;
- view.domouseup = mouseUp;
- view.dofocus = doRowSelectorFocus;
- }
- });
- //Disable default selection.
- g.selection.clickSelect = function(){};
-
- this._oldDeselectAll = g.selection.deselectAll;
- var _this = this;
- g.selection.selectRange = function(from, to){
- _this.selectRange("row", from, to, true);
- if(g.selection.preserver){
- g.selection.preserver._updateMapping(true, true, false, from, to);
- }
- g.selection.onChanged();
- };
- g.selection.deselectRange = function(from, to){
- _this.selectRange("row", from, to, false);
- if(g.selection.preserver){
- g.selection.preserver._updateMapping(true, false, false, from, to);
- }
- g.selection.onChanged();
- };
- g.selection.deselectAll = function(){
- g._selectingRange = true;
- _this._oldDeselectAll.apply(g.selection, arguments);
- _this._clearSelection("all");
- g._selectingRange = false;
- if(g.selection.preserver){
- g.selection.preserver._updateMapping(true, false, true);
- }
- g.selection.onChanged();
- };
-
- var rowSelector = g.views.views[0];
- //The default function re-write the whole className, so can not insert any other classes.
- if(rowSelector instanceof _RowSelector){
- rowSelector.doStyleRowNode = function(inRowIndex, inRowNode){
- html.removeClass(inRowNode, "dojoxGridRow");
- html.addClass(inRowNode, "dojoxGridRowbar");
- html.addClass(inRowNode, "dojoxGridNonNormalizedCell");
- html.toggleClass(inRowNode, "dojoxGridRowbarOver", g.rows.isOver(inRowIndex));
- html.toggleClass(inRowNode, "dojoxGridRowbarSelected", !!g.selection.isSelected(inRowIndex));
- };
- }
- this.connect(g, "updateRow", function(rowIndex){
- array.forEach(g.layout.cells, function(cell){
- if(this.isSelected("cell", rowIndex, cell.index)){
- this._highlightNode(cell.getNode(rowIndex), true);
- }
- }, this);
- });
- },
- _mixinGrid: function(){
- // summary:
- // Expose events to grid.
- var g = this.grid;
- g.setupSelectorConfig = lang.hitch(this, this.setupConfig);
- g.onStartSelect = function(){};
- g.onEndSelect = function(){};
- g.onStartDeselect = function(){};
- g.onEndDeselect = function(){};
- g.onSelectCleared = function(){};
- },
- _initEvents: function(){
- // summary:
- // Connect events, create event handlers.
- var g = this.grid,
- _this = this,
- dp = lang.partial,
- starter = function(type, e){
- if(type === "row"){
- _this._isUsingRowSelector = true;
- }
- //only left mouse button can select.
- if(_this.selectEnabled() && _this._config[type] && e.button != 2){
- if(_this._keyboardSelect.col || _this._keyboardSelect.row || _this._keyboardSelect.cell){
- _this._endSelect("all");
- _this._keyboardSelect.col = _this._keyboardSelect.row = _this._keyboardSelect.cell = 0;
- }
- if(_this._usingKeyboard){
- _this._usingKeyboard = false;
- }
- var target = _createItem(type, e.rowIndex, e.cell && e.cell.index);
- _this._startSelect(type, target, e.ctrlKey, e.shiftKey);
- }
- },
- ender = lang.hitch(this, "_endSelect");
- this.connect(g, "onHeaderCellMouseDown", dp(starter, "col"));
- this.connect(g, "onHeaderCellMouseUp", dp(ender, "col"));
-
- this.connect(g, "onRowSelectorMouseDown", dp(starter, "row"));
- this.connect(g, "onRowSelectorMouseUp", dp(ender, "row"));
-
- this.connect(g, "onCellMouseDown", function(e){
- if(e.cell && e.cell.isRowSelector){ return; }
- if(g.singleClickEdit){
- _this._singleClickEdit = true;
- g.singleClickEdit = false;
- }
- starter(_this._config["cell"] == DISABLED ? "row" : "cell", e);
- });
- this.connect(g, "onCellMouseUp", function(e){
- if(_this._singleClickEdit){
- delete _this._singleClickEdit;
- g.singleClickEdit = true;
- }
- ender("all", e);
- });
-
- this.connect(g, "onCellMouseOver", function(e){
- if(_this._curType != "row" && _this._selecting[_this._curType] && _this._config[_this._curType] == MULTI){
- _this._highlight("col", _createItem("col", e.cell.index), _this._toSelect);
- if(!_this._keyboardSelect.cell){
- _this._highlight("cell", _createItem("cell", e.rowIndex, e.cell.index), _this._toSelect);
- }
- }
- });
- this.connect(g, "onHeaderCellMouseOver", function(e){
- if(_this._selecting.col && _this._config.col == MULTI){
- _this._highlight("col", _createItem("col", e.cell.index), _this._toSelect);
- }
- });
- this.connect(g, "onRowMouseOver", function(e){
- if(_this._selecting.row && _this._config.row == MULTI){
- _this._highlight("row", _createItem("row", e.rowIndex), _this._toSelect);
- }
- });
-
- //When row order has changed in a unpredictable way (sorted or filtered), map the new rowindex.
- this.connect(g, "onSelectedById", "_onSelectedById");
-
- //When the grid refreshes, all those selected should still appear selected.
- this.connect(g, "_onFetchComplete", function(){
- //console.debug("refresh after buildPage:", g._notRefreshSelection);
- if(!g._notRefreshSelection){
- this._refreshSelected(true);
- }
- });
- //Small scroll might not refresh the grid.
- this.connect(g.scroller, "buildPage", function(){
- //console.debug("refresh after buildPage:", g._notRefreshSelection);
- if(!g._notRefreshSelection){
- this._refreshSelected(true);
- }
- });
-
- //Whenever the mouse is up, end selecting.
- this.connect(win.doc, "onmouseup", dp(ender, "all"));
-
- //If autoscroll is enabled, connect to it.
- this.connect(g, "onEndAutoScroll", function(isVertical, isForward, view, target){
- var selectCell = _this._selecting.cell,
- type, current, dir = isForward ? 1 : -1;
- if(isVertical && (selectCell || _this._selecting.row)){
- type = selectCell ? "cell" : "row";
- current = _this._currentPoint[type];
- _this._highlight(type, _createItem(type, current.row + dir, current.col), _this._toSelect);
- }else if(!isVertical && (selectCell || _this._selecting.col)){
- type = selectCell ? "cell" : "col";
- current = _this._currentPoint[type];
- _this._highlight(type, _createItem(type, current.row, target), _this._toSelect);
- }
- });
- //If the grid is changed, selection should be consistent.
- this.subscribe("dojox/grid/rearrange/move/" + g.id, "_onInternalRearrange");
- this.subscribe("dojox/grid/rearrange/copy/" + g.id, "_onInternalRearrange");
- this.subscribe("dojox/grid/rearrange/change/" + g.id, "_onExternalChange");
- this.subscribe("dojox/grid/rearrange/insert/" + g.id, "_onExternalChange");
- this.subscribe("dojox/grid/rearrange/remove/" + g.id, "clear");
-
- //have to also select when the grid's default select is used.
- this.connect(g, "onSelected", function(rowIndex){
- if(this._selectedRowModified && this._isUsingRowSelector){
- delete this._selectedRowModified;
- }else if(!this.grid._selectingRange){
- this.select("row", rowIndex);
- }
- });
- this.connect(g, "onDeselected", function(rowIndex){
- if(this._selectedRowModified && this._isUsingRowSelector){
- delete this._selectedRowModified;
- }else if(!this.grid._selectingRange){
- this.deselect("row", rowIndex);
- }
- });
- },
- _onSelectedById: function(id, newIndex, isSelected){
- if(this.grid._noInternalMapping){
- return;
- }
- var pointSet = [this._lastAnchorPoint.row, this._lastEndPoint.row,
- this._lastSelectedAnchorPoint.row, this._lastSelectedEndPoint.row];
- pointSet = pointSet.concat(this._selected.row);
- var found = false;
- array.forEach(pointSet, function(item){
- if(item){
- if(item.id === id){
- found = true;
- item.row = newIndex;
- }else if(item.row === newIndex && item.id){
- item.row = -1;
- }
- }
- });
- if(!found && isSelected){
- array.some(this._selected.row, function(item){
- if(item && !item.id && !item.except.length){
- item.id = id;
- item.row = newIndex;
- return true;
- }
- return false;
- });
- }
- found = false;
- pointSet = [this._lastAnchorPoint.cell, this._lastEndPoint.cell,
- this._lastSelectedAnchorPoint.cell, this._lastSelectedEndPoint.cell];
- pointSet = pointSet.concat(this._selected.cell);
- array.forEach(pointSet, function(item){
- if(item){
- if(item.id === id){
- found = true;
- item.row = newIndex;
- }else if(item.row === newIndex && item.id){
- item.row = -1;
- }
- }
- });
- },
- onSetStore: function(){
- this._clearSelection("all");
- },
- _onInternalRearrange: function(type, mapping){
- try{
- //The column can not refresh it self!
- this._refresh("col", false);
-
- array.forEach(this._selected.row, function(item){
- array.forEach(this.grid.layout.cells, function(cell){
- this._highlightNode(cell.getNode(item.row), false);
- }, this);
- }, this);
- //The rowbar must be cleaned manually
- query(".dojoxGridRowSelectorSelected").forEach(function(node){
- html.removeClass(node, "dojoxGridRowSelectorSelected");
- html.removeClass(node, "dojoxGridRowSelectorSelectedUp");
- html.removeClass(node, "dojoxGridRowSelectorSelectedDown");
- });
-
- var cleanUp = function(item){
- if(item){
- delete item.converted;
- }
- },
- pointSet = [this._lastAnchorPoint[type], this._lastEndPoint[type],
- this._lastSelectedAnchorPoint[type], this._lastSelectedEndPoint[type]];
-
- if(type === "cell"){
- this.selectRange("cell", mapping.to.min, mapping.to.max);
- var cells = this.grid.layout.cells;
- array.forEach(pointSet, function(item){
- if(item.converted){ return; }
- for(var r = mapping.from.min.row, tr = mapping.to.min.row; r <= mapping.from.max.row; ++r, ++tr){
- for(var c = mapping.from.min.col, tc = mapping.to.min.col; c <= mapping.from.max.col; ++c, ++tc){
- while(cells[c].hidden){ ++c; }
- while(cells[tc].hidden){ ++tc; }
- if(item.row == r && item.col == c){
- //console.log('mapping found: (', item.row, ",",item.col,") to (", tr, ",", tc,")");
- item.row = tr;
- item.col = tc;
- item.converted = true;
- return;
- }
- }
- }
- });
- }else{
- pointSet = this._selected.cell.concat(this._selected[type]).concat(pointSet).concat(
- [this._lastAnchorPoint.cell, this._lastEndPoint.cell,
- this._lastSelectedAnchorPoint.cell, this._lastSelectedEndPoint.cell]);
- array.forEach(pointSet, function(item){
- if(item && !item.converted){
- var from = item[type];
- if(from in mapping){
- item[type] = mapping[from];
- }
- item.converted = true;
- }
- });
- array.forEach(this._selected[_theOther[type]], function(item){
- for(var i = 0, len = item.except.length; i < len; ++i){
- var from = item.except[i];
- if(from in mapping){
- item.except[i] = mapping[from];
- }
- }
- });
- }
-
- array.forEach(pointSet, cleanUp);
-
- this._refreshSelected(true);
- this._focusPoint(type, this._lastEndPoint);
- }catch(e){
- console.warn("Selector._onInternalRearrange() error",e);
- }
- },
- _onExternalChange: function(type, target){
- var start = type == "cell" ? target.min : target[0],
- end = type == "cell" ? target.max : target[target.length - 1];
- this.selectRange(type, start, end);
- },
- _refresh: function(type, toHighlight){
- if(!this._keyboardSelect[type]){
- array.forEach(this._selected[type], function(item){
- this._highlightSingle(type, toHighlight, item, undefined, true);
- }, this);
- }
- },
- _refreshSelected: function(){
- this._refresh("col", true);
- this._refresh("row", true);
- this._refresh("cell", true);
- },
- _initAreas: function(){
- var g = this.grid, f = g.focus, _this = this,
- keyboardSelectReady = 1, duringKeyboardSelect = 2,
- onmove = function(type, createNewEnd, rowStep, colStep, evt){
- //Keyboard swipe selection is SHIFT + Direction Keys.
- var ks = _this._keyboardSelect;
- //Tricky, rely on valid status not being 0.
- if(evt.shiftKey && ks[type]){
- if(ks[type] === keyboardSelectReady){
- if(type === "cell"){
- var item = _this._lastEndPoint[type];
- if(f.cell != g.layout.cells[item.col + colStep] || f.rowIndex != item.row + rowStep){
- ks[type] = 0;
- return;
- }
- }
- //If selecting is not started, start it
- _this._startSelect(type, _this._lastAnchorPoint[type], true, false, true);
- _this._highlight(type, _this._lastEndPoint[type], _this._toSelect);
- ks[type] = duringKeyboardSelect;
- }
- //Highlight to the new end point.
- var newEnd = createNewEnd(type, rowStep, colStep, evt);
- if(_this._isValid(type, newEnd, g)){
- _this._highlight(type, newEnd, _this._toSelect);
- }
- _stopEvent(evt);
- }
- },
- onkeydown = function(type, getTarget, evt, isBubble){
- if(isBubble && _this.selectEnabled() && _this._config[type] != DISABLED){
- switch(evt.keyCode){
- case keys.SPACE:
- //Keyboard single point selection is SPACE.
- _this._startSelect(type, getTarget(), evt.ctrlKey, evt.shiftKey);
- _this._endSelect(type);
- break;
- case keys.SHIFT:
- //Keyboard swipe selection starts with SHIFT.
- if(_this._config[type] == MULTI && _this._isValid(type, _this._lastAnchorPoint[type], g)){
- //End last selection if any.
- _this._endSelect(type);
- _this._keyboardSelect[type] = keyboardSelectReady;
- _this._usingKeyboard = true;
- }
- }
- }
- },
- onkeyup = function(type, evt, isBubble){
- if(isBubble && evt.keyCode == keys.SHIFT && _this._keyboardSelect[type]){
- _this._endSelect(type);
- _this._keyboardSelect[type] = 0;
- }
- };
- //TODO: this area "rowHeader" should be put outside, same level as header/content.
- if(g.views.views[0] instanceof _RowSelector){
- this._lastFocusedRowBarIdx = 0;
- f.addArea({
- name:"rowHeader",
- onFocus: function(evt, step){
- var view = g.views.views[0];
- if(view instanceof _RowSelector){
- var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
- if(rowBarNode){
- html.toggleClass(rowBarNode, f.focusClass, false);
- }
- //evt might not be real event, it may be a mock object instead.
- if(evt && "rowIndex" in evt){
- if(evt.rowIndex >= 0){
- _this._lastFocusedRowBarIdx = evt.rowIndex;
- }else if(!_this._lastFocusedRowBarIdx){
- _this._lastFocusedRowBarIdx = 0;
- }
- }
- rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
- if(rowBarNode){
- dijitFocus.focus(rowBarNode);
- html.toggleClass(rowBarNode, f.focusClass, true);
- }
- f.rowIndex = _this._lastFocusedRowBarIdx;
- _stopEvent(evt);
- return true;
- }
- return false;
- },
- onBlur: function(evt, step){
- var view = g.views.views[0];
- if(view instanceof _RowSelector){
- var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
- if(rowBarNode){
- html.toggleClass(rowBarNode, f.focusClass, false);
- }
- _stopEvent(evt);
- }
- return true;
- },
- onMove: function(rowStep, colStep, evt){
- var view = g.views.views[0];
- if(rowStep && view instanceof _RowSelector){
- var next = _this._lastFocusedRowBarIdx + rowStep;
- if(next >= 0 && next < g.rowCount){
- //TODO: these logic require a better Scroller.
- _stopEvent(evt);
- var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
- html.toggleClass(rowBarNode, f.focusClass, false);
- //If the row is not fetched, fetch it.
- var sc = g.scroller;
- var lastPageRow = sc.getLastPageRow(sc.page);
- var rc = g.rowCount - 1, row = Math.min(rc, next);
- if(next > lastPageRow){
- g.setScrollTop(g.scrollTop + sc.findScrollTop(row) - sc.findScrollTop(_this._lastFocusedRowBarIdx));
- }
- //Now we have fetched the row.
- rowBarNode = view.getCellNode(next, 0);
- dijitFocus.focus(rowBarNode);
- html.toggleClass(rowBarNode, f.focusClass, true);
- _this._lastFocusedRowBarIdx = next;
- //If the row is out of view, scroll to it.
- f.cell = rowBarNode;
- f.cell.view = view;
- f.cell.getNode = function(index){
- return f.cell;
- };
- f.rowIndex = _this._lastFocusedRowBarIdx;
- f.scrollIntoView();
- f.cell = null;
- }
- }
- }
- });
- f.placeArea("rowHeader","before","content");
- }
- //Support keyboard selection.
- f.addArea({
- name:"cellselect",
- onMove: lang.partial(onmove, "cell", function(type, rowStep, colStep, evt){
- var current = _this._currentPoint[type];
- return _createItem("cell", current.row + rowStep, current.col + colStep);
- }),
- onKeyDown: lang.partial(onkeydown, "cell", function(){
- return _createItem("cell", f.rowIndex, f.cell.index);
- }),
- onKeyUp: lang.partial(onkeyup, "cell")
- });
- f.placeArea("cellselect","below","content");
- f.addArea({
- name:"colselect",
- onMove: lang.partial(onmove, "col", function(type, rowStep, colStep, evt){
- var current = _this._currentPoint[type];
- return _createItem("col", current.col + colStep);
- }),
- onKeyDown: lang.partial(onkeydown, "col", function(){
- return _createItem("col", f.getHeaderIndex());
- }),
- onKeyUp: lang.partial(onkeyup, "col")
- });
- f.placeArea("colselect","below","header");
- f.addArea({
- name:"rowselect",
- onMove: lang.partial(onmove, "row", function(type, rowStep, colStep, evt){
- return _createItem("row", f.rowIndex);
- }),
- onKeyDown: lang.partial(onkeydown, "row", function(){
- return _createItem("row", f.rowIndex);
- }),
- onKeyUp: lang.partial(onkeyup, "row")
- });
- f.placeArea("rowselect","below","rowHeader");
- },
- _clearSelection: function(type, reservedItem){
- // summary:
- // Clear selection for given type and fire events, but retain the highlight for *reservedItem*,
- // thus avoid "flashing".
- // tag:
- // private
- // type: String
- // "row", "col", or "cell
- // reservedItem: __SelectItem
- // The item to retain highlight.
- if(type == "all"){
- this._clearSelection("cell", reservedItem);
- this._clearSelection("col", reservedItem);
- this._clearSelection("row", reservedItem);
- return;
- }
- this._isUsingRowSelector = true;
- array.forEach(this._selected[type], function(item){
- if(!_isEqual(type, reservedItem, item)){
- this._highlightSingle(type, false, item);
- }
- }, this);
- this._blurPoint(type, this._currentPoint);
- this._selecting[type] = false;
- this._startPoint[type] = this._currentPoint[type] = null;
- this._selected[type] = [];
-
- //Have to also deselect default grid selection.
- if(type == "row" && !this.grid._selectingRange){
- this._oldDeselectAll.call(this.grid.selection);
- this.grid.selection._selectedById = {};
- }
-
- //Fire events.
- this.grid.onEndDeselect(type, null, null, this._selected);
- this.grid.onSelectCleared(type);
- },
- _startSelect: function(type, start, extending, isRange, mandatarySelect, toSelect){
- // summary:
- // Start selection, setup start point and current point, fire events.
- // tag:
- // private
- // type: String
- // "row", "col", or "cell"
- // extending: Boolean
- // Whether this is a multi selection
- // isRange: Boolean
- // Whether this is a range selection (i.e. select from the last end point to this point)
- // start: __SelectItem
- // The start point
- // mandatarySelect: Boolean
- // If true, toSelect will be same as the original selection status.
- if(!this._isValid(type, start)){
- return;
- }
- var lastIsSelected = this._isSelected(type, this._lastEndPoint[type]),
- isSelected = this._isSelected(type, start);
-
- if(this.noClear && !extending){
- this._toSelect = toSelect === undefined ? true : toSelect;
- }else{
- //If we are modifying the selection using keyboard, retain the old status.
- this._toSelect = mandatarySelect ? isSelected : !isSelected;
- }
-
- //If CTRL is not pressed or it's SINGLE mode, this is a brand new selection.
- if(!extending || (!isSelected && this._config[type] == SINGLE)){
- this._clearSelection("col", start);
- this._clearSelection("cell", start);
- if(!this.noClear || (type === 'row' && this._config[type] == SINGLE)){
- this._clearSelection('row', start);
- }
- this._toSelect = toSelect === undefined ? true : toSelect;
- }
-
- this._selecting[type] = true;
- this._currentPoint[type] = null;
-
- //We're holding SHIFT while clicking, it's a Click-Range selection.
- if(isRange && this._lastType == type && lastIsSelected == this._toSelect && this._config[type] == MULTI){
- if(type === "row"){
- this._isUsingRowSelector = true;
- }
- this._startPoint[type] = this._lastEndPoint[type];
- this._highlight(type, this._startPoint[type]);
- this._isUsingRowSelector = false;
- }else{
- this._startPoint[type] = start;
- }
- //Now start selection
- this._curType = type;
- this._fireEvent("start", type);
- this._isStartFocus = true;
- this._isUsingRowSelector = true;
- this._highlight(type, start, this._toSelect);
- this._isStartFocus = false;
- },
- _endSelect: function(type){
- // summary:
- // End selection. Keep records, fire events and cleanup status.
- // tag:
- // private
- // type: String
- // "row", "col", or "cell"
- if(type === "row"){
- delete this._isUsingRowSelector;
- }
- if(type == "all"){
- this._endSelect("col");
- this._endSelect("row");
- this._endSelect("cell");
- }else if(this._selecting[type]){
- this._addToSelected(type);
- this._lastAnchorPoint[type] = this._startPoint[type];
- this._lastEndPoint[type] = this._currentPoint[type];
- if(this._toSelect){
- this._lastSelectedAnchorPoint[type] = this._lastAnchorPoint[type];
- this._lastSelectedEndPoint[type] = this._lastEndPoint[type];
- }
- this._startPoint[type] = this._currentPoint[type] = null;
- this._selecting[type] = false;
- this._lastType = type;
- this._fireEvent("end", type);
- }
- },
- _fireEvent: function(evtName, type){
- switch(evtName){
- case "start":
- this.grid[this._toSelect ? "onStartSelect" : "onStartDeselect"](type, this._startPoint[type], this._selected);
- break;
- case "end":
- this.grid[this._toSelect ? "onEndSelect" : "onEndDeselect"](type, this._lastAnchorPoint[type], this._lastEndPoint[type], this._selected);
- break;
- }
- },
- _calcToHighlight: function(type, target, toHighlight, toSelect){
- // summary:
- // Calculate what status should *target* have.
- // If *toSelect* is not provided, this is a no op.
- // This function is time-critical!!
- if(toSelect !== undefined){
- var sltd;
- if(this._usingKeyboard && !toHighlight){
- var last = this._isInLastRange(this._lastType, target);
- if(last){
- sltd = this._isSelected(type, target);
- //This 2 cases makes the keyboard swipe selection valid!
- if(toSelect && sltd){
- return false;
- }
- if(!toSelect && !sltd && this._isInLastRange(this._lastType, target, true)){
- return true;
- }
- }
- }
- return toHighlight ? toSelect : (sltd || this._isSelected(type, target));
- }
- return toHighlight;
- },
- _highlightNode: function(node, toHighlight){
- // summary:
- // Do the actual highlight work.
- if(node){
- var selectCSSClass = "dojoxGridRowSelected";
- var selectCellClass = "dojoxGridCellSelected";
- html.toggleClass(node, selectCSSClass, toHighlight);
- html.toggleClass(node, selectCellClass, toHighlight);
- }
- },
- _highlightHeader: function(colIdx, toHighlight){
- var cells = this.grid.layout.cells;
- var node = cells[colIdx].getHeaderNode();
- var selectedClass = "dojoxGridHeaderSelected";
- html.toggleClass(node, selectedClass, toHighlight);
- },
- _highlightRowSelector: function(rowIdx, toHighlight){
- //var t1 = (new Date()).getTime();
- var rowSelector = this.grid.views.views[0];
- if(rowSelector instanceof _RowSelector){
- var node = rowSelector.getRowNode(rowIdx);
- if(node){
- var selectedClass = "dojoxGridRowSelectorSelected";
- html.toggleClass(node, selectedClass, toHighlight);
- }
- }
- //console.log((new Date()).getTime() - t1);
- },
- _highlightSingle: function(type, toHighlight, target, toSelect, isRefresh){
- // summary:
- // Highlight a single item.
- // This function is time critical!!
- var _this = this, toHL, g = _this.grid, cells = g.layout.cells;
- switch(type){
- case "cell":
- toHL = this._calcToHighlight(type, target, toHighlight, toSelect);
- var c = cells[target.col];
- if(!c.hidden && !c.notselectable){
- this._highlightNode(target.node || c.getNode(target.row), toHL);
- }
- break;
- case "col":
- toHL = this._calcToHighlight(type, target, toHighlight, toSelect);
- this._highlightHeader(target.col, toHL);
- query("td[idx='" + target.col + "']", g.domNode).forEach(function(cellNode){
- var rowNode = cells[target.col].view.content.findRowTarget(cellNode);
- if(rowNode){
- var rowIndex = rowNode[dojox.grid.util.rowIndexTag];
- _this._highlightSingle("cell", toHL, {
- "row": rowIndex,
- "col": target.col,
- "node": cellNode
- });
- }
- });
- break;
- case "row":
- toHL = this._calcToHighlight(type, target, toHighlight, toSelect);
- this._highlightRowSelector(target.row, toHL);
- if(this._config.cell){
- array.forEach(cells, function(cell){
- _this._highlightSingle("cell", toHL, {
- "row": target.row,
- "col": cell.index,
- "node": cell.getNode(target.row)
- });
- });
- }
- //To avoid dead lock
- this._selectedRowModified = true;
- if(!isRefresh){
- g.selection.setSelected(target.row, toHL);
- }
- }
- },
- _highlight: function(type, target, toSelect){
- // summary:
- // Highlight from start point to target.
- // toSelect: Boolean
- // Whether we are selecting or deselecting.
- // This function is time critical!!
- if(this._selecting[type] && target !== null){
- var start = this._startPoint[type],
- current = this._currentPoint[type],
- _this = this,
- highlight = function(from, to, toHL){
- _this._forEach(type, from, to, function(item){
- _this._highlightSingle(type, toHL, item, toSelect);
- }, true);
- };
- switch(type){
- case "col": case "row":
- if(current !== null){
- if(_inRange(type, target, start, current, true)){
- //target is between start and current, some selected should be deselected.
- highlight(current, target, false);
- }else{
- if(_inRange(type, start, target, current, true)){
- //selection has jumped to different direction, all should be deselected.
- highlight(current, start, false);
- current = start;
- }
- highlight(target, current, true);
- }
- }else{
- //First time select.
- this._highlightSingle(type, true, target, toSelect);
- }
- break;
- case "cell":
- if(current !== null){
- if(_inRange("row", target, start, current, true) ||
- _inRange("col", target, start, current, true) ||
- _inRange("row", start, target, current, true) ||
- _inRange("col", start, target, current, true)){
- highlight(start, current, false);
- }
- }
- highlight(start, target, true);
- }
- this._currentPoint[type] = target;
- this._focusPoint(type, this._currentPoint);
- }
- },
- _focusPoint: function(type, point){
- // summary:
- // Focus the current point, so when you move mouse, the focus indicator follows you.
- if(!this._isStartFocus){
- var current = point[type],
- f = this.grid.focus;
- if(type == "col"){
- f._colHeadFocusIdx = current.col;
- f.focusArea("header");
- }else if(type == "row"){
- f.focusArea("rowHeader", {
- "rowIndex": current.row
- });
- }else if(type == "cell"){
- f.setFocusIndex(current.row, current.col);
- }
- }
- },
- _blurPoint: function(type, point){
- // summary:
- // Blur the current point.
- var f = this.grid.focus;
- if(type == "cell"){
- f._blurContent();
- }
- },
- _addToSelected: function(type){
- // summary:
- // Record the selected items.
- var toSelect = this._toSelect, _this = this,
- toAdd = [], toRemove = [],
- start = this._startPoint[type],
- end = this._currentPoint[type];
- if(this._usingKeyboard){
- //If using keyboard, selection will be ended after every move. But we have to remember the original selection status,
- //so as to return to correct status when we shrink the selection region.
- this._forEach(type, this._lastAnchorPoint[type], this._lastEndPoint[type], function(item){
- //If the original selected item is not in current range, change its status.
- if(!_inRange(type, item, start, end)){
- (toSelect ? toRemove : toAdd).push(item);
- }
- });
- }
- this._forEach(type, start, end, function(item){
- var isSelected = _this._isSelected(type, item);
- if(toSelect && !isSelected){
- //Add new selected items
- toAdd.push(item);
- }else if(!toSelect){
- //Remove deselected items.
- toRemove.push(item);
- }
- });
- this._add(type, toAdd);
- this._remove(type, toRemove);
-
- // have to keep record in original grid selection
- array.forEach(this._selected.row, function(item){
- if(item.except.length > 0){
- //to avoid dead lock
- this._selectedRowModified = true;
- this.grid.selection.setSelected(item.row, false);
- }
- }, this);
- },
- _forEach: function(type, start, end, func, halfClose){
- // summary:
- // Go through items from *start* point to *end* point.
- // This function is time critical!!
- if(!this._isValid(type, start, true) || !this._isValid(type, end, true)){
- return;
- }
- switch(type){
- case "col": case "row":
- start = start[type];
- end = end[type];
- var dir = end > start ? 1 : -1;
- if(!halfClose){
- end += dir;
- }
- for(; start != end; start += dir){
- func(_createItem(type, start));
- }
- break;
- case "cell":
- var colDir = end.col > start.col ? 1 : -1,
- rowDir = end.row > start.row ? 1 : -1;
- for(var i = start.row, p = end.row + rowDir; i != p; i += rowDir){
- for(var j = start.col, q = end.col + colDir; j != q; j += colDir){
- func(_createItem(type, i, j));
- }
- }
- }
- },
- _makeupForExceptions: function(type, newCellItems){
- // summary:
- // When new cells is selected, maybe they will fill in the "holes" in selected rows and columns.
- var makedUps = [];
- array.forEach(this._selected[type], function(v1){
- array.forEach(newCellItems, function(v2){
- if(v1[type] == v2[type]){
- var pos = array.indexOf(v1.except, v2[_theOther[type]]);
- if(pos >= 0){
- v1.except.splice(pos, 1);
- }
- makedUps.push(v2);
- }
- });
- });
- return makedUps;
- },
- _makeupForCells: function(type, newItems){
- // summary:
- // When some rows/cols are selected, maybe they can cover some of the selected cells,
- // and fill some of the "holes" in the selected cols/rows.
- var toRemove = [];
- array.forEach(this._selected.cell, function(v1){
- array.some(newItems, function(v2){
- if(v1[type] == v2[type]){
- toRemove.push(v1);
- return true;
- }
- return false;
- });
- });
- this._remove("cell", toRemove);
- array.forEach(this._selected[_theOther[type]], function(v1){
- array.forEach(newItems, function(v2){
- var pos = array.indexOf(v1.except, v2[type]);
- if(pos >= 0){
- v1.except.splice(pos, 1);
- }
- });
- });
- },
- _addException: function(type, items){
- // summary:
- // If some rows/cols are deselected, maybe they have created "holes" in selected cols/rows.
- array.forEach(this._selected[type], function(v1){
- array.forEach(items, function(v2){
- v1.except.push(v2[_theOther[type]]);
- });
- });
- },
- _addCellException: function(type, items){
- // summary:
- // If some cells are deselected, maybe they have created "holes" in selected rows/cols.
- array.forEach(this._selected[type], function(v1){
- array.forEach(items, function(v2){
- if(v1[type] == v2[type]){
- v1.except.push(v2[_theOther[type]]);
- }
- });
- });
- },
- _add: function(type, items){
- // summary:
- // Add to the selection record.
- var cells = this.grid.layout.cells;
- if(type == "cell"){
- var colMakedup = this._makeupForExceptions("col", items);
- var rowMakedup = this._makeupForExceptions("row", items);
- //Step over hidden columns.
- items = array.filter(items, function(item){
- return array.indexOf(colMakedup, item) < 0 && array.indexOf(rowMakedup, item) < 0 &&
- !cells[item.col].hidden && !cells[item.col].notselectable;
- });
- }else{
- if(type == "col"){
- //Step over hidden columns.
- items = array.filter(items, function(item){
- return !cells[item.col].hidden && !cells[item.col].notselectable;
- });
- }
- this._makeupForCells(type, items);
- this._selected[type] = array.filter(this._selected[type], function(v){
- return array.every(items, function(item){
- return v[type] !== item[type];
- });
- });
- }
- if(type != "col" && this.grid._hasIdentity){
- array.forEach(items, function(item){
- var record = this.grid._by_idx[item.row];
- if(record){
- item.id = record.idty;
- }
- }, this);
- }
- this._selected[type] = this._selected[type].concat(items);
- },
- _remove: function(type, items){
- // summary:
- // Remove from the selection record.
- var comp = lang.partial(_isEqual, type);
- this._selected[type] = array.filter(this._selected[type], function(v1){
- return !array.some(items, function(v2){
- return comp(v1, v2);
- });
- });
- if(type == "cell"){
- this._addCellException("col", items);
- this._addCellException("row", items);
- }else if(this._config.cell){
- this._addException(_theOther[type], items);
- }
- },
- _isCellNotInExcept: function(type, item){
- // summary:
- // Return true only when a cell is covered by selected row/col, and its not a "hole".
- var attr = item[type], corres = item[_theOther[type]];
- return array.some(this._selected[type], function(v){
- return v[type] == attr && array.indexOf(v.except, corres) < 0;
- });
- },
- _isSelected: function(type, item){
- // summary:
- // Return true when the item is selected. (or logically selected, i.e, covered by a row/col).
- if(!item){ return false; }
- var res = array.some(this._selected[type], function(v){
- var ret = _isEqual(type, item, v);
- if(ret && type !== "cell"){
- return v.except.length === 0;
- }
- return ret;
- });
- if(!res && type === "cell"){
- res = (this._isCellNotInExcept("col", item) || this._isCellNotInExcept("row", item));
- if(type === "cell"){
- res = res && !this.grid.layout.cells[item.col].notselectable;
- }
- }
- return res;
- },
- _isInLastRange: function(type, item, isSelected){
- // summary:
- // Return true only when the item is in the last seletion/deseletion range.
- var start = this[isSelected ? "_lastSelectedAnchorPoint" : "_lastAnchorPoint"][type],
- end = this[isSelected ? "_lastSelectedEndPoint" : "_lastEndPoint"][type];
- if(!item || !start || !end){ return false; }
- return _inRange(type, item, start, end);
- },
- _isValid: function(type, item, allowNotSelectable){
- // summary:
- // Check whether the item is a valid __SelectItem for the given type.
- if(!item){ return false; }
- try{
- var g = this.grid, index = item[type];
- switch(type){
- case "col":
- return index >= 0 && index < g.layout.cells.length && lang.isArray(item.except) &&
- (allowNotSelectable || !g.layout.cells[index].notselectable);
- case "row":
- return index >= 0 && index < g.rowCount && lang.isArray(item.except);
- case "cell":
- return item.col >= 0 && item.col < g.layout.cells.length &&
- item.row >= 0 && item.row < g.rowCount &&
- (allowNotSelectable || !g.layout.cells[item.col].notselectable);
- }
- }catch(e){}
- return false;
- }
- });
- EnhancedGrid.registerPlugin(Selector/*name:'selector'*/, {
- "dependency": ["autoScroll"]
- });
- return Selector;
- });
- },
- 'dojo/dnd/Container':function(){
- define("dojo/dnd/Container", ["../main", "../Evented", "./common", "../parser"], function(dojo, Evented) {
- // module:
- // dojo/dnd/Container
- // summary:
- // TODOC
- /*
- Container states:
- "" - normal state
- "Over" - mouse over a container
- Container item states:
- "" - normal state
- "Over" - mouse over a container item
- */
- /*=====
- dojo.declare("dojo.dnd.__ContainerArgs", [], {
- creator: function(){
- // summary:
- // a creator function, which takes a data item, and returns an object like that:
- // {node: newNode, data: usedData, type: arrayOfStrings}
- },
- // skipForm: Boolean
- // don't start the drag operation, if clicked on form elements
- skipForm: false,
- // dropParent: Node||String
- // node or node's id to use as the parent node for dropped items
- // (must be underneath the 'node' parameter in the DOM)
- dropParent: null,
- // _skipStartup: Boolean
- // skip startup(), which collects children, for deferred initialization
- // (this is used in the markup mode)
- _skipStartup: false
- });
- dojo.dnd.Item = function(){
- // summary:
- // Represents (one of) the source node(s) being dragged.
- // Contains (at least) the "type" and "data" attributes.
- // type: String[]
- // Type(s) of this item, by default this is ["text"]
- // data: Object
- // Logical representation of the object being dragged.
- // If the drag object's type is "text" then data is a String,
- // if it's another type then data could be a different Object,
- // perhaps a name/value hash.
- this.type = type;
- this.data = data;
- }
- =====*/
- dojo.declare("dojo.dnd.Container", Evented, {
- // summary:
- // a Container object, which knows when mouse hovers over it,
- // and over which element it hovers
- // object attributes (for markup)
- skipForm: false,
- /*=====
- // current: DomNode
- // The DOM node the mouse is currently hovered over
- current: null,
- // map: Hash<String, dojo.dnd.Item>
- // Map from an item's id (which is also the DOMNode's id) to
- // the dojo.dnd.Item itself.
- map: {},
- =====*/
- constructor: function(node, params){
- // summary:
- // a constructor of the Container
- // node: Node
- // node or node's id to build the container on
- // params: dojo.dnd.__ContainerArgs
- // a dictionary of parameters
- this.node = dojo.byId(node);
- if(!params){ params = {}; }
- this.creator = params.creator || null;
- this.skipForm = params.skipForm;
- this.parent = params.dropParent && dojo.byId(params.dropParent);
- // class-specific variables
- this.map = {};
- this.current = null;
- // states
- this.containerState = "";
- dojo.addClass(this.node, "dojoDndContainer");
- // mark up children
- if(!(params && params._skipStartup)){
- this.startup();
- }
- // set up events
- this.events = [
- dojo.connect(this.node, "onmouseover", this, "onMouseOver"),
- dojo.connect(this.node, "onmouseout", this, "onMouseOut"),
- // cancel text selection and text dragging
- dojo.connect(this.node, "ondragstart", this, "onSelectStart"),
- dojo.connect(this.node, "onselectstart", this, "onSelectStart")
- ];
- },
- // object attributes (for markup)
- creator: function(){
- // summary:
- // creator function, dummy at the moment
- },
- // abstract access to the map
- getItem: function(/*String*/ key){
- // summary:
- // returns a data item by its key (id)
- return this.map[key]; // dojo.dnd.Item
- },
- setItem: function(/*String*/ key, /*dojo.dnd.Item*/ data){
- // summary:
- // associates a data item with its key (id)
- this.map[key] = data;
- },
- delItem: function(/*String*/ key){
- // summary:
- // removes a data item from the map by its key (id)
- delete this.map[key];
- },
- forInItems: function(/*Function*/ f, /*Object?*/ o){
- // summary:
- // iterates over a data map skipping members that
- // are present in the empty object (IE and/or 3rd-party libraries).
- o = o || dojo.global;
- var m = this.map, e = dojo.dnd._empty;
- for(var i in m){
- if(i in e){ continue; }
- f.call(o, m[i], i, this);
- }
- return o; // Object
- },
- clearItems: function(){
- // summary:
- // removes all data items from the map
- this.map = {};
- },
- // methods
- getAllNodes: function(){
- // summary:
- // returns a list (an array) of all valid child nodes
- return dojo.query("> .dojoDndItem", this.parent); // NodeList
- },
- sync: function(){
- // summary:
- // sync up the node list with the data map
- var map = {};
- this.getAllNodes().forEach(function(node){
- if(node.id){
- var item = this.getItem(node.id);
- if(item){
- map[node.id] = item;
- return;
- }
- }else{
- node.id = dojo.dnd.getUniqueId();
- }
- var type = node.getAttribute("dndType"),
- data = node.getAttribute("dndData");
- map[node.id] = {
- data: data || node.innerHTML,
- type: type ? type.split(/\s*,\s*/) : ["text"]
- };
- }, this);
- this.map = map;
- return this; // self
- },
- insertNodes: function(data, before, anchor){
- // summary:
- // inserts an array of new nodes before/after an anchor node
- // data: Array
- // a list of data items, which should be processed by the creator function
- // before: Boolean
- // insert before the anchor, if true, and after the anchor otherwise
- // anchor: Node
- // the anchor node to be used as a point of insertion
- if(!this.parent.firstChild){
- anchor = null;
- }else if(before){
- if(!anchor){
- anchor = this.parent.firstChild;
- }
- }else{
- if(anchor){
- anchor = anchor.nextSibling;
- }
- }
- if(anchor){
- for(var i = 0; i < data.length; ++i){
- var t = this._normalizedCreator(data[i]);
- this.setItem(t.node.id, {data: t.data, type: t.type});
- this.parent.insertBefore(t.node, anchor);
- }
- }else{
- for(var i = 0; i < data.length; ++i){
- var t = this._normalizedCreator(data[i]);
- this.setItem(t.node.id, {data: t.data, type: t.type});
- this.parent.appendChild(t.node);
- }
- }
- return this; // self
- },
- destroy: function(){
- // summary:
- // prepares this object to be garbage-collected
- dojo.forEach(this.events, dojo.disconnect);
- this.clearItems();
- this.node = this.parent = this.current = null;
- },
- // markup methods
- markupFactory: function(params, node, ctor){
- params._skipStartup = true;
- return new ctor(node, params);
- },
- startup: function(){
- // summary:
- // collects valid child items and populate the map
- // set up the real parent node
- if(!this.parent){
- // use the standard algorithm, if not assigned
- this.parent = this.node;
- if(this.parent.tagName.toLowerCase() == "table"){
- var c = this.parent.getElementsByTagName("tbody");
- if(c && c.length){ this.parent = c[0]; }
- }
- }
- this.defaultCreator = dojo.dnd._defaultCreator(this.parent);
- // process specially marked children
- this.sync();
- },
- // mouse events
- onMouseOver: function(e){
- // summary:
- // event processor for onmouseover
- // e: Event
- // mouse event
- var n = e.relatedTarget;
- while(n){
- if(n == this.node){ break; }
- try{
- n = n.parentNode;
- }catch(x){
- n = null;
- }
- }
- if(!n){
- this._changeState("Container", "Over");
- this.onOverEvent();
- }
- n = this._getChildByEvent(e);
- if(this.current == n){ return; }
- if(this.current){ this._removeItemClass(this.current, "Over"); }
- if(n){ this._addItemClass(n, "Over"); }
- this.current = n;
- },
- onMouseOut: function(e){
- // summary:
- // event processor for onmouseout
- // e: Event
- // mouse event
- for(var n = e.relatedTarget; n;){
- if(n == this.node){ return; }
- try{
- n = n.parentNode;
- }catch(x){
- n = null;
- }
- }
- if(this.current){
- this._removeItemClass(this.current, "Over");
- this.current = null;
- }
- this._changeState("Container", "");
- this.onOutEvent();
- },
- onSelectStart: function(e){
- // summary:
- // event processor for onselectevent and ondragevent
- // e: Event
- // mouse event
- if(!this.skipForm || !dojo.dnd.isFormElement(e)){
- dojo.stopEvent(e);
- }
- },
- // utilities
- onOverEvent: function(){
- // summary:
- // this function is called once, when mouse is over our container
- },
- onOutEvent: function(){
- // summary:
- // this function is called once, when mouse is out of our container
- },
- _changeState: function(type, newState){
- // summary:
- // changes a named state to new state value
- // type: String
- // a name of the state to change
- // newState: String
- // new state
- var prefix = "dojoDnd" + type;
- var state = type.toLowerCase() + "State";
- //dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
- dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
- this[state] = newState;
- },
- _addItemClass: function(node, type){
- // summary:
- // adds a class with prefix "dojoDndItem"
- // node: Node
- // a node
- // type: String
- // a variable suffix for a class name
- dojo.addClass(node, "dojoDndItem" + type);
- },
- _removeItemClass: function(node, type){
- // summary:
- // removes a class with prefix "dojoDndItem"
- // node: Node
- // a node
- // type: String
- // a variable suffix for a class name
- dojo.removeClass(node, "dojoDndItem" + type);
- },
- _getChildByEvent: function(e){
- // summary:
- // gets a child, which is under the mouse at the moment, or null
- // e: Event
- // a mouse event
- var node = e.target;
- if(node){
- for(var parent = node.parentNode; parent; node = parent, parent = node.parentNode){
- if(parent == this.parent && dojo.hasClass(node, "dojoDndItem")){ return node; }
- }
- }
- return null;
- },
- _normalizedCreator: function(/*dojo.dnd.Item*/ item, /*String*/ hint){
- // summary:
- // adds all necessary data to the output of the user-supplied creator function
- var t = (this.creator || this.defaultCreator).call(this, item, hint);
- if(!dojo.isArray(t.type)){ t.type = ["text"]; }
- if(!t.node.id){ t.node.id = dojo.dnd.getUniqueId(); }
- dojo.addClass(t.node, "dojoDndItem");
- return t;
- }
- });
- dojo.dnd._createNode = function(tag){
- // summary:
- // returns a function, which creates an element of given tag
- // (SPAN by default) and sets its innerHTML to given text
- // tag: String
- // a tag name or empty for SPAN
- if(!tag){ return dojo.dnd._createSpan; }
- return function(text){ // Function
- return dojo.create(tag, {innerHTML: text}); // Node
- };
- };
- dojo.dnd._createTrTd = function(text){
- // summary:
- // creates a TR/TD structure with given text as an innerHTML of TD
- // text: String
- // a text for TD
- var tr = dojo.create("tr");
- dojo.create("td", {innerHTML: text}, tr);
- return tr; // Node
- };
- dojo.dnd._createSpan = function(text){
- // summary:
- // creates a SPAN element with given text as its innerHTML
- // text: String
- // a text for SPAN
- return dojo.create("span", {innerHTML: text}); // Node
- };
- // dojo.dnd._defaultCreatorNodes: Object
- // a dictionary that maps container tag names to child tag names
- dojo.dnd._defaultCreatorNodes = {ul: "li", ol: "li", div: "div", p: "div"};
- dojo.dnd._defaultCreator = function(node){
- // summary:
- // takes a parent node, and returns an appropriate creator function
- // node: Node
- // a container node
- var tag = node.tagName.toLowerCase();
- var c = tag == "tbody" || tag == "thead" ? dojo.dnd._createTrTd :
- dojo.dnd._createNode(dojo.dnd._defaultCreatorNodes[tag]);
- return function(item, hint){ // Function
- var isObj = item && dojo.isObject(item), data, type, n;
- if(isObj && item.tagName && item.nodeType && item.getAttribute){
- // process a DOM node
- data = item.getAttribute("dndData") || item.innerHTML;
- type = item.getAttribute("dndType");
- type = type ? type.split(/\s*,\s*/) : ["text"];
- n = item; // this node is going to be moved rather than copied
- }else{
- // process a DnD item object or a string
- data = (isObj && item.data) ? item.data : item;
- type = (isObj && item.type) ? item.type : ["text"];
- n = (hint == "avatar" ? dojo.dnd._createSpan : c)(String(data));
- }
- if(!n.id){
- n.id = dojo.dnd.getUniqueId();
- }
- return {node: n, data: data, type: type};
- };
- };
- return dojo.dnd.Container;
- });
- },
- 'dijit/_Widget':function(){
- define("dijit/_Widget", [
- "dojo/aspect", // aspect.around
- "dojo/_base/config", // config.isDebug
- "dojo/_base/connect", // connect.connect
- "dojo/_base/declare", // declare
- "dojo/_base/kernel", // kernel.deprecated
- "dojo/_base/lang", // lang.hitch
- "dojo/query",
- "dojo/ready",
- "./registry", // registry.byNode
- "./_WidgetBase",
- "./_OnDijitClickMixin",
- "./_FocusMixin",
- "dojo/uacss", // browser sniffing (included for back-compat; subclasses may be using)
- "./hccss" // high contrast mode sniffing (included to set CSS classes on <body>, module ret value unused)
- ], function(aspect, config, connect, declare, kernel, lang, query, ready,
- registry, _WidgetBase, _OnDijitClickMixin, _FocusMixin){
- /*=====
- var _WidgetBase = dijit._WidgetBase;
- var _OnDijitClickMixin = dijit._OnDijitClickMixin;
- var _FocusMixin = dijit._FocusMixin;
- =====*/
- // module:
- // dijit/_Widget
- // summary:
- // Old base for widgets. New widgets should extend _WidgetBase instead
- function connectToDomNode(){
- // summary:
- // If user connects to a widget method === this function, then they will
- // instead actually be connecting the equivalent event on this.domNode
- }
- // Trap dojo.connect() calls to connectToDomNode methods, and redirect to _Widget.on()
- function aroundAdvice(originalConnect){
- return function(obj, event, scope, method){
- if(obj && typeof event == "string" && obj[event] == connectToDomNode){
- return obj.on(event.substring(2).toLowerCase(), lang.hitch(scope, method));
- }
- return originalConnect.apply(connect, arguments);
- };
- }
- aspect.around(connect, "connect", aroundAdvice);
- if(kernel.connect){
- aspect.around(kernel, "connect", aroundAdvice);
- }
- var _Widget = declare("dijit._Widget", [_WidgetBase, _OnDijitClickMixin, _FocusMixin], {
- // summary:
- // Base class for all Dijit widgets.
- //
- // Extends _WidgetBase, adding support for:
- // - declaratively/programatically specifying widget initialization parameters like
- // onMouseMove="foo" that call foo when this.domNode gets a mousemove event
- // - ondijitclick
- // Support new data-dojo-attach-event="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress
- // - focus related functions
- // In particular, the onFocus()/onBlur() callbacks. Driven internally by
- // dijit/_base/focus.js.
- // - deprecated methods
- // - onShow(), onHide(), onClose()
- //
- // Also, by loading code in dijit/_base, turns on:
- // - browser sniffing (putting browser id like .dj_ie on <html> node)
- // - high contrast mode sniffing (add .dijit_a11y class to <body> if machine is in high contrast mode)
- ////////////////// DEFERRED CONNECTS ///////////////////
- onClick: connectToDomNode,
- /*=====
- onClick: function(event){
- // summary:
- // Connect to this function to receive notifications of mouse click events.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onDblClick: connectToDomNode,
- /*=====
- onDblClick: function(event){
- // summary:
- // Connect to this function to receive notifications of mouse double click events.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onKeyDown: connectToDomNode,
- /*=====
- onKeyDown: function(event){
- // summary:
- // Connect to this function to receive notifications of keys being pressed down.
- // event:
- // key Event
- // tags:
- // callback
- },
- =====*/
- onKeyPress: connectToDomNode,
- /*=====
- onKeyPress: function(event){
- // summary:
- // Connect to this function to receive notifications of printable keys being typed.
- // event:
- // key Event
- // tags:
- // callback
- },
- =====*/
- onKeyUp: connectToDomNode,
- /*=====
- onKeyUp: function(event){
- // summary:
- // Connect to this function to receive notifications of keys being released.
- // event:
- // key Event
- // tags:
- // callback
- },
- =====*/
- onMouseDown: connectToDomNode,
- /*=====
- onMouseDown: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse button is pressed down.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onMouseMove: connectToDomNode,
- /*=====
- onMouseMove: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onMouseOut: connectToDomNode,
- /*=====
- onMouseOut: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onMouseOver: connectToDomNode,
- /*=====
- onMouseOver: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onMouseLeave: connectToDomNode,
- /*=====
- onMouseLeave: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse moves off of this widget.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onMouseEnter: connectToDomNode,
- /*=====
- onMouseEnter: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse moves onto this widget.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- onMouseUp: connectToDomNode,
- /*=====
- onMouseUp: function(event){
- // summary:
- // Connect to this function to receive notifications of when the mouse button is released.
- // event:
- // mouse Event
- // tags:
- // callback
- },
- =====*/
- constructor: function(params){
- // extract parameters like onMouseMove that should connect directly to this.domNode
- this._toConnect = {};
- for(var name in params){
- if(this[name] === connectToDomNode){
- this._toConnect[name.replace(/^on/, "").toLowerCase()] = params[name];
- delete params[name];
- }
- }
- },
- postCreate: function(){
- this.inherited(arguments);
- // perform connection from this.domNode to user specified handlers (ex: onMouseMove)
- for(var name in this._toConnect){
- this.on(name, this._toConnect[name]);
- }
- delete this._toConnect;
- },
- on: function(/*String*/ type, /*Function*/ func){
- if(this[this._onMap(type)] === connectToDomNode){
- // Use connect.connect() rather than on() to get handling for "onmouseenter" on non-IE, etc.
- // Also, need to specify context as "this" rather than the default context of the DOMNode
- return connect.connect(this.domNode, type.toLowerCase(), this, func);
- }
- return this.inherited(arguments);
- },
- _setFocusedAttr: function(val){
- // Remove this method in 2.0 (or sooner), just here to set _focused == focused, for back compat
- // (but since it's a private variable we aren't required to keep supporting it).
- this._focused = val;
- this._set("focused", val);
- },
- ////////////////// DEPRECATED METHODS ///////////////////
- setAttribute: function(/*String*/ attr, /*anything*/ value){
- // summary:
- // Deprecated. Use set() instead.
- // tags:
- // deprecated
- kernel.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
- this.set(attr, value);
- },
- attr: function(/*String|Object*/name, /*Object?*/value){
- // summary:
- // Set or get properties on a widget instance.
- // name:
- // The property to get or set. If an object is passed here and not
- // a string, its keys are used as names of attributes to be set
- // and the value of the object as values to set in the widget.
- // value:
- // Optional. If provided, attr() operates as a setter. If omitted,
- // the current value of the named property is returned.
- // description:
- // This method is deprecated, use get() or set() directly.
- // Print deprecation warning but only once per calling function
- if(config.isDebug){
- var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
- caller = (arguments.callee.caller || "unknown caller").toString();
- if(!alreadyCalledHash[caller]){
- kernel.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
- caller, "", "2.0");
- alreadyCalledHash[caller] = true;
- }
- }
- var args = arguments.length;
- if(args >= 2 || typeof name === "object"){ // setter
- return this.set.apply(this, arguments);
- }else{ // getter
- return this.get(name);
- }
- },
- getDescendants: function(){
- // summary:
- // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
- // This method should generally be avoided as it returns widgets declared in templates, which are
- // supposed to be internal/hidden, but it's left here for back-compat reasons.
- kernel.deprecated(this.declaredClass+"::getDescendants() is deprecated. Use getChildren() instead.", "", "2.0");
- return this.containerNode ? query('[widgetId]', this.containerNode).map(registry.byNode) : []; // dijit._Widget[]
- },
- ////////////////// MISCELLANEOUS METHODS ///////////////////
- _onShow: function(){
- // summary:
- // Internal method called when this widget is made visible.
- // See `onShow` for details.
- this.onShow();
- },
- onShow: function(){
- // summary:
- // Called when this widget becomes the selected pane in a
- // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
- // `dijit.layout.AccordionContainer`, etc.
- //
- // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
- // tags:
- // callback
- },
- onHide: function(){
- // summary:
- // Called when another widget becomes the selected pane in a
- // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
- // `dijit.layout.AccordionContainer`, etc.
- //
- // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
- // tags:
- // callback
- },
- onClose: function(){
- // summary:
- // Called when this widget is being displayed as a popup (ex: a Calendar popped
- // up from a DateTextBox), and it is hidden.
- // This is called from the dijit.popup code, and should not be called directly.
- //
- // Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
- // Callback if a user tries to close the child. Child will be closed if this function returns true.
- // tags:
- // extension
- return true; // Boolean
- }
- });
- // For back-compat, remove in 2.0.
- if(!kernel.isAsync){
- ready(0, function(){
- var requires = ["dijit/_base"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- return _Widget;
- });
- },
- 'dojo/touch':function(){
- define("dojo/touch", ["./_base/kernel", "./on", "./has", "./mouse"], function(dojo, on, has, mouse){
- // module:
- // dojo/touch
- /*=====
- dojo.touch = {
- // summary:
- // This module provides unified touch event handlers by exporting
- // press, move, release and cancel which can also run well on desktop.
- // Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
- //
- // example:
- // 1. Used with dojo.connect()
- // | dojo.connect(node, dojo.touch.press, function(e){});
- // | dojo.connect(node, dojo.touch.move, function(e){});
- // | dojo.connect(node, dojo.touch.release, function(e){});
- // | dojo.connect(node, dojo.touch.cancel, function(e){});
- //
- // 2. Used with dojo.on
- // | define(["dojo/on", "dojo/touch"], function(on, touch){
- // | on(node, touch.press, function(e){});
- // | on(node, touch.move, function(e){});
- // | on(node, touch.release, function(e){});
- // | on(node, touch.cancel, function(e){});
- //
- // 3. Used with dojo.touch.* directly
- // | dojo.touch.press(node, function(e){});
- // | dojo.touch.move(node, function(e){});
- // | dojo.touch.release(node, function(e){});
- // | dojo.touch.cancel(node, function(e){});
-
- press: function(node, listener){
- // summary:
- // Register a listener to 'touchstart'|'mousedown' for the given node
- // node: Dom
- // Target node to listen to
- // listener: Function
- // Callback function
- // returns:
- // A handle which will be used to remove the listener by handle.remove()
- },
- move: function(node, listener){
- // summary:
- // Register a listener to 'touchmove'|'mousemove' for the given node
- // node: Dom
- // Target node to listen to
- // listener: Function
- // Callback function
- // returns:
- // A handle which will be used to remove the listener by handle.remove()
- },
- release: function(node, listener){
- // summary:
- // Register a listener to 'touchend'|'mouseup' for the given node
- // node: Dom
- // Target node to listen to
- // listener: Function
- // Callback function
- // returns:
- // A handle which will be used to remove the listener by handle.remove()
- },
- cancel: function(node, listener){
- // summary:
- // Register a listener to 'touchcancel'|'mouseleave' for the given node
- // node: Dom
- // Target node to listen to
- // listener: Function
- // Callback function
- // returns:
- // A handle which will be used to remove the listener by handle.remove()
- }
- };
- =====*/
- function _handle(/*String - press | move | release | cancel*/type){
- return function(node, listener){//called by on(), see dojo.on
- return on(node, type, listener);
- };
- }
- var touch = has("touch");
- //device neutral events - dojo.touch.press|move|release|cancel
- dojo.touch = {
- press: _handle(touch ? "touchstart": "mousedown"),
- move: _handle(touch ? "touchmove": "mousemove"),
- release: _handle(touch ? "touchend": "mouseup"),
- cancel: touch ? _handle("touchcancel") : mouse.leave
- };
- return dojo.touch;
- });
- },
- 'dojox/grid/DataSelection':function(){
- define("dojox/grid/DataSelection", [
- "dojo/_base/declare",
- "./_SelectionPreserver",
- "./Selection"
- ], function(declare, _SelectionPreserver, Selection){
-
- return declare("dojox.grid.DataSelection", Selection, {
- constructor: function(grid){
- if(grid.keepSelection){
- this.preserver = new _SelectionPreserver(this);
- }
- },
-
- destroy: function(){
- if(this.preserver){
- this.preserver.destroy();
- }
- },
-
- getFirstSelected: function(){
- var idx = Selection.prototype.getFirstSelected.call(this);
- if(idx == -1){ return null; }
- return this.grid.getItem(idx);
- },
- getNextSelected: function(inPrev){
- var old_idx = this.grid.getItemIndex(inPrev);
- var idx = Selection.prototype.getNextSelected.call(this, old_idx);
- if(idx == -1){ return null; }
- return this.grid.getItem(idx);
- },
- getSelected: function(){
- var result = [];
- for(var i=0, l=this.selected.length; i<l; i++){
- if(this.selected[i]){
- result.push(this.grid.getItem(i));
- }
- }
- return result;
- },
- addToSelection: function(inItemOrIndex){
- if(this.mode == 'none'){ return; }
- var idx = null;
- if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
- idx = inItemOrIndex;
- }else{
- idx = this.grid.getItemIndex(inItemOrIndex);
- }
- Selection.prototype.addToSelection.call(this, idx);
- },
- deselect: function(inItemOrIndex){
- if(this.mode == 'none'){ return; }
- var idx = null;
- if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
- idx = inItemOrIndex;
- }else{
- idx = this.grid.getItemIndex(inItemOrIndex);
- }
- Selection.prototype.deselect.call(this, idx);
- },
- deselectAll: function(inItemOrIndex){
- var idx = null;
- if(inItemOrIndex || typeof inItemOrIndex == "number"){
- if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
- idx = inItemOrIndex;
- }else{
- idx = this.grid.getItemIndex(inItemOrIndex);
- }
- Selection.prototype.deselectAll.call(this, idx);
- }else{
- this.inherited(arguments);
- }
- }
- });
- });
- },
- 'dijit/_editor/selection':function(){
- define("dijit/_editor/selection", [
- "dojo/dom", // dom.byId
- "dojo/_base/lang",
- "dojo/_base/sniff", // has("ie") has("opera")
- "dojo/_base/window", // win.body win.doc win.doc.createElement win.doc.selection win.doc.selection.createRange win.doc.selection.type.toLowerCase win.global win.global.getSelection
- ".." // for exporting symbols to dijit._editor.selection (TODO: remove in 2.0)
- ], function(dom, lang, has, win, dijit){
- // module:
- // dijit/_editor/selection
- // summary:
- // Text selection API
- lang.getObject("_editor.selection", true, dijit);
- // FIXME:
- // all of these methods branch internally for IE. This is probably
- // sub-optimal in terms of runtime performance. We should investigate the
- // size difference for differentiating at definition time.
- lang.mixin(dijit._editor.selection, {
- getType: function(){
- // summary:
- // Get the selection type (like win.doc.select.type in IE).
- if(has("ie") < 9){
- return win.doc.selection.type.toLowerCase();
- }else{
- var stype = "text";
- // Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
- var oSel;
- try{
- oSel = win.global.getSelection();
- }catch(e){ /*squelch*/ }
- if(oSel && oSel.rangeCount == 1){
- var oRange = oSel.getRangeAt(0);
- if( (oRange.startContainer == oRange.endContainer) &&
- ((oRange.endOffset - oRange.startOffset) == 1) &&
- (oRange.startContainer.nodeType != 3 /* text node*/)
- ){
- stype = "control";
- }
- }
- return stype; //String
- }
- },
- getSelectedText: function(){
- // summary:
- // Return the text (no html tags) included in the current selection or null if no text is selected
- if(has("ie") < 9){
- if(dijit._editor.selection.getType() == 'control'){
- return null;
- }
- return win.doc.selection.createRange().text;
- }else{
- var selection = win.global.getSelection();
- if(selection){
- return selection.toString(); //String
- }
- }
- return '';
- },
- getSelectedHtml: function(){
- // summary:
- // Return the html text of the current selection or null if unavailable
- if(has("ie") < 9){
- if(dijit._editor.selection.getType() == 'control'){
- return null;
- }
- return win.doc.selection.createRange().htmlText;
- }else{
- var selection = win.global.getSelection();
- if(selection && selection.rangeCount){
- var i;
- var html = "";
- for(i = 0; i < selection.rangeCount; i++){
- //Handle selections spanning ranges, such as Opera
- var frag = selection.getRangeAt(i).cloneContents();
- var div = win.doc.createElement("div");
- div.appendChild(frag);
- html += div.innerHTML;
- }
- return html; //String
- }
- return null;
- }
- },
- getSelectedElement: function(){
- // summary:
- // Retrieves the selected element (if any), just in the case that
- // a single element (object like and image or a table) is
- // selected.
- if(dijit._editor.selection.getType() == "control"){
- if(has("ie") < 9){
- var range = win.doc.selection.createRange();
- if(range && range.item){
- return win.doc.selection.createRange().item(0);
- }
- }else{
- var selection = win.global.getSelection();
- return selection.anchorNode.childNodes[ selection.anchorOffset ];
- }
- }
- return null;
- },
- getParentElement: function(){
- // summary:
- // Get the parent element of the current selection
- if(dijit._editor.selection.getType() == "control"){
- var p = this.getSelectedElement();
- if(p){ return p.parentNode; }
- }else{
- if(has("ie") < 9){
- var r = win.doc.selection.createRange();
- r.collapse(true);
- return r.parentElement();
- }else{
- var selection = win.global.getSelection();
- if(selection){
- var node = selection.anchorNode;
- while(node && (node.nodeType != 1)){ // not an element
- node = node.parentNode;
- }
- return node;
- }
- }
- }
- return null;
- },
- hasAncestorElement: function(/*String*/tagName /* ... */){
- // summary:
- // Check whether current selection has a parent element which is
- // of type tagName (or one of the other specified tagName)
- // tagName: String
- // The tag name to determine if it has an ancestor of.
- return this.getAncestorElement.apply(this, arguments) != null; //Boolean
- },
- getAncestorElement: function(/*String*/tagName /* ... */){
- // summary:
- // Return the parent element of the current selection which is of
- // type tagName (or one of the other specified tagName)
- // tagName: String
- // The tag name to determine if it has an ancestor of.
- var node = this.getSelectedElement() || this.getParentElement();
- return this.getParentOfType(node, arguments); //DOMNode
- },
- isTag: function(/*DomNode*/ node, /*String[]*/ tags){
- // summary:
- // Function to determine if a node is one of an array of tags.
- // node:
- // The node to inspect.
- // tags:
- // An array of tag name strings to check to see if the node matches.
- if(node && node.tagName){
- var _nlc = node.tagName.toLowerCase();
- for(var i=0; i<tags.length; i++){
- var _tlc = String(tags[i]).toLowerCase();
- if(_nlc == _tlc){
- return _tlc; // String
- }
- }
- }
- return "";
- },
- getParentOfType: function(/*DomNode*/ node, /*String[]*/ tags){
- // summary:
- // Function to locate a parent node that matches one of a set of tags
- // node:
- // The node to inspect.
- // tags:
- // An array of tag name strings to check to see if the node matches.
- while(node){
- if(this.isTag(node, tags).length){
- return node; // DOMNode
- }
- node = node.parentNode;
- }
- return null;
- },
- collapse: function(/*Boolean*/beginning){
- // summary:
- // Function to collapse (clear), the current selection
- // beginning: Boolean
- // Boolean to indicate whether to collapse the cursor to the beginning of the selection or end.
- if(window.getSelection){
- var selection = win.global.getSelection();
- if(selection.removeAllRanges){ // Mozilla
- if(beginning){
- selection.collapseToStart();
- }else{
- selection.collapseToEnd();
- }
- }else{ // Safari
- // pulled from WebCore/ecma/kjs_window.cpp, line 2536
- selection.collapse(beginning);
- }
- }else if(has("ie")){ // IE
- var range = win.doc.selection.createRange();
- range.collapse(beginning);
- range.select();
- }
- },
- remove: function(){
- // summary:
- // Function to delete the currently selected content from the document.
- var sel = win.doc.selection;
- if(has("ie") < 9){
- if(sel.type.toLowerCase() != "none"){
- sel.clear();
- }
- return sel; //Selection
- }else{
- sel = win.global.getSelection();
- sel.deleteFromDocument();
- return sel; //Selection
- }
- },
- selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
- // summary:
- // clear previous selection and select the content of the node
- // (excluding the node itself)
- // element: DOMNode
- // The element you wish to select the children content of.
- // nochangefocus: Boolean
- // Boolean to indicate if the foxus should change or not.
- var global = win.global;
- var doc = win.doc;
- var range;
- element = dom.byId(element);
- if(doc.selection && has("ie") < 9 && win.body().createTextRange){ // IE
- range = element.ownerDocument.body.createTextRange();
- range.moveToElementText(element);
- if(!nochangefocus){
- try{
- range.select(); // IE throws an exception here if the widget is hidden. See #5439
- }catch(e){ /* squelch */}
- }
- }else if(global.getSelection){
- var selection = win.global.getSelection();
- if(has("opera")){
- //Opera's selectAllChildren doesn't seem to work right
- //against <body> nodes and possibly others ... so
- //we use the W3C range API
- if(selection.rangeCount){
- range = selection.getRangeAt(0);
- }else{
- range = doc.createRange();
- }
- range.setStart(element, 0);
- range.setEnd(element,(element.nodeType == 3)?element.length:element.childNodes.length);
- selection.addRange(range);
- }else{
- selection.selectAllChildren(element);
- }
- }
- },
- selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
- // summary:
- // clear previous selection and select element (including all its children)
- // element: DOMNode
- // The element to select.
- // nochangefocus: Boolean
- // Boolean indicating if the focus should be changed. IE only.
- var range;
- var doc = win.doc;
- var global = win.global;
- element = dom.byId(element);
- if(has("ie") < 9 && win.body().createTextRange){
- try{
- var tg = element.tagName ? element.tagName.toLowerCase() : "";
- if(tg === "img" || tg === "table"){
- range = win.body().createControlRange();
- }else{
- range = win.body().createRange();
- }
- range.addElement(element);
- if(!nochangefocus){
- range.select();
- }
- }catch(e){
- this.selectElementChildren(element,nochangefocus);
- }
- }else if(global.getSelection){
- var selection = global.getSelection();
- range = doc.createRange();
- if(selection.removeAllRanges){ // Mozilla
- // FIXME: does this work on Safari?
- if(has("opera")){
- //Opera works if you use the current range on
- //the selection if present.
- if(selection.getRangeAt(0)){
- range = selection.getRangeAt(0);
- }
- }
- range.selectNode(element);
- selection.removeAllRanges();
- selection.addRange(range);
- }
- }
- },
- inSelection: function(node){
- // summary:
- // This function determines if 'node' is
- // in the current selection.
- // tags:
- // public
- if(node){
- var newRange;
- var doc = win.doc;
- var range;
- if(win.global.getSelection){
- //WC3
- var sel = win.global.getSelection();
- if(sel && sel.rangeCount > 0){
- range = sel.getRangeAt(0);
- }
- if(range && range.compareBoundaryPoints && doc.createRange){
- try{
- newRange = doc.createRange();
- newRange.setStart(node, 0);
- if(range.compareBoundaryPoints(range.START_TO_END, newRange) === 1){
- return true;
- }
- }catch(e){ /* squelch */}
- }
- }else if(doc.selection){
- // Probably IE, so we can't use the range object as the pseudo
- // range doesn't implement the boundry checking, we have to
- // use IE specific crud.
- range = doc.selection.createRange();
- try{
- newRange = node.ownerDocument.body.createControlRange();
- if(newRange){
- newRange.addElement(node);
- }
- }catch(e1){
- try{
- newRange = node.ownerDocument.body.createTextRange();
- newRange.moveToElementText(node);
- }catch(e2){/* squelch */}
- }
- if(range && newRange){
- // We can finally compare similar to W3C
- if(range.compareEndPoints("EndToStart", newRange) === 1){
- return true;
- }
- }
- }
- }
- return false; // boolean
- }
- });
- return dijit._editor.selection;
- });
- },
- 'dojo/fx':function(){
- define("dojo/fx", [
- "./_base/lang",
- "./Evented",
- "./_base/kernel",
- "./_base/array",
- "./_base/connect",
- "./_base/fx",
- "./dom",
- "./dom-style",
- "./dom-geometry",
- "./ready",
- "require" // for context sensitive loading of Toggler
- ], function(lang, Evented, dojo, arrayUtil, connect, baseFx, dom, domStyle, geom, ready, require) {
- // module:
- // dojo/fx
- // summary:
- // TODOC
- /*=====
- dojo.fx = {
- // summary: Effects library on top of Base animations
- };
- var coreFx = dojo.fx;
- =====*/
-
- // For back-compat, remove in 2.0.
- if(!dojo.isAsync){
- ready(0, function(){
- var requires = ["./fx/Toggler"];
- require(requires); // use indirection so modules not rolled into a build
- });
- }
- var coreFx = dojo.fx = {};
- var _baseObj = {
- _fire: function(evt, args){
- if(this[evt]){
- this[evt].apply(this, args||[]);
- }
- return this;
- }
- };
- var _chain = function(animations){
- this._index = -1;
- this._animations = animations||[];
- this._current = this._onAnimateCtx = this._onEndCtx = null;
- this.duration = 0;
- arrayUtil.forEach(this._animations, function(a){
- this.duration += a.duration;
- if(a.delay){ this.duration += a.delay; }
- }, this);
- };
- _chain.prototype = new Evented();
- lang.extend(_chain, {
- _onAnimate: function(){
- this._fire("onAnimate", arguments);
- },
- _onEnd: function(){
- connect.disconnect(this._onAnimateCtx);
- connect.disconnect(this._onEndCtx);
- this._onAnimateCtx = this._onEndCtx = null;
- if(this._index + 1 == this._animations.length){
- this._fire("onEnd");
- }else{
- // switch animations
- this._current = this._animations[++this._index];
- this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
- this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
- this._current.play(0, true);
- }
- },
- play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
- if(!this._current){ this._current = this._animations[this._index = 0]; }
- if(!gotoStart && this._current.status() == "playing"){ return this; }
- var beforeBegin = connect.connect(this._current, "beforeBegin", this, function(){
- this._fire("beforeBegin");
- }),
- onBegin = connect.connect(this._current, "onBegin", this, function(arg){
- this._fire("onBegin", arguments);
- }),
- onPlay = connect.connect(this._current, "onPlay", this, function(arg){
- this._fire("onPlay", arguments);
- connect.disconnect(beforeBegin);
- connect.disconnect(onBegin);
- connect.disconnect(onPlay);
- });
- if(this._onAnimateCtx){
- connect.disconnect(this._onAnimateCtx);
- }
- this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
- if(this._onEndCtx){
- connect.disconnect(this._onEndCtx);
- }
- this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
- this._current.play.apply(this._current, arguments);
- return this;
- },
- pause: function(){
- if(this._current){
- var e = connect.connect(this._current, "onPause", this, function(arg){
- this._fire("onPause", arguments);
- connect.disconnect(e);
- });
- this._current.pause();
- }
- return this;
- },
- gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
- this.pause();
- var offset = this.duration * percent;
- this._current = null;
- arrayUtil.some(this._animations, function(a){
- if(a.duration <= offset){
- this._current = a;
- return true;
- }
- offset -= a.duration;
- return false;
- });
- if(this._current){
- this._current.gotoPercent(offset / this._current.duration, andPlay);
- }
- return this;
- },
- stop: function(/*boolean?*/ gotoEnd){
- if(this._current){
- if(gotoEnd){
- for(; this._index + 1 < this._animations.length; ++this._index){
- this._animations[this._index].stop(true);
- }
- this._current = this._animations[this._index];
- }
- var e = connect.connect(this._current, "onStop", this, function(arg){
- this._fire("onStop", arguments);
- connect.disconnect(e);
- });
- this._current.stop();
- }
- return this;
- },
- status: function(){
- return this._current ? this._current.status() : "stopped";
- },
- destroy: function(){
- if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); }
- if(this._onEndCtx){ connect.disconnect(this._onEndCtx); }
- }
- });
- lang.extend(_chain, _baseObj);
- coreFx.chain = /*===== dojo.fx.chain = =====*/ function(/*dojo.Animation[]*/ animations){
- // summary:
- // Chain a list of `dojo.Animation`s to run in sequence
- //
- // description:
- // Return a `dojo.Animation` which will play all passed
- // `dojo.Animation` instances in sequence, firing its own
- // synthesized events simulating a single animation. (eg:
- // onEnd of this animation means the end of the chain,
- // not the individual animations within)
- //
- // example:
- // Once `node` is faded out, fade in `otherNode`
- // | dojo.fx.chain([
- // | dojo.fadeIn({ node:node }),
- // | dojo.fadeOut({ node:otherNode })
- // | ]).play();
- //
- return new _chain(animations); // dojo.Animation
- };
- var _combine = function(animations){
- this._animations = animations||[];
- this._connects = [];
- this._finished = 0;
- this.duration = 0;
- arrayUtil.forEach(animations, function(a){
- var duration = a.duration;
- if(a.delay){ duration += a.delay; }
- if(this.duration < duration){ this.duration = duration; }
- this._connects.push(connect.connect(a, "onEnd", this, "_onEnd"));
- }, this);
- this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration});
- var self = this;
- arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"],
- function(evt){
- self._connects.push(connect.connect(self._pseudoAnimation, evt,
- function(){ self._fire(evt, arguments); }
- ));
- }
- );
- };
- lang.extend(_combine, {
- _doAction: function(action, args){
- arrayUtil.forEach(this._animations, function(a){
- a[action].apply(a, args);
- });
- return this;
- },
- _onEnd: function(){
- if(++this._finished > this._animations.length){
- this._fire("onEnd");
- }
- },
- _call: function(action, args){
- var t = this._pseudoAnimation;
- t[action].apply(t, args);
- },
- play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
- this._finished = 0;
- this._doAction("play", arguments);
- this._call("play", arguments);
- return this;
- },
- pause: function(){
- this._doAction("pause", arguments);
- this._call("pause", arguments);
- return this;
- },
- gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
- var ms = this.duration * percent;
- arrayUtil.forEach(this._animations, function(a){
- a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
- });
- this._call("gotoPercent", arguments);
- return this;
- },
- stop: function(/*boolean?*/ gotoEnd){
- this._doAction("stop", arguments);
- this._call("stop", arguments);
- return this;
- },
- status: function(){
- return this._pseudoAnimation.status();
- },
- destroy: function(){
- arrayUtil.forEach(this._connects, connect.disconnect);
- }
- });
- lang.extend(_combine, _baseObj);
- coreFx.combine = /*===== dojo.fx.combine = =====*/ function(/*dojo.Animation[]*/ animations){
- // summary:
- // Combine a list of `dojo.Animation`s to run in parallel
- //
- // description:
- // Combine an array of `dojo.Animation`s to run in parallel,
- // providing a new `dojo.Animation` instance encompasing each
- // animation, firing standard animation events.
- //
- // example:
- // Fade out `node` while fading in `otherNode` simultaneously
- // | dojo.fx.combine([
- // | dojo.fadeIn({ node:node }),
- // | dojo.fadeOut({ node:otherNode })
- // | ]).play();
- //
- // example:
- // When the longest animation ends, execute a function:
- // | var anim = dojo.fx.combine([
- // | dojo.fadeIn({ node: n, duration:700 }),
- // | dojo.fadeOut({ node: otherNode, duration: 300 })
- // | ]);
- // | dojo.connect(anim, "onEnd", function(){
- // | // overall animation is done.
- // | });
- // | anim.play(); // play the animation
- //
- return new _combine(animations); // dojo.Animation
- };
- coreFx.wipeIn = /*===== dojo.fx.wipeIn = =====*/ function(/*Object*/ args){
- // summary:
- // Expand a node to it's natural height.
- //
- // description:
- // Returns an animation that will expand the
- // node defined in 'args' object from it's current height to
- // it's natural height (with no scrollbar).
- // Node must have no margin/border/padding.
- //
- // args: Object
- // A hash-map of standard `dojo.Animation` constructor properties
- // (such as easing: node: duration: and so on)
- //
- // example:
- // | dojo.fx.wipeIn({
- // | node:"someId"
- // | }).play()
- var node = args.node = dom.byId(args.node), s = node.style, o;
- var anim = baseFx.animateProperty(lang.mixin({
- properties: {
- height: {
- // wrapped in functions so we wait till the last second to query (in case value has changed)
- start: function(){
- // start at current [computed] height, but use 1px rather than 0
- // because 0 causes IE to display the whole panel
- o = s.overflow;
- s.overflow = "hidden";
- if(s.visibility == "hidden" || s.display == "none"){
- s.height = "1px";
- s.display = "";
- s.visibility = "";
- return 1;
- }else{
- var height = domStyle.get(node, "height");
- return Math.max(height, 1);
- }
- },
- end: function(){
- return node.scrollHeight;
- }
- }
- }
- }, args));
- var fini = function(){
- s.height = "auto";
- s.overflow = o;
- };
- connect.connect(anim, "onStop", fini);
- connect.connect(anim, "onEnd", fini);
- return anim; // dojo.Animation
- };
- coreFx.wipeOut = /*===== dojo.fx.wipeOut = =====*/ function(/*Object*/ args){
- // summary:
- // Shrink a node to nothing and hide it.
- //
- // description:
- // Returns an animation that will shrink node defined in "args"
- // from it's current height to 1px, and then hide it.
- //
- // args: Object
- // A hash-map of standard `dojo.Animation` constructor properties
- // (such as easing: node: duration: and so on)
- //
- // example:
- // | dojo.fx.wipeOut({ node:"someId" }).play()
- var node = args.node = dom.byId(args.node), s = node.style, o;
- var anim = baseFx.animateProperty(lang.mixin({
- properties: {
- height: {
- end: 1 // 0 causes IE to display the whole panel
- }
- }
- }, args));
- connect.connect(anim, "beforeBegin", function(){
- o = s.overflow;
- s.overflow = "hidden";
- s.display = "";
- });
- var fini = function(){
- s.overflow = o;
- s.height = "auto";
- s.display = "none";
- };
- connect.connect(anim, "onStop", fini);
- connect.connect(anim, "onEnd", fini);
- return anim; // dojo.Animation
- };
- coreFx.slideTo = /*===== dojo.fx.slideTo = =====*/ function(/*Object*/ args){
- // summary:
- // Slide a node to a new top/left position
- //
- // description:
- // Returns an animation that will slide "node"
- // defined in args Object from its current position to
- // the position defined by (args.left, args.top).
- //
- // args: Object
- // A hash-map of standard `dojo.Animation` constructor properties
- // (such as easing: node: duration: and so on). Special args members
- // are `top` and `left`, which indicate the new position to slide to.
- //
- // example:
- // | .slideTo({ node: node, left:"40", top:"50", units:"px" }).play()
- var node = args.node = dom.byId(args.node),
- top = null, left = null;
- var init = (function(n){
- return function(){
- var cs = domStyle.getComputedStyle(n);
- var pos = cs.position;
- top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
- left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
- if(pos != 'absolute' && pos != 'relative'){
- var ret = geom.position(n, true);
- top = ret.y;
- left = ret.x;
- n.style.position="absolute";
- n.style.top=top+"px";
- n.style.left=left+"px";
- }
- };
- })(node);
- init();
- var anim = baseFx.animateProperty(lang.mixin({
- properties: {
- top: args.top || 0,
- left: args.left || 0
- }
- }, args));
- connect.connect(anim, "beforeBegin", anim, init);
- return anim; // dojo.Animation
- };
- return coreFx;
- });
- },
- 'dojox/form/uploader/Base':function(){
- define("dojox/form/uploader/Base", [
- "dojo/dom-form",
- "dojo/dom-style",
- "dojo/dom-construct",
- "dojo/dom-attr",
- "dojo/has",
- "dojo/_base/declare",
- "dojo/_base/event",
- "dijit/_Widget",
- "dijit/_TemplatedMixin",
- "dijit/_WidgetsInTemplateMixin"
- ],function(domForm, domStyle, domConstruct, domAttr, has, declare, event, Widget, TemplatedMixin, WidgetsInTemplateMixin){
- has.add('FormData', function(){return !!window.FormData;});
- has.add("xhr-sendAsBinary", function(){var xhr=window.XMLHttpRequest && new window.XMLHttpRequest(); return xhr && !!xhr.sendAsBinary;});
- has.add("file-multiple", function(){return !!({'true':1,'false':1}[domAttr.get(document.createElement('input',{type:"file"}), 'multiple')]);});
- /*=====
- Widget = dijit._Widget;
- TemplatedMixin = dijit._TemplatedMixin;
- WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
- =====*/
- return declare("dojox.form.uploader.Base", [Widget, TemplatedMixin, WidgetsInTemplateMixin], {
- //
- // Version: 1.6
- //
- // summary:
- // The Base class used for dojox.form.Uploader and dojox.form.uploader.FileList.
- //
- // description:
- // Should not be used as a standalone. To be mixed in with other classes.
- //
- getForm: function(){
- // summary:
- // Finds the parent form of the Uploader, if it exists.
- //
- if(!this.form){
- var n = this.domNode;
- while(n && n.tagName && n !== document.body){
- if(n.tagName.toLowerCase() == "form"){
- this.form = n;
- break;
- }
- n = n.parentNode;
- }
- }
- return this.form // Node;
- },
- getUrl: function(){
- // summary:
- // Finds the URL to upload to, whether it be the action in the parent form, this.url or
- // this.uploadUrl
- //
- if(this.uploadUrl) this.url = this.uploadUrl;
- if(this.url) return this.url;
- if(this.getForm()) this.url = this.form.action;
- return this.url; // String
- },
- connectForm: function(){
- // summary:
- // Internal. Connects to form if there is one.
- //
- this.url = this.getUrl();
- if(!this._fcon && !!this.getForm()){
- this._fcon = true;
- this.connect(this.form, "onsubmit", function(evt){
- event.stop(evt);
- this.submit(this.form);
- });
- }
- },
- supports: function(what){
- // summary:
- // Does feature testing for uploader capabilities. (No browser sniffing - yay)
- //
- switch(what){
- case "multiple":
- if(this.force == "flash" || this.force == "iframe") return false;
- return has("file-multiple");
- case "FormData":
- return has(what);
- case "sendAsBinary":
- return has("xhr-sendAsBinary");
- }
- return false; // Boolean
- },
- getMimeType: function(){
- // summary:
- // Returns the mime type that should be used in an HTML5 upload form. Return result
- // may change as the current use is very generic.
- //
- return "application/octet-stream"; //image/gif
- },
- getFileType: function(/* String */name){
- // summary:
- // Gets the extension of a file
- return name.substring(name.lastIndexOf(".")+1).toUpperCase(); // String
- },
- convertBytes: function(bytes){
- // summary:
- // Converts bytes. Returns an object with all conversions. The "value" property is
- // considered the most likely desired result.
- //
- var kb = Math.round(bytes/1024*100000)/100000;
- var mb = Math.round(bytes/1048576*100000)/100000;
- var gb = Math.round(bytes/1073741824*100000)/100000;
- var value = bytes;
- if(kb>1) value = kb.toFixed(1)+" kb";
- if(mb>1) value = mb.toFixed(1)+" mb";
- if(gb>1) value = gb.toFixed(1)+" gb";
- return {
- kb:kb,
- mb:mb,
- gb:gb,
- bytes:bytes,
- value: value
- }; // Object
- }
- });
- });
- },
- 'dojox/grid/_SelectionPreserver':function(){
- define("dojox/grid/_SelectionPreserver", [
- "dojo/_base/declare",
- "dojo/_base/connect",
- "dojo/_base/lang",
- "dojo/_base/array"
- ], function(declare, connect, lang, array){
- return declare("dojox.grid._SelectionPreserver", null, {
- // summary:
- // Preserve selections across various user actions.
- //
- // description:
- // When this feature is turned on, Grid will try to preserve selections across actions, e.g. sorting, filtering etc.
- //
- // Precondition - Identifier(id) is required for store since id is the only way for differentiating row items.
- // Known issue - The preserved selections might be inaccurate if some unloaded rows are previously selected by range(e.g.SHIFT + click)
- //
- // example:
- // | //To turn on this - please set 'keepSelection' attribute to true
- // | <div dojoType="dojox.grid.DataGrid" keepSelection = true .../>
- // | <div dojoType="dojox.grid.TreeGrid" keepSelection = true .../>
- // | <div dojoType="dojox.grid.LazyTreeGrid" keepSelection = true .../>
-
- constructor: function(selection){
- this.selection = selection;
- var grid = this.grid = selection.grid;
- this.reset();
- this._connects = [
- connect.connect(grid, '_setStore', this, 'reset'),
- connect.connect(grid, '_addItem', this, '_reSelectById'),
- connect.connect(selection, 'addToSelection', lang.hitch(this, '_selectById', true)),
- connect.connect(selection, 'deselect', lang.hitch(this, '_selectById', false)),
- connect.connect(selection, 'deselectAll', this, 'reset')
- ];
- },
- destroy: function(){
- this.reset();
- array.forEach(this._connects, connect.disconnect);
- delete this._connects;
- },
- reset: function(){
- this._selectedById = {};
- },
- _reSelectById: function(item, index){
- // summary:
- // When some rows is fetched, determine whether it should be selected.
- if(item && this.grid._hasIdentity){
- this.selection.selected[index] = this._selectedById[this.grid.store.getIdentity(item)];
- }
- },
- _selectById: function(toSelect, inItemOrIndex){
- // summary:
- // Record selected rows by ID.
- if(this.selection.mode == 'none' || !this.grid._hasIdentity){ return; }
- var item = inItemOrIndex, g = this.grid;
- if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
- var entry = g._by_idx[inItemOrIndex];
- item = entry && entry.item;
- }
- if(item){
- this._selectedById[g.store.getIdentity(item)] = !!toSelect;
- }
- return item;
- }
- });
- });
- },
- 'url:dojox/form/resources/Uploader.html':"<span class=\"dijit dijitReset dijitInline\"\r\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\r\n\t\tdojoAttachEvent=\"ondijitclick:_onClick\"\r\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\r\n\t\t\tdojoAttachPoint=\"titleNode,focusNode\"\r\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\r\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" dojoAttachPoint=\"iconNode\"></span\r\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\r\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\r\n\t\t\t\tid=\"${id}_label\"\r\n\t\t\t\tdojoAttachPoint=\"containerNode\"\r\n\t\t\t></span\r\n\t\t></span\r\n\t></span\r\n\t><!--no need to have this for Uploader \r\n\t<input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\r\n\t\tdojoAttachPoint=\"valueNode\"\r\n/--></span>\r\n",
- 'dijit/form/HorizontalSlider':function(){
- require({cache:{
- 'url:dijit/form/templates/HorizontalSlider.html':"<table class=\"dijit dijitReset dijitSlider dijitSliderH\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" data-dojo-attach-event=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\r\n\trole=\"presentation\"\r\n\t><tr class=\"dijitReset\"\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t\t><td data-dojo-attach-point=\"topDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationT dijitSliderDecorationH\"></td\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t></tr\r\n\t><tr class=\"dijitReset\"\r\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\r\n\t\t\t><div class=\"dijitSliderDecrementIconH\" style=\"display:none\" data-dojo-attach-point=\"decrementButton\"><span class=\"dijitSliderButtonInner\">-</span></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset\"\r\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper\" data-dojo-attach-event=\"press:_onClkDecBumper\"></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset\"\r\n\t\t\t><input data-dojo-attach-point=\"valueNode\" type=\"hidden\" ${!nameAttrSetting}\r\n\t\t\t/><div class=\"dijitReset dijitSliderBarContainerH\" role=\"presentation\" data-dojo-attach-point=\"sliderBarContainer\"\r\n\t\t\t\t><div role=\"presentation\" data-dojo-attach-point=\"progressBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH\" data-dojo-attach-event=\"press:_onBarClick\"\r\n\t\t\t\t\t><div class=\"dijitSliderMoveable dijitSliderMoveableH\"\r\n\t\t\t\t\t\t><div data-dojo-attach-point=\"sliderHandle,focusNode\" class=\"dijitSliderImageHandle dijitSliderImageHandleH\" data-dojo-attach-event=\"press:_onHandleClick\" role=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"></div\r\n\t\t\t\t\t></div\r\n\t\t\t\t></div\r\n\t\t\t\t><div role=\"presentation\" data-dojo-attach-point=\"remainingBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH\" data-dojo-attach-event=\"press:_onBarClick\"></div\r\n\t\t\t></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset\"\r\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper\" data-dojo-attach-event=\"press:_onClkIncBumper\"></div\r\n\t\t></td\r\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\r\n\t\t\t><div class=\"dijitSliderIncrementIconH\" style=\"display:none\" data-dojo-attach-point=\"incrementButton\"><span class=\"dijitSliderButtonInner\">+</span></div\r\n\t\t></td\r\n\t></tr\r\n\t><tr class=\"dijitReset\"\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t\t><td data-dojo-attach-point=\"containerNode,bottomDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationB dijitSliderDecorationH\"></td\r\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\r\n\t></tr\r\n></table>\r\n"}});
- define("dijit/form/HorizontalSlider", [
- "dojo/_base/array", // array.forEach
- "dojo/_base/declare", // declare
- "dojo/dnd/move",
- "dojo/_base/event", // event.stop
- "dojo/_base/fx", // fx.animateProperty
- "dojo/dom-geometry", // domGeometry.position
- "dojo/dom-style", // domStyle.getComputedStyle
- "dojo/keys", // keys.DOWN_ARROW keys.END keys.HOME keys.LEFT_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.RIGHT_ARROW keys.UP_ARROW
- "dojo/_base/lang", // lang.hitch
- "dojo/_base/sniff", // has("ie") has("mozilla")
- "dojo/dnd/Moveable", // Moveable
- "dojo/dnd/Mover", // Mover Mover.prototype.destroy.apply
- "dojo/query", // query
- "../registry", // registry.findWidgets
- "../focus", // focus.focus()
- "../typematic",
- "./Button",
- "./_FormValueWidget",
- "../_Container",
- "dojo/text!./templates/HorizontalSlider.html"
- ], function(array, declare, move, event, fx, domGeometry, domStyle, keys, lang, has, Moveable, Mover, query,
- registry, focus, typematic, Button, _FormValueWidget, _Container, template){
- /*=====
- var Button = dijit.form.Button;
- var _FormValueWidget = dijit.form._FormValueWidget;
- var _Container = dijit._Container;
- =====*/
- // module:
- // dijit/form/HorizontalSlider
- // summary:
- // A form widget that allows one to select a value with a horizontally draggable handle
- var _SliderMover = declare("dijit.form._SliderMover", Mover, {
- onMouseMove: function(e){
- var widget = this.widget;
- var abspos = widget._abspos;
- if(!abspos){
- abspos = widget._abspos = domGeometry.position(widget.sliderBarContainer, true);
- widget._setPixelValue_ = lang.hitch(widget, "_setPixelValue");
- widget._isReversed_ = widget._isReversed();
- }
- var pixelValue = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord];
- widget._setPixelValue_(widget._isReversed_ ? (abspos[widget._pixelCount]-pixelValue) : pixelValue, abspos[widget._pixelCount], false);
- },
- destroy: function(e){
- Mover.prototype.destroy.apply(this, arguments);
- var widget = this.widget;
- widget._abspos = null;
- widget._setValueAttr(widget.value, true);
- }
- });
- var HorizontalSlider = declare("dijit.form.HorizontalSlider", [_FormValueWidget, _Container], {
- // summary:
- // A form widget that allows one to select a value with a horizontally draggable handle
- templateString: template,
- // Overrides FormValueWidget.value to indicate numeric value
- value: 0,
- // showButtons: [const] Boolean
- // Show increment/decrement buttons at the ends of the slider?
- showButtons: true,
- // minimum:: [const] Integer
- // The minimum value the slider can be set to.
- minimum: 0,
- // maximum: [const] Integer
- // The maximum value the slider can be set to.
- maximum: 100,
- // discreteValues: Integer
- // If specified, indicates that the slider handle has only 'discreteValues' possible positions,
- // and that after dragging the handle, it will snap to the nearest possible position.
- // Thus, the slider has only 'discreteValues' possible values.
- //
- // For example, if minimum=10, maxiumum=30, and discreteValues=3, then the slider handle has
- // three possible positions, representing values 10, 20, or 30.
- //
- // If discreteValues is not specified or if it's value is higher than the number of pixels
- // in the slider bar, then the slider handle can be moved freely, and the slider's value will be
- // computed/reported based on pixel position (in this case it will likely be fractional,
- // such as 123.456789).
- discreteValues: Infinity,
- // pageIncrement: Integer
- // If discreteValues is also specified, this indicates the amount of clicks (ie, snap positions)
- // that the slider handle is moved via pageup/pagedown keys.
- // If discreteValues is not specified, it indicates the number of pixels.
- pageIncrement: 2,
- // clickSelect: Boolean
- // If clicking the slider bar changes the value or not
- clickSelect: true,
- // slideDuration: Number
- // The time in ms to take to animate the slider handle from 0% to 100%,
- // when clicking the slider bar to make the handle move.
- slideDuration: registry.defaultDuration,
- // Map widget attributes to DOMNode attributes.
- _setIdAttr: "", // Override _FormWidget which sends id to focusNode
- baseClass: "dijitSlider",
- // Apply CSS classes to up/down arrows and handle per mouse state
- cssStateNodes: {
- incrementButton: "dijitSliderIncrementButton",
- decrementButton: "dijitSliderDecrementButton",
- focusNode: "dijitSliderThumb"
- },
- _mousePixelCoord: "pageX",
- _pixelCount: "w",
- _startingPixelCoord: "x",
- _handleOffsetCoord: "left",
- _progressPixelSize: "width",
- _onKeyUp: function(/*Event*/ e){
- if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
- this._setValueAttr(this.value, true);
- },
- _onKeyPress: function(/*Event*/ e){
- if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
- switch(e.charOrCode){
- case keys.HOME:
- this._setValueAttr(this.minimum, false);
- break;
- case keys.END:
- this._setValueAttr(this.maximum, false);
- break;
- // this._descending === false: if ascending vertical (min on top)
- // (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
- case ((this._descending || this.isLeftToRight()) ? keys.RIGHT_ARROW : keys.LEFT_ARROW):
- case (this._descending === false ? keys.DOWN_ARROW : keys.UP_ARROW):
- case (this._descending === false ? keys.PAGE_DOWN : keys.PAGE_UP):
- this.increment(e);
- break;
- case ((this._descending || this.isLeftToRight()) ? keys.LEFT_ARROW : keys.RIGHT_ARROW):
- case (this._descending === false ? keys.UP_ARROW : keys.DOWN_ARROW):
- case (this._descending === false ? keys.PAGE_UP : keys.PAGE_DOWN):
- this.decrement(e);
- break;
- default:
- return;
- }
- event.stop(e);
- },
- _onHandleClick: function(e){
- if(this.disabled || this.readOnly){ return; }
- if(!has("ie")){
- // make sure you get focus when dragging the handle
- // (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
- focus.focus(this.sliderHandle);
- }
- event.stop(e);
- },
- _isReversed: function(){
- // summary:
- // Returns true if direction is from right to left
- // tags:
- // protected extension
- return !this.isLeftToRight();
- },
- _onBarClick: function(e){
- if(this.disabled || this.readOnly || !this.clickSelect){ return; }
- focus.focus(this.sliderHandle);
- event.stop(e);
- var abspos = domGeometry.position(this.sliderBarContainer, true);
- var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];
- this._setPixelValue(this._isReversed() ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);
- this._movable.onMouseDown(e);
- },
- _setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean?*/ priorityChange){
- if(this.disabled || this.readOnly){ return; }
- var count = this.discreteValues;
- if(count <= 1 || count == Infinity){ count = maxPixels; }
- count--;
- var pixelsPerValue = maxPixels / count;
- var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
- this._setValueAttr(Math.max(Math.min((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, this.maximum), this.minimum), priorityChange);
- },
- _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
- // summary:
- // Hook so set('value', value) works.
- this._set("value", value);
- this.valueNode.value = value;
- this.focusNode.setAttribute("aria-valuenow", value);
- this.inherited(arguments);
- var percent = (value - this.minimum) / (this.maximum - this.minimum);
- var progressBar = (this._descending === false) ? this.remainingBar : this.progressBar;
- var remainingBar = (this._descending === false) ? this.progressBar : this.remainingBar;
- if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
- this._inProgressAnim.stop(true);
- }
- if(priorityChange && this.slideDuration > 0 && progressBar.style[this._progressPixelSize]){
- // animate the slider
- var _this = this;
- var props = {};
- var start = parseFloat(progressBar.style[this._progressPixelSize]);
- var duration = this.slideDuration * (percent-start/100);
- if(duration == 0){ return; }
- if(duration < 0){ duration = 0 - duration; }
- props[this._progressPixelSize] = { start: start, end: percent*100, units:"%" };
- this._inProgressAnim = fx.animateProperty({ node: progressBar, duration: duration,
- onAnimate: function(v){
- remainingBar.style[_this._progressPixelSize] = (100 - parseFloat(v[_this._progressPixelSize])) + "%";
- },
- onEnd: function(){
- delete _this._inProgressAnim;
- },
- properties: props
- });
- this._inProgressAnim.play();
- }else{
- progressBar.style[this._progressPixelSize] = (percent*100) + "%";
- remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";
- }
- },
- _bumpValue: function(signedChange, /*Boolean?*/ priorityChange){
- if(this.disabled || this.readOnly){ return; }
- var s = domStyle.getComputedStyle(this.sliderBarContainer);
- var c = domGeometry.getContentBox(this.sliderBarContainer, s);
- var count = this.discreteValues;
- if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
- count--;
- var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
- if(value < 0){ value = 0; }
- if(value > count){ value = count; }
- value = value * (this.maximum - this.minimum) / count + this.minimum;
- this._setValueAttr(value, priorityChange);
- },
- _onClkBumper: function(val){
- if(this.disabled || this.readOnly || !this.clickSelect){ return; }
- this._setValueAttr(val, true);
- },
- _onClkIncBumper: function(){
- this._onClkBumper(this._descending === false ? this.minimum : this.maximum);
- },
- _onClkDecBumper: function(){
- this._onClkBumper(this._descending === false ? this.maximum : this.minimum);
- },
- decrement: function(/*Event*/ e){
- // summary:
- // Decrement slider
- // tags:
- // private
- this._bumpValue(e.charOrCode == keys.PAGE_DOWN ? -this.pageIncrement : -1);
- },
- increment: function(/*Event*/ e){
- // summary:
- // Increment slider
- // tags:
- // private
- this._bumpValue(e.charOrCode == keys.PAGE_UP ? this.pageIncrement : 1);
- },
- _mouseWheeled: function(/*Event*/ evt){
- // summary:
- // Event handler for mousewheel where supported
- event.stop(evt);
- var janky = !has("mozilla");
- var scroll = evt[(janky ? "wheelDelta" : "detail")] * (janky ? 1 : -1);
- this._bumpValue(scroll < 0 ? -1 : 1, true); // negative scroll acts like a decrement
- },
- startup: function(){
- if(this._started){ return; }
- array.forEach(this.getChildren(), function(child){
- if(this[child.container] != this.containerNode){
- this[child.container].appendChild(child.domNode);
- }
- }, this);
- this.inherited(arguments);
- },
- _typematicCallback: function(/*Number*/ count, /*Object*/ button, /*Event*/ e){
- if(count == -1){
- this._setValueAttr(this.value, true);
- }else{
- this[(button == (this._descending? this.incrementButton : this.decrementButton)) ? "decrement" : "increment"](e);
- }
- },
- buildRendering: function(){
- this.inherited(arguments);
- if(this.showButtons){
- this.incrementButton.style.display="";
- this.decrementButton.style.display="";
- }
- // find any associated label element and add to slider focusnode.
- var label = query('label[for="'+this.id+'"]');
- if(label.length){
- label[0].id = (this.id+"_label");
- this.focusNode.setAttribute("aria-labelledby", label[0].id);
- }
- this.focusNode.setAttribute("aria-valuemin", this.minimum);
- this.focusNode.setAttribute("aria-valuemax", this.maximum);
- },
- postCreate: function(){
- this.inherited(arguments);
- if(this.showButtons){
- this._connects.push(typematic.addMouseListener(
- this.decrementButton, this, "_typematicCallback", 25, 500));
- this._connects.push(typematic.addMouseListener(
- this.incrementButton, this, "_typematicCallback", 25, 500));
- }
- this.connect(this.domNode, !has("mozilla") ? "onmousewheel" : "DOMMouseScroll", "_mouseWheeled");
- // define a custom constructor for a SliderMover that points back to me
- var mover = declare(_SliderMover, {
- widget: this
- });
- this._movable = new Moveable(this.sliderHandle, {mover: mover});
- this._layoutHackIE7();
- },
- destroy: function(){
- this._movable.destroy();
- if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
- this._inProgressAnim.stop(true);
- }
- this._supportingWidgets = registry.findWidgets(this.domNode); // tells destroy about pseudo-child widgets (ruler/labels)
- this.inherited(arguments);
- }
- });
- HorizontalSlider._Mover = _SliderMover; // for monkey patching
- return HorizontalSlider;
- });
- },
- 'dijit/form/_FormValueWidget':function(){
- define("dijit/form/_FormValueWidget", [
- "dojo/_base/declare", // declare
- "dojo/_base/sniff", // has("ie")
- "./_FormWidget",
- "./_FormValueMixin"
- ], function(declare, has, _FormWidget, _FormValueMixin){
- /*=====
- var _FormWidget = dijit.form._FormWidget;
- var _FormValueMixin = dijit.form._FormValueMixin;
- =====*/
- // module:
- // dijit/form/_FormValueWidget
- // summary:
- // FormValueWidget
- return declare("dijit.form._FormValueWidget", [_FormWidget, _FormValueMixin],
- {
- // summary:
- // Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
- // description:
- // Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element,
- // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
- // works as expected.
- // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
- // directly in the template as read by the parser in order to function. IE is known to specifically
- // require the 'name' attribute at element creation time. See #8484, #8660.
- _layoutHackIE7: function(){
- // summary:
- // Work around table sizing bugs on IE7 by forcing redraw
- if(has("ie") == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
- var domNode = this.domNode;
- var parent = domNode.parentNode;
- var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
- var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
- var _this = this;
- while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
- (function ping(){
- var disconnectHandle = _this.connect(parent, "onscroll",
- function(){
- _this.disconnect(disconnectHandle); // only call once
- pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
- setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
- }
- );
- })();
- parent = parent.parentNode;
- }
- }
- }
- });
- });
- },
- '*now':function(r){r(['dojo/i18n!*preload*dojo/nls/pddojo*["ar","ca","cs","da","de-de","el","en-gb","en-us","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ru","sk","sl","sv","th","tr","zh-tw","zh-cn","ROOT"]']);}
- }});
- define("dojo/pddojo", [], 1);
|