sencha-touch-debug.js 494 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808
  1. /*
  2. This file is part of Sencha Touch 2.1
  3. Copyright (c) 2011-2012 Sencha Inc
  4. Contact: http://www.sencha.com/contact
  5. Commercial Usage
  6. Licensees holding valid commercial licenses may use this file in accordance with the Commercial
  7. Software License Agreement provided with the Software or, alternatively, in accordance with the
  8. terms contained in a written agreement between you and Sencha.
  9. If you are unsure which license is appropriate for your use, please contact the sales department
  10. at http://www.sencha.com/contact.
  11. Build date: 2012-11-05 22:31:29 (08c91901ae8449841ff23e5d3fb404d6128d3b0b)
  12. */
  13. //@tag foundation,core
  14. //@define Ext
  15. /**
  16. * @class Ext
  17. * @singleton
  18. */
  19. (function() {
  20. var global = this,
  21. objectPrototype = Object.prototype,
  22. toString = objectPrototype.toString,
  23. enumerables = true,
  24. enumerablesTest = { toString: 1 },
  25. emptyFn = function(){},
  26. i;
  27. if (typeof Ext === 'undefined') {
  28. global.Ext = {};
  29. }
  30. Ext.global = global;
  31. for (i in enumerablesTest) {
  32. enumerables = null;
  33. }
  34. if (enumerables) {
  35. enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
  36. 'toLocaleString', 'toString', 'constructor'];
  37. }
  38. /**
  39. * An array containing extra enumerables for old browsers.
  40. * @property {String[]}
  41. */
  42. Ext.enumerables = enumerables;
  43. /**
  44. * Copies all the properties of config to the specified object.
  45. * Note that if recursive merging and cloning without referencing the original objects / arrays is needed, use
  46. * {@link Ext.Object#merge} instead.
  47. * @param {Object} object The receiver of the properties.
  48. * @param {Object} config The source of the properties.
  49. * @param {Object} [defaults] A different object that will also be applied for default values.
  50. * @return {Object} returns obj
  51. */
  52. Ext.apply = function(object, config, defaults) {
  53. if (defaults) {
  54. Ext.apply(object, defaults);
  55. }
  56. if (object && config && typeof config === 'object') {
  57. var i, j, k;
  58. for (i in config) {
  59. object[i] = config[i];
  60. }
  61. if (enumerables) {
  62. for (j = enumerables.length; j--;) {
  63. k = enumerables[j];
  64. if (config.hasOwnProperty(k)) {
  65. object[k] = config[k];
  66. }
  67. }
  68. }
  69. }
  70. return object;
  71. };
  72. Ext.buildSettings = Ext.apply({
  73. baseCSSPrefix: 'x-',
  74. scopeResetCSS: false
  75. }, Ext.buildSettings || {});
  76. Ext.apply(Ext, {
  77. /**
  78. * @property {Function}
  79. * A reusable empty function
  80. */
  81. emptyFn: emptyFn,
  82. baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
  83. /**
  84. * Copies all the properties of config to object if they don't already exist.
  85. * @param {Object} object The receiver of the properties.
  86. * @param {Object} config The source of the properties.
  87. * @return {Object} returns obj
  88. */
  89. applyIf: function(object, config) {
  90. var property;
  91. if (object) {
  92. for (property in config) {
  93. if (object[property] === undefined) {
  94. object[property] = config[property];
  95. }
  96. }
  97. }
  98. return object;
  99. },
  100. /**
  101. * Iterates either an array or an object. This method delegates to
  102. * {@link Ext.Array#each Ext.Array.each} if the given value is iterable, and {@link Ext.Object#each Ext.Object.each} otherwise.
  103. *
  104. * @param {Object/Array} object The object or array to be iterated.
  105. * @param {Function} fn The function to be called for each iteration. See and {@link Ext.Array#each Ext.Array.each} and
  106. * {@link Ext.Object#each Ext.Object.each} for detailed lists of arguments passed to this function depending on the given object
  107. * type that is being iterated.
  108. * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
  109. * Defaults to the object being iterated itself.
  110. */
  111. iterate: function(object, fn, scope) {
  112. if (Ext.isEmpty(object)) {
  113. return;
  114. }
  115. if (scope === undefined) {
  116. scope = object;
  117. }
  118. if (Ext.isIterable(object)) {
  119. Ext.Array.each.call(Ext.Array, object, fn, scope);
  120. }
  121. else {
  122. Ext.Object.each.call(Ext.Object, object, fn, scope);
  123. }
  124. }
  125. });
  126. Ext.apply(Ext, {
  127. /**
  128. * This method deprecated. Use {@link Ext#define Ext.define} instead.
  129. * @method
  130. * @param {Function} superclass
  131. * @param {Object} overrides
  132. * @return {Function} The subclass constructor from the `overrides` parameter, or a generated one if not provided.
  133. * @deprecated 4.0.0 Please use {@link Ext#define Ext.define} instead
  134. */
  135. extend: function() {
  136. // inline overrides
  137. var objectConstructor = objectPrototype.constructor,
  138. inlineOverrides = function(o) {
  139. for (var m in o) {
  140. if (!o.hasOwnProperty(m)) {
  141. continue;
  142. }
  143. this[m] = o[m];
  144. }
  145. };
  146. return function(subclass, superclass, overrides) {
  147. // First we check if the user passed in just the superClass with overrides
  148. if (Ext.isObject(superclass)) {
  149. overrides = superclass;
  150. superclass = subclass;
  151. subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
  152. superclass.apply(this, arguments);
  153. };
  154. }
  155. //<debug>
  156. if (!superclass) {
  157. Ext.Error.raise({
  158. sourceClass: 'Ext',
  159. sourceMethod: 'extend',
  160. msg: 'Attempting to extend from a class which has not been loaded on the page.'
  161. });
  162. }
  163. //</debug>
  164. // We create a new temporary class
  165. var F = function() {},
  166. subclassProto, superclassProto = superclass.prototype;
  167. F.prototype = superclassProto;
  168. subclassProto = subclass.prototype = new F();
  169. subclassProto.constructor = subclass;
  170. subclass.superclass = superclassProto;
  171. if (superclassProto.constructor === objectConstructor) {
  172. superclassProto.constructor = superclass;
  173. }
  174. subclass.override = function(overrides) {
  175. Ext.override(subclass, overrides);
  176. };
  177. subclassProto.override = inlineOverrides;
  178. subclassProto.proto = subclassProto;
  179. subclass.override(overrides);
  180. subclass.extend = function(o) {
  181. return Ext.extend(subclass, o);
  182. };
  183. return subclass;
  184. };
  185. }(),
  186. /**
  187. * Proxy to {@link Ext.Base#override}. Please refer {@link Ext.Base#override} for further details.
  188. *
  189. * @param {Object} cls The class to override
  190. * @param {Object} overrides The properties to add to `origClass`. This should be specified as an object literal
  191. * containing one or more properties.
  192. * @method override
  193. * @deprecated 4.1.0 Please use {@link Ext#define Ext.define} instead.
  194. */
  195. override: function(cls, overrides) {
  196. if (cls.$isClass) {
  197. return cls.override(overrides);
  198. }
  199. else {
  200. Ext.apply(cls.prototype, overrides);
  201. }
  202. }
  203. });
  204. // A full set of static methods to do type checking
  205. Ext.apply(Ext, {
  206. /**
  207. * Returns the given value itself if it's not empty, as described in {@link Ext#isEmpty}; returns the default
  208. * value (second argument) otherwise.
  209. *
  210. * @param {Object} value The value to test.
  211. * @param {Object} defaultValue The value to return if the original value is empty.
  212. * @param {Boolean} [allowBlank=false] (optional) `true` to allow zero length strings to qualify as non-empty.
  213. * @return {Object} `value`, if non-empty, else `defaultValue`.
  214. */
  215. valueFrom: function(value, defaultValue, allowBlank){
  216. return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
  217. },
  218. /**
  219. * Returns the type of the given variable in string format. List of possible values are:
  220. *
  221. * - `undefined`: If the given value is `undefined`
  222. * - `null`: If the given value is `null`
  223. * - `string`: If the given value is a string
  224. * - `number`: If the given value is a number
  225. * - `boolean`: If the given value is a boolean value
  226. * - `date`: If the given value is a `Date` object
  227. * - `function`: If the given value is a function reference
  228. * - `object`: If the given value is an object
  229. * - `array`: If the given value is an array
  230. * - `regexp`: If the given value is a regular expression
  231. * - `element`: If the given value is a DOM Element
  232. * - `textnode`: If the given value is a DOM text node and contains something other than whitespace
  233. * - `whitespace`: If the given value is a DOM text node and contains only whitespace
  234. *
  235. * @param {Object} value
  236. * @return {String}
  237. */
  238. typeOf: function(value) {
  239. if (value === null) {
  240. return 'null';
  241. }
  242. var type = typeof value;
  243. if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
  244. return type;
  245. }
  246. var typeToString = toString.call(value);
  247. switch(typeToString) {
  248. case '[object Array]':
  249. return 'array';
  250. case '[object Date]':
  251. return 'date';
  252. case '[object Boolean]':
  253. return 'boolean';
  254. case '[object Number]':
  255. return 'number';
  256. case '[object RegExp]':
  257. return 'regexp';
  258. }
  259. if (type === 'function') {
  260. return 'function';
  261. }
  262. if (type === 'object') {
  263. if (value.nodeType !== undefined) {
  264. if (value.nodeType === 3) {
  265. return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
  266. }
  267. else {
  268. return 'element';
  269. }
  270. }
  271. return 'object';
  272. }
  273. //<debug error>
  274. Ext.Error.raise({
  275. sourceClass: 'Ext',
  276. sourceMethod: 'typeOf',
  277. msg: 'Failed to determine the type of the specified value "' + value + '". This is most likely a bug.'
  278. });
  279. //</debug>
  280. },
  281. /**
  282. * Returns `true` if the passed value is empty, `false` otherwise. The value is deemed to be empty if it is either:
  283. *
  284. * - `null`
  285. * - `undefined`
  286. * - a zero-length array.
  287. * - a zero-length string (Unless the `allowEmptyString` parameter is set to `true`).
  288. *
  289. * @param {Object} value The value to test.
  290. * @param {Boolean} [allowEmptyString=false] (optional) `true` to allow empty strings.
  291. * @return {Boolean}
  292. */
  293. isEmpty: function(value, allowEmptyString) {
  294. return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
  295. },
  296. /**
  297. * Returns `true` if the passed value is a JavaScript Array, `false` otherwise.
  298. *
  299. * @param {Object} target The target to test.
  300. * @return {Boolean}
  301. * @method
  302. */
  303. isArray: ('isArray' in Array) ? Array.isArray : function(value) {
  304. return toString.call(value) === '[object Array]';
  305. },
  306. /**
  307. * Returns `true` if the passed value is a JavaScript Date object, `false` otherwise.
  308. * @param {Object} object The object to test.
  309. * @return {Boolean}
  310. */
  311. isDate: function(value) {
  312. return toString.call(value) === '[object Date]';
  313. },
  314. /**
  315. * Returns `true` if the passed value is a JavaScript Object, `false` otherwise.
  316. * @param {Object} value The value to test.
  317. * @return {Boolean}
  318. * @method
  319. */
  320. isObject: (toString.call(null) === '[object Object]') ?
  321. function(value) {
  322. // check ownerDocument here as well to exclude DOM nodes
  323. return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
  324. } :
  325. function(value) {
  326. return toString.call(value) === '[object Object]';
  327. },
  328. /**
  329. * @private
  330. */
  331. isSimpleObject: function(value) {
  332. return value instanceof Object && value.constructor === Object;
  333. },
  334. /**
  335. * Returns `true` if the passed value is a JavaScript 'primitive', a string, number or Boolean.
  336. * @param {Object} value The value to test.
  337. * @return {Boolean}
  338. */
  339. isPrimitive: function(value) {
  340. var type = typeof value;
  341. return type === 'string' || type === 'number' || type === 'boolean';
  342. },
  343. /**
  344. * Returns `true` if the passed value is a JavaScript Function, `false` otherwise.
  345. * @param {Object} value The value to test.
  346. * @return {Boolean}
  347. * @method
  348. */
  349. isFunction:
  350. // Safari 3.x and 4.x returns 'function' for typeof <NodeList>, hence we need to fall back to using
  351. // Object.prorotype.toString (slower)
  352. (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
  353. return toString.call(value) === '[object Function]';
  354. } : function(value) {
  355. return typeof value === 'function';
  356. },
  357. /**
  358. * Returns `true` if the passed value is a number. Returns `false` for non-finite numbers.
  359. * @param {Object} value The value to test.
  360. * @return {Boolean}
  361. */
  362. isNumber: function(value) {
  363. return typeof value === 'number' && isFinite(value);
  364. },
  365. /**
  366. * Validates that a value is numeric.
  367. * @param {Object} value Examples: 1, '1', '2.34'
  368. * @return {Boolean} `true` if numeric, `false` otherwise.
  369. */
  370. isNumeric: function(value) {
  371. return !isNaN(parseFloat(value)) && isFinite(value);
  372. },
  373. /**
  374. * Returns `true` if the passed value is a string.
  375. * @param {Object} value The value to test.
  376. * @return {Boolean}
  377. */
  378. isString: function(value) {
  379. return typeof value === 'string';
  380. },
  381. /**
  382. * Returns `true` if the passed value is a Boolean.
  383. *
  384. * @param {Object} value The value to test.
  385. * @return {Boolean}
  386. */
  387. isBoolean: function(value) {
  388. return typeof value === 'boolean';
  389. },
  390. /**
  391. * Returns `true` if the passed value is an HTMLElement.
  392. * @param {Object} value The value to test.
  393. * @return {Boolean}
  394. */
  395. isElement: function(value) {
  396. return value ? value.nodeType === 1 : false;
  397. },
  398. /**
  399. * Returns `true` if the passed value is a TextNode.
  400. * @param {Object} value The value to test.
  401. * @return {Boolean}
  402. */
  403. isTextNode: function(value) {
  404. return value ? value.nodeName === "#text" : false;
  405. },
  406. /**
  407. * Returns `true` if the passed value is defined.
  408. * @param {Object} value The value to test.
  409. * @return {Boolean}
  410. */
  411. isDefined: function(value) {
  412. return typeof value !== 'undefined';
  413. },
  414. /**
  415. * Returns `true` if the passed value is iterable, `false` otherwise.
  416. * @param {Object} value The value to test.
  417. * @return {Boolean}
  418. */
  419. isIterable: function(value) {
  420. return (value && typeof value !== 'string') ? value.length !== undefined : false;
  421. }
  422. });
  423. Ext.apply(Ext, {
  424. /**
  425. * Clone almost any type of variable including array, object, DOM nodes and Date without keeping the old reference.
  426. * @param {Object} item The variable to clone.
  427. * @return {Object} clone
  428. */
  429. clone: function(item) {
  430. if (item === null || item === undefined) {
  431. return item;
  432. }
  433. // DOM nodes
  434. if (item.nodeType && item.cloneNode) {
  435. return item.cloneNode(true);
  436. }
  437. // Strings
  438. var type = toString.call(item);
  439. // Dates
  440. if (type === '[object Date]') {
  441. return new Date(item.getTime());
  442. }
  443. var i, j, k, clone, key;
  444. // Arrays
  445. if (type === '[object Array]') {
  446. i = item.length;
  447. clone = [];
  448. while (i--) {
  449. clone[i] = Ext.clone(item[i]);
  450. }
  451. }
  452. // Objects
  453. else if (type === '[object Object]' && item.constructor === Object) {
  454. clone = {};
  455. for (key in item) {
  456. clone[key] = Ext.clone(item[key]);
  457. }
  458. if (enumerables) {
  459. for (j = enumerables.length; j--;) {
  460. k = enumerables[j];
  461. clone[k] = item[k];
  462. }
  463. }
  464. }
  465. return clone || item;
  466. },
  467. /**
  468. * @private
  469. * Generate a unique reference of Ext in the global scope, useful for sandboxing.
  470. */
  471. getUniqueGlobalNamespace: function() {
  472. var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
  473. if (uniqueGlobalNamespace === undefined) {
  474. var i = 0;
  475. do {
  476. uniqueGlobalNamespace = 'ExtBox' + (++i);
  477. } while (Ext.global[uniqueGlobalNamespace] !== undefined);
  478. Ext.global[uniqueGlobalNamespace] = Ext;
  479. this.uniqueGlobalNamespace = uniqueGlobalNamespace;
  480. }
  481. return uniqueGlobalNamespace;
  482. },
  483. /**
  484. * @private
  485. */
  486. functionFactory: function() {
  487. var args = Array.prototype.slice.call(arguments),
  488. ln = args.length;
  489. if (ln > 0) {
  490. args[ln - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' + args[ln - 1];
  491. }
  492. return Function.prototype.constructor.apply(Function.prototype, args);
  493. },
  494. /**
  495. * @private
  496. */
  497. globalEval: ('execScript' in global) ? function(code) {
  498. global.execScript(code)
  499. } : function(code) {
  500. (function(){
  501. eval(code);
  502. })();
  503. }
  504. //<feature logger>
  505. /**
  506. * @private
  507. * @property
  508. */
  509. ,Logger: {
  510. log: function(message, priority) {
  511. if ('console' in global) {
  512. if (!priority || !(priority in global.console)) {
  513. priority = 'log';
  514. }
  515. message = '[' + priority.toUpperCase() + '] ' + message;
  516. global.console[priority](message);
  517. }
  518. },
  519. verbose: function(message) {
  520. this.log(message, 'verbose');
  521. },
  522. info: function(message) {
  523. this.log(message, 'info');
  524. },
  525. warn: function(message) {
  526. this.log(message, 'warn');
  527. },
  528. error: function(message) {
  529. throw new Error(message);
  530. },
  531. deprecate: function(message) {
  532. this.log(message, 'warn');
  533. }
  534. }
  535. //</feature>
  536. });
  537. /**
  538. * Old alias to {@link Ext#typeOf}.
  539. * @deprecated 4.0.0 Please use {@link Ext#typeOf} instead.
  540. * @method
  541. * @alias Ext#typeOf
  542. */
  543. Ext.type = Ext.typeOf;
  544. })();
  545. //@tag foundation,core
  546. //@define Ext.Version
  547. //@require Ext
  548. /**
  549. * @author Jacky Nguyen <jacky@sencha.com>
  550. * @docauthor Jacky Nguyen <jacky@sencha.com>
  551. * @class Ext.Version
  552. *
  553. * A utility class that wrap around a string version number and provide convenient
  554. * method to perform comparison. See also: {@link Ext.Version#compare compare}. Example:
  555. *
  556. * var version = new Ext.Version('1.0.2beta');
  557. * console.log("Version is " + version); // Version is 1.0.2beta
  558. *
  559. * console.log(version.getMajor()); // 1
  560. * console.log(version.getMinor()); // 0
  561. * console.log(version.getPatch()); // 2
  562. * console.log(version.getBuild()); // 0
  563. * console.log(version.getRelease()); // beta
  564. *
  565. * console.log(version.isGreaterThan('1.0.1')); // true
  566. * console.log(version.isGreaterThan('1.0.2alpha')); // true
  567. * console.log(version.isGreaterThan('1.0.2RC')); // false
  568. * console.log(version.isGreaterThan('1.0.2')); // false
  569. * console.log(version.isLessThan('1.0.2')); // true
  570. *
  571. * console.log(version.match(1.0)); // true
  572. * console.log(version.match('1.0.2')); // true
  573. */
  574. (function() {
  575. // Current core version
  576. var version = '4.1.0', Version;
  577. Ext.Version = Version = Ext.extend(Object, {
  578. /**
  579. * Creates new Version object.
  580. * @param {String/Number} version The version number in the follow standard format: major[.minor[.patch[.build[release]]]]
  581. * Examples: 1.0 or 1.2.3beta or 1.2.3.4RC
  582. * @return {Ext.Version} this
  583. */
  584. constructor: function(version) {
  585. var toNumber = this.toNumber,
  586. parts, releaseStartIndex;
  587. if (version instanceof Version) {
  588. return version;
  589. }
  590. this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
  591. releaseStartIndex = this.version.search(/([^\d\.])/);
  592. if (releaseStartIndex !== -1) {
  593. this.release = this.version.substr(releaseStartIndex, version.length);
  594. this.shortVersion = this.version.substr(0, releaseStartIndex);
  595. }
  596. this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
  597. parts = this.version.split('.');
  598. this.major = toNumber(parts.shift());
  599. this.minor = toNumber(parts.shift());
  600. this.patch = toNumber(parts.shift());
  601. this.build = toNumber(parts.shift());
  602. return this;
  603. },
  604. /**
  605. * @param value
  606. * @return {Number}
  607. */
  608. toNumber: function(value) {
  609. value = parseInt(value || 0, 10);
  610. if (isNaN(value)) {
  611. value = 0;
  612. }
  613. return value;
  614. },
  615. /**
  616. * Override the native `toString()` method.
  617. * @private
  618. * @return {String} version
  619. */
  620. toString: function() {
  621. return this.version;
  622. },
  623. /**
  624. * Override the native `valueOf()` method.
  625. * @private
  626. * @return {String} version
  627. */
  628. valueOf: function() {
  629. return this.version;
  630. },
  631. /**
  632. * Returns the major component value.
  633. * @return {Number} major
  634. */
  635. getMajor: function() {
  636. return this.major || 0;
  637. },
  638. /**
  639. * Returns the minor component value.
  640. * @return {Number} minor
  641. */
  642. getMinor: function() {
  643. return this.minor || 0;
  644. },
  645. /**
  646. * Returns the patch component value.
  647. * @return {Number} patch
  648. */
  649. getPatch: function() {
  650. return this.patch || 0;
  651. },
  652. /**
  653. * Returns the build component value.
  654. * @return {Number} build
  655. */
  656. getBuild: function() {
  657. return this.build || 0;
  658. },
  659. /**
  660. * Returns the release component value.
  661. * @return {Number} release
  662. */
  663. getRelease: function() {
  664. return this.release || '';
  665. },
  666. /**
  667. * Returns whether this version if greater than the supplied argument.
  668. * @param {String/Number} target The version to compare with.
  669. * @return {Boolean} `true` if this version if greater than the target, `false` otherwise.
  670. */
  671. isGreaterThan: function(target) {
  672. return Version.compare(this.version, target) === 1;
  673. },
  674. /**
  675. * Returns whether this version if greater than or equal to the supplied argument.
  676. * @param {String/Number} target The version to compare with.
  677. * @return {Boolean} `true` if this version if greater than or equal to the target, `false` otherwise.
  678. */
  679. isGreaterThanOrEqual: function(target) {
  680. return Version.compare(this.version, target) >= 0;
  681. },
  682. /**
  683. * Returns whether this version if smaller than the supplied argument.
  684. * @param {String/Number} target The version to compare with.
  685. * @return {Boolean} `true` if this version if smaller than the target, `false` otherwise.
  686. */
  687. isLessThan: function(target) {
  688. return Version.compare(this.version, target) === -1;
  689. },
  690. /**
  691. * Returns whether this version if less than or equal to the supplied argument.
  692. * @param {String/Number} target The version to compare with.
  693. * @return {Boolean} `true` if this version if less than or equal to the target, `false` otherwise.
  694. */
  695. isLessThanOrEqual: function(target) {
  696. return Version.compare(this.version, target) <= 0;
  697. },
  698. /**
  699. * Returns whether this version equals to the supplied argument.
  700. * @param {String/Number} target The version to compare with.
  701. * @return {Boolean} `true` if this version equals to the target, `false` otherwise.
  702. */
  703. equals: function(target) {
  704. return Version.compare(this.version, target) === 0;
  705. },
  706. /**
  707. * Returns whether this version matches the supplied argument. Example:
  708. *
  709. * var version = new Ext.Version('1.0.2beta');
  710. * console.log(version.match(1)); // true
  711. * console.log(version.match(1.0)); // true
  712. * console.log(version.match('1.0.2')); // true
  713. * console.log(version.match('1.0.2RC')); // false
  714. *
  715. * @param {String/Number} target The version to compare with.
  716. * @return {Boolean} `true` if this version matches the target, `false` otherwise.
  717. */
  718. match: function(target) {
  719. target = String(target);
  720. return this.version.substr(0, target.length) === target;
  721. },
  722. /**
  723. * Returns this format: [major, minor, patch, build, release]. Useful for comparison.
  724. * @return {Number[]}
  725. */
  726. toArray: function() {
  727. return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
  728. },
  729. /**
  730. * Returns shortVersion version without dots and release.
  731. * @return {String}
  732. */
  733. getShortVersion: function() {
  734. return this.shortVersion;
  735. },
  736. /**
  737. * Convenient alias to {@link Ext.Version#isGreaterThan isGreaterThan}
  738. * @param {String/Number} target
  739. * @return {Boolean}
  740. */
  741. gt: function() {
  742. return this.isGreaterThan.apply(this, arguments);
  743. },
  744. /**
  745. * Convenient alias to {@link Ext.Version#isLessThan isLessThan}
  746. * @param {String/Number} target
  747. * @return {Boolean}
  748. */
  749. lt: function() {
  750. return this.isLessThan.apply(this, arguments);
  751. },
  752. /**
  753. * Convenient alias to {@link Ext.Version#isGreaterThanOrEqual isGreaterThanOrEqual}
  754. * @param {String/Number} target
  755. * @return {Boolean}
  756. */
  757. gtEq: function() {
  758. return this.isGreaterThanOrEqual.apply(this, arguments);
  759. },
  760. /**
  761. * Convenient alias to {@link Ext.Version#isLessThanOrEqual isLessThanOrEqual}
  762. * @param {String/Number} target
  763. * @return {Boolean}
  764. */
  765. ltEq: function() {
  766. return this.isLessThanOrEqual.apply(this, arguments);
  767. }
  768. });
  769. Ext.apply(Version, {
  770. // @private
  771. releaseValueMap: {
  772. 'dev': -6,
  773. 'alpha': -5,
  774. 'a': -5,
  775. 'beta': -4,
  776. 'b': -4,
  777. 'rc': -3,
  778. '#': -2,
  779. 'p': -1,
  780. 'pl': -1
  781. },
  782. /**
  783. * Converts a version component to a comparable value.
  784. *
  785. * @static
  786. * @param {Object} value The value to convert
  787. * @return {Object}
  788. */
  789. getComponentValue: function(value) {
  790. return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
  791. },
  792. /**
  793. * Compare 2 specified versions, starting from left to right. If a part contains special version strings,
  794. * they are handled in the following order:
  795. * 'dev' < 'alpha' = 'a' < 'beta' = 'b' < 'RC' = 'rc' < '#' < 'pl' = 'p' < 'anything else'
  796. *
  797. * @static
  798. * @param {String} current The current version to compare to.
  799. * @param {String} target The target version to compare to.
  800. * @return {Number} Returns -1 if the current version is smaller than the target version, 1 if greater, and 0 if they're equivalent.
  801. */
  802. compare: function(current, target) {
  803. var currentValue, targetValue, i;
  804. current = new Version(current).toArray();
  805. target = new Version(target).toArray();
  806. for (i = 0; i < Math.max(current.length, target.length); i++) {
  807. currentValue = this.getComponentValue(current[i]);
  808. targetValue = this.getComponentValue(target[i]);
  809. if (currentValue < targetValue) {
  810. return -1;
  811. } else if (currentValue > targetValue) {
  812. return 1;
  813. }
  814. }
  815. return 0;
  816. }
  817. });
  818. Ext.apply(Ext, {
  819. /**
  820. * @private
  821. */
  822. versions: {},
  823. /**
  824. * @private
  825. */
  826. lastRegisteredVersion: null,
  827. /**
  828. * Set version number for the given package name.
  829. *
  830. * @param {String} packageName The package name, for example: 'core', 'touch', 'extjs'.
  831. * @param {String/Ext.Version} version The version, for example: '1.2.3alpha', '2.4.0-dev'.
  832. * @return {Ext}
  833. */
  834. setVersion: function(packageName, version) {
  835. Ext.versions[packageName] = new Version(version);
  836. Ext.lastRegisteredVersion = Ext.versions[packageName];
  837. return this;
  838. },
  839. /**
  840. * Get the version number of the supplied package name; will return the last registered version
  841. * (last `Ext.setVersion()` call) if there's no package name given.
  842. *
  843. * @param {String} packageName (Optional) The package name, for example: 'core', 'touch', 'extjs'.
  844. * @return {Ext.Version} The version.
  845. */
  846. getVersion: function(packageName) {
  847. if (packageName === undefined) {
  848. return Ext.lastRegisteredVersion;
  849. }
  850. return Ext.versions[packageName];
  851. },
  852. /**
  853. * Create a closure for deprecated code.
  854. *
  855. * // This means Ext.oldMethod is only supported in 4.0.0beta and older.
  856. * // If Ext.getVersion('extjs') returns a version that is later than '4.0.0beta', for example '4.0.0RC',
  857. * // the closure will not be invoked
  858. * Ext.deprecate('extjs', '4.0.0beta', function() {
  859. * Ext.oldMethod = Ext.newMethod;
  860. * // ...
  861. * });
  862. *
  863. * @param {String} packageName The package name.
  864. * @param {String} since The last version before it's deprecated.
  865. * @param {Function} closure The callback function to be executed with the specified version is less than the current version.
  866. * @param {Object} scope The execution scope (`this`) if the closure
  867. */
  868. deprecate: function(packageName, since, closure, scope) {
  869. if (Version.compare(Ext.getVersion(packageName), since) < 1) {
  870. closure.call(scope);
  871. }
  872. }
  873. }); // End Versioning
  874. Ext.setVersion('core', version);
  875. })();
  876. //@tag foundation,core
  877. //@define Ext.String
  878. //@require Ext.Version
  879. /**
  880. * @class Ext.String
  881. *
  882. * A collection of useful static methods to deal with strings.
  883. * @singleton
  884. */
  885. Ext.String = {
  886. trimRegex: /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
  887. escapeRe: /('|\\)/g,
  888. formatRe: /\{(\d+)\}/g,
  889. escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
  890. /**
  891. * Convert certain characters (&, <, >, and ") to their HTML character equivalents for literal display in web pages.
  892. * @param {String} value The string to encode.
  893. * @return {String} The encoded text.
  894. * @method
  895. */
  896. htmlEncode: (function() {
  897. var entities = {
  898. '&': '&amp;',
  899. '>': '&gt;',
  900. '<': '&lt;',
  901. '"': '&quot;'
  902. }, keys = [], p, regex;
  903. for (p in entities) {
  904. keys.push(p);
  905. }
  906. regex = new RegExp('(' + keys.join('|') + ')', 'g');
  907. return function(value) {
  908. return (!value) ? value : String(value).replace(regex, function(match, capture) {
  909. return entities[capture];
  910. });
  911. };
  912. })(),
  913. /**
  914. * Convert certain characters (&, <, >, and ") from their HTML character equivalents.
  915. * @param {String} value The string to decode.
  916. * @return {String} The decoded text.
  917. * @method
  918. */
  919. htmlDecode: (function() {
  920. var entities = {
  921. '&amp;': '&',
  922. '&gt;': '>',
  923. '&lt;': '<',
  924. '&quot;': '"'
  925. }, keys = [], p, regex;
  926. for (p in entities) {
  927. keys.push(p);
  928. }
  929. regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
  930. return function(value) {
  931. return (!value) ? value : String(value).replace(regex, function(match, capture) {
  932. if (capture in entities) {
  933. return entities[capture];
  934. } else {
  935. return String.fromCharCode(parseInt(capture.substr(2), 10));
  936. }
  937. });
  938. };
  939. })(),
  940. /**
  941. * Appends content to the query string of a URL, handling logic for whether to place
  942. * a question mark or ampersand.
  943. * @param {String} url The URL to append to.
  944. * @param {String} string The content to append to the URL.
  945. * @return {String} The resulting URL.
  946. */
  947. urlAppend : function(url, string) {
  948. if (!Ext.isEmpty(string)) {
  949. return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
  950. }
  951. return url;
  952. },
  953. /**
  954. * Trims whitespace from either end of a string, leaving spaces within the string intact. Example:
  955. *
  956. * @example
  957. * var s = ' foo bar ';
  958. * alert('-' + s + '-'); // alerts "- foo bar -"
  959. * alert('-' + Ext.String.trim(s) + '-'); // alerts "-foo bar-"
  960. *
  961. * @param {String} string The string to escape
  962. * @return {String} The trimmed string
  963. */
  964. trim: function(string) {
  965. return string.replace(Ext.String.trimRegex, "");
  966. },
  967. /**
  968. * Capitalize the given string.
  969. * @param {String} string
  970. * @return {String}
  971. */
  972. capitalize: function(string) {
  973. return string.charAt(0).toUpperCase() + string.substr(1);
  974. },
  975. /**
  976. * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length.
  977. * @param {String} value The string to truncate.
  978. * @param {Number} length The maximum length to allow before truncating.
  979. * @param {Boolean} word `true` to try to find a common word break.
  980. * @return {String} The converted text.
  981. */
  982. ellipsis: function(value, len, word) {
  983. if (value && value.length > len) {
  984. if (word) {
  985. var vs = value.substr(0, len - 2),
  986. index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
  987. if (index !== -1 && index >= (len - 15)) {
  988. return vs.substr(0, index) + "...";
  989. }
  990. }
  991. return value.substr(0, len - 3) + "...";
  992. }
  993. return value;
  994. },
  995. /**
  996. * Escapes the passed string for use in a regular expression.
  997. * @param {String} string
  998. * @return {String}
  999. */
  1000. escapeRegex: function(string) {
  1001. return string.replace(Ext.String.escapeRegexRe, "\\$1");
  1002. },
  1003. /**
  1004. * Escapes the passed string for ' and \.
  1005. * @param {String} string The string to escape.
  1006. * @return {String} The escaped string.
  1007. */
  1008. escape: function(string) {
  1009. return string.replace(Ext.String.escapeRe, "\\$1");
  1010. },
  1011. /**
  1012. * Utility function that allows you to easily switch a string between two alternating values. The passed value
  1013. * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
  1014. * they are already different, the first value passed in is returned. Note that this method returns the new value
  1015. * but does not change the current string.
  1016. *
  1017. * // alternate sort directions
  1018. * sort = Ext.String.toggle(sort, 'ASC', 'DESC');
  1019. *
  1020. * // instead of conditional logic:
  1021. * sort = (sort == 'ASC' ? 'DESC' : 'ASC');
  1022. *
  1023. * @param {String} string The current string.
  1024. * @param {String} value The value to compare to the current string.
  1025. * @param {String} other The new value to use if the string already equals the first value passed in.
  1026. * @return {String} The new value.
  1027. */
  1028. toggle: function(string, value, other) {
  1029. return string === value ? other : value;
  1030. },
  1031. /**
  1032. * Pads the left side of a string with a specified character. This is especially useful
  1033. * for normalizing number and date strings. Example usage:
  1034. *
  1035. * var s = Ext.String.leftPad('123', 5, '0');
  1036. * alert(s); // '00123'
  1037. *
  1038. * @param {String} string The original string.
  1039. * @param {Number} size The total length of the output string.
  1040. * @param {String} [character= ] (optional) The character with which to pad the original string (defaults to empty string " ").
  1041. * @return {String} The padded string.
  1042. */
  1043. leftPad: function(string, size, character) {
  1044. var result = String(string);
  1045. character = character || " ";
  1046. while (result.length < size) {
  1047. result = character + result;
  1048. }
  1049. return result;
  1050. },
  1051. /**
  1052. * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
  1053. * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
  1054. *
  1055. * var cls = 'my-class',
  1056. * text = 'Some text';
  1057. * var s = Ext.String.format('<div class="{0}">{1}</div>', cls, text);
  1058. * alert(s); // '<div class="my-class">Some text</div>'
  1059. *
  1060. * @param {String} string The tokenized string to be formatted.
  1061. * @param {String} value1 The value to replace token {0}.
  1062. * @param {String} value2 Etc...
  1063. * @return {String} The formatted string.
  1064. */
  1065. format: function(format) {
  1066. var args = Ext.Array.toArray(arguments, 1);
  1067. return format.replace(Ext.String.formatRe, function(m, i) {
  1068. return args[i];
  1069. });
  1070. },
  1071. /**
  1072. * Returns a string with a specified number of repetitions a given string pattern.
  1073. * The pattern be separated by a different string.
  1074. *
  1075. * var s = Ext.String.repeat('---', 4); // '------------'
  1076. * var t = Ext.String.repeat('--', 3, '/'); // '--/--/--'
  1077. *
  1078. * @param {String} pattern The pattern to repeat.
  1079. * @param {Number} count The number of times to repeat the pattern (may be 0).
  1080. * @param {String} sep An option string to separate each pattern.
  1081. */
  1082. repeat: function(pattern, count, sep) {
  1083. for (var buf = [], i = count; i--; ) {
  1084. buf.push(pattern);
  1085. }
  1086. return buf.join(sep || '');
  1087. }
  1088. };
  1089. /**
  1090. * Old alias to {@link Ext.String#htmlEncode}.
  1091. * @deprecated Use {@link Ext.String#htmlEncode} instead.
  1092. * @method
  1093. * @member Ext
  1094. * @alias Ext.String#htmlEncode
  1095. */
  1096. Ext.htmlEncode = Ext.String.htmlEncode;
  1097. /**
  1098. * Old alias to {@link Ext.String#htmlDecode}.
  1099. * @deprecated Use {@link Ext.String#htmlDecode} instead.
  1100. * @method
  1101. * @member Ext
  1102. * @alias Ext.String#htmlDecode
  1103. */
  1104. Ext.htmlDecode = Ext.String.htmlDecode;
  1105. /**
  1106. * Old alias to {@link Ext.String#urlAppend}.
  1107. * @deprecated Use {@link Ext.String#urlAppend} instead.
  1108. * @method
  1109. * @member Ext
  1110. * @alias Ext.String#urlAppend
  1111. */
  1112. Ext.urlAppend = Ext.String.urlAppend;
  1113. //@tag foundation,core
  1114. //@define Ext.Array
  1115. //@require Ext.String
  1116. /**
  1117. * @class Ext.Array
  1118. * @singleton
  1119. * @author Jacky Nguyen <jacky@sencha.com>
  1120. * @docauthor Jacky Nguyen <jacky@sencha.com>
  1121. *
  1122. * A set of useful static methods to deal with arrays; provide missing methods for older browsers.
  1123. */
  1124. (function() {
  1125. var arrayPrototype = Array.prototype,
  1126. slice = arrayPrototype.slice,
  1127. supportsSplice = function () {
  1128. var array = [],
  1129. lengthBefore,
  1130. j = 20;
  1131. if (!array.splice) {
  1132. return false;
  1133. }
  1134. // This detects a bug in IE8 splice method:
  1135. // see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/
  1136. while (j--) {
  1137. array.push("A");
  1138. }
  1139. array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
  1140. lengthBefore = array.length; //41
  1141. array.splice(13, 0, "XXX"); // add one element
  1142. if (lengthBefore+1 != array.length) {
  1143. return false;
  1144. }
  1145. // end IE8 bug
  1146. return true;
  1147. }(),
  1148. supportsForEach = 'forEach' in arrayPrototype,
  1149. supportsMap = 'map' in arrayPrototype,
  1150. supportsIndexOf = 'indexOf' in arrayPrototype,
  1151. supportsEvery = 'every' in arrayPrototype,
  1152. supportsSome = 'some' in arrayPrototype,
  1153. supportsFilter = 'filter' in arrayPrototype,
  1154. supportsSort = function() {
  1155. var a = [1,2,3,4,5].sort(function(){ return 0; });
  1156. return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
  1157. }(),
  1158. supportsSliceOnNodeList = true,
  1159. ExtArray;
  1160. try {
  1161. // IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList
  1162. if (typeof document !== 'undefined') {
  1163. slice.call(document.getElementsByTagName('body'));
  1164. }
  1165. } catch (e) {
  1166. supportsSliceOnNodeList = false;
  1167. }
  1168. function fixArrayIndex (array, index) {
  1169. return (index < 0) ? Math.max(0, array.length + index)
  1170. : Math.min(array.length, index);
  1171. }
  1172. /*
  1173. Does the same work as splice, but with a slightly more convenient signature. The splice
  1174. method has bugs in IE8, so this is the implementation we use on that platform.
  1175. The rippling of items in the array can be tricky. Consider two use cases:
  1176. index=2
  1177. removeCount=2
  1178. /=====\
  1179. +---+---+---+---+---+---+---+---+
  1180. | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
  1181. +---+---+---+---+---+---+---+---+
  1182. / \/ \/ \/ \
  1183. / /\ /\ /\ \
  1184. / / \/ \/ \ +--------------------------+
  1185. / / /\ /\ +--------------------------+ \
  1186. / / / \/ +--------------------------+ \ \
  1187. / / / /+--------------------------+ \ \ \
  1188. / / / / \ \ \ \
  1189. v v v v v v v v
  1190. +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
  1191. | 0 | 1 | 4 | 5 | 6 | 7 | | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
  1192. +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
  1193. A B \=========/
  1194. insert=[a,b,c]
  1195. In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
  1196. that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
  1197. must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].
  1198. */
  1199. function replaceSim (array, index, removeCount, insert) {
  1200. var add = insert ? insert.length : 0,
  1201. length = array.length,
  1202. pos = fixArrayIndex(array, index);
  1203. // we try to use Array.push when we can for efficiency...
  1204. if (pos === length) {
  1205. if (add) {
  1206. array.push.apply(array, insert);
  1207. }
  1208. } else {
  1209. var remove = Math.min(removeCount, length - pos),
  1210. tailOldPos = pos + remove,
  1211. tailNewPos = tailOldPos + add - remove,
  1212. tailCount = length - tailOldPos,
  1213. lengthAfterRemove = length - remove,
  1214. i;
  1215. if (tailNewPos < tailOldPos) { // case A
  1216. for (i = 0; i < tailCount; ++i) {
  1217. array[tailNewPos+i] = array[tailOldPos+i];
  1218. }
  1219. } else if (tailNewPos > tailOldPos) { // case B
  1220. for (i = tailCount; i--; ) {
  1221. array[tailNewPos+i] = array[tailOldPos+i];
  1222. }
  1223. } // else, add == remove (nothing to do)
  1224. if (add && pos === lengthAfterRemove) {
  1225. array.length = lengthAfterRemove; // truncate array
  1226. array.push.apply(array, insert);
  1227. } else {
  1228. array.length = lengthAfterRemove + add; // reserves space
  1229. for (i = 0; i < add; ++i) {
  1230. array[pos+i] = insert[i];
  1231. }
  1232. }
  1233. }
  1234. return array;
  1235. }
  1236. function replaceNative (array, index, removeCount, insert) {
  1237. if (insert && insert.length) {
  1238. if (index < array.length) {
  1239. array.splice.apply(array, [index, removeCount].concat(insert));
  1240. } else {
  1241. array.push.apply(array, insert);
  1242. }
  1243. } else {
  1244. array.splice(index, removeCount);
  1245. }
  1246. return array;
  1247. }
  1248. function eraseSim (array, index, removeCount) {
  1249. return replaceSim(array, index, removeCount);
  1250. }
  1251. function eraseNative (array, index, removeCount) {
  1252. array.splice(index, removeCount);
  1253. return array;
  1254. }
  1255. function spliceSim (array, index, removeCount) {
  1256. var pos = fixArrayIndex(array, index),
  1257. removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
  1258. if (arguments.length < 4) {
  1259. replaceSim(array, pos, removeCount);
  1260. } else {
  1261. replaceSim(array, pos, removeCount, slice.call(arguments, 3));
  1262. }
  1263. return removed;
  1264. }
  1265. function spliceNative (array) {
  1266. return array.splice.apply(array, slice.call(arguments, 1));
  1267. }
  1268. var erase = supportsSplice ? eraseNative : eraseSim,
  1269. replace = supportsSplice ? replaceNative : replaceSim,
  1270. splice = supportsSplice ? spliceNative : spliceSim;
  1271. // NOTE: from here on, use erase, replace or splice (not native methods)...
  1272. ExtArray = Ext.Array = {
  1273. /**
  1274. * Iterates an array or an iterable value and invoke the given callback function for each item.
  1275. *
  1276. * var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
  1277. *
  1278. * Ext.Array.each(countries, function(name, index, countriesItSelf) {
  1279. * console.log(name);
  1280. * });
  1281. *
  1282. * var sum = function() {
  1283. * var sum = 0;
  1284. *
  1285. * Ext.Array.each(arguments, function(value) {
  1286. * sum += value;
  1287. * });
  1288. *
  1289. * return sum;
  1290. * };
  1291. *
  1292. * sum(1, 2, 3); // returns 6
  1293. *
  1294. * The iteration can be stopped by returning false in the function callback.
  1295. *
  1296. * Ext.Array.each(countries, function(name, index, countriesItSelf) {
  1297. * if (name === 'Singapore') {
  1298. * return false; // break here
  1299. * }
  1300. * });
  1301. *
  1302. * {@link Ext#each Ext.each} is alias for {@link Ext.Array#each Ext.Array.each}
  1303. *
  1304. * @param {Array/NodeList/Object} iterable The value to be iterated. If this
  1305. * argument is not iterable, the callback function is called once.
  1306. * @param {Function} fn The callback function. If it returns `false`, the iteration stops and this method returns
  1307. * the current `index`.
  1308. * @param {Object} fn.item The item at the current `index` in the passed `array`
  1309. * @param {Number} fn.index The current `index` within the `array`
  1310. * @param {Array} fn.allItems The `array` itself which was passed as the first argument
  1311. * @param {Boolean} fn.return Return false to stop iteration.
  1312. * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
  1313. * @param {Boolean} [reverse=false] (Optional) Reverse the iteration order (loop from the end to the beginning).
  1314. * @return {Boolean} See description for the `fn` parameter.
  1315. */
  1316. each: function(array, fn, scope, reverse) {
  1317. array = ExtArray.from(array);
  1318. var i,
  1319. ln = array.length;
  1320. if (reverse !== true) {
  1321. for (i = 0; i < ln; i++) {
  1322. if (fn.call(scope || array[i], array[i], i, array) === false) {
  1323. return i;
  1324. }
  1325. }
  1326. }
  1327. else {
  1328. for (i = ln - 1; i > -1; i--) {
  1329. if (fn.call(scope || array[i], array[i], i, array) === false) {
  1330. return i;
  1331. }
  1332. }
  1333. }
  1334. return true;
  1335. },
  1336. /**
  1337. * Iterates an array and invoke the given callback function for each item. Note that this will simply
  1338. * delegate to the native `Array.prototype.forEach` method if supported. It doesn't support stopping the
  1339. * iteration by returning `false` in the callback function like {@link Ext.Array#each}. However, performance
  1340. * could be much better in modern browsers comparing with {@link Ext.Array#each}
  1341. *
  1342. * @param {Array} array The array to iterate.
  1343. * @param {Function} fn The callback function.
  1344. * @param {Object} fn.item The item at the current `index` in the passed `array`.
  1345. * @param {Number} fn.index The current `index` within the `array`.
  1346. * @param {Array} fn.allItems The `array` itself which was passed as the first argument.
  1347. * @param {Object} scope (Optional) The execution scope (`this`) in which the specified function is executed.
  1348. */
  1349. forEach: supportsForEach ? function(array, fn, scope) {
  1350. return array.forEach(fn, scope);
  1351. } : function(array, fn, scope) {
  1352. var i = 0,
  1353. ln = array.length;
  1354. for (; i < ln; i++) {
  1355. fn.call(scope, array[i], i, array);
  1356. }
  1357. },
  1358. /**
  1359. * Get the index of the provided `item` in the given `array`, a supplement for the
  1360. * missing arrayPrototype.indexOf in Internet Explorer.
  1361. *
  1362. * @param {Array} array The array to check.
  1363. * @param {Object} item The item to look for.
  1364. * @param {Number} from (Optional) The index at which to begin the search.
  1365. * @return {Number} The index of item in the array (or -1 if it is not found).
  1366. */
  1367. indexOf: (supportsIndexOf) ? function(array, item, from) {
  1368. return array.indexOf(item, from);
  1369. } : function(array, item, from) {
  1370. var i, length = array.length;
  1371. for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
  1372. if (array[i] === item) {
  1373. return i;
  1374. }
  1375. }
  1376. return -1;
  1377. },
  1378. /**
  1379. * Checks whether or not the given `array` contains the specified `item`.
  1380. *
  1381. * @param {Array} array The array to check.
  1382. * @param {Object} item The item to look for.
  1383. * @return {Boolean} `true` if the array contains the item, `false` otherwise.
  1384. */
  1385. contains: supportsIndexOf ? function(array, item) {
  1386. return array.indexOf(item) !== -1;
  1387. } : function(array, item) {
  1388. var i, ln;
  1389. for (i = 0, ln = array.length; i < ln; i++) {
  1390. if (array[i] === item) {
  1391. return true;
  1392. }
  1393. }
  1394. return false;
  1395. },
  1396. /**
  1397. * Converts any iterable (numeric indices and a length property) into a true array.
  1398. *
  1399. * function test() {
  1400. * var args = Ext.Array.toArray(arguments),
  1401. * fromSecondToLastArgs = Ext.Array.toArray(arguments, 1);
  1402. *
  1403. * alert(args.join(' '));
  1404. * alert(fromSecondToLastArgs.join(' '));
  1405. * }
  1406. *
  1407. * test('just', 'testing', 'here'); // alerts 'just testing here';
  1408. * // alerts 'testing here';
  1409. *
  1410. * Ext.Array.toArray(document.getElementsByTagName('div')); // will convert the NodeList into an array
  1411. * Ext.Array.toArray('splitted'); // returns ['s', 'p', 'l', 'i', 't', 't', 'e', 'd']
  1412. * Ext.Array.toArray('splitted', 0, 3); // returns ['s', 'p', 'l', 'i']
  1413. *
  1414. * {@link Ext#toArray Ext.toArray} is alias for {@link Ext.Array#toArray Ext.Array.toArray}
  1415. *
  1416. * @param {Object} iterable the iterable object to be turned into a true Array.
  1417. * @param {Number} [start=0] (Optional) a zero-based index that specifies the start of extraction.
  1418. * @param {Number} [end=-1] (Optional) a zero-based index that specifies the end of extraction.
  1419. * @return {Array}
  1420. */
  1421. toArray: function(iterable, start, end){
  1422. if (!iterable || !iterable.length) {
  1423. return [];
  1424. }
  1425. if (typeof iterable === 'string') {
  1426. iterable = iterable.split('');
  1427. }
  1428. if (supportsSliceOnNodeList) {
  1429. return slice.call(iterable, start || 0, end || iterable.length);
  1430. }
  1431. var array = [],
  1432. i;
  1433. start = start || 0;
  1434. end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
  1435. for (i = start; i < end; i++) {
  1436. array.push(iterable[i]);
  1437. }
  1438. return array;
  1439. },
  1440. /**
  1441. * Plucks the value of a property from each item in the Array. Example:
  1442. *
  1443. * Ext.Array.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
  1444. *
  1445. * @param {Array/NodeList} array The Array of items to pluck the value from.
  1446. * @param {String} propertyName The property name to pluck from each element.
  1447. * @return {Array} The value from each item in the Array.
  1448. */
  1449. pluck: function(array, propertyName) {
  1450. var ret = [],
  1451. i, ln, item;
  1452. for (i = 0, ln = array.length; i < ln; i++) {
  1453. item = array[i];
  1454. ret.push(item[propertyName]);
  1455. }
  1456. return ret;
  1457. },
  1458. /**
  1459. * Creates a new array with the results of calling a provided function on every element in this array.
  1460. *
  1461. * @param {Array} array
  1462. * @param {Function} fn Callback function for each item.
  1463. * @param {Object} scope Callback function scope.
  1464. * @return {Array} results
  1465. */
  1466. map: supportsMap ? function(array, fn, scope) {
  1467. return array.map(fn, scope);
  1468. } : function(array, fn, scope) {
  1469. var results = [],
  1470. i = 0,
  1471. len = array.length;
  1472. for (; i < len; i++) {
  1473. results[i] = fn.call(scope, array[i], i, array);
  1474. }
  1475. return results;
  1476. },
  1477. /**
  1478. * Executes the specified function for each array element until the function returns a falsy value.
  1479. * If such an item is found, the function will return `false` immediately.
  1480. * Otherwise, it will return `true`.
  1481. *
  1482. * @param {Array} array
  1483. * @param {Function} fn Callback function for each item.
  1484. * @param {Object} scope Callback function scope.
  1485. * @return {Boolean} `true` if no `false` value is returned by the callback function.
  1486. */
  1487. every: function(array, fn, scope) {
  1488. //<debug>
  1489. if (!fn) {
  1490. Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
  1491. }
  1492. //</debug>
  1493. if (supportsEvery) {
  1494. return array.every(fn, scope);
  1495. }
  1496. var i = 0,
  1497. ln = array.length;
  1498. for (; i < ln; ++i) {
  1499. if (!fn.call(scope, array[i], i, array)) {
  1500. return false;
  1501. }
  1502. }
  1503. return true;
  1504. },
  1505. /**
  1506. * Executes the specified function for each array element until the function returns a truthy value.
  1507. * If such an item is found, the function will return `true` immediately. Otherwise, it will return `false`.
  1508. *
  1509. * @param {Array} array
  1510. * @param {Function} fn Callback function for each item.
  1511. * @param {Object} scope Callback function scope.
  1512. * @return {Boolean} `true` if the callback function returns a truthy value.
  1513. */
  1514. some: function(array, fn, scope) {
  1515. //<debug>
  1516. if (!fn) {
  1517. Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
  1518. }
  1519. //</debug>
  1520. if (supportsSome) {
  1521. return array.some(fn, scope);
  1522. }
  1523. var i = 0,
  1524. ln = array.length;
  1525. for (; i < ln; ++i) {
  1526. if (fn.call(scope, array[i], i, array)) {
  1527. return true;
  1528. }
  1529. }
  1530. return false;
  1531. },
  1532. /**
  1533. * Filter through an array and remove empty item as defined in {@link Ext#isEmpty Ext.isEmpty}.
  1534. *
  1535. * See {@link Ext.Array#filter}
  1536. *
  1537. * @param {Array} array
  1538. * @return {Array} results
  1539. */
  1540. clean: function(array) {
  1541. var results = [],
  1542. i = 0,
  1543. ln = array.length,
  1544. item;
  1545. for (; i < ln; i++) {
  1546. item = array[i];
  1547. if (!Ext.isEmpty(item)) {
  1548. results.push(item);
  1549. }
  1550. }
  1551. return results;
  1552. },
  1553. /**
  1554. * Returns a new array with unique items.
  1555. *
  1556. * @param {Array} array
  1557. * @return {Array} results
  1558. */
  1559. unique: function(array) {
  1560. var clone = [],
  1561. i = 0,
  1562. ln = array.length,
  1563. item;
  1564. for (; i < ln; i++) {
  1565. item = array[i];
  1566. if (ExtArray.indexOf(clone, item) === -1) {
  1567. clone.push(item);
  1568. }
  1569. }
  1570. return clone;
  1571. },
  1572. /**
  1573. * Creates a new array with all of the elements of this array for which
  1574. * the provided filtering function returns `true`.
  1575. *
  1576. * @param {Array} array
  1577. * @param {Function} fn Callback function for each item.
  1578. * @param {Object} scope Callback function scope.
  1579. * @return {Array} results
  1580. */
  1581. filter: function(array, fn, scope) {
  1582. if (supportsFilter) {
  1583. return array.filter(fn, scope);
  1584. }
  1585. var results = [],
  1586. i = 0,
  1587. ln = array.length;
  1588. for (; i < ln; i++) {
  1589. if (fn.call(scope, array[i], i, array)) {
  1590. results.push(array[i]);
  1591. }
  1592. }
  1593. return results;
  1594. },
  1595. /**
  1596. * Converts a value to an array if it's not already an array; returns:
  1597. *
  1598. * - An empty array if given value is `undefined` or `null`
  1599. * - Itself if given value is already an array
  1600. * - An array copy if given value is {@link Ext#isIterable iterable} (arguments, NodeList and alike)
  1601. * - An array with one item which is the given value, otherwise
  1602. *
  1603. * @param {Object} value The value to convert to an array if it's not already is an array.
  1604. * @param {Boolean} [newReference=false] (Optional) `true` to clone the given array and return a new reference if necessary.
  1605. * @return {Array} array
  1606. */
  1607. from: function(value, newReference) {
  1608. if (value === undefined || value === null) {
  1609. return [];
  1610. }
  1611. if (Ext.isArray(value)) {
  1612. return (newReference) ? slice.call(value) : value;
  1613. }
  1614. if (value && value.length !== undefined && typeof value !== 'string') {
  1615. return ExtArray.toArray(value);
  1616. }
  1617. return [value];
  1618. },
  1619. /**
  1620. * Removes the specified item from the array if it exists.
  1621. *
  1622. * @param {Array} array The array.
  1623. * @param {Object} item The item to remove.
  1624. * @return {Array} The passed array itself.
  1625. */
  1626. remove: function(array, item) {
  1627. var index = ExtArray.indexOf(array, item);
  1628. if (index !== -1) {
  1629. erase(array, index, 1);
  1630. }
  1631. return array;
  1632. },
  1633. /**
  1634. * Push an item into the array only if the array doesn't contain it yet.
  1635. *
  1636. * @param {Array} array The array.
  1637. * @param {Object} item The item to include.
  1638. */
  1639. include: function(array, item) {
  1640. if (!ExtArray.contains(array, item)) {
  1641. array.push(item);
  1642. }
  1643. },
  1644. /**
  1645. * Clone a flat array without referencing the previous one. Note that this is different
  1646. * from `Ext.clone` since it doesn't handle recursive cloning. It's simply a convenient, easy-to-remember method
  1647. * for `Array.prototype.slice.call(array)`.
  1648. *
  1649. * @param {Array} array The array
  1650. * @return {Array} The clone array
  1651. */
  1652. clone: function(array) {
  1653. return slice.call(array);
  1654. },
  1655. /**
  1656. * Merge multiple arrays into one with unique items.
  1657. *
  1658. * {@link Ext.Array#union} is alias for {@link Ext.Array#merge}
  1659. *
  1660. * @param {Array} array1
  1661. * @param {Array} array2
  1662. * @param {Array} etc
  1663. * @return {Array} merged
  1664. */
  1665. merge: function() {
  1666. var args = slice.call(arguments),
  1667. array = [],
  1668. i, ln;
  1669. for (i = 0, ln = args.length; i < ln; i++) {
  1670. array = array.concat(args[i]);
  1671. }
  1672. return ExtArray.unique(array);
  1673. },
  1674. /**
  1675. * Merge multiple arrays into one with unique items that exist in all of the arrays.
  1676. *
  1677. * @param {Array} array1
  1678. * @param {Array} array2
  1679. * @param {Array} etc
  1680. * @return {Array} intersect
  1681. */
  1682. intersect: function() {
  1683. var intersect = [],
  1684. arrays = slice.call(arguments),
  1685. i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
  1686. if (!arrays.length) {
  1687. return intersect;
  1688. }
  1689. // Find the smallest array
  1690. for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
  1691. if (!minArray || array.length < minArray.length) {
  1692. minArray = array;
  1693. x = i;
  1694. }
  1695. }
  1696. minArray = ExtArray.unique(minArray);
  1697. erase(arrays, x, 1);
  1698. // Use the smallest unique'd array as the anchor loop. If the other array(s) do contain
  1699. // an item in the small array, we're likely to find it before reaching the end
  1700. // of the inner loop and can terminate the search early.
  1701. for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
  1702. var count = 0;
  1703. for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
  1704. for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
  1705. if (x === y) {
  1706. count++;
  1707. break;
  1708. }
  1709. }
  1710. }
  1711. if (count === arraysLn) {
  1712. intersect.push(x);
  1713. }
  1714. }
  1715. return intersect;
  1716. },
  1717. /**
  1718. * Perform a set difference A-B by subtracting all items in array B from array A.
  1719. *
  1720. * @param {Array} arrayA
  1721. * @param {Array} arrayB
  1722. * @return {Array} difference
  1723. */
  1724. difference: function(arrayA, arrayB) {
  1725. var clone = slice.call(arrayA),
  1726. ln = clone.length,
  1727. i, j, lnB;
  1728. for (i = 0,lnB = arrayB.length; i < lnB; i++) {
  1729. for (j = 0; j < ln; j++) {
  1730. if (clone[j] === arrayB[i]) {
  1731. erase(clone, j, 1);
  1732. j--;
  1733. ln--;
  1734. }
  1735. }
  1736. }
  1737. return clone;
  1738. },
  1739. /**
  1740. * Returns a shallow copy of a part of an array. This is equivalent to the native
  1741. * call `Array.prototype.slice.call(array, begin, end)`. This is often used when "array"
  1742. * is "arguments" since the arguments object does not supply a slice method but can
  1743. * be the context object to `Array.prototype.slice()`.
  1744. *
  1745. * @param {Array} array The array (or arguments object).
  1746. * @param {Number} begin The index at which to begin. Negative values are offsets from
  1747. * the end of the array.
  1748. * @param {Number} end The index at which to end. The copied items do not include
  1749. * end. Negative values are offsets from the end of the array. If end is omitted,
  1750. * all items up to the end of the array are copied.
  1751. * @return {Array} The copied piece of the array.
  1752. */
  1753. slice: function(array, begin, end) {
  1754. return slice.call(array, begin, end);
  1755. },
  1756. /**
  1757. * Sorts the elements of an Array.
  1758. * By default, this method sorts the elements alphabetically and ascending.
  1759. *
  1760. * @param {Array} array The array to sort.
  1761. * @param {Function} sortFn (optional) The comparison function.
  1762. * @return {Array} The sorted array.
  1763. */
  1764. sort: function(array, sortFn) {
  1765. if (supportsSort) {
  1766. if (sortFn) {
  1767. return array.sort(sortFn);
  1768. } else {
  1769. return array.sort();
  1770. }
  1771. }
  1772. var length = array.length,
  1773. i = 0,
  1774. comparison,
  1775. j, min, tmp;
  1776. for (; i < length; i++) {
  1777. min = i;
  1778. for (j = i + 1; j < length; j++) {
  1779. if (sortFn) {
  1780. comparison = sortFn(array[j], array[min]);
  1781. if (comparison < 0) {
  1782. min = j;
  1783. }
  1784. } else if (array[j] < array[min]) {
  1785. min = j;
  1786. }
  1787. }
  1788. if (min !== i) {
  1789. tmp = array[i];
  1790. array[i] = array[min];
  1791. array[min] = tmp;
  1792. }
  1793. }
  1794. return array;
  1795. },
  1796. /**
  1797. * Recursively flattens into 1-d Array. Injects Arrays inline.
  1798. *
  1799. * @param {Array} array The array to flatten
  1800. * @return {Array} The 1-d array.
  1801. */
  1802. flatten: function(array) {
  1803. var worker = [];
  1804. function rFlatten(a) {
  1805. var i, ln, v;
  1806. for (i = 0, ln = a.length; i < ln; i++) {
  1807. v = a[i];
  1808. if (Ext.isArray(v)) {
  1809. rFlatten(v);
  1810. } else {
  1811. worker.push(v);
  1812. }
  1813. }
  1814. return worker;
  1815. }
  1816. return rFlatten(array);
  1817. },
  1818. /**
  1819. * Returns the minimum value in the Array.
  1820. *
  1821. * @param {Array/NodeList} array The Array from which to select the minimum value.
  1822. * @param {Function} comparisonFn (optional) a function to perform the comparison which determines minimization.
  1823. * If omitted the "<" operator will be used.
  1824. * __Note:__ gt = 1; eq = 0; lt = -1
  1825. * @return {Object} minValue The minimum value.
  1826. */
  1827. min: function(array, comparisonFn) {
  1828. var min = array[0],
  1829. i, ln, item;
  1830. for (i = 0, ln = array.length; i < ln; i++) {
  1831. item = array[i];
  1832. if (comparisonFn) {
  1833. if (comparisonFn(min, item) === 1) {
  1834. min = item;
  1835. }
  1836. }
  1837. else {
  1838. if (item < min) {
  1839. min = item;
  1840. }
  1841. }
  1842. }
  1843. return min;
  1844. },
  1845. /**
  1846. * Returns the maximum value in the Array.
  1847. *
  1848. * @param {Array/NodeList} array The Array from which to select the maximum value.
  1849. * @param {Function} comparisonFn (optional) a function to perform the comparison which determines maximization.
  1850. * If omitted the ">" operator will be used.
  1851. * __Note:__ gt = 1; eq = 0; lt = -1
  1852. * @return {Object} maxValue The maximum value
  1853. */
  1854. max: function(array, comparisonFn) {
  1855. var max = array[0],
  1856. i, ln, item;
  1857. for (i = 0, ln = array.length; i < ln; i++) {
  1858. item = array[i];
  1859. if (comparisonFn) {
  1860. if (comparisonFn(max, item) === -1) {
  1861. max = item;
  1862. }
  1863. }
  1864. else {
  1865. if (item > max) {
  1866. max = item;
  1867. }
  1868. }
  1869. }
  1870. return max;
  1871. },
  1872. /**
  1873. * Calculates the mean of all items in the array.
  1874. *
  1875. * @param {Array} array The Array to calculate the mean value of.
  1876. * @return {Number} The mean.
  1877. */
  1878. mean: function(array) {
  1879. return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
  1880. },
  1881. /**
  1882. * Calculates the sum of all items in the given array.
  1883. *
  1884. * @param {Array} array The Array to calculate the sum value of.
  1885. * @return {Number} The sum.
  1886. */
  1887. sum: function(array) {
  1888. var sum = 0,
  1889. i, ln, item;
  1890. for (i = 0,ln = array.length; i < ln; i++) {
  1891. item = array[i];
  1892. sum += item;
  1893. }
  1894. return sum;
  1895. },
  1896. //<debug>
  1897. _replaceSim: replaceSim, // for unit testing
  1898. _spliceSim: spliceSim,
  1899. //</debug>
  1900. /**
  1901. * Removes items from an array. This is functionally equivalent to the splice method
  1902. * of Array, but works around bugs in IE8's splice method and does not copy the
  1903. * removed elements in order to return them (because very often they are ignored).
  1904. *
  1905. * @param {Array} array The Array on which to replace.
  1906. * @param {Number} index The index in the array at which to operate.
  1907. * @param {Number} removeCount The number of items to remove at index.
  1908. * @return {Array} The array passed.
  1909. * @method
  1910. */
  1911. erase: erase,
  1912. /**
  1913. * Inserts items in to an array.
  1914. *
  1915. * @param {Array} array The Array on which to replace.
  1916. * @param {Number} index The index in the array at which to operate.
  1917. * @param {Array} items The array of items to insert at index.
  1918. * @return {Array} The array passed.
  1919. */
  1920. insert: function (array, index, items) {
  1921. return replace(array, index, 0, items);
  1922. },
  1923. /**
  1924. * Replaces items in an array. This is functionally equivalent to the splice method
  1925. * of Array, but works around bugs in IE8's splice method and is often more convenient
  1926. * to call because it accepts an array of items to insert rather than use a variadic
  1927. * argument list.
  1928. *
  1929. * @param {Array} array The Array on which to replace.
  1930. * @param {Number} index The index in the array at which to operate.
  1931. * @param {Number} removeCount The number of items to remove at index (can be 0).
  1932. * @param {Array} insert (optional) An array of items to insert at index.
  1933. * @return {Array} The array passed.
  1934. * @method
  1935. */
  1936. replace: replace,
  1937. /**
  1938. * Replaces items in an array. This is equivalent to the splice method of Array, but
  1939. * works around bugs in IE8's splice method. The signature is exactly the same as the
  1940. * splice method except that the array is the first argument. All arguments following
  1941. * removeCount are inserted in the array at index.
  1942. *
  1943. * @param {Array} array The Array on which to replace.
  1944. * @param {Number} index The index in the array at which to operate.
  1945. * @param {Number} removeCount The number of items to remove at index (can be 0).
  1946. * @return {Array} An array containing the removed items.
  1947. * @method
  1948. */
  1949. splice: splice
  1950. };
  1951. /**
  1952. * @method
  1953. * @member Ext
  1954. * @alias Ext.Array#each
  1955. */
  1956. Ext.each = ExtArray.each;
  1957. /**
  1958. * @method
  1959. * @member Ext.Array
  1960. * @alias Ext.Array#merge
  1961. */
  1962. ExtArray.union = ExtArray.merge;
  1963. /**
  1964. * Old alias to {@link Ext.Array#min}
  1965. * @deprecated 4.0.0 Please use {@link Ext.Array#min} instead
  1966. * @method
  1967. * @member Ext
  1968. * @alias Ext.Array#min
  1969. */
  1970. Ext.min = ExtArray.min;
  1971. /**
  1972. * Old alias to {@link Ext.Array#max}
  1973. * @deprecated 4.0.0 Please use {@link Ext.Array#max} instead
  1974. * @method
  1975. * @member Ext
  1976. * @alias Ext.Array#max
  1977. */
  1978. Ext.max = ExtArray.max;
  1979. /**
  1980. * Old alias to {@link Ext.Array#sum}
  1981. * @deprecated 4.0.0 Please use {@link Ext.Array#sum} instead
  1982. * @method
  1983. * @member Ext
  1984. * @alias Ext.Array#sum
  1985. */
  1986. Ext.sum = ExtArray.sum;
  1987. /**
  1988. * Old alias to {@link Ext.Array#mean}
  1989. * @deprecated 4.0.0 Please use {@link Ext.Array#mean} instead
  1990. * @method
  1991. * @member Ext
  1992. * @alias Ext.Array#mean
  1993. */
  1994. Ext.mean = ExtArray.mean;
  1995. /**
  1996. * Old alias to {@link Ext.Array#flatten}
  1997. * @deprecated 4.0.0 Please use {@link Ext.Array#flatten} instead
  1998. * @method
  1999. * @member Ext
  2000. * @alias Ext.Array#flatten
  2001. */
  2002. Ext.flatten = ExtArray.flatten;
  2003. /**
  2004. * Old alias to {@link Ext.Array#clean}
  2005. * @deprecated 4.0.0 Please use {@link Ext.Array#clean} instead
  2006. * @method
  2007. * @member Ext
  2008. * @alias Ext.Array#clean
  2009. */
  2010. Ext.clean = ExtArray.clean;
  2011. /**
  2012. * Old alias to {@link Ext.Array#unique}
  2013. * @deprecated 4.0.0 Please use {@link Ext.Array#unique} instead
  2014. * @method
  2015. * @member Ext
  2016. * @alias Ext.Array#unique
  2017. */
  2018. Ext.unique = ExtArray.unique;
  2019. /**
  2020. * Old alias to {@link Ext.Array#pluck Ext.Array.pluck}
  2021. * @deprecated 4.0.0 Please use {@link Ext.Array#pluck Ext.Array.pluck} instead
  2022. * @method
  2023. * @member Ext
  2024. * @alias Ext.Array#pluck
  2025. */
  2026. Ext.pluck = ExtArray.pluck;
  2027. /**
  2028. * @method
  2029. * @member Ext
  2030. * @alias Ext.Array#toArray
  2031. */
  2032. Ext.toArray = function() {
  2033. return ExtArray.toArray.apply(ExtArray, arguments);
  2034. };
  2035. })();
  2036. //@tag foundation,core
  2037. //@define Ext.Number
  2038. //@require Ext.Array
  2039. /**
  2040. * @class Ext.Number
  2041. *
  2042. * A collection of useful static methods to deal with numbers
  2043. * @singleton
  2044. */
  2045. (function() {
  2046. var isToFixedBroken = (0.9).toFixed() !== '1';
  2047. Ext.Number = {
  2048. /**
  2049. * Checks whether or not the passed number is within a desired range. If the number is already within the
  2050. * range it is returned, otherwise the min or max value is returned depending on which side of the range is
  2051. * exceeded. Note that this method returns the constrained value but does not change the current number.
  2052. * @param {Number} number The number to check
  2053. * @param {Number} min The minimum number in the range
  2054. * @param {Number} max The maximum number in the range
  2055. * @return {Number} The constrained value if outside the range, otherwise the current value
  2056. */
  2057. constrain: function(number, min, max) {
  2058. number = parseFloat(number);
  2059. if (!isNaN(min)) {
  2060. number = Math.max(number, min);
  2061. }
  2062. if (!isNaN(max)) {
  2063. number = Math.min(number, max);
  2064. }
  2065. return number;
  2066. },
  2067. /**
  2068. * Snaps the passed number between stopping points based upon a passed increment value.
  2069. * @param {Number} value The unsnapped value.
  2070. * @param {Number} increment The increment by which the value must move.
  2071. * @param {Number} minValue The minimum value to which the returned value must be constrained. Overrides the increment..
  2072. * @param {Number} maxValue The maximum value to which the returned value must be constrained. Overrides the increment..
  2073. * @return {Number} The value of the nearest snap target.
  2074. */
  2075. snap : function(value, increment, minValue, maxValue) {
  2076. var newValue = value,
  2077. m;
  2078. if (!(increment && value)) {
  2079. return value;
  2080. }
  2081. m = value % increment;
  2082. if (m !== 0) {
  2083. newValue -= m;
  2084. if (m * 2 >= increment) {
  2085. newValue += increment;
  2086. } else if (m * 2 < -increment) {
  2087. newValue -= increment;
  2088. }
  2089. }
  2090. return Ext.Number.constrain(newValue, minValue, maxValue);
  2091. },
  2092. /**
  2093. * Formats a number using fixed-point notation
  2094. * @param {Number} value The number to format
  2095. * @param {Number} precision The number of digits to show after the decimal point
  2096. */
  2097. toFixed: function(value, precision) {
  2098. if (isToFixedBroken) {
  2099. precision = precision || 0;
  2100. var pow = Math.pow(10, precision);
  2101. return (Math.round(value * pow) / pow).toFixed(precision);
  2102. }
  2103. return value.toFixed(precision);
  2104. },
  2105. /**
  2106. * Validate that a value is numeric and convert it to a number if necessary. Returns the specified default value if
  2107. * it is not.
  2108. Ext.Number.from('1.23', 1); // returns 1.23
  2109. Ext.Number.from('abc', 1); // returns 1
  2110. * @param {Object} value
  2111. * @param {Number} defaultValue The value to return if the original value is non-numeric
  2112. * @return {Number} value, if numeric, defaultValue otherwise
  2113. */
  2114. from: function(value, defaultValue) {
  2115. if (isFinite(value)) {
  2116. value = parseFloat(value);
  2117. }
  2118. return !isNaN(value) ? value : defaultValue;
  2119. }
  2120. };
  2121. })();
  2122. /**
  2123. * This method is deprecated, please use {@link Ext.Number#from Ext.Number.from} instead
  2124. *
  2125. * @deprecated 4.0.0 Replaced by Ext.Number.from
  2126. * @member Ext
  2127. * @method num
  2128. */
  2129. Ext.num = function() {
  2130. return Ext.Number.from.apply(this, arguments);
  2131. };
  2132. //@tag foundation,core
  2133. //@define Ext.Object
  2134. //@require Ext.Number
  2135. /**
  2136. * @author Jacky Nguyen <jacky@sencha.com>
  2137. * @docauthor Jacky Nguyen <jacky@sencha.com>
  2138. * @class Ext.Object
  2139. *
  2140. * A collection of useful static methods to deal with objects.
  2141. *
  2142. * @singleton
  2143. */
  2144. (function() {
  2145. // The "constructor" for chain:
  2146. var TemplateClass = function(){};
  2147. var ExtObject = Ext.Object = {
  2148. /**
  2149. * Returns a new object with the given object as the prototype chain.
  2150. * @param {Object} object The prototype chain for the new object.
  2151. */
  2152. chain: ('create' in Object) ? function(object){
  2153. return Object.create(object);
  2154. } : function (object) {
  2155. TemplateClass.prototype = object;
  2156. var result = new TemplateClass();
  2157. TemplateClass.prototype = null;
  2158. return result;
  2159. },
  2160. /**
  2161. * Convert a `name` - `value` pair to an array of objects with support for nested structures; useful to construct
  2162. * query strings. For example:
  2163. *
  2164. * Non-recursive:
  2165. *
  2166. * var objects = Ext.Object.toQueryObjects('hobbies', ['reading', 'cooking', 'swimming']);
  2167. *
  2168. * // objects then equals:
  2169. * [
  2170. * { name: 'hobbies', value: 'reading' },
  2171. * { name: 'hobbies', value: 'cooking' },
  2172. * { name: 'hobbies', value: 'swimming' }
  2173. * ]
  2174. *
  2175. * Recursive:
  2176. *
  2177. * var objects = Ext.Object.toQueryObjects('dateOfBirth', {
  2178. * day: 3,
  2179. * month: 8,
  2180. * year: 1987,
  2181. * extra: {
  2182. * hour: 4,
  2183. * minute: 30
  2184. * }
  2185. * }, true);
  2186. *
  2187. * // objects then equals:
  2188. * [
  2189. * { name: 'dateOfBirth[day]', value: 3 },
  2190. * { name: 'dateOfBirth[month]', value: 8 },
  2191. * { name: 'dateOfBirth[year]', value: 1987 },
  2192. * { name: 'dateOfBirth[extra][hour]', value: 4 },
  2193. * { name: 'dateOfBirth[extra][minute]', value: 30 }
  2194. * ]
  2195. *
  2196. * @param {String} name
  2197. * @param {Object} value
  2198. * @param {Boolean} [recursive=false] `true` to recursively encode any sub-objects.
  2199. * @return {Object[]} Array of objects with `name` and `value` fields.
  2200. */
  2201. toQueryObjects: function(name, value, recursive) {
  2202. var self = ExtObject.toQueryObjects,
  2203. objects = [],
  2204. i, ln;
  2205. if (Ext.isArray(value)) {
  2206. for (i = 0, ln = value.length; i < ln; i++) {
  2207. if (recursive) {
  2208. objects = objects.concat(self(name + '[' + i + ']', value[i], true));
  2209. }
  2210. else {
  2211. objects.push({
  2212. name: name,
  2213. value: value[i]
  2214. });
  2215. }
  2216. }
  2217. }
  2218. else if (Ext.isObject(value)) {
  2219. for (i in value) {
  2220. if (value.hasOwnProperty(i)) {
  2221. if (recursive) {
  2222. objects = objects.concat(self(name + '[' + i + ']', value[i], true));
  2223. }
  2224. else {
  2225. objects.push({
  2226. name: name,
  2227. value: value[i]
  2228. });
  2229. }
  2230. }
  2231. }
  2232. }
  2233. else {
  2234. objects.push({
  2235. name: name,
  2236. value: value
  2237. });
  2238. }
  2239. return objects;
  2240. },
  2241. /**
  2242. * Takes an object and converts it to an encoded query string.
  2243. *
  2244. * Non-recursive:
  2245. *
  2246. * Ext.Object.toQueryString({foo: 1, bar: 2}); // returns "foo=1&bar=2"
  2247. * Ext.Object.toQueryString({foo: null, bar: 2}); // returns "foo=&bar=2"
  2248. * Ext.Object.toQueryString({'some price': '$300'}); // returns "some%20price=%24300"
  2249. * Ext.Object.toQueryString({date: new Date(2011, 0, 1)}); // returns "date=%222011-01-01T00%3A00%3A00%22"
  2250. * Ext.Object.toQueryString({colors: ['red', 'green', 'blue']}); // returns "colors=red&colors=green&colors=blue"
  2251. *
  2252. * Recursive:
  2253. *
  2254. * Ext.Object.toQueryString({
  2255. * username: 'Jacky',
  2256. * dateOfBirth: {
  2257. * day: 1,
  2258. * month: 2,
  2259. * year: 1911
  2260. * },
  2261. * hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
  2262. * }, true);
  2263. *
  2264. * // returns the following string (broken down and url-decoded for ease of reading purpose):
  2265. * // username=Jacky
  2266. * // &dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911
  2267. * // &hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&hobbies[3][0]=nested&hobbies[3][1]=stuff
  2268. *
  2269. * @param {Object} object The object to encode.
  2270. * @param {Boolean} [recursive=false] Whether or not to interpret the object in recursive format.
  2271. * (PHP / Ruby on Rails servers and similar).
  2272. * @return {String} queryString
  2273. */
  2274. toQueryString: function(object, recursive) {
  2275. var paramObjects = [],
  2276. params = [],
  2277. i, j, ln, paramObject, value;
  2278. for (i in object) {
  2279. if (object.hasOwnProperty(i)) {
  2280. paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
  2281. }
  2282. }
  2283. for (j = 0, ln = paramObjects.length; j < ln; j++) {
  2284. paramObject = paramObjects[j];
  2285. value = paramObject.value;
  2286. if (Ext.isEmpty(value)) {
  2287. value = '';
  2288. }
  2289. else if (Ext.isDate(value)) {
  2290. value = Ext.Date.toString(value);
  2291. }
  2292. params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
  2293. }
  2294. return params.join('&');
  2295. },
  2296. /**
  2297. * Converts a query string back into an object.
  2298. *
  2299. * Non-recursive:
  2300. *
  2301. * Ext.Object.fromQueryString("foo=1&bar=2"); // returns {foo: 1, bar: 2}
  2302. * Ext.Object.fromQueryString("foo=&bar=2"); // returns {foo: null, bar: 2}
  2303. * Ext.Object.fromQueryString("some%20price=%24300"); // returns {'some price': '$300'}
  2304. * Ext.Object.fromQueryString("colors=red&colors=green&colors=blue"); // returns {colors: ['red', 'green', 'blue']}
  2305. *
  2306. * Recursive:
  2307. *
  2308. * Ext.Object.fromQueryString("username=Jacky&dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911&hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&hobbies[3][0]=nested&hobbies[3][1]=stuff", true);
  2309. *
  2310. * // returns
  2311. * {
  2312. * username: 'Jacky',
  2313. * dateOfBirth: {
  2314. * day: '1',
  2315. * month: '2',
  2316. * year: '1911'
  2317. * },
  2318. * hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
  2319. * }
  2320. *
  2321. * @param {String} queryString The query string to decode.
  2322. * @param {Boolean} [recursive=false] Whether or not to recursively decode the string. This format is supported by
  2323. * PHP / Ruby on Rails servers and similar.
  2324. * @return {Object}
  2325. */
  2326. fromQueryString: function(queryString, recursive) {
  2327. var parts = queryString.replace(/^\?/, '').split('&'),
  2328. object = {},
  2329. temp, components, name, value, i, ln,
  2330. part, j, subLn, matchedKeys, matchedName,
  2331. keys, key, nextKey;
  2332. for (i = 0, ln = parts.length; i < ln; i++) {
  2333. part = parts[i];
  2334. if (part.length > 0) {
  2335. components = part.split('=');
  2336. name = decodeURIComponent(components[0]);
  2337. value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
  2338. if (!recursive) {
  2339. if (object.hasOwnProperty(name)) {
  2340. if (!Ext.isArray(object[name])) {
  2341. object[name] = [object[name]];
  2342. }
  2343. object[name].push(value);
  2344. }
  2345. else {
  2346. object[name] = value;
  2347. }
  2348. }
  2349. else {
  2350. matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
  2351. matchedName = name.match(/^([^\[]+)/);
  2352. //<debug error>
  2353. if (!matchedName) {
  2354. throw new Error('[Ext.Object.fromQueryString] Malformed query string given, failed parsing name from "' + part + '"');
  2355. }
  2356. //</debug>
  2357. name = matchedName[0];
  2358. keys = [];
  2359. if (matchedKeys === null) {
  2360. object[name] = value;
  2361. continue;
  2362. }
  2363. for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
  2364. key = matchedKeys[j];
  2365. key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
  2366. keys.push(key);
  2367. }
  2368. keys.unshift(name);
  2369. temp = object;
  2370. for (j = 0, subLn = keys.length; j < subLn; j++) {
  2371. key = keys[j];
  2372. if (j === subLn - 1) {
  2373. if (Ext.isArray(temp) && key === '') {
  2374. temp.push(value);
  2375. }
  2376. else {
  2377. temp[key] = value;
  2378. }
  2379. }
  2380. else {
  2381. if (temp[key] === undefined || typeof temp[key] === 'string') {
  2382. nextKey = keys[j+1];
  2383. temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
  2384. }
  2385. temp = temp[key];
  2386. }
  2387. }
  2388. }
  2389. }
  2390. }
  2391. return object;
  2392. },
  2393. /**
  2394. * Iterate through an object and invoke the given callback function for each iteration. The iteration can be stop
  2395. * by returning `false` in the callback function. For example:
  2396. *
  2397. * var person = {
  2398. * name: 'Jacky',
  2399. * hairColor: 'black',
  2400. * loves: ['food', 'sleeping', 'wife']
  2401. * };
  2402. *
  2403. * Ext.Object.each(person, function(key, value, myself) {
  2404. * console.log(key + ":" + value);
  2405. *
  2406. * if (key === 'hairColor') {
  2407. * return false; // stop the iteration
  2408. * }
  2409. * });
  2410. *
  2411. * @param {Object} object The object to iterate
  2412. * @param {Function} fn The callback function.
  2413. * @param {String} fn.key
  2414. * @param {Mixed} fn.value
  2415. * @param {Object} fn.object The object itself
  2416. * @param {Object} [scope] The execution scope (`this`) of the callback function
  2417. */
  2418. each: function(object, fn, scope) {
  2419. for (var property in object) {
  2420. if (object.hasOwnProperty(property)) {
  2421. if (fn.call(scope || object, property, object[property], object) === false) {
  2422. return;
  2423. }
  2424. }
  2425. }
  2426. },
  2427. /**
  2428. * Merges any number of objects recursively without referencing them or their children.
  2429. *
  2430. * var extjs = {
  2431. * companyName: 'Ext JS',
  2432. * products: ['Ext JS', 'Ext GWT', 'Ext Designer'],
  2433. * isSuperCool: true,
  2434. * office: {
  2435. * size: 2000,
  2436. * location: 'Palo Alto',
  2437. * isFun: true
  2438. * }
  2439. * };
  2440. *
  2441. * var newStuff = {
  2442. * companyName: 'Sencha Inc.',
  2443. * products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
  2444. * office: {
  2445. * size: 40000,
  2446. * location: 'Redwood City'
  2447. * }
  2448. * };
  2449. *
  2450. * var sencha = Ext.Object.merge({}, extjs, newStuff);
  2451. *
  2452. * // sencha then equals to
  2453. * {
  2454. * companyName: 'Sencha Inc.',
  2455. * products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
  2456. * isSuperCool: true
  2457. * office: {
  2458. * size: 40000,
  2459. * location: 'Redwood City'
  2460. * isFun: true
  2461. * }
  2462. * }
  2463. *
  2464. * @param {Object} source The first object into which to merge the others.
  2465. * @param {Object...} objs One or more objects to be merged into the first.
  2466. * @return {Object} The object that is created as a result of merging all the objects passed in.
  2467. */
  2468. merge: function(source) {
  2469. var i = 1,
  2470. ln = arguments.length,
  2471. mergeFn = ExtObject.merge,
  2472. cloneFn = Ext.clone,
  2473. object, key, value, sourceKey;
  2474. for (; i < ln; i++) {
  2475. object = arguments[i];
  2476. for (key in object) {
  2477. value = object[key];
  2478. if (value && value.constructor === Object) {
  2479. sourceKey = source[key];
  2480. if (sourceKey && sourceKey.constructor === Object) {
  2481. mergeFn(sourceKey, value);
  2482. }
  2483. else {
  2484. source[key] = cloneFn(value);
  2485. }
  2486. }
  2487. else {
  2488. source[key] = value;
  2489. }
  2490. }
  2491. }
  2492. return source;
  2493. },
  2494. /**
  2495. * @private
  2496. * @param source
  2497. */
  2498. mergeIf: function(source) {
  2499. var i = 1,
  2500. ln = arguments.length,
  2501. cloneFn = Ext.clone,
  2502. object, key, value;
  2503. for (; i < ln; i++) {
  2504. object = arguments[i];
  2505. for (key in object) {
  2506. if (!(key in source)) {
  2507. value = object[key];
  2508. if (value && value.constructor === Object) {
  2509. source[key] = cloneFn(value);
  2510. }
  2511. else {
  2512. source[key] = value;
  2513. }
  2514. }
  2515. }
  2516. }
  2517. return source;
  2518. },
  2519. /**
  2520. * Returns the first matching key corresponding to the given value.
  2521. * If no matching value is found, `null` is returned.
  2522. *
  2523. * var person = {
  2524. * name: 'Jacky',
  2525. * loves: 'food'
  2526. * };
  2527. *
  2528. * alert(Ext.Object.getKey(sencha, 'food')); // alerts 'loves'
  2529. *
  2530. * @param {Object} object
  2531. * @param {Object} value The value to find
  2532. */
  2533. getKey: function(object, value) {
  2534. for (var property in object) {
  2535. if (object.hasOwnProperty(property) && object[property] === value) {
  2536. return property;
  2537. }
  2538. }
  2539. return null;
  2540. },
  2541. /**
  2542. * Gets all values of the given object as an array.
  2543. *
  2544. * var values = Ext.Object.getValues({
  2545. * name: 'Jacky',
  2546. * loves: 'food'
  2547. * }); // ['Jacky', 'food']
  2548. *
  2549. * @param {Object} object
  2550. * @return {Array} An array of values from the object.
  2551. */
  2552. getValues: function(object) {
  2553. var values = [],
  2554. property;
  2555. for (property in object) {
  2556. if (object.hasOwnProperty(property)) {
  2557. values.push(object[property]);
  2558. }
  2559. }
  2560. return values;
  2561. },
  2562. /**
  2563. * Gets all keys of the given object as an array.
  2564. *
  2565. * var values = Ext.Object.getKeys({
  2566. * name: 'Jacky',
  2567. * loves: 'food'
  2568. * }); // ['name', 'loves']
  2569. *
  2570. * @param {Object} object
  2571. * @return {String[]} An array of keys from the object.
  2572. * @method
  2573. */
  2574. getKeys: ('keys' in Object) ? Object.keys : function(object) {
  2575. var keys = [],
  2576. property;
  2577. for (property in object) {
  2578. if (object.hasOwnProperty(property)) {
  2579. keys.push(property);
  2580. }
  2581. }
  2582. return keys;
  2583. },
  2584. /**
  2585. * Gets the total number of this object's own properties.
  2586. *
  2587. * var size = Ext.Object.getSize({
  2588. * name: 'Jacky',
  2589. * loves: 'food'
  2590. * }); // size equals 2
  2591. *
  2592. * @param {Object} object
  2593. * @return {Number} size
  2594. */
  2595. getSize: function(object) {
  2596. var size = 0,
  2597. property;
  2598. for (property in object) {
  2599. if (object.hasOwnProperty(property)) {
  2600. size++;
  2601. }
  2602. }
  2603. return size;
  2604. },
  2605. /**
  2606. * @private
  2607. */
  2608. classify: function(object) {
  2609. var objectProperties = [],
  2610. arrayProperties = [],
  2611. propertyClassesMap = {},
  2612. objectClass = function() {
  2613. var i = 0,
  2614. ln = objectProperties.length,
  2615. property;
  2616. for (; i < ln; i++) {
  2617. property = objectProperties[i];
  2618. this[property] = new propertyClassesMap[property];
  2619. }
  2620. ln = arrayProperties.length;
  2621. for (i = 0; i < ln; i++) {
  2622. property = arrayProperties[i];
  2623. this[property] = object[property].slice();
  2624. }
  2625. },
  2626. key, value, constructor;
  2627. for (key in object) {
  2628. if (object.hasOwnProperty(key)) {
  2629. value = object[key];
  2630. if (value) {
  2631. constructor = value.constructor;
  2632. if (constructor === Object) {
  2633. objectProperties.push(key);
  2634. propertyClassesMap[key] = ExtObject.classify(value);
  2635. }
  2636. else if (constructor === Array) {
  2637. arrayProperties.push(key);
  2638. }
  2639. }
  2640. }
  2641. }
  2642. objectClass.prototype = object;
  2643. return objectClass;
  2644. },
  2645. defineProperty: ('defineProperty' in Object) ? Object.defineProperty : function(object, name, descriptor) {
  2646. if (descriptor.get) {
  2647. object.__defineGetter__(name, descriptor.get);
  2648. }
  2649. if (descriptor.set) {
  2650. object.__defineSetter__(name, descriptor.set);
  2651. }
  2652. }
  2653. };
  2654. /**
  2655. * A convenient alias method for {@link Ext.Object#merge}.
  2656. *
  2657. * @member Ext
  2658. * @method merge
  2659. */
  2660. Ext.merge = Ext.Object.merge;
  2661. /**
  2662. * @private
  2663. */
  2664. Ext.mergeIf = Ext.Object.mergeIf;
  2665. /**
  2666. * A convenient alias method for {@link Ext.Object#toQueryString}.
  2667. *
  2668. * @member Ext
  2669. * @method urlEncode
  2670. * @deprecated 4.0.0 Please use `{@link Ext.Object#toQueryString Ext.Object.toQueryString}` instead
  2671. */
  2672. Ext.urlEncode = function() {
  2673. var args = Ext.Array.from(arguments),
  2674. prefix = '';
  2675. // Support for the old `pre` argument
  2676. if ((typeof args[1] === 'string')) {
  2677. prefix = args[1] + '&';
  2678. args[1] = false;
  2679. }
  2680. return prefix + ExtObject.toQueryString.apply(ExtObject, args);
  2681. };
  2682. /**
  2683. * A convenient alias method for {@link Ext.Object#fromQueryString}.
  2684. *
  2685. * @member Ext
  2686. * @method urlDecode
  2687. * @deprecated 4.0.0 Please use {@link Ext.Object#fromQueryString Ext.Object.fromQueryString} instead
  2688. */
  2689. Ext.urlDecode = function() {
  2690. return ExtObject.fromQueryString.apply(ExtObject, arguments);
  2691. };
  2692. })();
  2693. //@tag foundation,core
  2694. //@define Ext.Function
  2695. //@require Ext.Object
  2696. /**
  2697. * @class Ext.Function
  2698. *
  2699. * A collection of useful static methods to deal with function callbacks.
  2700. * @singleton
  2701. * @alternateClassName Ext.util.Functions
  2702. */
  2703. Ext.Function = {
  2704. /**
  2705. * A very commonly used method throughout the framework. It acts as a wrapper around another method
  2706. * which originally accepts 2 arguments for `name` and `value`.
  2707. * The wrapped function then allows "flexible" value setting of either:
  2708. *
  2709. * - `name` and `value` as 2 arguments
  2710. * - one single object argument with multiple key - value pairs
  2711. *
  2712. * For example:
  2713. *
  2714. * var setValue = Ext.Function.flexSetter(function(name, value) {
  2715. * this[name] = value;
  2716. * });
  2717. *
  2718. * // Afterwards
  2719. * // Setting a single name - value
  2720. * setValue('name1', 'value1');
  2721. *
  2722. * // Settings multiple name - value pairs
  2723. * setValue({
  2724. * name1: 'value1',
  2725. * name2: 'value2',
  2726. * name3: 'value3'
  2727. * });
  2728. *
  2729. * @param {Function} setter
  2730. * @return {Function} flexSetter
  2731. */
  2732. flexSetter: function(fn) {
  2733. return function(a, b) {
  2734. var k, i;
  2735. if (a === null) {
  2736. return this;
  2737. }
  2738. if (typeof a !== 'string') {
  2739. for (k in a) {
  2740. if (a.hasOwnProperty(k)) {
  2741. fn.call(this, k, a[k]);
  2742. }
  2743. }
  2744. if (Ext.enumerables) {
  2745. for (i = Ext.enumerables.length; i--;) {
  2746. k = Ext.enumerables[i];
  2747. if (a.hasOwnProperty(k)) {
  2748. fn.call(this, k, a[k]);
  2749. }
  2750. }
  2751. }
  2752. } else {
  2753. fn.call(this, a, b);
  2754. }
  2755. return this;
  2756. };
  2757. },
  2758. /**
  2759. * Create a new function from the provided `fn`, change `this` to the provided scope, optionally
  2760. * overrides arguments for the call. Defaults to the arguments passed by the caller.
  2761. *
  2762. * {@link Ext#bind Ext.bind} is alias for {@link Ext.Function#bind Ext.Function.bind}
  2763. *
  2764. * @param {Function} fn The function to delegate.
  2765. * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
  2766. * **If omitted, defaults to the browser window.**
  2767. * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
  2768. * @param {Boolean/Number} appendArgs (optional) if `true` args are appended to call args instead of overriding,
  2769. * if a number the args are inserted at the specified position.
  2770. * @return {Function} The new function.
  2771. */
  2772. bind: function(fn, scope, args, appendArgs) {
  2773. if (arguments.length === 2) {
  2774. return function() {
  2775. return fn.apply(scope, arguments);
  2776. }
  2777. }
  2778. var method = fn,
  2779. slice = Array.prototype.slice;
  2780. return function() {
  2781. var callArgs = args || arguments;
  2782. if (appendArgs === true) {
  2783. callArgs = slice.call(arguments, 0);
  2784. callArgs = callArgs.concat(args);
  2785. }
  2786. else if (typeof appendArgs == 'number') {
  2787. callArgs = slice.call(arguments, 0); // copy arguments first
  2788. Ext.Array.insert(callArgs, appendArgs, args);
  2789. }
  2790. return method.apply(scope || window, callArgs);
  2791. };
  2792. },
  2793. /**
  2794. * Create a new function from the provided `fn`, the arguments of which are pre-set to `args`.
  2795. * New arguments passed to the newly created callback when it's invoked are appended after the pre-set ones.
  2796. * This is especially useful when creating callbacks.
  2797. *
  2798. * For example:
  2799. *
  2800. * var originalFunction = function(){
  2801. * alert(Ext.Array.from(arguments).join(' '));
  2802. * };
  2803. *
  2804. * var callback = Ext.Function.pass(originalFunction, ['Hello', 'World']);
  2805. *
  2806. * callback(); // alerts 'Hello World'
  2807. * callback('by Me'); // alerts 'Hello World by Me'
  2808. *
  2809. * {@link Ext#pass Ext.pass} is alias for {@link Ext.Function#pass Ext.Function.pass}
  2810. *
  2811. * @param {Function} fn The original function.
  2812. * @param {Array} args The arguments to pass to new callback.
  2813. * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
  2814. * @return {Function} The new callback function.
  2815. */
  2816. pass: function(fn, args, scope) {
  2817. if (!Ext.isArray(args)) {
  2818. args = Ext.Array.clone(args);
  2819. }
  2820. return function() {
  2821. args.push.apply(args, arguments);
  2822. return fn.apply(scope || this, args);
  2823. };
  2824. },
  2825. /**
  2826. * Create an alias to the provided method property with name `methodName` of `object`.
  2827. * Note that the execution scope will still be bound to the provided `object` itself.
  2828. *
  2829. * @param {Object/Function} object
  2830. * @param {String} methodName
  2831. * @return {Function} aliasFn
  2832. */
  2833. alias: function(object, methodName) {
  2834. return function() {
  2835. return object[methodName].apply(object, arguments);
  2836. };
  2837. },
  2838. /**
  2839. * Create a "clone" of the provided method. The returned method will call the given
  2840. * method passing along all arguments and the "this" pointer and return its result.
  2841. *
  2842. * @param {Function} method
  2843. * @return {Function} cloneFn
  2844. */
  2845. clone: function(method) {
  2846. return function() {
  2847. return method.apply(this, arguments);
  2848. };
  2849. },
  2850. /**
  2851. * Creates an interceptor function. The passed function is called before the original one. If it returns false,
  2852. * the original one is not called. The resulting function returns the results of the original function.
  2853. * The passed function is called with the parameters of the original function. Example usage:
  2854. *
  2855. * var sayHi = function(name){
  2856. * alert('Hi, ' + name);
  2857. * };
  2858. *
  2859. * sayHi('Fred'); // alerts "Hi, Fred"
  2860. *
  2861. * // create a new function that validates input without
  2862. * // directly modifying the original function:
  2863. * var sayHiToFriend = Ext.Function.createInterceptor(sayHi, function(name){
  2864. * return name === 'Brian';
  2865. * });
  2866. *
  2867. * sayHiToFriend('Fred'); // no alert
  2868. * sayHiToFriend('Brian'); // alerts "Hi, Brian"
  2869. *
  2870. * @param {Function} origFn The original function.
  2871. * @param {Function} newFn The function to call before the original.
  2872. * @param {Object} scope (optional) The scope (`this` reference) in which the passed function is executed.
  2873. * **If omitted, defaults to the scope in which the original function is called or the browser window.**
  2874. * @param {Object} [returnValue=null] (optional) The value to return if the passed function return `false`.
  2875. * @return {Function} The new function.
  2876. */
  2877. createInterceptor: function(origFn, newFn, scope, returnValue) {
  2878. var method = origFn;
  2879. if (!Ext.isFunction(newFn)) {
  2880. return origFn;
  2881. }
  2882. else {
  2883. return function() {
  2884. var me = this,
  2885. args = arguments;
  2886. newFn.target = me;
  2887. newFn.method = origFn;
  2888. return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
  2889. };
  2890. }
  2891. },
  2892. /**
  2893. * Creates a delegate (callback) which, when called, executes after a specific delay.
  2894. *
  2895. * @param {Function} fn The function which will be called on a delay when the returned function is called.
  2896. * Optionally, a replacement (or additional) argument list may be specified.
  2897. * @param {Number} delay The number of milliseconds to defer execution by whenever called.
  2898. * @param {Object} scope (optional) The scope (`this` reference) used by the function at execution time.
  2899. * @param {Array} args (optional) Override arguments for the call. (Defaults to the arguments passed by the caller)
  2900. * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
  2901. * if a number the args are inserted at the specified position.
  2902. * @return {Function} A function which, when called, executes the original function after the specified delay.
  2903. */
  2904. createDelayed: function(fn, delay, scope, args, appendArgs) {
  2905. if (scope || args) {
  2906. fn = Ext.Function.bind(fn, scope, args, appendArgs);
  2907. }
  2908. return function() {
  2909. var me = this,
  2910. args = Array.prototype.slice.call(arguments);
  2911. setTimeout(function() {
  2912. fn.apply(me, args);
  2913. }, delay);
  2914. }
  2915. },
  2916. /**
  2917. * Calls this function after the number of milliseconds specified, optionally in a specific scope. Example usage:
  2918. *
  2919. * var sayHi = function(name){
  2920. * alert('Hi, ' + name);
  2921. * };
  2922. *
  2923. * // executes immediately:
  2924. * sayHi('Fred');
  2925. *
  2926. * // executes after 2 seconds:
  2927. * Ext.Function.defer(sayHi, 2000, this, ['Fred']);
  2928. *
  2929. * // this syntax is sometimes useful for deferring
  2930. * // execution of an anonymous function:
  2931. * Ext.Function.defer(function(){
  2932. * alert('Anonymous');
  2933. * }, 100);
  2934. *
  2935. * {@link Ext#defer Ext.defer} is alias for {@link Ext.Function#defer Ext.Function.defer}
  2936. *
  2937. * @param {Function} fn The function to defer.
  2938. * @param {Number} millis The number of milliseconds for the `setTimeout()` call.
  2939. * If less than or equal to 0 the function is executed immediately.
  2940. * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
  2941. * If omitted, defaults to the browser window.
  2942. * @param {Array} args (optional) Overrides arguments for the call. Defaults to the arguments passed by the caller.
  2943. * @param {Boolean/Number} appendArgs (optional) if `true`, args are appended to call args instead of overriding,
  2944. * if a number the args are inserted at the specified position.
  2945. * @return {Number} The timeout id that can be used with `clearTimeout()`.
  2946. */
  2947. defer: function(fn, millis, scope, args, appendArgs) {
  2948. fn = Ext.Function.bind(fn, scope, args, appendArgs);
  2949. if (millis > 0) {
  2950. return setTimeout(fn, millis);
  2951. }
  2952. fn();
  2953. return 0;
  2954. },
  2955. /**
  2956. * Create a combined function call sequence of the original function + the passed function.
  2957. * The resulting function returns the results of the original function.
  2958. * The passed function is called with the parameters of the original function. Example usage:
  2959. *
  2960. * var sayHi = function(name){
  2961. * alert('Hi, ' + name);
  2962. * };
  2963. *
  2964. * sayHi('Fred'); // alerts "Hi, Fred"
  2965. *
  2966. * var sayGoodbye = Ext.Function.createSequence(sayHi, function(name){
  2967. * alert('Bye, ' + name);
  2968. * });
  2969. *
  2970. * sayGoodbye('Fred'); // both alerts show
  2971. *
  2972. * @param {Function} originalFn The original function.
  2973. * @param {Function} newFn The function to sequence.
  2974. * @param {Object} scope (optional) The scope (`this` reference) in which the passed function is executed.
  2975. * If omitted, defaults to the scope in which the original function is called or the browser window.
  2976. * @return {Function} The new function.
  2977. */
  2978. createSequence: function(originalFn, newFn, scope) {
  2979. if (!newFn) {
  2980. return originalFn;
  2981. }
  2982. else {
  2983. return function() {
  2984. var result = originalFn.apply(this, arguments);
  2985. newFn.apply(scope || this, arguments);
  2986. return result;
  2987. };
  2988. }
  2989. },
  2990. /**
  2991. * Creates a delegate function, optionally with a bound scope which, when called, buffers
  2992. * the execution of the passed function for the configured number of milliseconds.
  2993. * If called again within that period, the impending invocation will be canceled, and the
  2994. * timeout period will begin again.
  2995. *
  2996. * @param {Function} fn The function to invoke on a buffered timer.
  2997. * @param {Number} buffer The number of milliseconds by which to buffer the invocation of the
  2998. * function.
  2999. * @param {Object} scope (optional) The scope (`this` reference) in which
  3000. * the passed function is executed. If omitted, defaults to the scope specified by the caller.
  3001. * @param {Array} args (optional) Override arguments for the call. Defaults to the arguments
  3002. * passed by the caller.
  3003. * @return {Function} A function which invokes the passed function after buffering for the specified time.
  3004. */
  3005. createBuffered: function(fn, buffer, scope, args) {
  3006. var timerId;
  3007. return function() {
  3008. var callArgs = args || Array.prototype.slice.call(arguments, 0),
  3009. me = scope || this;
  3010. if (timerId) {
  3011. clearTimeout(timerId);
  3012. }
  3013. timerId = setTimeout(function(){
  3014. fn.apply(me, callArgs);
  3015. }, buffer);
  3016. };
  3017. },
  3018. /**
  3019. * Creates a throttled version of the passed function which, when called repeatedly and
  3020. * rapidly, invokes the passed function only after a certain interval has elapsed since the
  3021. * previous invocation.
  3022. *
  3023. * This is useful for wrapping functions which may be called repeatedly, such as
  3024. * a handler of a mouse move event when the processing is expensive.
  3025. *
  3026. * @param {Function} fn The function to execute at a regular time interval.
  3027. * @param {Number} interval The interval, in milliseconds, on which the passed function is executed.
  3028. * @param {Object} scope (optional) The scope (`this` reference) in which
  3029. * the passed function is executed. If omitted, defaults to the scope specified by the caller.
  3030. * @return {Function} A function which invokes the passed function at the specified interval.
  3031. */
  3032. createThrottled: function(fn, interval, scope) {
  3033. var lastCallTime, elapsed, lastArgs, timer, execute = function() {
  3034. fn.apply(scope || this, lastArgs);
  3035. lastCallTime = new Date().getTime();
  3036. };
  3037. return function() {
  3038. elapsed = new Date().getTime() - lastCallTime;
  3039. lastArgs = arguments;
  3040. clearTimeout(timer);
  3041. if (!lastCallTime || (elapsed >= interval)) {
  3042. execute();
  3043. } else {
  3044. timer = setTimeout(execute, interval - elapsed);
  3045. }
  3046. };
  3047. },
  3048. interceptBefore: function(object, methodName, fn) {
  3049. var method = object[methodName] || Ext.emptyFn;
  3050. return object[methodName] = function() {
  3051. var ret = fn.apply(this, arguments);
  3052. method.apply(this, arguments);
  3053. return ret;
  3054. };
  3055. },
  3056. interceptAfter: function(object, methodName, fn) {
  3057. var method = object[methodName] || Ext.emptyFn;
  3058. return object[methodName] = function() {
  3059. method.apply(this, arguments);
  3060. return fn.apply(this, arguments);
  3061. };
  3062. }
  3063. };
  3064. /**
  3065. * @method
  3066. * @member Ext
  3067. * @alias Ext.Function#defer
  3068. */
  3069. Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
  3070. /**
  3071. * @method
  3072. * @member Ext
  3073. * @alias Ext.Function#pass
  3074. */
  3075. Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
  3076. /**
  3077. * @method
  3078. * @member Ext
  3079. * @alias Ext.Function#bind
  3080. */
  3081. Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
  3082. //@tag foundation,core
  3083. //@define Ext.JSON
  3084. //@require Ext.Function
  3085. /**
  3086. * @class Ext.JSON
  3087. * Modified version of Douglas Crockford's json.js that doesn't
  3088. * mess with the Object prototype.
  3089. * [http://www.json.org/js.html](http://www.json.org/js.html)
  3090. * @singleton
  3091. */
  3092. Ext.JSON = new(function() {
  3093. var useHasOwn = !! {}.hasOwnProperty,
  3094. isNative = function() {
  3095. var useNative = null;
  3096. return function() {
  3097. if (useNative === null) {
  3098. useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
  3099. }
  3100. return useNative;
  3101. };
  3102. }(),
  3103. pad = function(n) {
  3104. return n < 10 ? "0" + n : n;
  3105. },
  3106. doDecode = function(json) {
  3107. return eval("(" + json + ')');
  3108. },
  3109. doEncode = function(o) {
  3110. if (!Ext.isDefined(o) || o === null) {
  3111. return "null";
  3112. } else if (Ext.isArray(o)) {
  3113. return encodeArray(o);
  3114. } else if (Ext.isDate(o)) {
  3115. return Ext.JSON.encodeDate(o);
  3116. } else if (Ext.isString(o)) {
  3117. return encodeString(o);
  3118. } else if (typeof o == "number") {
  3119. //don't use isNumber here, since finite checks happen inside isNumber
  3120. return isFinite(o) ? String(o) : "null";
  3121. } else if (Ext.isBoolean(o)) {
  3122. return String(o);
  3123. } else if (Ext.isObject(o)) {
  3124. return encodeObject(o);
  3125. } else if (typeof o === "function") {
  3126. return "null";
  3127. }
  3128. return 'undefined';
  3129. },
  3130. m = {
  3131. "\b": '\\b',
  3132. "\t": '\\t',
  3133. "\n": '\\n',
  3134. "\f": '\\f',
  3135. "\r": '\\r',
  3136. '"': '\\"',
  3137. "\\": '\\\\',
  3138. '\x0b': '\\u000b' //ie doesn't handle \v
  3139. },
  3140. charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g,
  3141. encodeString = function(s) {
  3142. return '"' + s.replace(charToReplace, function(a) {
  3143. var c = m[a];
  3144. return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
  3145. }) + '"';
  3146. },
  3147. encodeArray = function(o) {
  3148. var a = ["[", ""],
  3149. // Note empty string in case there are no serializable members.
  3150. len = o.length,
  3151. i;
  3152. for (i = 0; i < len; i += 1) {
  3153. a.push(doEncode(o[i]), ',');
  3154. }
  3155. // Overwrite trailing comma (or empty string)
  3156. a[a.length - 1] = ']';
  3157. return a.join("");
  3158. },
  3159. encodeObject = function(o) {
  3160. var a = ["{", ""],
  3161. // Note empty string in case there are no serializable members.
  3162. i;
  3163. for (i in o) {
  3164. if (!useHasOwn || o.hasOwnProperty(i)) {
  3165. a.push(doEncode(i), ":", doEncode(o[i]), ',');
  3166. }
  3167. }
  3168. // Overwrite trailing comma (or empty string)
  3169. a[a.length - 1] = '}';
  3170. return a.join("");
  3171. };
  3172. /**
  3173. * Encodes a Date. This returns the actual string which is inserted into the JSON string as the literal expression.
  3174. * __The returned value includes enclosing double quotation marks.__
  3175. *
  3176. * The default return format is "yyyy-mm-ddThh:mm:ss".
  3177. *
  3178. * To override this:
  3179. *
  3180. * Ext.JSON.encodeDate = function(d) {
  3181. * return Ext.Date.format(d, '"Y-m-d"');
  3182. * };
  3183. *
  3184. * @param {Date} d The Date to encode.
  3185. * @return {String} The string literal to use in a JSON string.
  3186. */
  3187. this.encodeDate = function(o) {
  3188. return '"' + o.getFullYear() + "-"
  3189. + pad(o.getMonth() + 1) + "-"
  3190. + pad(o.getDate()) + "T"
  3191. + pad(o.getHours()) + ":"
  3192. + pad(o.getMinutes()) + ":"
  3193. + pad(o.getSeconds()) + '"';
  3194. };
  3195. /**
  3196. * Encodes an Object, Array or other value.
  3197. * @param {Object} o The variable to encode.
  3198. * @return {String} The JSON string.
  3199. * @method
  3200. */
  3201. this.encode = function() {
  3202. var ec;
  3203. return function(o) {
  3204. if (!ec) {
  3205. // setup encoding function on first access
  3206. ec = isNative() ? JSON.stringify : doEncode;
  3207. }
  3208. return ec(o);
  3209. };
  3210. }();
  3211. /**
  3212. * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a Error unless the safe option is set.
  3213. * @param {String} json The JSON string.
  3214. * @param {Boolean} safe (optional) Whether to return `null` or throw an exception if the JSON is invalid.
  3215. * @return {Object/null} The resulting object.
  3216. * @method
  3217. */
  3218. this.decode = function() {
  3219. var dc;
  3220. return function(json, safe) {
  3221. if (!dc) {
  3222. // setup decoding function on first access
  3223. dc = isNative() ? JSON.parse : doDecode;
  3224. }
  3225. try {
  3226. return dc(json);
  3227. } catch (e) {
  3228. if (safe === true) {
  3229. return null;
  3230. }
  3231. Ext.Error.raise({
  3232. sourceClass: "Ext.JSON",
  3233. sourceMethod: "decode",
  3234. msg: "You're trying to decode an invalid JSON String: " + json
  3235. });
  3236. }
  3237. };
  3238. }();
  3239. })();
  3240. /**
  3241. * Shorthand for {@link Ext.JSON#encode}.
  3242. * @member Ext
  3243. * @method encode
  3244. * @alias Ext.JSON#encode
  3245. */
  3246. Ext.encode = Ext.JSON.encode;
  3247. /**
  3248. * Shorthand for {@link Ext.JSON#decode}.
  3249. * @member Ext
  3250. * @method decode
  3251. * @alias Ext.JSON#decode
  3252. */
  3253. Ext.decode = Ext.JSON.decode;
  3254. //@tag foundation,core
  3255. //@define Ext.Error
  3256. //@require Ext.JSON
  3257. Ext.Error = {
  3258. raise: function(object) {
  3259. throw new Error(object.msg);
  3260. }
  3261. };
  3262. //@tag foundation,core
  3263. //@define Ext.Date
  3264. //@require Ext.Error
  3265. /**
  3266. *
  3267. */
  3268. Ext.Date = {
  3269. /** @ignore */
  3270. now: Date.now,
  3271. /**
  3272. * @private
  3273. * Private for now
  3274. */
  3275. toString: function(date) {
  3276. if (!date) {
  3277. date = new Date();
  3278. }
  3279. var pad = Ext.String.leftPad;
  3280. return date.getFullYear() + "-"
  3281. + pad(date.getMonth() + 1, 2, '0') + "-"
  3282. + pad(date.getDate(), 2, '0') + "T"
  3283. + pad(date.getHours(), 2, '0') + ":"
  3284. + pad(date.getMinutes(), 2, '0') + ":"
  3285. + pad(date.getSeconds(), 2, '0');
  3286. }
  3287. };
  3288. //@tag foundation,core
  3289. //@define Ext.Base
  3290. //@require Ext.Date
  3291. /**
  3292. * @class Ext.Base
  3293. *
  3294. * @author Jacky Nguyen <jacky@sencha.com>
  3295. * @aside guide class_system
  3296. * @aside video class-system
  3297. *
  3298. * The root of all classes created with {@link Ext#define}.
  3299. *
  3300. * Ext.Base is the building block of all Ext classes. All classes in Ext inherit from Ext.Base. All prototype and static
  3301. * members of this class are inherited by all other classes.
  3302. *
  3303. * See the [Class System Guide](#!/guide/class_system) for more.
  3304. *
  3305. */
  3306. (function(flexSetter) {
  3307. var noArgs = [],
  3308. Base = function(){};
  3309. // These static properties will be copied to every newly created class with {@link Ext#define}
  3310. Ext.apply(Base, {
  3311. $className: 'Ext.Base',
  3312. $isClass: true,
  3313. /**
  3314. * Create a new instance of this Class.
  3315. *
  3316. * Ext.define('My.cool.Class', {
  3317. * // ...
  3318. * });
  3319. *
  3320. * My.cool.Class.create({
  3321. * someConfig: true
  3322. * });
  3323. *
  3324. * All parameters are passed to the constructor of the class.
  3325. *
  3326. * @return {Object} the created instance.
  3327. * @static
  3328. * @inheritable
  3329. */
  3330. create: function() {
  3331. return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
  3332. },
  3333. /**
  3334. * @private
  3335. * @static
  3336. * @inheritable
  3337. */
  3338. extend: function(parent) {
  3339. var parentPrototype = parent.prototype,
  3340. prototype, i, ln, name, statics;
  3341. prototype = this.prototype = Ext.Object.chain(parentPrototype);
  3342. prototype.self = this;
  3343. this.superclass = prototype.superclass = parentPrototype;
  3344. if (!parent.$isClass) {
  3345. Ext.apply(prototype, Ext.Base.prototype);
  3346. prototype.constructor = function() {
  3347. parentPrototype.constructor.apply(this, arguments);
  3348. };
  3349. }
  3350. //<feature classSystem.inheritableStatics>
  3351. // Statics inheritance
  3352. statics = parentPrototype.$inheritableStatics;
  3353. if (statics) {
  3354. for (i = 0,ln = statics.length; i < ln; i++) {
  3355. name = statics[i];
  3356. if (!this.hasOwnProperty(name)) {
  3357. this[name] = parent[name];
  3358. }
  3359. }
  3360. }
  3361. //</feature>
  3362. if (parent.$onExtended) {
  3363. this.$onExtended = parent.$onExtended.slice();
  3364. }
  3365. //<feature classSystem.config>
  3366. prototype.config = prototype.defaultConfig = new prototype.configClass;
  3367. prototype.initConfigList = prototype.initConfigList.slice();
  3368. prototype.initConfigMap = Ext.Object.chain(prototype.initConfigMap);
  3369. //</feature>
  3370. },
  3371. /**
  3372. * @private
  3373. * @static
  3374. * @inheritable
  3375. */
  3376. '$onExtended': [],
  3377. /**
  3378. * @private
  3379. * @static
  3380. * @inheritable
  3381. */
  3382. triggerExtended: function() {
  3383. var callbacks = this.$onExtended,
  3384. ln = callbacks.length,
  3385. i, callback;
  3386. if (ln > 0) {
  3387. for (i = 0; i < ln; i++) {
  3388. callback = callbacks[i];
  3389. callback.fn.apply(callback.scope || this, arguments);
  3390. }
  3391. }
  3392. },
  3393. /**
  3394. * @private
  3395. * @static
  3396. * @inheritable
  3397. */
  3398. onExtended: function(fn, scope) {
  3399. this.$onExtended.push({
  3400. fn: fn,
  3401. scope: scope
  3402. });
  3403. return this;
  3404. },
  3405. /**
  3406. * @private
  3407. * @static
  3408. * @inheritable
  3409. */
  3410. addConfig: function(config, fullMerge) {
  3411. var prototype = this.prototype,
  3412. initConfigList = prototype.initConfigList,
  3413. initConfigMap = prototype.initConfigMap,
  3414. defaultConfig = prototype.defaultConfig,
  3415. hasInitConfigItem, name, value;
  3416. fullMerge = Boolean(fullMerge);
  3417. for (name in config) {
  3418. if (config.hasOwnProperty(name) && (fullMerge || !(name in defaultConfig))) {
  3419. value = config[name];
  3420. hasInitConfigItem = initConfigMap[name];
  3421. if (value !== null) {
  3422. if (!hasInitConfigItem) {
  3423. initConfigMap[name] = true;
  3424. initConfigList.push(name);
  3425. }
  3426. }
  3427. else if (hasInitConfigItem) {
  3428. initConfigMap[name] = false;
  3429. Ext.Array.remove(initConfigList, name);
  3430. }
  3431. }
  3432. }
  3433. if (fullMerge) {
  3434. Ext.merge(defaultConfig, config);
  3435. }
  3436. else {
  3437. Ext.mergeIf(defaultConfig, config);
  3438. }
  3439. prototype.configClass = Ext.Object.classify(defaultConfig);
  3440. },
  3441. /**
  3442. * Add / override static properties of this class.
  3443. *
  3444. * Ext.define('My.cool.Class', {
  3445. * // this.se
  3446. * });
  3447. *
  3448. * My.cool.Class.addStatics({
  3449. * someProperty: 'someValue', // My.cool.Class.someProperty = 'someValue'
  3450. * method1: function() { }, // My.cool.Class.method1 = function() { ... };
  3451. * method2: function() { } // My.cool.Class.method2 = function() { ... };
  3452. * });
  3453. *
  3454. * @param {Object} members
  3455. * @return {Ext.Base} this
  3456. * @static
  3457. * @inheritable
  3458. */
  3459. addStatics: function(members) {
  3460. var member, name;
  3461. //<debug>
  3462. var className = Ext.getClassName(this);
  3463. //</debug>
  3464. for (name in members) {
  3465. if (members.hasOwnProperty(name)) {
  3466. member = members[name];
  3467. //<debug>
  3468. if (typeof member == 'function') {
  3469. member.displayName = className + '.' + name;
  3470. }
  3471. //</debug>
  3472. this[name] = member;
  3473. }
  3474. }
  3475. return this;
  3476. },
  3477. /**
  3478. * @private
  3479. * @static
  3480. * @inheritable
  3481. */
  3482. addInheritableStatics: function(members) {
  3483. var inheritableStatics,
  3484. hasInheritableStatics,
  3485. prototype = this.prototype,
  3486. name, member;
  3487. inheritableStatics = prototype.$inheritableStatics;
  3488. hasInheritableStatics = prototype.$hasInheritableStatics;
  3489. if (!inheritableStatics) {
  3490. inheritableStatics = prototype.$inheritableStatics = [];
  3491. hasInheritableStatics = prototype.$hasInheritableStatics = {};
  3492. }
  3493. //<debug>
  3494. var className = Ext.getClassName(this);
  3495. //</debug>
  3496. for (name in members) {
  3497. if (members.hasOwnProperty(name)) {
  3498. member = members[name];
  3499. //<debug>
  3500. if (typeof member == 'function') {
  3501. member.displayName = className + '.' + name;
  3502. }
  3503. //</debug>
  3504. this[name] = member;
  3505. if (!hasInheritableStatics[name]) {
  3506. hasInheritableStatics[name] = true;
  3507. inheritableStatics.push(name);
  3508. }
  3509. }
  3510. }
  3511. return this;
  3512. },
  3513. /**
  3514. * Add methods / properties to the prototype of this class.
  3515. *
  3516. * @example
  3517. * Ext.define('My.awesome.Cat', {
  3518. * constructor: function() {
  3519. * // ...
  3520. * }
  3521. * });
  3522. *
  3523. * My.awesome.Cat.addMembers({
  3524. * meow: function() {
  3525. * alert('Meowww...');
  3526. * }
  3527. * });
  3528. *
  3529. * var kitty = new My.awesome.Cat();
  3530. * kitty.meow();
  3531. *
  3532. * @param {Object} members
  3533. * @static
  3534. * @inheritable
  3535. */
  3536. addMembers: function(members) {
  3537. var prototype = this.prototype,
  3538. names = [],
  3539. name, member;
  3540. //<debug>
  3541. var className = this.$className || '';
  3542. //</debug>
  3543. for (name in members) {
  3544. if (members.hasOwnProperty(name)) {
  3545. member = members[name];
  3546. if (typeof member == 'function' && !member.$isClass && member !== Ext.emptyFn) {
  3547. member.$owner = this;
  3548. member.$name = name;
  3549. //<debug>
  3550. member.displayName = className + '#' + name;
  3551. //</debug>
  3552. }
  3553. prototype[name] = member;
  3554. }
  3555. }
  3556. return this;
  3557. },
  3558. /**
  3559. * @private
  3560. * @static
  3561. * @inheritable
  3562. */
  3563. addMember: function(name, member) {
  3564. if (typeof member == 'function' && !member.$isClass && member !== Ext.emptyFn) {
  3565. member.$owner = this;
  3566. member.$name = name;
  3567. //<debug>
  3568. member.displayName = (this.$className || '') + '#' + name;
  3569. //</debug>
  3570. }
  3571. this.prototype[name] = member;
  3572. return this;
  3573. },
  3574. /**
  3575. * @private
  3576. * @static
  3577. * @inheritable
  3578. */
  3579. implement: function() {
  3580. this.addMembers.apply(this, arguments);
  3581. },
  3582. /**
  3583. * Borrow another class' members to the prototype of this class.
  3584. *
  3585. * Ext.define('Bank', {
  3586. * money: '$$$',
  3587. * printMoney: function() {
  3588. * alert('$$$$$$$');
  3589. * }
  3590. * });
  3591. *
  3592. * Ext.define('Thief', {
  3593. * // ...
  3594. * });
  3595. *
  3596. * Thief.borrow(Bank, ['money', 'printMoney']);
  3597. *
  3598. * var steve = new Thief();
  3599. *
  3600. * alert(steve.money); // alerts '$$$'
  3601. * steve.printMoney(); // alerts '$$$$$$$'
  3602. *
  3603. * @param {Ext.Base} fromClass The class to borrow members from
  3604. * @param {Array/String} members The names of the members to borrow
  3605. * @return {Ext.Base} this
  3606. * @static
  3607. * @inheritable
  3608. * @private
  3609. */
  3610. borrow: function(fromClass, members) {
  3611. var prototype = this.prototype,
  3612. fromPrototype = fromClass.prototype,
  3613. //<debug>
  3614. className = Ext.getClassName(this),
  3615. //</debug>
  3616. i, ln, name, fn, toBorrow;
  3617. members = Ext.Array.from(members);
  3618. for (i = 0,ln = members.length; i < ln; i++) {
  3619. name = members[i];
  3620. toBorrow = fromPrototype[name];
  3621. if (typeof toBorrow == 'function') {
  3622. fn = function() {
  3623. return toBorrow.apply(this, arguments);
  3624. };
  3625. //<debug>
  3626. if (className) {
  3627. fn.displayName = className + '#' + name;
  3628. }
  3629. //</debug>
  3630. fn.$owner = this;
  3631. fn.$name = name;
  3632. prototype[name] = fn;
  3633. }
  3634. else {
  3635. prototype[name] = toBorrow;
  3636. }
  3637. }
  3638. return this;
  3639. },
  3640. /**
  3641. * Override members of this class. Overridden methods can be invoked via
  3642. * {@link Ext.Base#callParent}.
  3643. *
  3644. * Ext.define('My.Cat', {
  3645. * constructor: function() {
  3646. * alert("I'm a cat!");
  3647. * }
  3648. * });
  3649. *
  3650. * My.Cat.override({
  3651. * constructor: function() {
  3652. * alert("I'm going to be a cat!");
  3653. *
  3654. * var instance = this.callParent(arguments);
  3655. *
  3656. * alert("Meeeeoooowwww");
  3657. *
  3658. * return instance;
  3659. * }
  3660. * });
  3661. *
  3662. * var kitty = new My.Cat(); // alerts "I'm going to be a cat!"
  3663. * // alerts "I'm a cat!"
  3664. * // alerts "Meeeeoooowwww"
  3665. *
  3666. * As of 2.1, direct use of this method is deprecated. Use {@link Ext#define Ext.define}
  3667. * instead:
  3668. *
  3669. * Ext.define('My.CatOverride', {
  3670. * override: 'My.Cat',
  3671. *
  3672. * constructor: function() {
  3673. * alert("I'm going to be a cat!");
  3674. *
  3675. * var instance = this.callParent(arguments);
  3676. *
  3677. * alert("Meeeeoooowwww");
  3678. *
  3679. * return instance;
  3680. * }
  3681. * });
  3682. *
  3683. * The above accomplishes the same result but can be managed by the {@link Ext.Loader}
  3684. * which can properly order the override and its target class and the build process
  3685. * can determine whether the override is needed based on the required state of the
  3686. * target class (My.Cat).
  3687. *
  3688. * @param {Object} members The properties to add to this class. This should be
  3689. * specified as an object literal containing one or more properties.
  3690. * @return {Ext.Base} this class
  3691. * @static
  3692. * @inheritable
  3693. * @deprecated 2.1.0 Please use {@link Ext#define Ext.define} instead
  3694. */
  3695. override: function(members) {
  3696. var me = this,
  3697. enumerables = Ext.enumerables,
  3698. target = me.prototype,
  3699. cloneFunction = Ext.Function.clone,
  3700. name, index, member, statics, names, previous;
  3701. if (arguments.length === 2) {
  3702. name = members;
  3703. members = {};
  3704. members[name] = arguments[1];
  3705. enumerables = null;
  3706. }
  3707. do {
  3708. names = []; // clean slate for prototype (1st pass) and static (2nd pass)
  3709. statics = null; // not needed 1st pass, but needs to be cleared for 2nd pass
  3710. for (name in members) { // hasOwnProperty is checked in the next loop...
  3711. if (name == 'statics') {
  3712. statics = members[name];
  3713. }
  3714. else if (name == 'config') {
  3715. me.addConfig(members[name], true);
  3716. }
  3717. else {
  3718. names.push(name);
  3719. }
  3720. }
  3721. if (enumerables) {
  3722. names.push.apply(names, enumerables);
  3723. }
  3724. for (index = names.length; index--; ) {
  3725. name = names[index];
  3726. if (members.hasOwnProperty(name)) {
  3727. member = members[name];
  3728. if (typeof member == 'function' && !member.$className && member !== Ext.emptyFn) {
  3729. if (typeof member.$owner != 'undefined') {
  3730. member = cloneFunction(member);
  3731. }
  3732. //<debug>
  3733. var className = me.$className;
  3734. if (className) {
  3735. member.displayName = className + '#' + name;
  3736. }
  3737. //</debug>
  3738. member.$owner = me;
  3739. member.$name = name;
  3740. previous = target[name];
  3741. if (previous) {
  3742. member.$previous = previous;
  3743. }
  3744. }
  3745. target[name] = member;
  3746. }
  3747. }
  3748. target = me; // 2nd pass is for statics
  3749. members = statics; // statics will be null on 2nd pass
  3750. } while (members);
  3751. return this;
  3752. },
  3753. /**
  3754. * @protected
  3755. * @static
  3756. * @inheritable
  3757. */
  3758. callParent: function(args) {
  3759. var method;
  3760. // This code is intentionally inlined for the least amount of debugger stepping
  3761. return (method = this.callParent.caller) && (method.$previous ||
  3762. ((method = method.$owner ? method : method.caller) &&
  3763. method.$owner.superclass.$class[method.$name])).apply(this, args || noArgs);
  3764. },
  3765. //<feature classSystem.mixins>
  3766. /**
  3767. * Used internally by the mixins pre-processor
  3768. * @private
  3769. * @static
  3770. * @inheritable
  3771. */
  3772. mixin: function(name, mixinClass) {
  3773. var mixin = mixinClass.prototype,
  3774. prototype = this.prototype,
  3775. key;
  3776. if (typeof mixin.onClassMixedIn != 'undefined') {
  3777. mixin.onClassMixedIn.call(mixinClass, this);
  3778. }
  3779. if (!prototype.hasOwnProperty('mixins')) {
  3780. if ('mixins' in prototype) {
  3781. prototype.mixins = Ext.Object.chain(prototype.mixins);
  3782. }
  3783. else {
  3784. prototype.mixins = {};
  3785. }
  3786. }
  3787. for (key in mixin) {
  3788. if (key === 'mixins') {
  3789. Ext.merge(prototype.mixins, mixin[key]);
  3790. }
  3791. else if (typeof prototype[key] == 'undefined' && key != 'mixinId' && key != 'config') {
  3792. prototype[key] = mixin[key];
  3793. }
  3794. }
  3795. //<feature classSystem.config>
  3796. if ('config' in mixin) {
  3797. this.addConfig(mixin.config, false);
  3798. }
  3799. //</feature>
  3800. prototype.mixins[name] = mixin;
  3801. },
  3802. //</feature>
  3803. /**
  3804. * Get the current class' name in string format.
  3805. *
  3806. * Ext.define('My.cool.Class', {
  3807. * constructor: function() {
  3808. * alert(this.self.getName()); // alerts 'My.cool.Class'
  3809. * }
  3810. * });
  3811. *
  3812. * My.cool.Class.getName(); // 'My.cool.Class'
  3813. *
  3814. * @return {String} className
  3815. * @static
  3816. * @inheritable
  3817. */
  3818. getName: function() {
  3819. return Ext.getClassName(this);
  3820. },
  3821. /**
  3822. * Create aliases for existing prototype methods. Example:
  3823. *
  3824. * Ext.define('My.cool.Class', {
  3825. * method1: function() { },
  3826. * method2: function() { }
  3827. * });
  3828. *
  3829. * var test = new My.cool.Class();
  3830. *
  3831. * My.cool.Class.createAlias({
  3832. * method3: 'method1',
  3833. * method4: 'method2'
  3834. * });
  3835. *
  3836. * test.method3(); // test.method1()
  3837. *
  3838. * My.cool.Class.createAlias('method5', 'method3');
  3839. *
  3840. * test.method5(); // test.method3() -> test.method1()
  3841. *
  3842. * @param {String/Object} alias The new method name, or an object to set multiple aliases. See
  3843. * {@link Ext.Function#flexSetter flexSetter}
  3844. * @param {String/Object} origin The original method name
  3845. * @static
  3846. * @inheritable
  3847. * @method
  3848. */
  3849. createAlias: flexSetter(function(alias, origin) {
  3850. this.override(alias, function() {
  3851. return this[origin].apply(this, arguments);
  3852. });
  3853. }),
  3854. /**
  3855. * @private
  3856. * @static
  3857. * @inheritable
  3858. */
  3859. addXtype: function(xtype) {
  3860. var prototype = this.prototype,
  3861. xtypesMap = prototype.xtypesMap,
  3862. xtypes = prototype.xtypes,
  3863. xtypesChain = prototype.xtypesChain;
  3864. if (!prototype.hasOwnProperty('xtypesMap')) {
  3865. xtypesMap = prototype.xtypesMap = Ext.merge({}, prototype.xtypesMap || {});
  3866. xtypes = prototype.xtypes = prototype.xtypes ? [].concat(prototype.xtypes) : [];
  3867. xtypesChain = prototype.xtypesChain = prototype.xtypesChain ? [].concat(prototype.xtypesChain) : [];
  3868. prototype.xtype = xtype;
  3869. }
  3870. if (!xtypesMap[xtype]) {
  3871. xtypesMap[xtype] = true;
  3872. xtypes.push(xtype);
  3873. xtypesChain.push(xtype);
  3874. Ext.ClassManager.setAlias(this, 'widget.' + xtype);
  3875. }
  3876. return this;
  3877. }
  3878. });
  3879. Base.implement({
  3880. isInstance: true,
  3881. $className: 'Ext.Base',
  3882. configClass: Ext.emptyFn,
  3883. initConfigList: [],
  3884. initConfigMap: {},
  3885. /**
  3886. * Get the reference to the class from which this object was instantiated. Note that unlike {@link Ext.Base#self},
  3887. * `this.statics()` is scope-independent and it always returns the class from which it was called, regardless of what
  3888. * `this` points to during run-time
  3889. *
  3890. * Ext.define('My.Cat', {
  3891. * statics: {
  3892. * totalCreated: 0,
  3893. * speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
  3894. * },
  3895. *
  3896. * constructor: function() {
  3897. * var statics = this.statics();
  3898. *
  3899. * alert(statics.speciesName); // always equals to 'Cat' no matter what 'this' refers to
  3900. * // equivalent to: My.Cat.speciesName
  3901. *
  3902. * alert(this.self.speciesName); // dependent on 'this'
  3903. *
  3904. * statics.totalCreated++;
  3905. * },
  3906. *
  3907. * clone: function() {
  3908. * var cloned = new this.self(); // dependent on 'this'
  3909. *
  3910. * cloned.groupName = this.statics().speciesName; // equivalent to: My.Cat.speciesName
  3911. *
  3912. * return cloned;
  3913. * }
  3914. * });
  3915. *
  3916. *
  3917. * Ext.define('My.SnowLeopard', {
  3918. * extend: 'My.Cat',
  3919. *
  3920. * statics: {
  3921. * speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'
  3922. * },
  3923. *
  3924. * constructor: function() {
  3925. * this.callParent();
  3926. * }
  3927. * });
  3928. *
  3929. * var cat = new My.Cat(); // alerts 'Cat', then alerts 'Cat'
  3930. *
  3931. * var snowLeopard = new My.SnowLeopard(); // alerts 'Cat', then alerts 'Snow Leopard'
  3932. *
  3933. * var clone = snowLeopard.clone();
  3934. * alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'
  3935. * alert(clone.groupName); // alerts 'Cat'
  3936. *
  3937. * alert(My.Cat.totalCreated); // alerts 3
  3938. *
  3939. * @protected
  3940. * @return {Ext.Class}
  3941. */
  3942. statics: function() {
  3943. var method = this.statics.caller,
  3944. self = this.self;
  3945. if (!method) {
  3946. return self;
  3947. }
  3948. return method.$owner;
  3949. },
  3950. /**
  3951. * Call the "parent" method of the current method. That is the method previously
  3952. * overridden by derivation or by an override (see {@link Ext#define}).
  3953. *
  3954. * Ext.define('My.Base', {
  3955. * constructor: function (x) {
  3956. * this.x = x;
  3957. * },
  3958. *
  3959. * statics: {
  3960. * method: function (x) {
  3961. * return x;
  3962. * }
  3963. * }
  3964. * });
  3965. *
  3966. * Ext.define('My.Derived', {
  3967. * extend: 'My.Base',
  3968. *
  3969. * constructor: function () {
  3970. * this.callParent([21]);
  3971. * }
  3972. * });
  3973. *
  3974. * var obj = new My.Derived();
  3975. *
  3976. * alert(obj.x); // alerts 21
  3977. *
  3978. * This can be used with an override as follows:
  3979. *
  3980. * Ext.define('My.DerivedOverride', {
  3981. * override: 'My.Derived',
  3982. *
  3983. * constructor: function (x) {
  3984. * this.callParent([x*2]); // calls original My.Derived constructor
  3985. * }
  3986. * });
  3987. *
  3988. * var obj = new My.Derived();
  3989. *
  3990. * alert(obj.x); // now alerts 42
  3991. *
  3992. * This also works with static methods.
  3993. *
  3994. * Ext.define('My.Derived2', {
  3995. * extend: 'My.Base',
  3996. *
  3997. * statics: {
  3998. * method: function (x) {
  3999. * return this.callParent([x*2]); // calls My.Base.method
  4000. * }
  4001. * }
  4002. * });
  4003. *
  4004. * alert(My.Base.method(10)); // alerts 10
  4005. * alert(My.Derived2.method(10)); // alerts 20
  4006. *
  4007. * Lastly, it also works with overridden static methods.
  4008. *
  4009. * Ext.define('My.Derived2Override', {
  4010. * override: 'My.Derived2',
  4011. *
  4012. * statics: {
  4013. * method: function (x) {
  4014. * return this.callParent([x*2]); // calls My.Derived2.method
  4015. * }
  4016. * }
  4017. * });
  4018. *
  4019. * alert(My.Derived2.method(10)); // now alerts 40
  4020. *
  4021. * To override a method and replace it and also call the superclass method, use
  4022. * {@link #callSuper}. This is often done to patch a method to fix a bug.
  4023. *
  4024. * @protected
  4025. * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
  4026. * from the current method, for example: `this.callParent(arguments)`
  4027. * @return {Object} Returns the result of calling the parent method
  4028. */
  4029. callParent: function(args) {
  4030. // NOTE: this code is deliberately as few expressions (and no function calls)
  4031. // as possible so that a debugger can skip over this noise with the minimum number
  4032. // of steps. Basically, just hit Step Into until you are where you really wanted
  4033. // to be.
  4034. var method,
  4035. superMethod = (method = this.callParent.caller) && (method.$previous ||
  4036. ((method = method.$owner ? method : method.caller) &&
  4037. method.$owner.superclass[method.$name]));
  4038. //<debug error>
  4039. if (!superMethod) {
  4040. method = this.callParent.caller;
  4041. var parentClass, methodName;
  4042. if (!method.$owner) {
  4043. if (!method.caller) {
  4044. throw new Error("Attempting to call a protected method from the public scope, which is not allowed");
  4045. }
  4046. method = method.caller;
  4047. }
  4048. parentClass = method.$owner.superclass;
  4049. methodName = method.$name;
  4050. if (!(methodName in parentClass)) {
  4051. throw new Error("this.callParent() was called but there's no such method (" + methodName +
  4052. ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")");
  4053. }
  4054. }
  4055. //</debug>
  4056. return superMethod.apply(this, args || noArgs);
  4057. },
  4058. /**
  4059. * This method is used by an override to call the superclass method but bypass any
  4060. * overridden method. This is often done to "patch" a method that contains a bug
  4061. * but for whatever reason cannot be fixed directly.
  4062. *
  4063. * Consider:
  4064. *
  4065. * Ext.define('Ext.some.Class', {
  4066. * method: function () {
  4067. * console.log('Good');
  4068. * }
  4069. * });
  4070. *
  4071. * Ext.define('Ext.some.DerivedClass', {
  4072. * method: function () {
  4073. * console.log('Bad');
  4074. *
  4075. * // ... logic but with a bug ...
  4076. *
  4077. * this.callParent();
  4078. * }
  4079. * });
  4080. *
  4081. * To patch the bug in `DerivedClass.method`, the typical solution is to create an
  4082. * override:
  4083. *
  4084. * Ext.define('App.paches.DerivedClass', {
  4085. * override: 'Ext.some.DerivedClass',
  4086. *
  4087. * method: function () {
  4088. * console.log('Fixed');
  4089. *
  4090. * // ... logic but with bug fixed ...
  4091. *
  4092. * this.callSuper();
  4093. * }
  4094. * });
  4095. *
  4096. * The patch method cannot use `callParent` to call the superclass `method` since
  4097. * that would call the overridden method containing the bug. In other words, the
  4098. * above patch would only produce "Fixed" then "Good" in the console log, whereas,
  4099. * using `callParent` would produce "Fixed" then "Bad" then "Good".
  4100. *
  4101. * @protected
  4102. * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
  4103. * from the current method, for example: `this.callSuper(arguments)`
  4104. * @return {Object} Returns the result of calling the superclass method
  4105. */
  4106. callSuper: function(args) {
  4107. var method,
  4108. superMethod = (method = this.callSuper.caller) && ((method = method.$owner ? method : method.caller) &&
  4109. method.$owner.superclass[method.$name]);
  4110. //<debug error>
  4111. if (!superMethod) {
  4112. method = this.callSuper.caller;
  4113. var parentClass, methodName;
  4114. if (!method.$owner) {
  4115. if (!method.caller) {
  4116. throw new Error("Attempting to call a protected method from the public scope, which is not allowed");
  4117. }
  4118. method = method.caller;
  4119. }
  4120. parentClass = method.$owner.superclass;
  4121. methodName = method.$name;
  4122. if (!(methodName in parentClass)) {
  4123. throw new Error("this.callSuper() was called but there's no such method (" + methodName +
  4124. ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")");
  4125. }
  4126. }
  4127. //</debug>
  4128. return superMethod.apply(this, args || noArgs);
  4129. },
  4130. /**
  4131. * Call the original method that was previously overridden with {@link Ext.Base#override},
  4132. *
  4133. * This method is deprecated as {@link #callParent} does the same thing.
  4134. *
  4135. * Ext.define('My.Cat', {
  4136. * constructor: function() {
  4137. * alert("I'm a cat!");
  4138. * }
  4139. * });
  4140. *
  4141. * My.Cat.override({
  4142. * constructor: function() {
  4143. * alert("I'm going to be a cat!");
  4144. *
  4145. * var instance = this.callOverridden();
  4146. *
  4147. * alert("Meeeeoooowwww");
  4148. *
  4149. * return instance;
  4150. * }
  4151. * });
  4152. *
  4153. * var kitty = new My.Cat(); // alerts "I'm going to be a cat!"
  4154. * // alerts "I'm a cat!"
  4155. * // alerts "Meeeeoooowwww"
  4156. *
  4157. * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
  4158. * from the current method, for example: `this.callOverridden(arguments)`
  4159. * @return {Object} Returns the result of calling the overridden method
  4160. * @protected
  4161. * @deprecated Use callParent instead
  4162. */
  4163. callOverridden: function(args) {
  4164. var method;
  4165. return (method = this.callOverridden.caller) && method.$previous.apply(this, args || noArgs);
  4166. },
  4167. /**
  4168. * @property {Ext.Class} self
  4169. *
  4170. * Get the reference to the current class from which this object was instantiated. Unlike {@link Ext.Base#statics},
  4171. * `this.self` is scope-dependent and it's meant to be used for dynamic inheritance. See {@link Ext.Base#statics}
  4172. * for a detailed comparison
  4173. *
  4174. * Ext.define('My.Cat', {
  4175. * statics: {
  4176. * speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
  4177. * },
  4178. *
  4179. * constructor: function() {
  4180. * alert(this.self.speciesName); // dependent on 'this'
  4181. * },
  4182. *
  4183. * clone: function() {
  4184. * return new this.self();
  4185. * }
  4186. * });
  4187. *
  4188. *
  4189. * Ext.define('My.SnowLeopard', {
  4190. * extend: 'My.Cat',
  4191. * statics: {
  4192. * speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'
  4193. * }
  4194. * });
  4195. *
  4196. * var cat = new My.Cat(); // alerts 'Cat'
  4197. * var snowLeopard = new My.SnowLeopard(); // alerts 'Snow Leopard'
  4198. *
  4199. * var clone = snowLeopard.clone();
  4200. * alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'
  4201. *
  4202. * @protected
  4203. */
  4204. self: Base,
  4205. // Default constructor, simply returns `this`
  4206. constructor: function() {
  4207. return this;
  4208. },
  4209. //<feature classSystem.config>
  4210. wasInstantiated: false,
  4211. /**
  4212. * Initialize configuration for this class. a typical example:
  4213. *
  4214. * Ext.define('My.awesome.Class', {
  4215. * // The default config
  4216. * config: {
  4217. * name: 'Awesome',
  4218. * isAwesome: true
  4219. * },
  4220. *
  4221. * constructor: function(config) {
  4222. * this.initConfig(config);
  4223. * }
  4224. * });
  4225. *
  4226. * var awesome = new My.awesome.Class({
  4227. * name: 'Super Awesome'
  4228. * });
  4229. *
  4230. * alert(awesome.getName()); // 'Super Awesome'
  4231. *
  4232. * @protected
  4233. * @param {Object} instanceConfig
  4234. * @return {Object} mixins The mixin prototypes as key - value pairs
  4235. */
  4236. initConfig: function(instanceConfig) {
  4237. //<debug>
  4238. // if (instanceConfig && instanceConfig.breakOnInitConfig) {
  4239. // debugger;
  4240. // }
  4241. //</debug>
  4242. var configNameCache = Ext.Class.configNameCache,
  4243. prototype = this.self.prototype,
  4244. initConfigList = this.initConfigList,
  4245. initConfigMap = this.initConfigMap,
  4246. config = new this.configClass,
  4247. defaultConfig = this.defaultConfig,
  4248. i, ln, name, value, nameMap, getName;
  4249. this.initConfig = Ext.emptyFn;
  4250. this.initialConfig = instanceConfig || {};
  4251. if (instanceConfig) {
  4252. Ext.merge(config, instanceConfig);
  4253. }
  4254. this.config = config;
  4255. // Optimize initConfigList *once* per class based on the existence of apply* and update* methods
  4256. // Happens only once during the first instantiation
  4257. if (!prototype.hasOwnProperty('wasInstantiated')) {
  4258. prototype.wasInstantiated = true;
  4259. for (i = 0,ln = initConfigList.length; i < ln; i++) {
  4260. name = initConfigList[i];
  4261. nameMap = configNameCache[name];
  4262. value = defaultConfig[name];
  4263. if (!(nameMap.apply in prototype)
  4264. && !(nameMap.update in prototype)
  4265. && prototype[nameMap.set].$isDefault
  4266. && typeof value != 'object') {
  4267. prototype[nameMap.internal] = defaultConfig[name];
  4268. initConfigMap[name] = false;
  4269. Ext.Array.remove(initConfigList, name);
  4270. i--;
  4271. ln--;
  4272. }
  4273. }
  4274. }
  4275. if (instanceConfig) {
  4276. initConfigList = initConfigList.slice();
  4277. for (name in instanceConfig) {
  4278. if (name in defaultConfig && !initConfigMap[name]) {
  4279. initConfigList.push(name);
  4280. }
  4281. }
  4282. }
  4283. // Point all getters to the initGetters
  4284. for (i = 0,ln = initConfigList.length; i < ln; i++) {
  4285. name = initConfigList[i];
  4286. nameMap = configNameCache[name];
  4287. this[nameMap.get] = this[nameMap.initGet];
  4288. }
  4289. this.beforeInitConfig(config);
  4290. for (i = 0,ln = initConfigList.length; i < ln; i++) {
  4291. name = initConfigList[i];
  4292. nameMap = configNameCache[name];
  4293. getName = nameMap.get;
  4294. if (this.hasOwnProperty(getName)) {
  4295. this[nameMap.set].call(this, config[name]);
  4296. delete this[getName];
  4297. }
  4298. }
  4299. return this;
  4300. },
  4301. beforeInitConfig: Ext.emptyFn,
  4302. /**
  4303. * @private
  4304. */
  4305. getCurrentConfig: function() {
  4306. var defaultConfig = this.defaultConfig,
  4307. configNameCache = Ext.Class.configNameCache,
  4308. config = {},
  4309. name, nameMap;
  4310. for (name in defaultConfig) {
  4311. nameMap = configNameCache[name];
  4312. config[name] = this[nameMap.get].call(this);
  4313. }
  4314. return config;
  4315. },
  4316. /**
  4317. * @private
  4318. */
  4319. setConfig: function(config, applyIfNotSet) {
  4320. if (!config) {
  4321. return this;
  4322. }
  4323. var configNameCache = Ext.Class.configNameCache,
  4324. currentConfig = this.config,
  4325. defaultConfig = this.defaultConfig,
  4326. initialConfig = this.initialConfig,
  4327. configList = [],
  4328. name, i, ln, nameMap;
  4329. applyIfNotSet = Boolean(applyIfNotSet);
  4330. for (name in config) {
  4331. if ((applyIfNotSet && (name in initialConfig))) {
  4332. continue;
  4333. }
  4334. currentConfig[name] = config[name];
  4335. if (name in defaultConfig) {
  4336. configList.push(name);
  4337. nameMap = configNameCache[name];
  4338. this[nameMap.get] = this[nameMap.initGet];
  4339. }
  4340. }
  4341. for (i = 0,ln = configList.length; i < ln; i++) {
  4342. name = configList[i];
  4343. nameMap = configNameCache[name];
  4344. this[nameMap.set].call(this, config[name]);
  4345. delete this[nameMap.get];
  4346. }
  4347. return this;
  4348. },
  4349. set: function(name, value) {
  4350. return this[Ext.Class.configNameCache[name].set].call(this, value);
  4351. },
  4352. get: function(name) {
  4353. return this[Ext.Class.configNameCache[name].get].call(this);
  4354. },
  4355. /**
  4356. * @private
  4357. */
  4358. getConfig: function(name) {
  4359. return this[Ext.Class.configNameCache[name].get].call(this);
  4360. },
  4361. /**
  4362. * @private
  4363. */
  4364. hasConfig: function(name) {
  4365. return (name in this.defaultConfig);
  4366. },
  4367. /**
  4368. * Returns the initial configuration passed to constructor.
  4369. *
  4370. * @param {String} [name] When supplied, value for particular configuration
  4371. * option is returned, otherwise the full config object is returned.
  4372. * @return {Object/Mixed}
  4373. */
  4374. getInitialConfig: function(name) {
  4375. var config = this.config;
  4376. if (!name) {
  4377. return config;
  4378. }
  4379. else {
  4380. return config[name];
  4381. }
  4382. },
  4383. /**
  4384. * @private
  4385. */
  4386. onConfigUpdate: function(names, callback, scope) {
  4387. var self = this.self,
  4388. //<debug>
  4389. className = self.$className,
  4390. //</debug>
  4391. i, ln, name,
  4392. updaterName, updater, newUpdater;
  4393. names = Ext.Array.from(names);
  4394. scope = scope || this;
  4395. for (i = 0,ln = names.length; i < ln; i++) {
  4396. name = names[i];
  4397. updaterName = 'update' + Ext.String.capitalize(name);
  4398. updater = this[updaterName] || Ext.emptyFn;
  4399. newUpdater = function() {
  4400. updater.apply(this, arguments);
  4401. scope[callback].apply(scope, arguments);
  4402. };
  4403. newUpdater.$name = updaterName;
  4404. newUpdater.$owner = self;
  4405. //<debug>
  4406. newUpdater.displayName = className + '#' + updaterName;
  4407. //</debug>
  4408. this[updaterName] = newUpdater;
  4409. }
  4410. },
  4411. //</feature>
  4412. /**
  4413. * @private
  4414. * @param name
  4415. * @param value
  4416. * @return {Mixed}
  4417. */
  4418. link: function(name, value) {
  4419. this.$links = {};
  4420. this.link = this.doLink;
  4421. return this.link.apply(this, arguments);
  4422. },
  4423. doLink: function(name, value) {
  4424. this.$links[name] = true;
  4425. this[name] = value;
  4426. return value;
  4427. },
  4428. /**
  4429. * @private
  4430. */
  4431. unlink: function() {
  4432. var i, ln, link, value;
  4433. for (i = 0, ln = arguments.length; i < ln; i++) {
  4434. link = arguments[i];
  4435. if (this.hasOwnProperty(link)) {
  4436. value = this[link];
  4437. if (value) {
  4438. if (value.isInstance && !value.isDestroyed) {
  4439. value.destroy();
  4440. }
  4441. else if (value.parentNode && 'nodeType' in value) {
  4442. value.parentNode.removeChild(value);
  4443. }
  4444. }
  4445. delete this[link];
  4446. }
  4447. }
  4448. return this;
  4449. },
  4450. /**
  4451. * @protected
  4452. */
  4453. destroy: function() {
  4454. this.destroy = Ext.emptyFn;
  4455. this.isDestroyed = true;
  4456. if (this.hasOwnProperty('$links')) {
  4457. this.unlink.apply(this, Ext.Object.getKeys(this.$links));
  4458. delete this.$links;
  4459. }
  4460. }
  4461. });
  4462. Ext.Base = Base;
  4463. })(Ext.Function.flexSetter);
  4464. //@tag foundation,core
  4465. //@define Ext.Class
  4466. //@require Ext.Base
  4467. /**
  4468. * @class Ext.Class
  4469. *
  4470. * @author Jacky Nguyen <jacky@sencha.com>
  4471. * @aside guide class_system
  4472. * @aside video class-system
  4473. *
  4474. * Handles class creation throughout the framework. This is a low level factory that is used by Ext.ClassManager and generally
  4475. * should not be used directly. If you choose to use Ext.Class you will lose out on the namespace, aliasing and dependency loading
  4476. * features made available by Ext.ClassManager. The only time you would use Ext.Class directly is to create an anonymous class.
  4477. *
  4478. * If you wish to create a class you should use {@link Ext#define Ext.define} which aliases
  4479. * {@link Ext.ClassManager#create Ext.ClassManager.create} to enable namespacing and dynamic dependency resolution.
  4480. *
  4481. * Ext.Class is the factory and **not** the superclass of everything. For the base class that **all** Ext classes inherit
  4482. * from, see {@link Ext.Base}.
  4483. */
  4484. (function() {
  4485. var ExtClass,
  4486. Base = Ext.Base,
  4487. baseStaticMembers = [],
  4488. baseStaticMember, baseStaticMemberLength;
  4489. for (baseStaticMember in Base) {
  4490. if (Base.hasOwnProperty(baseStaticMember)) {
  4491. baseStaticMembers.push(baseStaticMember);
  4492. }
  4493. }
  4494. baseStaticMemberLength = baseStaticMembers.length;
  4495. /**
  4496. * @method constructor
  4497. * Creates a new anonymous class.
  4498. *
  4499. * @param {Object} data An object represent the properties of this class.
  4500. * @param {Function} onCreated (optional) The callback function to be executed when this class is fully created.
  4501. * Note that the creation process can be asynchronous depending on the pre-processors used.
  4502. *
  4503. * @return {Ext.Base} The newly created class
  4504. */
  4505. Ext.Class = ExtClass = function(Class, data, onCreated) {
  4506. if (typeof Class != 'function') {
  4507. onCreated = data;
  4508. data = Class;
  4509. Class = null;
  4510. }
  4511. if (!data) {
  4512. data = {};
  4513. }
  4514. Class = ExtClass.create(Class);
  4515. ExtClass.process(Class, data, onCreated);
  4516. return Class;
  4517. };
  4518. Ext.apply(ExtClass, {
  4519. /**
  4520. * @private
  4521. * @static
  4522. */
  4523. onBeforeCreated: function(Class, data, hooks) {
  4524. Class.addMembers(data);
  4525. hooks.onCreated.call(Class, Class);
  4526. },
  4527. /**
  4528. * @private
  4529. * @static
  4530. */
  4531. create: function(Class) {
  4532. var name, i;
  4533. if (!Class) {
  4534. Class = function() {
  4535. return this.constructor.apply(this, arguments);
  4536. };
  4537. }
  4538. for (i = 0; i < baseStaticMemberLength; i++) {
  4539. name = baseStaticMembers[i];
  4540. Class[name] = Base[name];
  4541. }
  4542. return Class;
  4543. },
  4544. /**
  4545. * @private
  4546. * @static
  4547. */
  4548. process: function(Class, data, onCreated) {
  4549. var preprocessorStack = data.preprocessors || ExtClass.defaultPreprocessors,
  4550. preprocessors = this.preprocessors,
  4551. hooks = {
  4552. onBeforeCreated: this.onBeforeCreated,
  4553. onCreated: onCreated || Ext.emptyFn
  4554. },
  4555. index = 0,
  4556. name, preprocessor, properties,
  4557. i, ln, fn, property, process;
  4558. delete data.preprocessors;
  4559. process = function(Class, data, hooks) {
  4560. fn = null;
  4561. while (fn === null) {
  4562. name = preprocessorStack[index++];
  4563. if (name) {
  4564. preprocessor = preprocessors[name];
  4565. properties = preprocessor.properties;
  4566. if (properties === true) {
  4567. fn = preprocessor.fn;
  4568. }
  4569. else {
  4570. for (i = 0,ln = properties.length; i < ln; i++) {
  4571. property = properties[i];
  4572. if (data.hasOwnProperty(property)) {
  4573. fn = preprocessor.fn;
  4574. break;
  4575. }
  4576. }
  4577. }
  4578. }
  4579. else {
  4580. hooks.onBeforeCreated.apply(this, arguments);
  4581. return;
  4582. }
  4583. }
  4584. if (fn.call(this, Class, data, hooks, process) !== false) {
  4585. process.apply(this, arguments);
  4586. }
  4587. };
  4588. process.call(this, Class, data, hooks);
  4589. },
  4590. /**
  4591. * @private
  4592. * @static
  4593. */
  4594. preprocessors: {},
  4595. /**
  4596. * Register a new pre-processor to be used during the class creation process.
  4597. *
  4598. * @private
  4599. * @static
  4600. * @param {String} name The pre-processor's name.
  4601. * @param {Function} fn The callback function to be executed. Typical format:
  4602. *
  4603. * function(cls, data, fn) {
  4604. * // Your code here
  4605. *
  4606. * // Execute this when the processing is finished.
  4607. * // Asynchronous processing is perfectly OK
  4608. * if (fn) {
  4609. * fn.call(this, cls, data);
  4610. * }
  4611. * });
  4612. *
  4613. * @param {Function} fn.cls The created class.
  4614. * @param {Object} fn.data The set of properties passed in {@link Ext.Class} constructor.
  4615. * @param {Function} fn.fn The callback function that __must__ to be executed when this pre-processor finishes,
  4616. * regardless of whether the processing is synchronous or asynchronous.
  4617. *
  4618. * @return {Ext.Class} this
  4619. */
  4620. registerPreprocessor: function(name, fn, properties, position, relativeTo) {
  4621. if (!position) {
  4622. position = 'last';
  4623. }
  4624. if (!properties) {
  4625. properties = [name];
  4626. }
  4627. this.preprocessors[name] = {
  4628. name: name,
  4629. properties: properties || false,
  4630. fn: fn
  4631. };
  4632. this.setDefaultPreprocessorPosition(name, position, relativeTo);
  4633. return this;
  4634. },
  4635. /**
  4636. * Retrieve a pre-processor callback function by its name, which has been registered before.
  4637. *
  4638. * @private
  4639. * @static
  4640. * @param {String} name
  4641. * @return {Function} preprocessor
  4642. */
  4643. getPreprocessor: function(name) {
  4644. return this.preprocessors[name];
  4645. },
  4646. /**
  4647. * @private
  4648. * @static
  4649. */
  4650. getPreprocessors: function() {
  4651. return this.preprocessors;
  4652. },
  4653. /**
  4654. * @private
  4655. * @static
  4656. */
  4657. defaultPreprocessors: [],
  4658. /**
  4659. * Retrieve the array stack of default pre-processors.
  4660. * @private
  4661. * @static
  4662. * @return {Function} defaultPreprocessors
  4663. */
  4664. getDefaultPreprocessors: function() {
  4665. return this.defaultPreprocessors;
  4666. },
  4667. /**
  4668. * Set the default array stack of default pre-processors.
  4669. *
  4670. * @private
  4671. * @static
  4672. * @param {Array} preprocessors
  4673. * @return {Ext.Class} this
  4674. */
  4675. setDefaultPreprocessors: function(preprocessors) {
  4676. this.defaultPreprocessors = Ext.Array.from(preprocessors);
  4677. return this;
  4678. },
  4679. /**
  4680. * Insert this pre-processor at a specific position in the stack, optionally relative to
  4681. * any existing pre-processor. For example:
  4682. *
  4683. * Ext.Class.registerPreprocessor('debug', function(cls, data, fn) {
  4684. * // Your code here
  4685. *
  4686. * if (fn) {
  4687. * fn.call(this, cls, data);
  4688. * }
  4689. * }).insertDefaultPreprocessor('debug', 'last');
  4690. *
  4691. * @private
  4692. * @static
  4693. * @param {String} name The pre-processor name. Note that it needs to be registered with
  4694. * {@link Ext.Class#registerPreprocessor registerPreprocessor} before this.
  4695. * @param {String} offset The insertion position. Four possible values are:
  4696. * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument).
  4697. * @param {String} relativeName
  4698. * @return {Ext.Class} this
  4699. */
  4700. setDefaultPreprocessorPosition: function(name, offset, relativeName) {
  4701. var defaultPreprocessors = this.defaultPreprocessors,
  4702. index;
  4703. if (typeof offset == 'string') {
  4704. if (offset === 'first') {
  4705. defaultPreprocessors.unshift(name);
  4706. return this;
  4707. }
  4708. else if (offset === 'last') {
  4709. defaultPreprocessors.push(name);
  4710. return this;
  4711. }
  4712. offset = (offset === 'after') ? 1 : -1;
  4713. }
  4714. index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
  4715. if (index !== -1) {
  4716. Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
  4717. }
  4718. return this;
  4719. },
  4720. /**
  4721. * @private
  4722. * @static
  4723. */
  4724. configNameCache: {},
  4725. /**
  4726. * @private
  4727. * @static
  4728. */
  4729. getConfigNameMap: function(name) {
  4730. var cache = this.configNameCache,
  4731. map = cache[name],
  4732. capitalizedName;
  4733. if (!map) {
  4734. capitalizedName = name.charAt(0).toUpperCase() + name.substr(1);
  4735. map = cache[name] = {
  4736. name: name,
  4737. internal: '_' + name,
  4738. initializing: 'is' + capitalizedName + 'Initializing',
  4739. apply: 'apply' + capitalizedName,
  4740. update: 'update' + capitalizedName,
  4741. set: 'set' + capitalizedName,
  4742. get: 'get' + capitalizedName,
  4743. initGet: 'initGet' + capitalizedName,
  4744. doSet : 'doSet' + capitalizedName,
  4745. changeEvent: name.toLowerCase() + 'change'
  4746. }
  4747. }
  4748. return map;
  4749. },
  4750. /**
  4751. * @private
  4752. * @static
  4753. */
  4754. generateSetter: function(nameMap) {
  4755. var internalName = nameMap.internal,
  4756. getName = nameMap.get,
  4757. applyName = nameMap.apply,
  4758. updateName = nameMap.update,
  4759. setter;
  4760. setter = function(value) {
  4761. var oldValue = this[internalName],
  4762. applier = this[applyName],
  4763. updater = this[updateName];
  4764. delete this[getName];
  4765. if (applier) {
  4766. value = applier.call(this, value, oldValue);
  4767. }
  4768. if (typeof value != 'undefined') {
  4769. this[internalName] = value;
  4770. if (updater && value !== oldValue) {
  4771. updater.call(this, value, oldValue);
  4772. }
  4773. }
  4774. return this;
  4775. };
  4776. setter.$isDefault = true;
  4777. return setter;
  4778. },
  4779. /**
  4780. * @private
  4781. * @static
  4782. */
  4783. generateInitGetter: function(nameMap) {
  4784. var name = nameMap.name,
  4785. setName = nameMap.set,
  4786. getName = nameMap.get,
  4787. initializingName = nameMap.initializing;
  4788. return function() {
  4789. this[initializingName] = true;
  4790. delete this[getName];
  4791. this[setName].call(this, this.config[name]);
  4792. delete this[initializingName];
  4793. return this[getName].apply(this, arguments);
  4794. }
  4795. },
  4796. /**
  4797. * @private
  4798. * @static
  4799. */
  4800. generateGetter: function(nameMap) {
  4801. var internalName = nameMap.internal;
  4802. return function() {
  4803. return this[internalName];
  4804. }
  4805. }
  4806. });
  4807. /**
  4808. * @cfg {String} extend
  4809. * The parent class that this class extends. For example:
  4810. *
  4811. * @example
  4812. * Ext.define('Person', {
  4813. * say: function(text) {
  4814. * alert(text);
  4815. * }
  4816. * });
  4817. *
  4818. * Ext.define('Developer', {
  4819. * extend: 'Person',
  4820. * say: function(text) {
  4821. * this.callParent(["print " + text]);
  4822. * }
  4823. * });
  4824. *
  4825. * var person1 = Ext.create("Person");
  4826. * person1.say("Bill");
  4827. *
  4828. * var developer1 = Ext.create("Developer");
  4829. * developer1.say("Ted");
  4830. */
  4831. ExtClass.registerPreprocessor('extend', function(Class, data) {
  4832. var Base = Ext.Base,
  4833. extend = data.extend,
  4834. Parent;
  4835. delete data.extend;
  4836. if (extend && extend !== Object) {
  4837. Parent = extend;
  4838. }
  4839. else {
  4840. Parent = Base;
  4841. }
  4842. Class.extend(Parent);
  4843. Class.triggerExtended.apply(Class, arguments);
  4844. if (data.onClassExtended) {
  4845. Class.onExtended(data.onClassExtended, Class);
  4846. delete data.onClassExtended;
  4847. }
  4848. }, true);
  4849. //<feature classSystem.statics>
  4850. /**
  4851. * @cfg {Object} statics
  4852. * List of static methods for this class. For example:
  4853. *
  4854. * Ext.define('Computer', {
  4855. * statics: {
  4856. * factory: function(brand) {
  4857. * // 'this' in static methods refer to the class itself
  4858. * return new this(brand);
  4859. * }
  4860. * },
  4861. *
  4862. * constructor: function() {
  4863. * // ...
  4864. * }
  4865. * });
  4866. *
  4867. * var dellComputer = Computer.factory('Dell');
  4868. */
  4869. ExtClass.registerPreprocessor('statics', function(Class, data) {
  4870. Class.addStatics(data.statics);
  4871. delete data.statics;
  4872. });
  4873. //</feature>
  4874. //<feature classSystem.inheritableStatics>
  4875. /**
  4876. * @cfg {Object} inheritableStatics
  4877. * List of inheritable static methods for this class.
  4878. * Otherwise just like {@link #statics} but subclasses inherit these methods.
  4879. */
  4880. ExtClass.registerPreprocessor('inheritableStatics', function(Class, data) {
  4881. Class.addInheritableStatics(data.inheritableStatics);
  4882. delete data.inheritableStatics;
  4883. });
  4884. //</feature>
  4885. //<feature classSystem.config>
  4886. /**
  4887. * @cfg {Object} config
  4888. *
  4889. * List of configuration options with their default values.
  4890. *
  4891. * __Note:__ You need to make sure {@link Ext.Base#initConfig} is called from your constructor if you are defining
  4892. * your own class or singleton, unless you are extending a Component. Otherwise the generated getter and setter
  4893. * methods will not be initialized.
  4894. *
  4895. * Each config item will have its own setter and getter method automatically generated inside the class prototype
  4896. * during class creation time, if the class does not have those methods explicitly defined.
  4897. *
  4898. * As an example, let's convert the name property of a Person class to be a config item, then add extra age and
  4899. * gender items.
  4900. *
  4901. * Ext.define('My.sample.Person', {
  4902. * config: {
  4903. * name: 'Mr. Unknown',
  4904. * age: 0,
  4905. * gender: 'Male'
  4906. * },
  4907. *
  4908. * constructor: function(config) {
  4909. * this.initConfig(config);
  4910. *
  4911. * return this;
  4912. * }
  4913. *
  4914. * // ...
  4915. * });
  4916. *
  4917. * Within the class, this.name still has the default value of "Mr. Unknown". However, it's now publicly accessible
  4918. * without sacrificing encapsulation, via setter and getter methods.
  4919. *
  4920. * var jacky = new Person({
  4921. * name: "Jacky",
  4922. * age: 35
  4923. * });
  4924. *
  4925. * alert(jacky.getAge()); // alerts 35
  4926. * alert(jacky.getGender()); // alerts "Male"
  4927. *
  4928. * jacky.walk(10); // alerts "Jacky is walking 10 steps"
  4929. *
  4930. * jacky.setName("Mr. Nguyen");
  4931. * alert(jacky.getName()); // alerts "Mr. Nguyen"
  4932. *
  4933. * jacky.walk(10); // alerts "Mr. Nguyen is walking 10 steps"
  4934. *
  4935. * Notice that we changed the class constructor to invoke this.initConfig() and pass in the provided config object.
  4936. * Two key things happened:
  4937. *
  4938. * - The provided config object when the class is instantiated is recursively merged with the default config object.
  4939. * - All corresponding setter methods are called with the merged values.
  4940. *
  4941. * Beside storing the given values, throughout the frameworks, setters generally have two key responsibilities:
  4942. *
  4943. * - Filtering / validation / transformation of the given value before it's actually stored within the instance.
  4944. * - Notification (such as firing events) / post-processing after the value has been set, or changed from a
  4945. * previous value.
  4946. *
  4947. * By standardize this common pattern, the default generated setters provide two extra template methods that you
  4948. * can put your own custom logics into, i.e: an "applyFoo" and "updateFoo" method for a "foo" config item, which are
  4949. * executed before and after the value is actually set, respectively. Back to the example class, let's validate that
  4950. * age must be a valid positive number, and fire an 'agechange' if the value is modified.
  4951. *
  4952. * Ext.define('My.sample.Person', {
  4953. * config: {
  4954. * // ...
  4955. * },
  4956. *
  4957. * constructor: {
  4958. * // ...
  4959. * },
  4960. *
  4961. * applyAge: function(age) {
  4962. * if (typeof age !== 'number' || age < 0) {
  4963. * console.warn("Invalid age, must be a positive number");
  4964. * return;
  4965. * }
  4966. *
  4967. * return age;
  4968. * },
  4969. *
  4970. * updateAge: function(newAge, oldAge) {
  4971. * // age has changed from "oldAge" to "newAge"
  4972. * this.fireEvent('agechange', this, newAge, oldAge);
  4973. * }
  4974. *
  4975. * // ...
  4976. * });
  4977. *
  4978. * var jacky = new Person({
  4979. * name: "Jacky",
  4980. * age: 'invalid'
  4981. * });
  4982. *
  4983. * alert(jacky.getAge()); // alerts 0
  4984. *
  4985. * alert(jacky.setAge(-100)); // alerts 0
  4986. * alert(jacky.getAge()); // alerts 0
  4987. *
  4988. * alert(jacky.setAge(35)); // alerts 0
  4989. * alert(jacky.getAge()); // alerts 35
  4990. *
  4991. * In other words, when leveraging the config feature, you mostly never need to define setter and getter methods
  4992. * explicitly. Instead, "apply*" and "update*" methods should be implemented where necessary. Your code will be
  4993. * consistent throughout and only contain the minimal logic that you actually care about.
  4994. *
  4995. * When it comes to inheritance, the default config of the parent class is automatically, recursively merged with
  4996. * the child's default config. The same applies for mixins.
  4997. */
  4998. ExtClass.registerPreprocessor('config', function(Class, data) {
  4999. var config = data.config,
  5000. prototype = Class.prototype,
  5001. defaultConfig = prototype.config,
  5002. nameMap, name, setName, getName, initGetName, internalName, value;
  5003. delete data.config;
  5004. for (name in config) {
  5005. // Once per config item, per class hierarchy
  5006. if (config.hasOwnProperty(name) && !(name in defaultConfig)) {
  5007. value = config[name];
  5008. nameMap = this.getConfigNameMap(name);
  5009. setName = nameMap.set;
  5010. getName = nameMap.get;
  5011. initGetName = nameMap.initGet;
  5012. internalName = nameMap.internal;
  5013. data[initGetName] = this.generateInitGetter(nameMap);
  5014. if (value === null && !data.hasOwnProperty(internalName)) {
  5015. data[internalName] = null;
  5016. }
  5017. if (!data.hasOwnProperty(getName)) {
  5018. data[getName] = this.generateGetter(nameMap);
  5019. }
  5020. if (!data.hasOwnProperty(setName)) {
  5021. data[setName] = this.generateSetter(nameMap);
  5022. }
  5023. }
  5024. }
  5025. Class.addConfig(config, true);
  5026. });
  5027. //</feature>
  5028. //<feature classSystem.mixins>
  5029. /**
  5030. * @cfg {Object} mixins
  5031. * List of classes to mix into this class. For example:
  5032. *
  5033. * Ext.define('CanSing', {
  5034. * sing: function() {
  5035. * alert("I'm on the highway to hell...");
  5036. * }
  5037. * });
  5038. *
  5039. * Ext.define('Musician', {
  5040. * extend: 'Person',
  5041. *
  5042. * mixins: {
  5043. * canSing: 'CanSing'
  5044. * }
  5045. * });
  5046. */
  5047. ExtClass.registerPreprocessor('mixins', function(Class, data, hooks) {
  5048. var mixins = data.mixins,
  5049. name, mixin, i, ln;
  5050. delete data.mixins;
  5051. Ext.Function.interceptBefore(hooks, 'onCreated', function() {
  5052. if (mixins instanceof Array) {
  5053. for (i = 0,ln = mixins.length; i < ln; i++) {
  5054. mixin = mixins[i];
  5055. name = mixin.prototype.mixinId || mixin.$className;
  5056. Class.mixin(name, mixin);
  5057. }
  5058. }
  5059. else {
  5060. for (name in mixins) {
  5061. if (mixins.hasOwnProperty(name)) {
  5062. Class.mixin(name, mixins[name]);
  5063. }
  5064. }
  5065. }
  5066. });
  5067. });
  5068. //</feature>
  5069. //<feature classSystem.backwardsCompatible>
  5070. // Backwards compatible
  5071. Ext.extend = function(Class, Parent, members) {
  5072. if (arguments.length === 2 && Ext.isObject(Parent)) {
  5073. members = Parent;
  5074. Parent = Class;
  5075. Class = null;
  5076. }
  5077. var cls;
  5078. if (!Parent) {
  5079. throw new Error("[Ext.extend] Attempting to extend from a class which has not been loaded on the page.");
  5080. }
  5081. members.extend = Parent;
  5082. members.preprocessors = [
  5083. 'extend'
  5084. //<feature classSystem.statics>
  5085. ,'statics'
  5086. //</feature>
  5087. //<feature classSystem.inheritableStatics>
  5088. ,'inheritableStatics'
  5089. //</feature>
  5090. //<feature classSystem.mixins>
  5091. ,'mixins'
  5092. //</feature>
  5093. //<feature classSystem.config>
  5094. ,'config'
  5095. //</feature>
  5096. ];
  5097. if (Class) {
  5098. cls = new ExtClass(Class, members);
  5099. }
  5100. else {
  5101. cls = new ExtClass(members);
  5102. }
  5103. cls.prototype.override = function(o) {
  5104. for (var m in o) {
  5105. if (o.hasOwnProperty(m)) {
  5106. this[m] = o[m];
  5107. }
  5108. }
  5109. };
  5110. return cls;
  5111. };
  5112. //</feature>
  5113. })();
  5114. //@tag foundation,core
  5115. //@define Ext.ClassManager
  5116. //@require Ext.Class
  5117. /**
  5118. * @class Ext.ClassManager
  5119. *
  5120. * @author Jacky Nguyen <jacky@sencha.com>
  5121. * @aside guide class_system
  5122. * @aside video class-system
  5123. *
  5124. * Ext.ClassManager manages all classes and handles mapping from string class name to
  5125. * actual class objects throughout the whole framework. It is not generally accessed directly, rather through
  5126. * these convenient shorthands:
  5127. *
  5128. * - {@link Ext#define Ext.define}
  5129. * - {@link Ext.ClassManager#create Ext.create}
  5130. * - {@link Ext#widget Ext.widget}
  5131. * - {@link Ext#getClass Ext.getClass}
  5132. * - {@link Ext#getClassName Ext.getClassName}
  5133. *
  5134. * ## Basic syntax:
  5135. *
  5136. * Ext.define(className, properties);
  5137. *
  5138. * in which `properties` is an object represent a collection of properties that apply to the class. See
  5139. * {@link Ext.ClassManager#create} for more detailed instructions.
  5140. *
  5141. * @example
  5142. * Ext.define('Person', {
  5143. * name: 'Unknown',
  5144. *
  5145. * constructor: function(name) {
  5146. * if (name) {
  5147. * this.name = name;
  5148. * }
  5149. *
  5150. * return this;
  5151. * },
  5152. *
  5153. * eat: function(foodType) {
  5154. * alert("I'm eating: " + foodType);
  5155. *
  5156. * return this;
  5157. * }
  5158. * });
  5159. *
  5160. * var aaron = new Person("Aaron");
  5161. * aaron.eat("Sandwich"); // alert("I'm eating: Sandwich");
  5162. *
  5163. * Ext.Class has a powerful set of extensible {@link Ext.Class#registerPreprocessor pre-processors} which takes care of
  5164. * everything related to class creation, including but not limited to inheritance, mixins, configuration, statics, etc.
  5165. *
  5166. * ## Inheritance:
  5167. *
  5168. * Ext.define('Developer', {
  5169. * extend: 'Person',
  5170. *
  5171. * constructor: function(name, isGeek) {
  5172. * this.isGeek = isGeek;
  5173. *
  5174. * // Apply a method from the parent class' prototype
  5175. * this.callParent([name]);
  5176. *
  5177. * return this;
  5178. *
  5179. * },
  5180. *
  5181. * code: function(language) {
  5182. * alert("I'm coding in: " + language);
  5183. *
  5184. * this.eat("Bugs");
  5185. *
  5186. * return this;
  5187. * }
  5188. * });
  5189. *
  5190. * var jacky = new Developer("Jacky", true);
  5191. * jacky.code("JavaScript"); // alert("I'm coding in: JavaScript");
  5192. * // alert("I'm eating: Bugs");
  5193. *
  5194. * See {@link Ext.Base#callParent} for more details on calling superclass' methods
  5195. *
  5196. * ## Mixins:
  5197. *
  5198. * Ext.define('CanPlayGuitar', {
  5199. * playGuitar: function() {
  5200. * alert("F#...G...D...A");
  5201. * }
  5202. * });
  5203. *
  5204. * Ext.define('CanComposeSongs', {
  5205. * composeSongs: function() { }
  5206. * });
  5207. *
  5208. * Ext.define('CanSing', {
  5209. * sing: function() {
  5210. * alert("I'm on the highway to hell...");
  5211. * }
  5212. * });
  5213. *
  5214. * Ext.define('Musician', {
  5215. * extend: 'Person',
  5216. *
  5217. * mixins: {
  5218. * canPlayGuitar: 'CanPlayGuitar',
  5219. * canComposeSongs: 'CanComposeSongs',
  5220. * canSing: 'CanSing'
  5221. * }
  5222. * });
  5223. *
  5224. * Ext.define('CoolPerson', {
  5225. * extend: 'Person',
  5226. *
  5227. * mixins: {
  5228. * canPlayGuitar: 'CanPlayGuitar',
  5229. * canSing: 'CanSing'
  5230. * },
  5231. *
  5232. * sing: function() {
  5233. * alert("Ahem...");
  5234. *
  5235. * this.mixins.canSing.sing.call(this);
  5236. *
  5237. * alert("[Playing guitar at the same time...]");
  5238. *
  5239. * this.playGuitar();
  5240. * }
  5241. * });
  5242. *
  5243. * var me = new CoolPerson("Jacky");
  5244. *
  5245. * me.sing(); // alert("Ahem...");
  5246. * // alert("I'm on the highway to hell...");
  5247. * // alert("[Playing guitar at the same time...]");
  5248. * // alert("F#...G...D...A");
  5249. *
  5250. * ## Config:
  5251. *
  5252. * Ext.define('SmartPhone', {
  5253. * config: {
  5254. * hasTouchScreen: false,
  5255. * operatingSystem: 'Other',
  5256. * price: 500
  5257. * },
  5258. *
  5259. * isExpensive: false,
  5260. *
  5261. * constructor: function(config) {
  5262. * this.initConfig(config);
  5263. *
  5264. * return this;
  5265. * },
  5266. *
  5267. * applyPrice: function(price) {
  5268. * this.isExpensive = (price > 500);
  5269. *
  5270. * return price;
  5271. * },
  5272. *
  5273. * applyOperatingSystem: function(operatingSystem) {
  5274. * if (!(/^(iOS|Android|BlackBerry)$/i).test(operatingSystem)) {
  5275. * return 'Other';
  5276. * }
  5277. *
  5278. * return operatingSystem;
  5279. * }
  5280. * });
  5281. *
  5282. * var iPhone = new SmartPhone({
  5283. * hasTouchScreen: true,
  5284. * operatingSystem: 'iOS'
  5285. * });
  5286. *
  5287. * iPhone.getPrice(); // 500;
  5288. * iPhone.getOperatingSystem(); // 'iOS'
  5289. * iPhone.getHasTouchScreen(); // true;
  5290. *
  5291. * iPhone.isExpensive; // false;
  5292. * iPhone.setPrice(600);
  5293. * iPhone.getPrice(); // 600
  5294. * iPhone.isExpensive; // true;
  5295. *
  5296. * iPhone.setOperatingSystem('AlienOS');
  5297. * iPhone.getOperatingSystem(); // 'Other'
  5298. *
  5299. * ## Statics:
  5300. *
  5301. * Ext.define('Computer', {
  5302. * statics: {
  5303. * factory: function(brand) {
  5304. * // 'this' in static methods refer to the class itself
  5305. * return new this(brand);
  5306. * }
  5307. * },
  5308. *
  5309. * constructor: function() { }
  5310. * });
  5311. *
  5312. * var dellComputer = Computer.factory('Dell');
  5313. *
  5314. * Also see {@link Ext.Base#statics} and {@link Ext.Base#self} for more details on accessing
  5315. * static properties within class methods
  5316. *
  5317. * @singleton
  5318. */
  5319. (function(Class, alias, arraySlice, arrayFrom, global) {
  5320. var Manager = Ext.ClassManager = {
  5321. /**
  5322. * @property classes
  5323. * @type Object
  5324. * All classes which were defined through the ClassManager. Keys are the
  5325. * name of the classes and the values are references to the classes.
  5326. * @private
  5327. */
  5328. classes: {},
  5329. /**
  5330. * @private
  5331. */
  5332. existCache: {},
  5333. /**
  5334. * @private
  5335. */
  5336. namespaceRewrites: [{
  5337. from: 'Ext.',
  5338. to: Ext
  5339. }],
  5340. /**
  5341. * @private
  5342. */
  5343. maps: {
  5344. alternateToName: {},
  5345. aliasToName: {},
  5346. nameToAliases: {},
  5347. nameToAlternates: {}
  5348. },
  5349. /** @private */
  5350. enableNamespaceParseCache: true,
  5351. /** @private */
  5352. namespaceParseCache: {},
  5353. /** @private */
  5354. instantiators: [],
  5355. /**
  5356. * Checks if a class has already been created.
  5357. *
  5358. * @param {String} className
  5359. * @return {Boolean} exist
  5360. */
  5361. isCreated: function(className) {
  5362. var existCache = this.existCache,
  5363. i, ln, part, root, parts;
  5364. //<debug error>
  5365. if (typeof className != 'string' || className.length < 1) {
  5366. throw new Error("[Ext.ClassManager] Invalid classname, must be a string and must not be empty");
  5367. }
  5368. //</debug>
  5369. if (this.classes[className] || existCache[className]) {
  5370. return true;
  5371. }
  5372. root = global;
  5373. parts = this.parseNamespace(className);
  5374. for (i = 0, ln = parts.length; i < ln; i++) {
  5375. part = parts[i];
  5376. if (typeof part != 'string') {
  5377. root = part;
  5378. } else {
  5379. if (!root || !root[part]) {
  5380. return false;
  5381. }
  5382. root = root[part];
  5383. }
  5384. }
  5385. existCache[className] = true;
  5386. this.triggerCreated(className);
  5387. return true;
  5388. },
  5389. /**
  5390. * @private
  5391. */
  5392. createdListeners: [],
  5393. /**
  5394. * @private
  5395. */
  5396. nameCreatedListeners: {},
  5397. /**
  5398. * @private
  5399. */
  5400. triggerCreated: function(className) {
  5401. var listeners = this.createdListeners,
  5402. nameListeners = this.nameCreatedListeners,
  5403. alternateNames = this.maps.nameToAlternates[className],
  5404. names = [className],
  5405. i, ln, j, subLn, listener, name;
  5406. for (i = 0,ln = listeners.length; i < ln; i++) {
  5407. listener = listeners[i];
  5408. listener.fn.call(listener.scope, className);
  5409. }
  5410. if (alternateNames) {
  5411. names.push.apply(names, alternateNames);
  5412. }
  5413. for (i = 0,ln = names.length; i < ln; i++) {
  5414. name = names[i];
  5415. listeners = nameListeners[name];
  5416. if (listeners) {
  5417. for (j = 0,subLn = listeners.length; j < subLn; j++) {
  5418. listener = listeners[j];
  5419. listener.fn.call(listener.scope, name);
  5420. }
  5421. delete nameListeners[name];
  5422. }
  5423. }
  5424. },
  5425. /**
  5426. * @private
  5427. */
  5428. onCreated: function(fn, scope, className) {
  5429. var listeners = this.createdListeners,
  5430. nameListeners = this.nameCreatedListeners,
  5431. listener = {
  5432. fn: fn,
  5433. scope: scope
  5434. };
  5435. if (className) {
  5436. if (this.isCreated(className)) {
  5437. fn.call(scope, className);
  5438. return;
  5439. }
  5440. if (!nameListeners[className]) {
  5441. nameListeners[className] = [];
  5442. }
  5443. nameListeners[className].push(listener);
  5444. }
  5445. else {
  5446. listeners.push(listener);
  5447. }
  5448. },
  5449. /**
  5450. * Supports namespace rewriting.
  5451. * @private
  5452. */
  5453. parseNamespace: function(namespace) {
  5454. //<debug error>
  5455. if (typeof namespace != 'string') {
  5456. throw new Error("[Ext.ClassManager] Invalid namespace, must be a string");
  5457. }
  5458. //</debug>
  5459. var cache = this.namespaceParseCache;
  5460. if (this.enableNamespaceParseCache) {
  5461. if (cache.hasOwnProperty(namespace)) {
  5462. return cache[namespace];
  5463. }
  5464. }
  5465. var parts = [],
  5466. rewrites = this.namespaceRewrites,
  5467. root = global,
  5468. name = namespace,
  5469. rewrite, from, to, i, ln;
  5470. for (i = 0, ln = rewrites.length; i < ln; i++) {
  5471. rewrite = rewrites[i];
  5472. from = rewrite.from;
  5473. to = rewrite.to;
  5474. if (name === from || name.substring(0, from.length) === from) {
  5475. name = name.substring(from.length);
  5476. if (typeof to != 'string') {
  5477. root = to;
  5478. } else {
  5479. parts = parts.concat(to.split('.'));
  5480. }
  5481. break;
  5482. }
  5483. }
  5484. parts.push(root);
  5485. parts = parts.concat(name.split('.'));
  5486. if (this.enableNamespaceParseCache) {
  5487. cache[namespace] = parts;
  5488. }
  5489. return parts;
  5490. },
  5491. /**
  5492. * Creates a namespace and assign the `value` to the created object.
  5493. *
  5494. * Ext.ClassManager.setNamespace('MyCompany.pkg.Example', someObject);
  5495. * alert(MyCompany.pkg.Example === someObject); // alerts true
  5496. *
  5497. * @param {String} name
  5498. * @param {Mixed} value
  5499. */
  5500. setNamespace: function(name, value) {
  5501. var root = global,
  5502. parts = this.parseNamespace(name),
  5503. ln = parts.length - 1,
  5504. leaf = parts[ln],
  5505. i, part;
  5506. for (i = 0; i < ln; i++) {
  5507. part = parts[i];
  5508. if (typeof part != 'string') {
  5509. root = part;
  5510. } else {
  5511. if (!root[part]) {
  5512. root[part] = {};
  5513. }
  5514. root = root[part];
  5515. }
  5516. }
  5517. root[leaf] = value;
  5518. return root[leaf];
  5519. },
  5520. /**
  5521. * The new Ext.ns, supports namespace rewriting.
  5522. * @private
  5523. */
  5524. createNamespaces: function() {
  5525. var root = global,
  5526. parts, part, i, j, ln, subLn;
  5527. for (i = 0, ln = arguments.length; i < ln; i++) {
  5528. parts = this.parseNamespace(arguments[i]);
  5529. for (j = 0, subLn = parts.length; j < subLn; j++) {
  5530. part = parts[j];
  5531. if (typeof part != 'string') {
  5532. root = part;
  5533. } else {
  5534. if (!root[part]) {
  5535. root[part] = {};
  5536. }
  5537. root = root[part];
  5538. }
  5539. }
  5540. }
  5541. return root;
  5542. },
  5543. /**
  5544. * Sets a name reference to a class.
  5545. *
  5546. * @param {String} name
  5547. * @param {Object} value
  5548. * @return {Ext.ClassManager} this
  5549. */
  5550. set: function(name, value) {
  5551. var me = this,
  5552. maps = me.maps,
  5553. nameToAlternates = maps.nameToAlternates,
  5554. targetName = me.getName(value),
  5555. alternates;
  5556. me.classes[name] = me.setNamespace(name, value);
  5557. if (targetName && targetName !== name) {
  5558. maps.alternateToName[name] = targetName;
  5559. alternates = nameToAlternates[targetName] || (nameToAlternates[targetName] = []);
  5560. alternates.push(name);
  5561. }
  5562. return this;
  5563. },
  5564. /**
  5565. * Retrieve a class by its name.
  5566. *
  5567. * @param {String} name
  5568. * @return {Ext.Class} class
  5569. */
  5570. get: function(name) {
  5571. var classes = this.classes;
  5572. if (classes[name]) {
  5573. return classes[name];
  5574. }
  5575. var root = global,
  5576. parts = this.parseNamespace(name),
  5577. part, i, ln;
  5578. for (i = 0, ln = parts.length; i < ln; i++) {
  5579. part = parts[i];
  5580. if (typeof part != 'string') {
  5581. root = part;
  5582. } else {
  5583. if (!root || !root[part]) {
  5584. return null;
  5585. }
  5586. root = root[part];
  5587. }
  5588. }
  5589. return root;
  5590. },
  5591. /**
  5592. * Register the alias for a class.
  5593. *
  5594. * @param {Ext.Class/String} cls a reference to a class or a `className`.
  5595. * @param {String} alias Alias to use when referring to this class.
  5596. */
  5597. setAlias: function(cls, alias) {
  5598. var aliasToNameMap = this.maps.aliasToName,
  5599. nameToAliasesMap = this.maps.nameToAliases,
  5600. className;
  5601. if (typeof cls == 'string') {
  5602. className = cls;
  5603. } else {
  5604. className = this.getName(cls);
  5605. }
  5606. if (alias && aliasToNameMap[alias] !== className) {
  5607. //<debug info>
  5608. if (aliasToNameMap[alias]) {
  5609. Ext.Logger.info("[Ext.ClassManager] Overriding existing alias: '" + alias + "' " +
  5610. "of: '" + aliasToNameMap[alias] + "' with: '" + className + "'. Be sure it's intentional.");
  5611. }
  5612. //</debug>
  5613. aliasToNameMap[alias] = className;
  5614. }
  5615. if (!nameToAliasesMap[className]) {
  5616. nameToAliasesMap[className] = [];
  5617. }
  5618. if (alias) {
  5619. Ext.Array.include(nameToAliasesMap[className], alias);
  5620. }
  5621. return this;
  5622. },
  5623. /**
  5624. * Adds a batch of class name to alias mappings
  5625. * @param {Object} aliases The set of mappings of the form
  5626. * className : [values...]
  5627. */
  5628. addNameAliasMappings: function(aliases){
  5629. var aliasToNameMap = this.maps.aliasToName,
  5630. nameToAliasesMap = this.maps.nameToAliases,
  5631. className, aliasList, alias, i;
  5632. for (className in aliases) {
  5633. aliasList = nameToAliasesMap[className] ||
  5634. (nameToAliasesMap[className] = []);
  5635. for (i = 0; i < aliases[className].length; i++) {
  5636. alias = aliases[className][i];
  5637. if (!aliasToNameMap[alias]) {
  5638. aliasToNameMap[alias] = className;
  5639. aliasList.push(alias);
  5640. }
  5641. }
  5642. }
  5643. return this;
  5644. },
  5645. /**
  5646. *
  5647. * @param {Object} alternates The set of mappings of the form
  5648. * className : [values...]
  5649. */
  5650. addNameAlternateMappings: function(alternates) {
  5651. var alternateToName = this.maps.alternateToName,
  5652. nameToAlternates = this.maps.nameToAlternates,
  5653. className, aliasList, alternate, i;
  5654. for (className in alternates) {
  5655. aliasList = nameToAlternates[className] ||
  5656. (nameToAlternates[className] = []);
  5657. for (i = 0; i < alternates[className].length; i++) {
  5658. alternate = alternates[className];
  5659. if (!alternateToName[alternate]) {
  5660. alternateToName[alternate] = className;
  5661. aliasList.push(alternate);
  5662. }
  5663. }
  5664. }
  5665. return this;
  5666. },
  5667. /**
  5668. * Get a reference to the class by its alias.
  5669. *
  5670. * @param {String} alias
  5671. * @return {Ext.Class} class
  5672. */
  5673. getByAlias: function(alias) {
  5674. return this.get(this.getNameByAlias(alias));
  5675. },
  5676. /**
  5677. * Get the name of a class by its alias.
  5678. *
  5679. * @param {String} alias
  5680. * @return {String} className
  5681. */
  5682. getNameByAlias: function(alias) {
  5683. return this.maps.aliasToName[alias] || '';
  5684. },
  5685. /**
  5686. * Get the name of a class by its alternate name.
  5687. *
  5688. * @param {String} alternate
  5689. * @return {String} className
  5690. */
  5691. getNameByAlternate: function(alternate) {
  5692. return this.maps.alternateToName[alternate] || '';
  5693. },
  5694. /**
  5695. * Get the aliases of a class by the class name
  5696. *
  5697. * @param {String} name
  5698. * @return {Array} aliases
  5699. */
  5700. getAliasesByName: function(name) {
  5701. return this.maps.nameToAliases[name] || [];
  5702. },
  5703. /**
  5704. * Get the name of the class by its reference or its instance;
  5705. * usually invoked by the shorthand {@link Ext#getClassName Ext.getClassName}
  5706. *
  5707. * Ext.ClassManager.getName(Ext.Action); // returns "Ext.Action"
  5708. *
  5709. * @param {Ext.Class/Object} object
  5710. * @return {String} className
  5711. */
  5712. getName: function(object) {
  5713. return object && object.$className || '';
  5714. },
  5715. /**
  5716. * Get the class of the provided object; returns null if it's not an instance
  5717. * of any class created with Ext.define. This is usually invoked by the shorthand {@link Ext#getClass Ext.getClass}.
  5718. *
  5719. * var component = new Ext.Component();
  5720. *
  5721. * Ext.ClassManager.getClass(component); // returns Ext.Component
  5722. *
  5723. * @param {Object} object
  5724. * @return {Ext.Class} class
  5725. */
  5726. getClass: function(object) {
  5727. return object && object.self || null;
  5728. },
  5729. /**
  5730. * @private
  5731. */
  5732. create: function(className, data, createdFn) {
  5733. //<debug error>
  5734. if (typeof className != 'string') {
  5735. throw new Error("[Ext.define] Invalid class name '" + className + "' specified, must be a non-empty string");
  5736. }
  5737. //</debug>
  5738. data.$className = className;
  5739. return new Class(data, function() {
  5740. var postprocessorStack = data.postprocessors || Manager.defaultPostprocessors,
  5741. registeredPostprocessors = Manager.postprocessors,
  5742. index = 0,
  5743. postprocessors = [],
  5744. postprocessor, process, i, ln, j, subLn, postprocessorProperties, postprocessorProperty;
  5745. delete data.postprocessors;
  5746. for (i = 0,ln = postprocessorStack.length; i < ln; i++) {
  5747. postprocessor = postprocessorStack[i];
  5748. if (typeof postprocessor == 'string') {
  5749. postprocessor = registeredPostprocessors[postprocessor];
  5750. postprocessorProperties = postprocessor.properties;
  5751. if (postprocessorProperties === true) {
  5752. postprocessors.push(postprocessor.fn);
  5753. }
  5754. else if (postprocessorProperties) {
  5755. for (j = 0,subLn = postprocessorProperties.length; j < subLn; j++) {
  5756. postprocessorProperty = postprocessorProperties[j];
  5757. if (data.hasOwnProperty(postprocessorProperty)) {
  5758. postprocessors.push(postprocessor.fn);
  5759. break;
  5760. }
  5761. }
  5762. }
  5763. }
  5764. else {
  5765. postprocessors.push(postprocessor);
  5766. }
  5767. }
  5768. process = function(clsName, cls, clsData) {
  5769. postprocessor = postprocessors[index++];
  5770. if (!postprocessor) {
  5771. Manager.set(className, cls);
  5772. if (createdFn) {
  5773. createdFn.call(cls, cls);
  5774. }
  5775. Manager.triggerCreated(className);
  5776. return;
  5777. }
  5778. if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
  5779. process.apply(this, arguments);
  5780. }
  5781. };
  5782. process.call(Manager, className, this, data);
  5783. });
  5784. },
  5785. createOverride: function(className, data) {
  5786. var overriddenClassName = data.override,
  5787. requires = Ext.Array.from(data.requires);
  5788. delete data.override;
  5789. delete data.requires;
  5790. this.existCache[className] = true;
  5791. Ext.require(requires, function() {
  5792. // Override the target class right after it's created
  5793. this.onCreated(function() {
  5794. this.get(overriddenClassName).override(data);
  5795. // This push the overridding file itself into Ext.Loader.history
  5796. // Hence if the target class never exists, the overriding file will
  5797. // never be included in the build
  5798. this.triggerCreated(className);
  5799. }, this, overriddenClassName);
  5800. }, this);
  5801. return this;
  5802. },
  5803. /**
  5804. * Instantiate a class by its alias; usually invoked by the convenient shorthand {@link Ext#createByAlias Ext.createByAlias}
  5805. * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
  5806. * attempt to load the class via synchronous loading.
  5807. *
  5808. * var window = Ext.ClassManager.instantiateByAlias('widget.window', { width: 600, height: 800 });
  5809. *
  5810. * @param {String} alias
  5811. * @param {Mixed...} args Additional arguments after the alias will be passed to the class constructor.
  5812. * @return {Object} instance
  5813. */
  5814. instantiateByAlias: function() {
  5815. var alias = arguments[0],
  5816. args = arraySlice.call(arguments),
  5817. className = this.getNameByAlias(alias);
  5818. if (!className) {
  5819. className = this.maps.aliasToName[alias];
  5820. //<debug error>
  5821. if (!className) {
  5822. throw new Error("[Ext.createByAlias] Cannot create an instance of unrecognized alias: " + alias);
  5823. }
  5824. //</debug>
  5825. //<debug warn>
  5826. Ext.Logger.warn("[Ext.Loader] Synchronously loading '" + className + "'; consider adding " +
  5827. "Ext.require('" + alias + "') above Ext.onReady");
  5828. //</debug>
  5829. Ext.syncRequire(className);
  5830. }
  5831. args[0] = className;
  5832. return this.instantiate.apply(this, args);
  5833. },
  5834. /**
  5835. * Instantiate a class by either full name, alias or alternate name; usually invoked by the convenient
  5836. * shorthand {@link Ext.ClassManager#create Ext.create}.
  5837. *
  5838. * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
  5839. * attempt to load the class via synchronous loading.
  5840. *
  5841. * For example, all these three lines return the same result:
  5842. *
  5843. * // alias
  5844. * var formPanel = Ext.create('widget.formpanel', { width: 600, height: 800 });
  5845. *
  5846. * // alternate name
  5847. * var formPanel = Ext.create('Ext.form.FormPanel', { width: 600, height: 800 });
  5848. *
  5849. * // full class name
  5850. * var formPanel = Ext.create('Ext.form.Panel', { width: 600, height: 800 });
  5851. *
  5852. * @param {String} name
  5853. * @param {Mixed} args Additional arguments after the name will be passed to the class' constructor.
  5854. * @return {Object} instance
  5855. */
  5856. instantiate: function() {
  5857. var name = arguments[0],
  5858. args = arraySlice.call(arguments, 1),
  5859. alias = name,
  5860. possibleName, cls;
  5861. if (typeof name != 'function') {
  5862. //<debug error>
  5863. if ((typeof name != 'string' || name.length < 1)) {
  5864. throw new Error("[Ext.create] Invalid class name or alias '" + name + "' specified, must be a non-empty string");
  5865. }
  5866. //</debug>
  5867. cls = this.get(name);
  5868. }
  5869. else {
  5870. cls = name;
  5871. }
  5872. // No record of this class name, it's possibly an alias, so look it up
  5873. if (!cls) {
  5874. possibleName = this.getNameByAlias(name);
  5875. if (possibleName) {
  5876. name = possibleName;
  5877. cls = this.get(name);
  5878. }
  5879. }
  5880. // Still no record of this class name, it's possibly an alternate name, so look it up
  5881. if (!cls) {
  5882. possibleName = this.getNameByAlternate(name);
  5883. if (possibleName) {
  5884. name = possibleName;
  5885. cls = this.get(name);
  5886. }
  5887. }
  5888. // Still not existing at this point, try to load it via synchronous mode as the last resort
  5889. if (!cls) {
  5890. //<debug warn>
  5891. Ext.Logger.warn("[Ext.Loader] Synchronously loading '" + name + "'; consider adding '" +
  5892. ((possibleName) ? alias : name) + "' explicitly as a require of the corresponding class");
  5893. //</debug>
  5894. Ext.syncRequire(name);
  5895. cls = this.get(name);
  5896. }
  5897. //<debug error>
  5898. if (!cls) {
  5899. throw new Error("[Ext.create] Cannot create an instance of unrecognized class name / alias: " + alias);
  5900. }
  5901. if (typeof cls != 'function') {
  5902. throw new Error("[Ext.create] '" + name + "' is a singleton and cannot be instantiated");
  5903. }
  5904. //</debug>
  5905. return this.getInstantiator(args.length)(cls, args);
  5906. },
  5907. /**
  5908. * @private
  5909. * @param name
  5910. * @param args
  5911. */
  5912. dynInstantiate: function(name, args) {
  5913. args = arrayFrom(args, true);
  5914. args.unshift(name);
  5915. return this.instantiate.apply(this, args);
  5916. },
  5917. /**
  5918. * @private
  5919. * @param length
  5920. */
  5921. getInstantiator: function(length) {
  5922. var instantiators = this.instantiators,
  5923. instantiator;
  5924. instantiator = instantiators[length];
  5925. if (!instantiator) {
  5926. var i = length,
  5927. args = [];
  5928. for (i = 0; i < length; i++) {
  5929. args.push('a[' + i + ']');
  5930. }
  5931. instantiator = instantiators[length] = new Function('c', 'a', 'return new c(' + args.join(',') + ')');
  5932. //<debug>
  5933. instantiator.displayName = "Ext.ClassManager.instantiate" + length;
  5934. //</debug>
  5935. }
  5936. return instantiator;
  5937. },
  5938. /**
  5939. * @private
  5940. */
  5941. postprocessors: {},
  5942. /**
  5943. * @private
  5944. */
  5945. defaultPostprocessors: [],
  5946. /**
  5947. * Register a post-processor function.
  5948. *
  5949. * @private
  5950. * @param {String} name
  5951. * @param {Function} postprocessor
  5952. */
  5953. registerPostprocessor: function(name, fn, properties, position, relativeTo) {
  5954. if (!position) {
  5955. position = 'last';
  5956. }
  5957. if (!properties) {
  5958. properties = [name];
  5959. }
  5960. this.postprocessors[name] = {
  5961. name: name,
  5962. properties: properties || false,
  5963. fn: fn
  5964. };
  5965. this.setDefaultPostprocessorPosition(name, position, relativeTo);
  5966. return this;
  5967. },
  5968. /**
  5969. * Set the default post processors array stack which are applied to every class.
  5970. *
  5971. * @private
  5972. * @param {String/Array} The name of a registered post processor or an array of registered names.
  5973. * @return {Ext.ClassManager} this
  5974. */
  5975. setDefaultPostprocessors: function(postprocessors) {
  5976. this.defaultPostprocessors = arrayFrom(postprocessors);
  5977. return this;
  5978. },
  5979. /**
  5980. * Insert this post-processor at a specific position in the stack, optionally relative to
  5981. * any existing post-processor
  5982. *
  5983. * @private
  5984. * @param {String} name The post-processor name. Note that it needs to be registered with
  5985. * {@link Ext.ClassManager#registerPostprocessor} before this
  5986. * @param {String} offset The insertion position. Four possible values are:
  5987. * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
  5988. * @param {String} relativeName
  5989. * @return {Ext.ClassManager} this
  5990. */
  5991. setDefaultPostprocessorPosition: function(name, offset, relativeName) {
  5992. var defaultPostprocessors = this.defaultPostprocessors,
  5993. index;
  5994. if (typeof offset == 'string') {
  5995. if (offset === 'first') {
  5996. defaultPostprocessors.unshift(name);
  5997. return this;
  5998. }
  5999. else if (offset === 'last') {
  6000. defaultPostprocessors.push(name);
  6001. return this;
  6002. }
  6003. offset = (offset === 'after') ? 1 : -1;
  6004. }
  6005. index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
  6006. if (index !== -1) {
  6007. Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);
  6008. }
  6009. return this;
  6010. },
  6011. /**
  6012. * Converts a string expression to an array of matching class names. An expression can either refers to class aliases
  6013. * or class names. Expressions support wildcards:
  6014. *
  6015. * // returns ['Ext.window.Window']
  6016. * var window = Ext.ClassManager.getNamesByExpression('widget.window');
  6017. *
  6018. * // returns ['widget.panel', 'widget.window', ...]
  6019. * var allWidgets = Ext.ClassManager.getNamesByExpression('widget.*');
  6020. *
  6021. * // returns ['Ext.data.Store', 'Ext.data.ArrayProxy', ...]
  6022. * var allData = Ext.ClassManager.getNamesByExpression('Ext.data.*');
  6023. *
  6024. * @param {String} expression
  6025. * @return {Array} classNames
  6026. */
  6027. getNamesByExpression: function(expression) {
  6028. var nameToAliasesMap = this.maps.nameToAliases,
  6029. names = [],
  6030. name, alias, aliases, possibleName, regex, i, ln;
  6031. //<debug error>
  6032. if (typeof expression != 'string' || expression.length < 1) {
  6033. throw new Error("[Ext.ClassManager.getNamesByExpression] Expression " + expression + " is invalid, must be a non-empty string");
  6034. }
  6035. //</debug>
  6036. if (expression.indexOf('*') !== -1) {
  6037. expression = expression.replace(/\*/g, '(.*?)');
  6038. regex = new RegExp('^' + expression + '$');
  6039. for (name in nameToAliasesMap) {
  6040. if (nameToAliasesMap.hasOwnProperty(name)) {
  6041. aliases = nameToAliasesMap[name];
  6042. if (name.search(regex) !== -1) {
  6043. names.push(name);
  6044. }
  6045. else {
  6046. for (i = 0, ln = aliases.length; i < ln; i++) {
  6047. alias = aliases[i];
  6048. if (alias.search(regex) !== -1) {
  6049. names.push(name);
  6050. break;
  6051. }
  6052. }
  6053. }
  6054. }
  6055. }
  6056. } else {
  6057. possibleName = this.getNameByAlias(expression);
  6058. if (possibleName) {
  6059. names.push(possibleName);
  6060. } else {
  6061. possibleName = this.getNameByAlternate(expression);
  6062. if (possibleName) {
  6063. names.push(possibleName);
  6064. } else {
  6065. names.push(expression);
  6066. }
  6067. }
  6068. }
  6069. return names;
  6070. }
  6071. };
  6072. //<feature classSystem.alias>
  6073. /**
  6074. * @cfg {String[]} alias
  6075. * @member Ext.Class
  6076. * List of short aliases for class names. Most useful for defining xtypes for widgets:
  6077. *
  6078. * Ext.define('MyApp.CoolPanel', {
  6079. * extend: 'Ext.panel.Panel',
  6080. * alias: ['widget.coolpanel'],
  6081. * title: 'Yeah!'
  6082. * });
  6083. *
  6084. * // Using Ext.create
  6085. * Ext.create('widget.coolpanel');
  6086. *
  6087. * // Using the shorthand for widgets and in xtypes
  6088. * Ext.widget('panel', {
  6089. * items: [
  6090. * {xtype: 'coolpanel', html: 'Foo'},
  6091. * {xtype: 'coolpanel', html: 'Bar'}
  6092. * ]
  6093. * });
  6094. */
  6095. Manager.registerPostprocessor('alias', function(name, cls, data) {
  6096. var aliases = data.alias,
  6097. i, ln;
  6098. for (i = 0,ln = aliases.length; i < ln; i++) {
  6099. alias = aliases[i];
  6100. this.setAlias(cls, alias);
  6101. }
  6102. }, ['xtype', 'alias']);
  6103. //</feature>
  6104. //<feature classSystem.singleton>
  6105. /**
  6106. * @cfg {Boolean} singleton
  6107. * @member Ext.Class
  6108. * When set to true, the class will be instantiated as singleton. For example:
  6109. *
  6110. * Ext.define('Logger', {
  6111. * singleton: true,
  6112. * log: function(msg) {
  6113. * console.log(msg);
  6114. * }
  6115. * });
  6116. *
  6117. * Logger.log('Hello');
  6118. */
  6119. Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
  6120. fn.call(this, name, new cls(), data);
  6121. return false;
  6122. });
  6123. //</feature>
  6124. //<feature classSystem.alternateClassName>
  6125. /**
  6126. * @cfg {String/String[]} alternateClassName
  6127. * @member Ext.Class
  6128. * Defines alternate names for this class. For example:
  6129. *
  6130. * @example
  6131. * Ext.define('Developer', {
  6132. * alternateClassName: ['Coder', 'Hacker'],
  6133. * code: function(msg) {
  6134. * alert('Typing... ' + msg);
  6135. * }
  6136. * });
  6137. *
  6138. * var joe = Ext.create('Developer');
  6139. * joe.code('stackoverflow');
  6140. *
  6141. * var rms = Ext.create('Hacker');
  6142. * rms.code('hack hack');
  6143. */
  6144. Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
  6145. var alternates = data.alternateClassName,
  6146. i, ln, alternate;
  6147. if (!(alternates instanceof Array)) {
  6148. alternates = [alternates];
  6149. }
  6150. for (i = 0, ln = alternates.length; i < ln; i++) {
  6151. alternate = alternates[i];
  6152. //<debug error>
  6153. if (typeof alternate != 'string') {
  6154. throw new Error("[Ext.define] Invalid alternate of: '" + alternate + "' for class: '" + name + "'; must be a valid string");
  6155. }
  6156. //</debug>
  6157. this.set(alternate, cls);
  6158. }
  6159. });
  6160. //</feature>
  6161. Ext.apply(Ext, {
  6162. /**
  6163. * Instantiate a class by either full name, alias or alternate name.
  6164. *
  6165. * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has not been defined yet, it will
  6166. * attempt to load the class via synchronous loading.
  6167. *
  6168. * For example, all these three lines return the same result:
  6169. *
  6170. * // alias
  6171. * var formPanel = Ext.create('widget.formpanel', { width: 600, height: 800 });
  6172. *
  6173. * // alternate name
  6174. * var formPanel = Ext.create('Ext.form.FormPanel', { width: 600, height: 800 });
  6175. *
  6176. * // full class name
  6177. * var formPanel = Ext.create('Ext.form.Panel', { width: 600, height: 800 });
  6178. *
  6179. * @param {String} name
  6180. * @param {Mixed} args Additional arguments after the name will be passed to the class' constructor.
  6181. * @return {Object} instance
  6182. * @member Ext
  6183. */
  6184. create: alias(Manager, 'instantiate'),
  6185. /**
  6186. * Convenient shorthand to create a widget by its xtype, also see {@link Ext.ClassManager#instantiateByAlias}
  6187. *
  6188. * var button = Ext.widget('button'); // Equivalent to Ext.create('widget.button')
  6189. * var panel = Ext.widget('panel'); // Equivalent to Ext.create('widget.panel')
  6190. *
  6191. * @member Ext
  6192. * @method widget
  6193. */
  6194. widget: function(name) {
  6195. var args = arraySlice.call(arguments);
  6196. args[0] = 'widget.' + name;
  6197. return Manager.instantiateByAlias.apply(Manager, args);
  6198. },
  6199. /**
  6200. * Convenient shorthand, see {@link Ext.ClassManager#instantiateByAlias}.
  6201. * @member Ext
  6202. * @method createByAlias
  6203. */
  6204. createByAlias: alias(Manager, 'instantiateByAlias'),
  6205. /**
  6206. * Defines a class or override. A basic class is defined like this:
  6207. *
  6208. * Ext.define('My.awesome.Class', {
  6209. * someProperty: 'something',
  6210. *
  6211. * someMethod: function(s) {
  6212. * console.log(s + this.someProperty);
  6213. * }
  6214. * });
  6215. *
  6216. * var obj = new My.awesome.Class();
  6217. *
  6218. * obj.someMethod('Say '); // logs 'Say something' to the console
  6219. *
  6220. * To defines an override, include the `override` property. The content of an
  6221. * override is aggregated with the specified class in order to extend or modify
  6222. * that class. This can be as simple as setting default property values or it can
  6223. * extend and/or replace methods. This can also extend the statics of the class.
  6224. *
  6225. * One use for an override is to break a large class into manageable pieces.
  6226. *
  6227. * // File: /src/app/Panel.js
  6228. * Ext.define('My.app.Panel', {
  6229. * extend: 'Ext.panel.Panel',
  6230. * requires: [
  6231. * 'My.app.PanelPart2',
  6232. * 'My.app.PanelPart3'
  6233. * ],
  6234. *
  6235. * constructor: function (config) {
  6236. * this.callParent(arguments); // calls Ext.panel.Panel's constructor
  6237. * // ...
  6238. * },
  6239. *
  6240. * statics: {
  6241. * method: function () {
  6242. * return 'abc';
  6243. * }
  6244. * }
  6245. * });
  6246. *
  6247. * // File: /src/app/PanelPart2.js
  6248. * Ext.define('My.app.PanelPart2', {
  6249. * override: 'My.app.Panel',
  6250. *
  6251. * constructor: function (config) {
  6252. * this.callParent(arguments); // calls My.app.Panel's constructor
  6253. * // ...
  6254. * }
  6255. * });
  6256. *
  6257. * Another use for an override is to provide optional parts of classes that can be
  6258. * independently required. In this case, the class may even be unaware of the
  6259. * override altogether.
  6260. *
  6261. * Ext.define('My.ux.CoolTip', {
  6262. * override: 'Ext.tip.ToolTip',
  6263. *
  6264. * constructor: function (config) {
  6265. * this.callParent(arguments); // calls Ext.tip.ToolTip's constructor
  6266. * // ...
  6267. * }
  6268. * });
  6269. *
  6270. * The above override can now be required as normal.
  6271. *
  6272. * Ext.define('My.app.App', {
  6273. * requires: [
  6274. * 'My.ux.CoolTip'
  6275. * ]
  6276. * });
  6277. *
  6278. * Overrides can also contain statics:
  6279. *
  6280. * Ext.define('My.app.BarMod', {
  6281. * override: 'Ext.foo.Bar',
  6282. *
  6283. * statics: {
  6284. * method: function (x) {
  6285. * return this.callParent([x * 2]); // call Ext.foo.Bar.method
  6286. * }
  6287. * }
  6288. * });
  6289. *
  6290. * __IMPORTANT:__ An override is only included in a build if the class it overrides is
  6291. * required. Otherwise, the override, like the target class, is not included.
  6292. *
  6293. * @param {String} className The class name to create in string dot-namespaced format, for example:
  6294. * 'My.very.awesome.Class', 'FeedViewer.plugin.CoolPager'
  6295. *
  6296. * It is highly recommended to follow this simple convention:
  6297. * - The root and the class name are 'CamelCased'
  6298. * - Everything else is lower-cased
  6299. *
  6300. * @param {Object} data The key - value pairs of properties to apply to this class. Property names can be of
  6301. * any valid strings, except those in the reserved listed below:
  6302. *
  6303. * - `mixins`
  6304. * - `statics`
  6305. * - `config`
  6306. * - `alias`
  6307. * - `self`
  6308. * - `singleton`
  6309. * - `alternateClassName`
  6310. * - `override`
  6311. *
  6312. * @param {Function} [createdFn] Optional callback to execute after the class (or override)
  6313. * is created. The execution scope (`this`) will be the newly created class itself.
  6314. * @return {Ext.Base}
  6315. *
  6316. * @member Ext
  6317. * @method define
  6318. */
  6319. define: function (className, data, createdFn) {
  6320. if ('override' in data) {
  6321. return Manager.createOverride.apply(Manager, arguments);
  6322. }
  6323. return Manager.create.apply(Manager, arguments);
  6324. },
  6325. /**
  6326. * Convenient shorthand for {@link Ext.ClassManager#getName}.
  6327. * @member Ext
  6328. * @method getClassName
  6329. * @inheritdoc Ext.ClassManager#getName
  6330. */
  6331. getClassName: alias(Manager, 'getName'),
  6332. /**
  6333. * Returns the display name for object. This name is looked for in order from the following places:
  6334. *
  6335. * - `displayName` field of the object.
  6336. * - `$name` and `$class` fields of the object.
  6337. * - '$className` field of the object.
  6338. *
  6339. * This method is used by {@link Ext.Logger#log} to display information about objects.
  6340. *
  6341. * @param {Mixed} [object] The object who's display name to determine.
  6342. * @return {String} The determined display name, or "Anonymous" if none found.
  6343. * @member Ext
  6344. */
  6345. getDisplayName: function(object) {
  6346. if (object) {
  6347. if (object.displayName) {
  6348. return object.displayName;
  6349. }
  6350. if (object.$name && object.$class) {
  6351. return Ext.getClassName(object.$class) + '#' + object.$name;
  6352. }
  6353. if (object.$className) {
  6354. return object.$className;
  6355. }
  6356. }
  6357. return 'Anonymous';
  6358. },
  6359. /**
  6360. * Convenient shorthand, see {@link Ext.ClassManager#getClass}.
  6361. * @member Ext
  6362. * @method getClass
  6363. */
  6364. getClass: alias(Manager, 'getClass'),
  6365. /**
  6366. * Creates namespaces to be used for scoping variables and classes so that they are not global.
  6367. * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
  6368. *
  6369. * Ext.namespace('Company', 'Company.data');
  6370. *
  6371. * // equivalent and preferable to the above syntax
  6372. * Ext.namespace('Company.data');
  6373. *
  6374. * Company.Widget = function() {
  6375. * // ...
  6376. * };
  6377. *
  6378. * Company.data.CustomStore = function(config) {
  6379. * // ...
  6380. * };
  6381. *
  6382. * @param {String} namespace1
  6383. * @param {String} namespace2
  6384. * @param {String} etc
  6385. * @return {Object} The namespace object. If multiple arguments are passed, this will be the last namespace created.
  6386. * @member Ext
  6387. * @method namespace
  6388. */
  6389. namespace: alias(Manager, 'createNamespaces')
  6390. });
  6391. /**
  6392. * Old name for {@link Ext#widget}.
  6393. * @deprecated 4.0.0 Please use {@link Ext#widget} instead.
  6394. * @method createWidget
  6395. * @member Ext
  6396. */
  6397. Ext.createWidget = Ext.widget;
  6398. /**
  6399. * Convenient alias for {@link Ext#namespace Ext.namespace}.
  6400. * @member Ext
  6401. * @method ns
  6402. */
  6403. Ext.ns = Ext.namespace;
  6404. Class.registerPreprocessor('className', function(cls, data) {
  6405. if (data.$className) {
  6406. cls.$className = data.$className;
  6407. //<debug>
  6408. cls.displayName = cls.$className;
  6409. //</debug>
  6410. }
  6411. }, true, 'first');
  6412. Class.registerPreprocessor('alias', function(cls, data) {
  6413. var prototype = cls.prototype,
  6414. xtypes = arrayFrom(data.xtype),
  6415. aliases = arrayFrom(data.alias),
  6416. widgetPrefix = 'widget.',
  6417. widgetPrefixLength = widgetPrefix.length,
  6418. xtypesChain = Array.prototype.slice.call(prototype.xtypesChain || []),
  6419. xtypesMap = Ext.merge({}, prototype.xtypesMap || {}),
  6420. i, ln, alias, xtype;
  6421. for (i = 0,ln = aliases.length; i < ln; i++) {
  6422. alias = aliases[i];
  6423. //<debug error>
  6424. if (typeof alias != 'string' || alias.length < 1) {
  6425. throw new Error("[Ext.define] Invalid alias of: '" + alias + "' for class: '" + name + "'; must be a valid string");
  6426. }
  6427. //</debug>
  6428. if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {
  6429. xtype = alias.substring(widgetPrefixLength);
  6430. Ext.Array.include(xtypes, xtype);
  6431. }
  6432. }
  6433. cls.xtype = data.xtype = xtypes[0];
  6434. data.xtypes = xtypes;
  6435. for (i = 0,ln = xtypes.length; i < ln; i++) {
  6436. xtype = xtypes[i];
  6437. if (!xtypesMap[xtype]) {
  6438. xtypesMap[xtype] = true;
  6439. xtypesChain.push(xtype);
  6440. }
  6441. }
  6442. data.xtypesChain = xtypesChain;
  6443. data.xtypesMap = xtypesMap;
  6444. Ext.Function.interceptAfter(data, 'onClassCreated', function() {
  6445. var mixins = prototype.mixins,
  6446. key, mixin;
  6447. for (key in mixins) {
  6448. if (mixins.hasOwnProperty(key)) {
  6449. mixin = mixins[key];
  6450. xtypes = mixin.xtypes;
  6451. if (xtypes) {
  6452. for (i = 0,ln = xtypes.length; i < ln; i++) {
  6453. xtype = xtypes[i];
  6454. if (!xtypesMap[xtype]) {
  6455. xtypesMap[xtype] = true;
  6456. xtypesChain.push(xtype);
  6457. }
  6458. }
  6459. }
  6460. }
  6461. }
  6462. });
  6463. for (i = 0,ln = xtypes.length; i < ln; i++) {
  6464. xtype = xtypes[i];
  6465. //<debug error>
  6466. if (typeof xtype != 'string' || xtype.length < 1) {
  6467. throw new Error("[Ext.define] Invalid xtype of: '" + xtype + "' for class: '" + name + "'; must be a valid non-empty string");
  6468. }
  6469. //</debug>
  6470. Ext.Array.include(aliases, widgetPrefix + xtype);
  6471. }
  6472. data.alias = aliases;
  6473. }, ['xtype', 'alias']);
  6474. })(Ext.Class, Ext.Function.alias, Array.prototype.slice, Ext.Array.from, Ext.global);
  6475. //@tag foundation,core
  6476. //@define Ext.Loader
  6477. //@require Ext.ClassManager
  6478. /**
  6479. * @class Ext.Loader
  6480. *
  6481. * @author Jacky Nguyen <jacky@sencha.com>
  6482. * @docauthor Jacky Nguyen <jacky@sencha.com>
  6483. * @aside guide mvc_dependencies
  6484. *
  6485. * Ext.Loader is the heart of the new dynamic dependency loading capability in Ext JS 4+. It is most commonly used
  6486. * via the {@link Ext#require} shorthand. Ext.Loader supports both asynchronous and synchronous loading
  6487. * approaches, and leverage their advantages for the best development flow.
  6488. * We'll discuss about the pros and cons of each approach.
  6489. *
  6490. * __Note:__ The Loader is only enabled by default in development versions of the library (eg sencha-touch-debug.js). To
  6491. * explicitly enable the loader, use `Ext.Loader.setConfig({ enabled: true });` before the start of your script.
  6492. *
  6493. * ## Asynchronous Loading
  6494. *
  6495. * - Advantages:
  6496. * + Cross-domain
  6497. * + No web server needed: you can run the application via the file system protocol (i.e: `file://path/to/your/index
  6498. * .html`)
  6499. * + Best possible debugging experience: error messages come with the exact file name and line number
  6500. *
  6501. * - Disadvantages:
  6502. * + Dependencies need to be specified before-hand
  6503. *
  6504. * ### Method 1: Explicitly include what you need: ###
  6505. *
  6506. * // Syntax
  6507. * // Ext.require({String/Array} expressions);
  6508. *
  6509. * // Example: Single alias
  6510. * Ext.require('widget.window');
  6511. *
  6512. * // Example: Single class name
  6513. * Ext.require('Ext.window.Window');
  6514. *
  6515. * // Example: Multiple aliases / class names mix
  6516. * Ext.require(['widget.window', 'layout.border', 'Ext.data.Connection']);
  6517. *
  6518. * // Wildcards
  6519. * Ext.require(['widget.*', 'layout.*', 'Ext.data.*']);
  6520. *
  6521. * ### Method 2: Explicitly exclude what you don't need: ###
  6522. *
  6523. * // Syntax: Note that it must be in this chaining format.
  6524. * // Ext.exclude({String/Array} expressions)
  6525. * // .require({String/Array} expressions);
  6526. *
  6527. * // Include everything except Ext.data.*
  6528. * Ext.exclude('Ext.data.*').require('*');
  6529. *
  6530. * // Include all widgets except widget.checkbox*,
  6531. * // which will match widget.checkbox, widget.checkboxfield, widget.checkboxgroup, etc.
  6532. * Ext.exclude('widget.checkbox*').require('widget.*');
  6533. *
  6534. * # Synchronous Loading on Demand #
  6535. *
  6536. * - *Advantages:*
  6537. * + There's no need to specify dependencies before-hand, which is always the convenience of including ext-all.js
  6538. * before
  6539. *
  6540. * - *Disadvantages:*
  6541. * + Not as good debugging experience since file name won't be shown (except in Firebug at the moment)
  6542. * + Must be from the same domain due to XHR restriction
  6543. * + Need a web server, same reason as above
  6544. *
  6545. * There's one simple rule to follow: Instantiate everything with Ext.create instead of the `new` keyword
  6546. *
  6547. * Ext.create('widget.window', {}); // Instead of new Ext.window.Window({...});
  6548. *
  6549. * Ext.create('Ext.window.Window', {}); // Same as above, using full class name instead of alias
  6550. *
  6551. * Ext.widget('window', {}); // Same as above, all you need is the traditional `xtype`
  6552. *
  6553. * Behind the scene, {@link Ext.ClassManager} will automatically check whether the given class name / alias has already
  6554. * existed on the page. If it's not, Ext.Loader will immediately switch itself to synchronous mode and automatic load the given
  6555. * class and all its dependencies.
  6556. *
  6557. * # Hybrid Loading - The Best of Both Worlds #
  6558. *
  6559. * It has all the advantages combined from asynchronous and synchronous loading. The development flow is simple:
  6560. *
  6561. * ### Step 1: Start writing your application using synchronous approach. ###
  6562. * Ext.Loader will automatically fetch all dependencies on demand as they're
  6563. * needed during run-time. For example:
  6564. *
  6565. * Ext.onReady(function(){
  6566. * var window = Ext.createWidget('window', {
  6567. * width: 500,
  6568. * height: 300,
  6569. * layout: {
  6570. * type: 'border',
  6571. * padding: 5
  6572. * },
  6573. * title: 'Hello Dialog',
  6574. * items: [{
  6575. * title: 'Navigation',
  6576. * collapsible: true,
  6577. * region: 'west',
  6578. * width: 200,
  6579. * html: 'Hello',
  6580. * split: true
  6581. * }, {
  6582. * title: 'TabPanel',
  6583. * region: 'center'
  6584. * }]
  6585. * });
  6586. *
  6587. * window.show();
  6588. * });
  6589. *
  6590. * ### Step 2: Along the way, when you need better debugging ability, watch the console for warnings like these: ###
  6591. *
  6592. * [Ext.Loader] Synchronously loading 'Ext.window.Window'; consider adding Ext.require('Ext.window.Window') before your application's code
  6593. * ClassManager.js:432
  6594. * [Ext.Loader] Synchronously loading 'Ext.layout.container.Border'; consider adding Ext.require('Ext.layout.container.Border') before your application's code
  6595. *
  6596. * Simply copy and paste the suggested code above `Ext.onReady`, i.e:
  6597. *
  6598. * Ext.require('Ext.window.Window');
  6599. * Ext.require('Ext.layout.container.Border');
  6600. *
  6601. * Ext.onReady(function () {
  6602. * // ...
  6603. * });
  6604. *
  6605. * Everything should now load via asynchronous mode.
  6606. *
  6607. * # Deployment #
  6608. *
  6609. * It's important to note that dynamic loading should only be used during development on your local machines.
  6610. * During production, all dependencies should be combined into one single JavaScript file. Ext.Loader makes
  6611. * the whole process of transitioning from / to between development / maintenance and production as easy as
  6612. * possible. Internally {@link Ext.Loader#history Ext.Loader.history} maintains the list of all dependencies your application
  6613. * needs in the exact loading sequence. It's as simple as concatenating all files in this array into one,
  6614. * then include it on top of your application.
  6615. *
  6616. * This process will be automated with Sencha Command, to be released and documented towards Ext JS 4 Final.
  6617. *
  6618. * @singleton
  6619. */
  6620. (function(Manager, Class, flexSetter, alias, pass, arrayFrom, arrayErase, arrayInclude) {
  6621. var
  6622. dependencyProperties = ['extend', 'mixins', 'requires'],
  6623. Loader,
  6624. setPathCount = 0;;
  6625. Loader = Ext.Loader = {
  6626. /**
  6627. * @private
  6628. */
  6629. isInHistory: {},
  6630. /**
  6631. * An array of class names to keep track of the dependency loading order.
  6632. * This is not guaranteed to be the same every time due to the asynchronous
  6633. * nature of the Loader.
  6634. *
  6635. * @property history
  6636. * @type Array
  6637. */
  6638. history: [],
  6639. /**
  6640. * Configuration
  6641. * @private
  6642. */
  6643. config: {
  6644. /**
  6645. * Whether or not to enable the dynamic dependency loading feature.
  6646. * @cfg {Boolean} enabled
  6647. */
  6648. enabled: true,
  6649. /**
  6650. * @cfg {Boolean} disableCaching
  6651. * Appends current timestamp to script files to prevent caching.
  6652. */
  6653. disableCaching: true,
  6654. /**
  6655. * @cfg {String} disableCachingParam
  6656. * The get parameter name for the cache buster's timestamp.
  6657. */
  6658. disableCachingParam: '_dc',
  6659. /**
  6660. * @cfg {Object} paths
  6661. * The mapping from namespaces to file paths.
  6662. *
  6663. * {
  6664. * 'Ext': '.', // This is set by default, Ext.layout.container.Container will be
  6665. * // loaded from ./layout/Container.js
  6666. *
  6667. * 'My': './src/my_own_folder' // My.layout.Container will be loaded from
  6668. * // ./src/my_own_folder/layout/Container.js
  6669. * }
  6670. *
  6671. * Note that all relative paths are relative to the current HTML document.
  6672. * If not being specified, for example, `Other.awesome.Class`
  6673. * will simply be loaded from `./Other/awesome/Class.js`.
  6674. */
  6675. paths: {
  6676. 'Ext': '.'
  6677. }
  6678. },
  6679. /**
  6680. * Set the configuration for the loader. This should be called right after ext-(debug).js
  6681. * is included in the page, and before Ext.onReady. i.e:
  6682. *
  6683. * <script type="text/javascript" src="ext-core-debug.js"></script>
  6684. * <script type="text/javascript">
  6685. * Ext.Loader.setConfig({
  6686. * enabled: true,
  6687. * paths: {
  6688. * 'My': 'my_own_path'
  6689. * }
  6690. * });
  6691. * <script>
  6692. * <script type="text/javascript">
  6693. * Ext.require(...);
  6694. *
  6695. * Ext.onReady(function() {
  6696. * // application code here
  6697. * });
  6698. * </script>
  6699. *
  6700. * Refer to config options of {@link Ext.Loader} for the list of possible properties.
  6701. *
  6702. * @param {Object} config The config object to override the default values.
  6703. * @return {Ext.Loader} this
  6704. */
  6705. setConfig: function(name, value) {
  6706. if (Ext.isObject(name) && arguments.length === 1) {
  6707. Ext.merge(this.config, name);
  6708. }
  6709. else {
  6710. this.config[name] = (Ext.isObject(value)) ? Ext.merge(this.config[name], value) : value;
  6711. }
  6712. setPathCount += 1;
  6713. return this;
  6714. },
  6715. /**
  6716. * Get the config value corresponding to the specified name. If no name is given, will return the config object.
  6717. * @param {String} name The config property name.
  6718. * @return {Object/Mixed}
  6719. */
  6720. getConfig: function(name) {
  6721. if (name) {
  6722. return this.config[name];
  6723. }
  6724. return this.config;
  6725. },
  6726. /**
  6727. * Sets the path of a namespace.
  6728. * For example:
  6729. *
  6730. * Ext.Loader.setPath('Ext', '.');
  6731. *
  6732. * @param {String/Object} name See {@link Ext.Function#flexSetter flexSetter}
  6733. * @param {String} [path] See {@link Ext.Function#flexSetter flexSetter}
  6734. * @return {Ext.Loader} this
  6735. * @method
  6736. */
  6737. setPath: flexSetter(function(name, path) {
  6738. this.config.paths[name] = path;
  6739. setPathCount += 1;
  6740. return this;
  6741. }),
  6742. /**
  6743. * Sets a batch of path entries
  6744. *
  6745. * @param {Object } paths a set of className: path mappings
  6746. * @return {Ext.Loader} this
  6747. */
  6748. addClassPathMappings: function(paths) {
  6749. var name;
  6750. if(setPathCount == 0){
  6751. Loader.config.paths = paths;
  6752. } else {
  6753. for(name in paths){
  6754. Loader.config.paths[name] = paths[name];
  6755. }
  6756. }
  6757. setPathCount++;
  6758. return Loader;
  6759. },
  6760. /**
  6761. * Translates a className to a file path by adding the
  6762. * the proper prefix and converting the .'s to /'s. For example:
  6763. *
  6764. * Ext.Loader.setPath('My', '/path/to/My');
  6765. *
  6766. * alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/path/to/My/awesome/Class.js'
  6767. *
  6768. * Note that the deeper namespace levels, if explicitly set, are always resolved first. For example:
  6769. *
  6770. * Ext.Loader.setPath({
  6771. * 'My': '/path/to/lib',
  6772. * 'My.awesome': '/other/path/for/awesome/stuff',
  6773. * 'My.awesome.more': '/more/awesome/path'
  6774. * });
  6775. *
  6776. * alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/other/path/for/awesome/stuff/Class.js'
  6777. *
  6778. * alert(Ext.Loader.getPath('My.awesome.more.Class')); // alerts '/more/awesome/path/Class.js'
  6779. *
  6780. * alert(Ext.Loader.getPath('My.cool.Class')); // alerts '/path/to/lib/cool/Class.js'
  6781. *
  6782. * alert(Ext.Loader.getPath('Unknown.strange.Stuff')); // alerts 'Unknown/strange/Stuff.js'
  6783. *
  6784. * @param {String} className
  6785. * @return {String} path
  6786. */
  6787. getPath: function(className) {
  6788. var path = '',
  6789. paths = this.config.paths,
  6790. prefix = this.getPrefix(className);
  6791. if (prefix.length > 0) {
  6792. if (prefix === className) {
  6793. return paths[prefix];
  6794. }
  6795. path = paths[prefix];
  6796. className = className.substring(prefix.length + 1);
  6797. }
  6798. if (path.length > 0) {
  6799. path += '/';
  6800. }
  6801. return path.replace(/\/\.\//g, '/') + className.replace(/\./g, "/") + '.js';
  6802. },
  6803. /**
  6804. * @private
  6805. * @param {String} className
  6806. */
  6807. getPrefix: function(className) {
  6808. var paths = this.config.paths,
  6809. prefix, deepestPrefix = '';
  6810. if (paths.hasOwnProperty(className)) {
  6811. return className;
  6812. }
  6813. for (prefix in paths) {
  6814. if (paths.hasOwnProperty(prefix) && prefix + '.' === className.substring(0, prefix.length + 1)) {
  6815. if (prefix.length > deepestPrefix.length) {
  6816. deepestPrefix = prefix;
  6817. }
  6818. }
  6819. }
  6820. return deepestPrefix;
  6821. },
  6822. /**
  6823. * Loads all classes by the given names and all their direct dependencies; optionally executes the given callback function when
  6824. * finishes, within the optional scope. This method is aliased by {@link Ext#require Ext.require} for convenience.
  6825. * @param {String/Array} expressions Can either be a string or an array of string.
  6826. * @param {Function} fn (optional) The callback function.
  6827. * @param {Object} scope (optional) The execution scope (`this`) of the callback function.
  6828. * @param {String/Array} excludes (optional) Classes to be excluded, useful when being used with expressions.
  6829. */
  6830. require: function(expressions, fn, scope, excludes) {
  6831. if (fn) {
  6832. fn.call(scope);
  6833. }
  6834. },
  6835. /**
  6836. * Synchronously loads all classes by the given names and all their direct dependencies; optionally executes the given callback function when finishes, within the optional scope. This method is aliased by {@link Ext#syncRequire} for convenience
  6837. * @param {String/Array} expressions Can either be a string or an array of string
  6838. * @param {Function} fn (optional) The callback function
  6839. * @param {Object} scope (optional) The execution scope (`this`) of the callback function
  6840. * @param {String/Array} excludes (optional) Classes to be excluded, useful when being used with expressions
  6841. */
  6842. syncRequire: function() {},
  6843. /**
  6844. * Explicitly exclude files from being loaded. Useful when used in conjunction with a broad include expression.
  6845. * Can be chained with more `require` and `exclude` methods, eg:
  6846. *
  6847. * Ext.exclude('Ext.data.*').require('*');
  6848. *
  6849. * Ext.exclude('widget.button*').require('widget.*');
  6850. *
  6851. * @param {Array} excludes
  6852. * @return {Object} object contains `require` method for chaining.
  6853. */
  6854. exclude: function(excludes) {
  6855. var me = this;
  6856. return {
  6857. require: function(expressions, fn, scope) {
  6858. return me.require(expressions, fn, scope, excludes);
  6859. },
  6860. syncRequire: function(expressions, fn, scope) {
  6861. return me.syncRequire(expressions, fn, scope, excludes);
  6862. }
  6863. };
  6864. },
  6865. /**
  6866. * Add a new listener to be executed when all required scripts are fully loaded.
  6867. *
  6868. * @param {Function} fn The function callback to be executed.
  6869. * @param {Object} scope The execution scope (`this`) of the callback function.
  6870. * @param {Boolean} withDomReady Whether or not to wait for document DOM ready as well.
  6871. */
  6872. onReady: function(fn, scope, withDomReady, options) {
  6873. var oldFn;
  6874. if (withDomReady !== false && Ext.onDocumentReady) {
  6875. oldFn = fn;
  6876. fn = function() {
  6877. Ext.onDocumentReady(oldFn, scope, options);
  6878. };
  6879. }
  6880. fn.call(scope);
  6881. }
  6882. };
  6883. //<feature classSystem.loader>
  6884. Ext.apply(Loader, {
  6885. /**
  6886. * @private
  6887. */
  6888. documentHead: typeof document != 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
  6889. /**
  6890. * Flag indicating whether there are still files being loaded
  6891. * @private
  6892. */
  6893. isLoading: false,
  6894. /**
  6895. * Maintain the queue for all dependencies. Each item in the array is an object of the format:
  6896. *
  6897. * {
  6898. * requires: [...], // The required classes for this queue item
  6899. * callback: function() { ... } // The function to execute when all classes specified in requires exist
  6900. * }
  6901. * @private
  6902. */
  6903. queue: [],
  6904. /**
  6905. * Maintain the list of files that have already been handled so that they never get double-loaded
  6906. * @private
  6907. */
  6908. isClassFileLoaded: {},
  6909. /**
  6910. * @private
  6911. */
  6912. isFileLoaded: {},
  6913. /**
  6914. * Maintain the list of listeners to execute when all required scripts are fully loaded
  6915. * @private
  6916. */
  6917. readyListeners: [],
  6918. /**
  6919. * Contains optional dependencies to be loaded last
  6920. * @private
  6921. */
  6922. optionalRequires: [],
  6923. /**
  6924. * Map of fully qualified class names to an array of dependent classes.
  6925. * @private
  6926. */
  6927. requiresMap: {},
  6928. /**
  6929. * @private
  6930. */
  6931. numPendingFiles: 0,
  6932. /**
  6933. * @private
  6934. */
  6935. numLoadedFiles: 0,
  6936. /** @private */
  6937. hasFileLoadError: false,
  6938. /**
  6939. * @private
  6940. */
  6941. classNameToFilePathMap: {},
  6942. /**
  6943. * @private
  6944. */
  6945. syncModeEnabled: false,
  6946. scriptElements: {},
  6947. /**
  6948. * Refresh all items in the queue. If all dependencies for an item exist during looping,
  6949. * it will execute the callback and call refreshQueue again. Triggers onReady when the queue is
  6950. * empty
  6951. * @private
  6952. */
  6953. refreshQueue: function() {
  6954. var queue = this.queue,
  6955. ln = queue.length,
  6956. i, item, j, requires, references;
  6957. if (ln === 0) {
  6958. this.triggerReady();
  6959. return;
  6960. }
  6961. for (i = 0; i < ln; i++) {
  6962. item = queue[i];
  6963. if (item) {
  6964. requires = item.requires;
  6965. references = item.references;
  6966. // Don't bother checking when the number of files loaded
  6967. // is still less than the array length
  6968. if (requires.length > this.numLoadedFiles) {
  6969. continue;
  6970. }
  6971. j = 0;
  6972. do {
  6973. if (Manager.isCreated(requires[j])) {
  6974. // Take out from the queue
  6975. arrayErase(requires, j, 1);
  6976. }
  6977. else {
  6978. j++;
  6979. }
  6980. } while (j < requires.length);
  6981. if (item.requires.length === 0) {
  6982. arrayErase(queue, i, 1);
  6983. item.callback.call(item.scope);
  6984. this.refreshQueue();
  6985. break;
  6986. }
  6987. }
  6988. }
  6989. return this;
  6990. },
  6991. /**
  6992. * Inject a script element to document's head, call onLoad and onError accordingly
  6993. * @private
  6994. */
  6995. injectScriptElement: function(url, onLoad, onError, scope) {
  6996. var script = document.createElement('script'),
  6997. me = this,
  6998. onLoadFn = function() {
  6999. me.cleanupScriptElement(script);
  7000. onLoad.call(scope);
  7001. },
  7002. onErrorFn = function() {
  7003. me.cleanupScriptElement(script);
  7004. onError.call(scope);
  7005. };
  7006. script.type = 'text/javascript';
  7007. script.src = url;
  7008. script.onload = onLoadFn;
  7009. script.onerror = onErrorFn;
  7010. script.onreadystatechange = function() {
  7011. if (this.readyState === 'loaded' || this.readyState === 'complete') {
  7012. onLoadFn();
  7013. }
  7014. };
  7015. this.documentHead.appendChild(script);
  7016. return script;
  7017. },
  7018. removeScriptElement: function(url) {
  7019. var scriptElements = this.scriptElements;
  7020. if (scriptElements[url]) {
  7021. this.cleanupScriptElement(scriptElements[url], true);
  7022. delete scriptElements[url];
  7023. }
  7024. return this;
  7025. },
  7026. /**
  7027. * @private
  7028. */
  7029. cleanupScriptElement: function(script, remove) {
  7030. script.onload = null;
  7031. script.onreadystatechange = null;
  7032. script.onerror = null;
  7033. if (remove) {
  7034. this.documentHead.removeChild(script);
  7035. }
  7036. return this;
  7037. },
  7038. /**
  7039. * Load a script file, supports both asynchronous and synchronous approaches
  7040. *
  7041. * @param {String} url
  7042. * @param {Function} onLoad
  7043. * @param {Object} scope
  7044. * @param {Boolean} synchronous
  7045. * @private
  7046. */
  7047. loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
  7048. var me = this,
  7049. isFileLoaded = this.isFileLoaded,
  7050. scriptElements = this.scriptElements,
  7051. noCacheUrl = url + (this.getConfig('disableCaching') ? ('?' + this.getConfig('disableCachingParam') + '=' + Ext.Date.now()) : ''),
  7052. xhr, status, content, onScriptError;
  7053. if (isFileLoaded[url]) {
  7054. return this;
  7055. }
  7056. scope = scope || this;
  7057. this.isLoading = true;
  7058. if (!synchronous) {
  7059. onScriptError = function() {
  7060. //<debug error>
  7061. onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
  7062. //</debug>
  7063. };
  7064. if (!Ext.isReady && Ext.onDocumentReady) {
  7065. Ext.onDocumentReady(function() {
  7066. if (!isFileLoaded[url]) {
  7067. scriptElements[url] = me.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
  7068. }
  7069. });
  7070. }
  7071. else {
  7072. scriptElements[url] = this.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
  7073. }
  7074. }
  7075. else {
  7076. if (typeof XMLHttpRequest != 'undefined') {
  7077. xhr = new XMLHttpRequest();
  7078. } else {
  7079. xhr = new ActiveXObject('Microsoft.XMLHTTP');
  7080. }
  7081. try {
  7082. xhr.open('GET', noCacheUrl, false);
  7083. xhr.send(null);
  7084. }
  7085. catch (e) {
  7086. //<debug error>
  7087. onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " +
  7088. "being loaded from a different domain or from the local file system whereby cross origin " +
  7089. "requests are not allowed due to security reasons. Use asynchronous loading with " +
  7090. "Ext.require instead.", synchronous);
  7091. //</debug>
  7092. }
  7093. status = (xhr.status == 1223) ? 204 : xhr.status;
  7094. content = xhr.responseText;
  7095. if ((status >= 200 && status < 300) || status == 304 || (status == 0 && content.length > 0)) {
  7096. // Debugger friendly, file names are still shown even though they're eval'ed code
  7097. // Breakpoints work on both Firebug and Chrome's Web Inspector
  7098. Ext.globalEval(content + "\n//@ sourceURL=" + url);
  7099. onLoad.call(scope);
  7100. }
  7101. else {
  7102. //<debug>
  7103. onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; please " +
  7104. "verify that the file exists. " +
  7105. "XHR status code: " + status, synchronous);
  7106. //</debug>
  7107. }
  7108. // Prevent potential IE memory leak
  7109. xhr = null;
  7110. }
  7111. },
  7112. // documented above
  7113. syncRequire: function() {
  7114. var syncModeEnabled = this.syncModeEnabled;
  7115. if (!syncModeEnabled) {
  7116. this.syncModeEnabled = true;
  7117. }
  7118. this.require.apply(this, arguments);
  7119. if (!syncModeEnabled) {
  7120. this.syncModeEnabled = false;
  7121. }
  7122. this.refreshQueue();
  7123. },
  7124. // documented above
  7125. require: function(expressions, fn, scope, excludes) {
  7126. var excluded = {},
  7127. included = {},
  7128. queue = this.queue,
  7129. classNameToFilePathMap = this.classNameToFilePathMap,
  7130. isClassFileLoaded = this.isClassFileLoaded,
  7131. excludedClassNames = [],
  7132. possibleClassNames = [],
  7133. classNames = [],
  7134. references = [],
  7135. callback,
  7136. syncModeEnabled,
  7137. filePath, expression, exclude, className,
  7138. possibleClassName, i, j, ln, subLn;
  7139. if (excludes) {
  7140. excludes = arrayFrom(excludes);
  7141. for (i = 0,ln = excludes.length; i < ln; i++) {
  7142. exclude = excludes[i];
  7143. if (typeof exclude == 'string' && exclude.length > 0) {
  7144. excludedClassNames = Manager.getNamesByExpression(exclude);
  7145. for (j = 0,subLn = excludedClassNames.length; j < subLn; j++) {
  7146. excluded[excludedClassNames[j]] = true;
  7147. }
  7148. }
  7149. }
  7150. }
  7151. expressions = arrayFrom(expressions);
  7152. if (fn) {
  7153. if (fn.length > 0) {
  7154. callback = function() {
  7155. var classes = [],
  7156. i, ln, name;
  7157. for (i = 0,ln = references.length; i < ln; i++) {
  7158. name = references[i];
  7159. classes.push(Manager.get(name));
  7160. }
  7161. return fn.apply(this, classes);
  7162. };
  7163. }
  7164. else {
  7165. callback = fn;
  7166. }
  7167. }
  7168. else {
  7169. callback = Ext.emptyFn;
  7170. }
  7171. scope = scope || Ext.global;
  7172. for (i = 0,ln = expressions.length; i < ln; i++) {
  7173. expression = expressions[i];
  7174. if (typeof expression == 'string' && expression.length > 0) {
  7175. possibleClassNames = Manager.getNamesByExpression(expression);
  7176. subLn = possibleClassNames.length;
  7177. for (j = 0; j < subLn; j++) {
  7178. possibleClassName = possibleClassNames[j];
  7179. if (excluded[possibleClassName] !== true) {
  7180. references.push(possibleClassName);
  7181. if (!Manager.isCreated(possibleClassName) && !included[possibleClassName]) {
  7182. included[possibleClassName] = true;
  7183. classNames.push(possibleClassName);
  7184. }
  7185. }
  7186. }
  7187. }
  7188. }
  7189. // If the dynamic dependency feature is not being used, throw an error
  7190. // if the dependencies are not defined
  7191. if (classNames.length > 0) {
  7192. if (!this.config.enabled) {
  7193. throw new Error("Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
  7194. "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', '));
  7195. }
  7196. }
  7197. else {
  7198. callback.call(scope);
  7199. return this;
  7200. }
  7201. syncModeEnabled = this.syncModeEnabled;
  7202. if (!syncModeEnabled) {
  7203. queue.push({
  7204. requires: classNames.slice(), // this array will be modified as the queue is processed,
  7205. // so we need a copy of it
  7206. callback: callback,
  7207. scope: scope
  7208. });
  7209. }
  7210. ln = classNames.length;
  7211. for (i = 0; i < ln; i++) {
  7212. className = classNames[i];
  7213. filePath = this.getPath(className);
  7214. // If we are synchronously loading a file that has already been asynchronously loaded before
  7215. // we need to destroy the script tag and revert the count
  7216. // This file will then be forced loaded in synchronous
  7217. if (syncModeEnabled && isClassFileLoaded.hasOwnProperty(className)) {
  7218. this.numPendingFiles--;
  7219. this.removeScriptElement(filePath);
  7220. delete isClassFileLoaded[className];
  7221. }
  7222. if (!isClassFileLoaded.hasOwnProperty(className)) {
  7223. isClassFileLoaded[className] = false;
  7224. classNameToFilePathMap[className] = filePath;
  7225. this.numPendingFiles++;
  7226. this.loadScriptFile(
  7227. filePath,
  7228. pass(this.onFileLoaded, [className, filePath], this),
  7229. pass(this.onFileLoadError, [className, filePath]),
  7230. this,
  7231. syncModeEnabled
  7232. );
  7233. }
  7234. }
  7235. if (syncModeEnabled) {
  7236. callback.call(scope);
  7237. if (ln === 1) {
  7238. return Manager.get(className);
  7239. }
  7240. }
  7241. return this;
  7242. },
  7243. /**
  7244. * @private
  7245. * @param {String} className
  7246. * @param {String} filePath
  7247. */
  7248. onFileLoaded: function(className, filePath) {
  7249. this.numLoadedFiles++;
  7250. this.isClassFileLoaded[className] = true;
  7251. this.isFileLoaded[filePath] = true;
  7252. this.numPendingFiles--;
  7253. if (this.numPendingFiles === 0) {
  7254. this.refreshQueue();
  7255. }
  7256. //<debug>
  7257. if (!this.syncModeEnabled && this.numPendingFiles === 0 && this.isLoading && !this.hasFileLoadError) {
  7258. var queue = this.queue,
  7259. missingClasses = [],
  7260. missingPaths = [],
  7261. requires,
  7262. i, ln, j, subLn;
  7263. for (i = 0,ln = queue.length; i < ln; i++) {
  7264. requires = queue[i].requires;
  7265. for (j = 0,subLn = requires.length; j < subLn; j++) {
  7266. if (this.isClassFileLoaded[requires[j]]) {
  7267. missingClasses.push(requires[j]);
  7268. }
  7269. }
  7270. }
  7271. if (missingClasses.length < 1) {
  7272. return;
  7273. }
  7274. missingClasses = Ext.Array.filter(Ext.Array.unique(missingClasses), function(item) {
  7275. return !this.requiresMap.hasOwnProperty(item);
  7276. }, this);
  7277. for (i = 0,ln = missingClasses.length; i < ln; i++) {
  7278. missingPaths.push(this.classNameToFilePathMap[missingClasses[i]]);
  7279. }
  7280. throw new Error("The following classes are not declared even if their files have been " +
  7281. "loaded: '" + missingClasses.join("', '") + "'. Please check the source code of their " +
  7282. "corresponding files for possible typos: '" + missingPaths.join("', '"));
  7283. }
  7284. //</debug>
  7285. },
  7286. /**
  7287. * @private
  7288. */
  7289. onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
  7290. this.numPendingFiles--;
  7291. this.hasFileLoadError = true;
  7292. //<debug error>
  7293. throw new Error("[Ext.Loader] " + errorMessage);
  7294. //</debug>
  7295. },
  7296. /**
  7297. * @private
  7298. */
  7299. addOptionalRequires: function(requires) {
  7300. var optionalRequires = this.optionalRequires,
  7301. i, ln, require;
  7302. requires = arrayFrom(requires);
  7303. for (i = 0, ln = requires.length; i < ln; i++) {
  7304. require = requires[i];
  7305. arrayInclude(optionalRequires, require);
  7306. }
  7307. return this;
  7308. },
  7309. /**
  7310. * @private
  7311. */
  7312. triggerReady: function(force) {
  7313. var readyListeners = this.readyListeners,
  7314. optionalRequires = this.optionalRequires,
  7315. listener;
  7316. if (this.isLoading || force) {
  7317. this.isLoading = false;
  7318. if (optionalRequires.length !== 0) {
  7319. // Clone then empty the array to eliminate potential recursive loop issue
  7320. optionalRequires = optionalRequires.slice();
  7321. // Empty the original array
  7322. this.optionalRequires.length = 0;
  7323. this.require(optionalRequires, pass(this.triggerReady, [true], this), this);
  7324. return this;
  7325. }
  7326. while (readyListeners.length) {
  7327. listener = readyListeners.shift();
  7328. listener.fn.call(listener.scope);
  7329. if (this.isLoading) {
  7330. return this;
  7331. }
  7332. }
  7333. }
  7334. return this;
  7335. },
  7336. // duplicate definition (documented above)
  7337. onReady: function(fn, scope, withDomReady, options) {
  7338. var oldFn;
  7339. if (withDomReady !== false && Ext.onDocumentReady) {
  7340. oldFn = fn;
  7341. fn = function() {
  7342. Ext.onDocumentReady(oldFn, scope, options);
  7343. };
  7344. }
  7345. if (!this.isLoading) {
  7346. fn.call(scope);
  7347. }
  7348. else {
  7349. this.readyListeners.push({
  7350. fn: fn,
  7351. scope: scope
  7352. });
  7353. }
  7354. },
  7355. /**
  7356. * @private
  7357. * @param {String} className
  7358. */
  7359. historyPush: function(className) {
  7360. var isInHistory = this.isInHistory;
  7361. if (className && this.isClassFileLoaded.hasOwnProperty(className) && !isInHistory[className]) {
  7362. isInHistory[className] = true;
  7363. this.history.push(className);
  7364. }
  7365. return this;
  7366. }
  7367. });
  7368. //</feature>
  7369. /**
  7370. * Convenient alias of {@link Ext.Loader#require}. Please see the introduction documentation of
  7371. * {@link Ext.Loader} for examples.
  7372. * @member Ext
  7373. * @method require
  7374. * @inheritdoc Ext.Loader#require
  7375. */
  7376. Ext.require = alias(Loader, 'require');
  7377. /**
  7378. * Synchronous version of {@link Ext#require}, convenient alias of {@link Ext.Loader#syncRequire}.
  7379. * @member Ext
  7380. * @method syncRequire
  7381. * @inheritdoc Ext.Loader#syncRequire
  7382. */
  7383. Ext.syncRequire = alias(Loader, 'syncRequire');
  7384. /**
  7385. * Convenient shortcut to {@link Ext.Loader#exclude}.
  7386. * @member Ext
  7387. * @method exclude
  7388. * @inheritdoc Ext.Loader#exclude
  7389. */
  7390. Ext.exclude = alias(Loader, 'exclude');
  7391. /**
  7392. * Adds a listener to be notified when the document is ready and all dependencies are loaded.
  7393. *
  7394. * @param {Function} fn The method the event invokes.
  7395. * @param {Object} [scope] The scope in which the handler function executes. Defaults to the browser window.
  7396. * @param {Boolean} [options] Options object as passed to {@link Ext.Element#addListener}. It is recommended
  7397. * that the options `{single: true}` be used so that the handler is removed on first invocation.
  7398. * @member Ext
  7399. * @method onReady
  7400. */
  7401. Ext.onReady = function(fn, scope, options) {
  7402. Loader.onReady(fn, scope, true, options);
  7403. };
  7404. Class.registerPreprocessor('loader', function(cls, data, hooks, continueFn) {
  7405. var me = this,
  7406. dependencies = [],
  7407. className = Manager.getName(cls),
  7408. i, j, ln, subLn, value, propertyName, propertyValue;
  7409. /*
  7410. Loop through the dependencyProperties, look for string class names and push
  7411. them into a stack, regardless of whether the property's value is a string, array or object. For example:
  7412. {
  7413. extend: 'Ext.MyClass',
  7414. requires: ['Ext.some.OtherClass'],
  7415. mixins: {
  7416. observable: 'Ext.mixin.Observable';
  7417. }
  7418. }
  7419. which will later be transformed into:
  7420. {
  7421. extend: Ext.MyClass,
  7422. requires: [Ext.some.OtherClass],
  7423. mixins: {
  7424. observable: Ext.mixin.Observable;
  7425. }
  7426. }
  7427. */
  7428. for (i = 0,ln = dependencyProperties.length; i < ln; i++) {
  7429. propertyName = dependencyProperties[i];
  7430. if (data.hasOwnProperty(propertyName)) {
  7431. propertyValue = data[propertyName];
  7432. if (typeof propertyValue == 'string') {
  7433. dependencies.push(propertyValue);
  7434. }
  7435. else if (propertyValue instanceof Array) {
  7436. for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
  7437. value = propertyValue[j];
  7438. if (typeof value == 'string') {
  7439. dependencies.push(value);
  7440. }
  7441. }
  7442. }
  7443. else if (typeof propertyValue != 'function') {
  7444. for (j in propertyValue) {
  7445. if (propertyValue.hasOwnProperty(j)) {
  7446. value = propertyValue[j];
  7447. if (typeof value == 'string') {
  7448. dependencies.push(value);
  7449. }
  7450. }
  7451. }
  7452. }
  7453. }
  7454. }
  7455. if (dependencies.length === 0) {
  7456. return;
  7457. }
  7458. //<feature classSystem.loader>
  7459. //<debug error>
  7460. var deadlockPath = [],
  7461. requiresMap = Loader.requiresMap,
  7462. detectDeadlock;
  7463. /*
  7464. Automatically detect deadlocks before-hand,
  7465. will throw an error with detailed path for ease of debugging. Examples of deadlock cases:
  7466. - A extends B, then B extends A
  7467. - A requires B, B requires C, then C requires A
  7468. The detectDeadlock function will recursively transverse till the leaf, hence it can detect deadlocks
  7469. no matter how deep the path is.
  7470. */
  7471. if (className) {
  7472. requiresMap[className] = dependencies;
  7473. //<debug>
  7474. if (!Loader.requiredByMap) Loader.requiredByMap = {};
  7475. Ext.Array.each(dependencies, function(dependency){
  7476. if (!Loader.requiredByMap[dependency]) Loader.requiredByMap[dependency] = [];
  7477. Loader.requiredByMap[dependency].push(className);
  7478. });
  7479. //</debug>
  7480. detectDeadlock = function(cls) {
  7481. deadlockPath.push(cls);
  7482. if (requiresMap[cls]) {
  7483. if (Ext.Array.contains(requiresMap[cls], className)) {
  7484. throw new Error("Deadlock detected while loading dependencies! '" + className + "' and '" +
  7485. deadlockPath[1] + "' " + "mutually require each other. Path: " +
  7486. deadlockPath.join(' -> ') + " -> " + deadlockPath[0]);
  7487. }
  7488. for (i = 0,ln = requiresMap[cls].length; i < ln; i++) {
  7489. detectDeadlock(requiresMap[cls][i]);
  7490. }
  7491. }
  7492. };
  7493. detectDeadlock(className);
  7494. }
  7495. //</debug>
  7496. //</feature>
  7497. Loader.require(dependencies, function() {
  7498. for (i = 0,ln = dependencyProperties.length; i < ln; i++) {
  7499. propertyName = dependencyProperties[i];
  7500. if (data.hasOwnProperty(propertyName)) {
  7501. propertyValue = data[propertyName];
  7502. if (typeof propertyValue == 'string') {
  7503. data[propertyName] = Manager.get(propertyValue);
  7504. }
  7505. else if (propertyValue instanceof Array) {
  7506. for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
  7507. value = propertyValue[j];
  7508. if (typeof value == 'string') {
  7509. data[propertyName][j] = Manager.get(value);
  7510. }
  7511. }
  7512. }
  7513. else if (typeof propertyValue != 'function') {
  7514. for (var k in propertyValue) {
  7515. if (propertyValue.hasOwnProperty(k)) {
  7516. value = propertyValue[k];
  7517. if (typeof value == 'string') {
  7518. data[propertyName][k] = Manager.get(value);
  7519. }
  7520. }
  7521. }
  7522. }
  7523. }
  7524. }
  7525. continueFn.call(me, cls, data, hooks);
  7526. });
  7527. return false;
  7528. }, true, 'after', 'className');
  7529. //<feature classSystem.loader>
  7530. /**
  7531. * @cfg {String[]} uses
  7532. * @member Ext.Class
  7533. * List of optional classes to load together with this class. These aren't necessarily loaded before
  7534. * this class is created, but are guaranteed to be available before Ext.onReady listeners are
  7535. * invoked
  7536. */
  7537. Manager.registerPostprocessor('uses', function(name, cls, data) {
  7538. var uses = arrayFrom(data.uses),
  7539. items = [],
  7540. i, ln, item;
  7541. for (i = 0,ln = uses.length; i < ln; i++) {
  7542. item = uses[i];
  7543. if (typeof item == 'string') {
  7544. items.push(item);
  7545. }
  7546. }
  7547. Loader.addOptionalRequires(items);
  7548. });
  7549. Manager.onCreated(function(className) {
  7550. this.historyPush(className);
  7551. }, Loader);
  7552. //</feature>
  7553. })(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias,
  7554. Ext.Function.pass, Ext.Array.from, Ext.Array.erase, Ext.Array.include);
  7555. // initalize the default path of the framework
  7556. // trimmed down version of sench-touch-debug-suffix.js
  7557. // with alias / alternates removed, as those are handled separately by
  7558. // compiler-generated metadata
  7559. (function() {
  7560. var scripts = document.getElementsByTagName('script'),
  7561. currentScript = scripts[scripts.length - 1],
  7562. src = currentScript.src,
  7563. path = src.substring(0, src.lastIndexOf('/') + 1),
  7564. Loader = Ext.Loader;
  7565. //<debug>
  7566. // if we're running in dev mode out of the repo src tree, then this
  7567. // file will potentially be loaded from the touch/src/core/class folder
  7568. // so we'll need to adjust for that
  7569. if(src.indexOf("src/core/class/") != -1) {
  7570. path = path + "../../../";
  7571. }
  7572. //</debug>
  7573. Loader.setConfig({
  7574. enabled: true,
  7575. disableCaching: !/[?&](cache|breakpoint)/i.test(location.search),
  7576. paths: {
  7577. 'Ext' : path + 'src'
  7578. }
  7579. });
  7580. })();
  7581. //@tag dom,core
  7582. //@define Ext.EventManager
  7583. //@define Ext.core.EventManager
  7584. //@require Ext.Loader
  7585. /**
  7586. * @class Ext.EventManager
  7587. *
  7588. * This object has been deprecated in Sencha Touch 2.0.0. Please refer to the method documentation for specific alternatives.
  7589. *
  7590. * @deprecated 2.0.0
  7591. * @singleton
  7592. * @private
  7593. */
  7594. //@tag dom,core
  7595. //@define Ext-more
  7596. //@require Ext.EventManager
  7597. /**
  7598. * @class Ext
  7599. *
  7600. * Ext is the global namespace for the whole Sencha Touch framework. Every class, function and configuration for the
  7601. * whole framework exists under this single global variable. The Ext singleton itself contains a set of useful helper
  7602. * functions (like {@link #apply}, {@link #min} and others), but most of the framework that you use day to day exists
  7603. * in specialized classes (for example {@link Ext.Panel}, {@link Ext.Carousel} and others).
  7604. *
  7605. * If you are new to Sencha Touch we recommend starting with the [Getting Started Guide][getting_started] to
  7606. * get a feel for how the framework operates. After that, use the more focused guides on subjects like panels, forms and data
  7607. * to broaden your understanding. The MVC guides take you through the process of building full applications using the
  7608. * framework, and detail how to deploy them to production.
  7609. *
  7610. * The functions listed below are mostly utility functions used internally by many of the classes shipped in the
  7611. * framework, but also often useful in your own apps.
  7612. *
  7613. * A method that is crucial to beginning your application is {@link #setup Ext.setup}. Please refer to it's documentation, or the
  7614. * [Getting Started Guide][getting_started] as a reference on beginning your application.
  7615. *
  7616. * Ext.setup({
  7617. * onReady: function() {
  7618. * Ext.Viewport.add({
  7619. * xtype: 'component',
  7620. * html: 'Hello world!'
  7621. * });
  7622. * }
  7623. * });
  7624. *
  7625. * [getting_started]: #!/guide/getting_started
  7626. */
  7627. Ext.setVersion('touch', '2.1.0');
  7628. Ext.apply(Ext, {
  7629. /**
  7630. * The version of the framework
  7631. * @type String
  7632. */
  7633. version: Ext.getVersion('touch'),
  7634. /**
  7635. * @private
  7636. */
  7637. idSeed: 0,
  7638. /**
  7639. * Repaints the whole page. This fixes frequently encountered painting issues in mobile Safari.
  7640. */
  7641. repaint: function() {
  7642. var mask = Ext.getBody().createChild({
  7643. cls: Ext.baseCSSPrefix + 'mask ' + Ext.baseCSSPrefix + 'mask-transparent'
  7644. });
  7645. setTimeout(function() {
  7646. mask.destroy();
  7647. }, 0);
  7648. },
  7649. /**
  7650. * Generates unique ids. If the element already has an `id`, it is unchanged.
  7651. * @param {Mixed} el (optional) The element to generate an id for.
  7652. * @param {String} [prefix=ext-gen] (optional) The `id` prefix.
  7653. * @return {String} The generated `id`.
  7654. */
  7655. id: function(el, prefix) {
  7656. if (el && el.id) {
  7657. return el.id;
  7658. }
  7659. el = Ext.getDom(el) || {};
  7660. if (el === document || el === document.documentElement) {
  7661. el.id = 'ext-application';
  7662. }
  7663. else if (el === document.body) {
  7664. el.id = 'ext-viewport';
  7665. }
  7666. else if (el === window) {
  7667. el.id = 'ext-window';
  7668. }
  7669. el.id = el.id || ((prefix || 'ext-element-') + (++Ext.idSeed));
  7670. return el.id;
  7671. },
  7672. /**
  7673. * Returns the current document body as an {@link Ext.Element}.
  7674. * @return {Ext.Element} The document body.
  7675. */
  7676. getBody: function() {
  7677. if (!Ext.documentBodyElement) {
  7678. if (!document.body) {
  7679. throw new Error("[Ext.getBody] document.body does not exist at this point");
  7680. }
  7681. Ext.documentBodyElement = Ext.get(document.body);
  7682. }
  7683. return Ext.documentBodyElement;
  7684. },
  7685. /**
  7686. * Returns the current document head as an {@link Ext.Element}.
  7687. * @return {Ext.Element} The document head.
  7688. */
  7689. getHead: function() {
  7690. if (!Ext.documentHeadElement) {
  7691. Ext.documentHeadElement = Ext.get(document.head || document.getElementsByTagName('head')[0]);
  7692. }
  7693. return Ext.documentHeadElement;
  7694. },
  7695. /**
  7696. * Returns the current HTML document object as an {@link Ext.Element}.
  7697. * @return {Ext.Element} The document.
  7698. */
  7699. getDoc: function() {
  7700. if (!Ext.documentElement) {
  7701. Ext.documentElement = Ext.get(document);
  7702. }
  7703. return Ext.documentElement;
  7704. },
  7705. /**
  7706. * This is shorthand reference to {@link Ext.ComponentMgr#get}.
  7707. * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#getId id}
  7708. * @param {String} id The component {@link Ext.Component#getId id}
  7709. * @return {Ext.Component} The Component, `undefined` if not found, or `null` if a
  7710. * Class was found.
  7711. */
  7712. getCmp: function(id) {
  7713. return Ext.ComponentMgr.get(id);
  7714. },
  7715. /**
  7716. * Copies a set of named properties from the source object to the destination object.
  7717. *
  7718. * Example:
  7719. *
  7720. * ImageComponent = Ext.extend(Ext.Component, {
  7721. * initComponent: function() {
  7722. * this.autoEl = { tag: 'img' };
  7723. * MyComponent.superclass.initComponent.apply(this, arguments);
  7724. * this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
  7725. * }
  7726. * });
  7727. *
  7728. * Important note: To borrow class prototype methods, use {@link Ext.Base#borrow} instead.
  7729. *
  7730. * @param {Object} dest The destination object.
  7731. * @param {Object} source The source object.
  7732. * @param {String/String[]} names Either an Array of property names, or a comma-delimited list
  7733. * of property names to copy.
  7734. * @param {Boolean} [usePrototypeKeys=false] (optional) Pass `true` to copy keys off of the prototype as well as the instance.
  7735. * @return {Object} The modified object.
  7736. */
  7737. copyTo : function(dest, source, names, usePrototypeKeys) {
  7738. if (typeof names == 'string') {
  7739. names = names.split(/[,;\s]/);
  7740. }
  7741. Ext.each (names, function(name) {
  7742. if (usePrototypeKeys || source.hasOwnProperty(name)) {
  7743. dest[name] = source[name];
  7744. }
  7745. }, this);
  7746. return dest;
  7747. },
  7748. /**
  7749. * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
  7750. * DOM (if applicable) and calling their destroy functions (if available). This method is primarily
  7751. * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}.
  7752. * Any number of elements and/or components can be passed into this function in a single
  7753. * call as separate arguments.
  7754. * @param {Mixed...} args An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy.
  7755. */
  7756. destroy: function() {
  7757. var args = arguments,
  7758. ln = args.length,
  7759. i, item;
  7760. for (i = 0; i < ln; i++) {
  7761. item = args[i];
  7762. if (item) {
  7763. if (Ext.isArray(item)) {
  7764. this.destroy.apply(this, item);
  7765. }
  7766. else if (Ext.isFunction(item.destroy)) {
  7767. item.destroy();
  7768. }
  7769. }
  7770. }
  7771. },
  7772. /**
  7773. * Return the dom node for the passed String (id), dom node, or Ext.Element.
  7774. * Here are some examples:
  7775. *
  7776. * // gets dom node based on id
  7777. * var elDom = Ext.getDom('elId');
  7778. *
  7779. * // gets dom node based on the dom node
  7780. * var elDom1 = Ext.getDom(elDom);
  7781. *
  7782. * // If we don't know if we are working with an
  7783. * // Ext.Element or a dom node use Ext.getDom
  7784. * function(el){
  7785. * var dom = Ext.getDom(el);
  7786. * // do something with the dom node
  7787. * }
  7788. *
  7789. * __Note:__ the dom node to be found actually needs to exist (be rendered, etc)
  7790. * when this method is called to be successful.
  7791. * @param {Mixed} el
  7792. * @return {HTMLElement}
  7793. */
  7794. getDom: function(el) {
  7795. if (!el || !document) {
  7796. return null;
  7797. }
  7798. return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
  7799. },
  7800. /**
  7801. * Removes this element from the document, removes all DOM event listeners, and deletes the cache reference.
  7802. * All DOM event listeners are removed from this element.
  7803. * @param {HTMLElement} node The node to remove.
  7804. */
  7805. removeNode: function(node) {
  7806. if (node && node.parentNode && node.tagName != 'BODY') {
  7807. Ext.get(node).clearListeners();
  7808. node.parentNode.removeChild(node);
  7809. delete Ext.cache[node.id];
  7810. }
  7811. },
  7812. /**
  7813. * @private
  7814. */
  7815. defaultSetupConfig: {
  7816. eventPublishers: {
  7817. dom: {
  7818. xclass: 'Ext.event.publisher.Dom'
  7819. },
  7820. touchGesture: {
  7821. xclass: 'Ext.event.publisher.TouchGesture',
  7822. recognizers: {
  7823. drag: {
  7824. xclass: 'Ext.event.recognizer.Drag'
  7825. },
  7826. tap: {
  7827. xclass: 'Ext.event.recognizer.Tap'
  7828. },
  7829. doubleTap: {
  7830. xclass: 'Ext.event.recognizer.DoubleTap'
  7831. },
  7832. longPress: {
  7833. xclass: 'Ext.event.recognizer.LongPress'
  7834. },
  7835. swipe: {
  7836. xclass: 'Ext.event.recognizer.HorizontalSwipe'
  7837. },
  7838. pinch: {
  7839. xclass: 'Ext.event.recognizer.Pinch'
  7840. },
  7841. rotate: {
  7842. xclass: 'Ext.event.recognizer.Rotate'
  7843. }
  7844. }
  7845. },
  7846. componentDelegation: {
  7847. xclass: 'Ext.event.publisher.ComponentDelegation'
  7848. },
  7849. componentPaint: {
  7850. xclass: 'Ext.event.publisher.ComponentPaint'
  7851. },
  7852. // componentSize: {
  7853. // xclass: 'Ext.event.publisher.ComponentSize'
  7854. // },
  7855. elementPaint: {
  7856. xclass: 'Ext.event.publisher.ElementPaint'
  7857. },
  7858. elementSize: {
  7859. xclass: 'Ext.event.publisher.ElementSize'
  7860. }
  7861. },
  7862. //<feature logger>
  7863. logger: {
  7864. enabled: true,
  7865. xclass: 'Ext.log.Logger',
  7866. minPriority: 'deprecate',
  7867. writers: {
  7868. console: {
  7869. xclass: 'Ext.log.writer.Console',
  7870. throwOnErrors: true,
  7871. formatter: {
  7872. xclass: 'Ext.log.formatter.Default'
  7873. }
  7874. }
  7875. }
  7876. },
  7877. //</feature>
  7878. animator: {
  7879. xclass: 'Ext.fx.Runner'
  7880. },
  7881. viewport: {
  7882. xclass: 'Ext.viewport.Viewport'
  7883. }
  7884. },
  7885. /**
  7886. * @private
  7887. */
  7888. isSetup: false,
  7889. /**
  7890. * This indicate the start timestamp of current cycle.
  7891. * It is only reliable during dom-event-initiated cycles and
  7892. * {@link Ext.draw.Animator} initiated cycles.
  7893. */
  7894. frameStartTime: +new Date(),
  7895. /**
  7896. * @private
  7897. */
  7898. setupListeners: [],
  7899. /**
  7900. * @private
  7901. */
  7902. onSetup: function(fn, scope) {
  7903. if (Ext.isSetup) {
  7904. fn.call(scope);
  7905. }
  7906. else {
  7907. Ext.setupListeners.push({
  7908. fn: fn,
  7909. scope: scope
  7910. });
  7911. }
  7912. },
  7913. /**
  7914. * Ext.setup() is the entry-point to initialize a Sencha Touch application. Note that if your application makes
  7915. * use of MVC architecture, use {@link Ext#application} instead.
  7916. *
  7917. * This method accepts one single argument in object format. The most basic use of Ext.setup() is as follows:
  7918. *
  7919. * Ext.setup({
  7920. * onReady: function() {
  7921. * // ...
  7922. * }
  7923. * });
  7924. *
  7925. * This sets up the viewport, initializes the event system, instantiates a default animation runner, and a default
  7926. * logger (during development). When all of that is ready, it invokes the callback function given to the `onReady` key.
  7927. *
  7928. * The default scope (`this`) of `onReady` is the main viewport. By default the viewport instance is stored in
  7929. * {@link Ext.Viewport}. For example, this snippet adds a 'Hello World' button that is centered on the screen:
  7930. *
  7931. * Ext.setup({
  7932. * onReady: function() {
  7933. * this.add({
  7934. * xtype: 'button',
  7935. * centered: true,
  7936. * text: 'Hello world!'
  7937. * }); // Equivalent to Ext.Viewport.add(...)
  7938. * }
  7939. * });
  7940. *
  7941. * @param {Object} config An object with the following config options:
  7942. *
  7943. * @param {Function} config.onReady
  7944. * A function to be called when the application is ready. Your application logic should be here.
  7945. *
  7946. * @param {Object} config.viewport
  7947. * A custom config object to be used when creating the global {@link Ext.Viewport} instance. Please refer to the
  7948. * {@link Ext.Viewport} documentation for more information.
  7949. *
  7950. * Ext.setup({
  7951. * viewport: {
  7952. * width: 500,
  7953. * height: 500
  7954. * },
  7955. * onReady: function() {
  7956. * // ...
  7957. * }
  7958. * });
  7959. *
  7960. * @param {String/Object} config.icon
  7961. * Specifies a set of URLs to the application icon for different device form factors. This icon is displayed
  7962. * when the application is added to the device's Home Screen.
  7963. *
  7964. * Ext.setup({
  7965. * icon: {
  7966. * 57: 'resources/icons/Icon.png',
  7967. * 72: 'resources/icons/Icon~ipad.png',
  7968. * 114: 'resources/icons/Icon@2x.png',
  7969. * 144: 'resources/icons/Icon~ipad@2x.png'
  7970. * },
  7971. * onReady: function() {
  7972. * // ...
  7973. * }
  7974. * });
  7975. *
  7976. * Each key represents the dimension of the icon as a square shape. For example: '57' is the key for a 57 x 57
  7977. * icon image. Here is the breakdown of each dimension and its device target:
  7978. *
  7979. * - 57: Non-retina iPhone, iPod touch, and all Android devices
  7980. * - 72: Retina iPhone and iPod touch
  7981. * - 114: Non-retina iPad (first and second generation)
  7982. * - 144: Retina iPad (third generation)
  7983. *
  7984. * Note that the dimensions of the icon images must be exactly 57x57, 72x72, 114x114 and 144x144 respectively.
  7985. *
  7986. * It is highly recommended that you provide all these different sizes to accommodate a full range of
  7987. * devices currently available. However if you only have one icon in one size, make it 57x57 in size and
  7988. * specify it as a string value. This same icon will be used on all supported devices.
  7989. *
  7990. * Ext.setup({
  7991. * icon: 'resources/icons/Icon.png',
  7992. * onReady: function() {
  7993. * // ...
  7994. * }
  7995. * });
  7996. *
  7997. * @param {Object} config.startupImage
  7998. * Specifies a set of URLs to the application startup images for different device form factors. This image is
  7999. * displayed when the application is being launched from the Home Screen icon. Note that this currently only applies
  8000. * to iOS devices.
  8001. *
  8002. * Ext.setup({
  8003. * startupImage: {
  8004. * '320x460': 'resources/startup/320x460.jpg',
  8005. * '640x920': 'resources/startup/640x920.png',
  8006. * '640x1096': 'resources/startup/640x1096.png',
  8007. * '768x1004': 'resources/startup/768x1004.png',
  8008. * '748x1024': 'resources/startup/748x1024.png',
  8009. * '1536x2008': 'resources/startup/1536x2008.png',
  8010. * '1496x2048': 'resources/startup/1496x2048.png'
  8011. * },
  8012. * onReady: function() {
  8013. * // ...
  8014. * }
  8015. * });
  8016. *
  8017. * Each key represents the dimension of the image. For example: '320x460' is the key for a 320px x 460px image.
  8018. * Here is the breakdown of each dimension and its device target:
  8019. *
  8020. * - 320x460: Non-retina iPhone, iPod touch, and all Android devices
  8021. * - 640x920: Retina iPhone and iPod touch
  8022. * - 640x1096: iPhone 5 and iPod touch (fifth generation)
  8023. * - 768x1004: Non-retina iPad (first and second generation) in portrait orientation
  8024. * - 748x1024: Non-retina iPad (first and second generation) in landscape orientation
  8025. * - 1536x2008: Retina iPad (third generation) in portrait orientation
  8026. * - 1496x2048: Retina iPad (third generation) in landscape orientation
  8027. *
  8028. * Please note that there's no automatic fallback mechanism for the startup images. In other words, if you don't specify
  8029. * a valid image for a certain device, nothing will be displayed while the application is being launched on that device.
  8030. *
  8031. * @param {Boolean} isIconPrecomposed
  8032. * True to not having a glossy effect added to the icon by the OS, which will preserve its exact look. This currently
  8033. * only applies to iOS devices.
  8034. *
  8035. * @param {String} statusBarStyle
  8036. * The style of status bar to be shown on applications added to the iOS home screen. Valid options are:
  8037. *
  8038. * * `default`
  8039. * * `black`
  8040. * * `black-translucent`
  8041. *
  8042. * @param {String[]} config.requires
  8043. * An array of required classes for your application which will be automatically loaded before `onReady` is invoked.
  8044. * Please refer to {@link Ext.Loader} and {@link Ext.Loader#require} for more information.
  8045. *
  8046. * Ext.setup({
  8047. * requires: ['Ext.Button', 'Ext.tab.Panel'],
  8048. * onReady: function() {
  8049. * // ...
  8050. * }
  8051. * });
  8052. *
  8053. * @param {Object} config.eventPublishers
  8054. * Sencha Touch, by default, includes various {@link Ext.event.recognizer.Recognizer} subclasses to recognize events fired
  8055. * in your application. The list of default recognizers can be found in the documentation for
  8056. * {@link Ext.event.recognizer.Recognizer}.
  8057. *
  8058. * To change the default recognizers, you can use the following syntax:
  8059. *
  8060. * Ext.setup({
  8061. * eventPublishers: {
  8062. * touchGesture: {
  8063. * recognizers: {
  8064. * swipe: {
  8065. * // this will include both vertical and horizontal swipe recognizers
  8066. * xclass: 'Ext.event.recognizer.Swipe'
  8067. * }
  8068. * }
  8069. * }
  8070. * },
  8071. * onReady: function() {
  8072. * // ...
  8073. * }
  8074. * });
  8075. *
  8076. * You can also disable recognizers using this syntax:
  8077. *
  8078. * Ext.setup({
  8079. * eventPublishers: {
  8080. * touchGesture: {
  8081. * recognizers: {
  8082. * swipe: null,
  8083. * pinch: null,
  8084. * rotate: null
  8085. * }
  8086. * }
  8087. * },
  8088. * onReady: function() {
  8089. * // ...
  8090. * }
  8091. * });
  8092. */
  8093. setup: function(config) {
  8094. var defaultSetupConfig = Ext.defaultSetupConfig,
  8095. emptyFn = Ext.emptyFn,
  8096. onReady = config.onReady || emptyFn,
  8097. onUpdated = config.onUpdated || emptyFn,
  8098. scope = config.scope,
  8099. requires = Ext.Array.from(config.requires),
  8100. extOnReady = Ext.onReady,
  8101. head = Ext.getHead(),
  8102. callback, viewport, precomposed;
  8103. Ext.setup = function() {
  8104. throw new Error("Ext.setup has already been called before");
  8105. };
  8106. delete config.requires;
  8107. delete config.onReady;
  8108. delete config.onUpdated;
  8109. delete config.scope;
  8110. Ext.require(['Ext.event.Dispatcher']);
  8111. callback = function() {
  8112. var listeners = Ext.setupListeners,
  8113. ln = listeners.length,
  8114. i, listener;
  8115. delete Ext.setupListeners;
  8116. Ext.isSetup = true;
  8117. for (i = 0; i < ln; i++) {
  8118. listener = listeners[i];
  8119. listener.fn.call(listener.scope);
  8120. }
  8121. Ext.onReady = extOnReady;
  8122. Ext.onReady(onReady, scope);
  8123. };
  8124. Ext.onUpdated = onUpdated;
  8125. Ext.onReady = function(fn, scope) {
  8126. var origin = onReady;
  8127. onReady = function() {
  8128. origin();
  8129. Ext.onReady(fn, scope);
  8130. };
  8131. };
  8132. config = Ext.merge({}, defaultSetupConfig, config);
  8133. Ext.onDocumentReady(function() {
  8134. Ext.factoryConfig(config, function(data) {
  8135. Ext.event.Dispatcher.getInstance().setPublishers(data.eventPublishers);
  8136. if (data.logger) {
  8137. Ext.Logger = data.logger;
  8138. }
  8139. if (data.animator) {
  8140. Ext.Animator = data.animator;
  8141. }
  8142. if (data.viewport) {
  8143. Ext.Viewport = viewport = data.viewport;
  8144. if (!scope) {
  8145. scope = viewport;
  8146. }
  8147. Ext.require(requires, function() {
  8148. Ext.Viewport.on('ready', callback, null, {single: true});
  8149. });
  8150. }
  8151. else {
  8152. Ext.require(requires, callback);
  8153. }
  8154. });
  8155. });
  8156. function addMeta(name, content) {
  8157. var meta = document.createElement('meta');
  8158. meta.setAttribute('name', name);
  8159. meta.setAttribute('content', content);
  8160. head.append(meta);
  8161. }
  8162. function addIcon(href, sizes, precomposed) {
  8163. var link = document.createElement('link');
  8164. link.setAttribute('rel', 'apple-touch-icon' + (precomposed ? '-precomposed' : ''));
  8165. link.setAttribute('href', href);
  8166. if (sizes) {
  8167. link.setAttribute('sizes', sizes);
  8168. }
  8169. head.append(link);
  8170. }
  8171. function addStartupImage(href, media) {
  8172. var link = document.createElement('link');
  8173. link.setAttribute('rel', 'apple-touch-startup-image');
  8174. link.setAttribute('href', href);
  8175. if (media) {
  8176. link.setAttribute('media', media);
  8177. }
  8178. head.append(link);
  8179. }
  8180. var icon = config.icon,
  8181. isIconPrecomposed = Boolean(config.isIconPrecomposed),
  8182. startupImage = config.startupImage || {},
  8183. statusBarStyle = config.statusBarStyle,
  8184. devicePixelRatio = window.devicePixelRatio || 1;
  8185. if (navigator.standalone) {
  8186. addMeta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0');
  8187. }
  8188. else {
  8189. addMeta('viewport', 'initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0');
  8190. }
  8191. addMeta('apple-mobile-web-app-capable', 'yes');
  8192. addMeta('apple-touch-fullscreen', 'yes');
  8193. // status bar style
  8194. if (statusBarStyle) {
  8195. addMeta('apple-mobile-web-app-status-bar-style', statusBarStyle);
  8196. }
  8197. if (Ext.isString(icon)) {
  8198. icon = {
  8199. 57: icon,
  8200. 72: icon,
  8201. 114: icon,
  8202. 144: icon
  8203. };
  8204. }
  8205. else if (!icon) {
  8206. icon = {};
  8207. }
  8208. if (Ext.os.is.iPad) {
  8209. if (devicePixelRatio >= 2) {
  8210. // Retina iPad - Landscape
  8211. if ('1496x2048' in startupImage) {
  8212. addStartupImage(startupImage['1496x2048'], '(orientation: landscape)');
  8213. }
  8214. // Retina iPad - Portrait
  8215. if ('1536x2008' in startupImage) {
  8216. addStartupImage(startupImage['1536x2008'], '(orientation: portrait)');
  8217. }
  8218. // Retina iPad
  8219. if ('144' in icon) {
  8220. addIcon(icon['144'], '144x144', isIconPrecomposed);
  8221. }
  8222. }
  8223. else {
  8224. // Non-Retina iPad - Landscape
  8225. if ('748x1024' in startupImage) {
  8226. addStartupImage(startupImage['748x1024'], '(orientation: landscape)');
  8227. }
  8228. // Non-Retina iPad - Portrait
  8229. if ('768x1004' in startupImage) {
  8230. addStartupImage(startupImage['768x1004'], '(orientation: portrait)');
  8231. }
  8232. // Non-Retina iPad
  8233. if ('72' in icon) {
  8234. addIcon(icon['72'], '72x72', isIconPrecomposed);
  8235. }
  8236. }
  8237. }
  8238. else {
  8239. // Retina iPhone, iPod touch with iOS version >= 4.3
  8240. if (devicePixelRatio >= 2 && Ext.os.version.gtEq('4.3')) {
  8241. if (Ext.os.is.iPhone5) {
  8242. addStartupImage(startupImage['640x1096']);
  8243. } else {
  8244. addStartupImage(startupImage['640x920']);
  8245. }
  8246. // Retina iPhone and iPod touch
  8247. if ('114' in icon) {
  8248. addIcon(icon['114'], '114x114', isIconPrecomposed);
  8249. }
  8250. }
  8251. else {
  8252. addStartupImage(startupImage['320x460']);
  8253. // Non-Retina iPhone, iPod touch, and Android devices
  8254. if ('57' in icon) {
  8255. addIcon(icon['57'], null, isIconPrecomposed);
  8256. }
  8257. }
  8258. }
  8259. },
  8260. /**
  8261. * @member Ext
  8262. * @method application
  8263. *
  8264. * Loads Ext.app.Application class and starts it up with given configuration after the page is ready.
  8265. *
  8266. * Ext.application({
  8267. * launch: function() {
  8268. * alert('Application launched!');
  8269. * }
  8270. * });
  8271. *
  8272. * See {@link Ext.app.Application} for details.
  8273. *
  8274. * @param {Object} config An object with the following config options:
  8275. *
  8276. * @param {Function} config.launch
  8277. * A function to be called when the application is ready. Your application logic should be here. Please see {@link Ext.app.Application}
  8278. * for details.
  8279. *
  8280. * @param {Object} config.viewport
  8281. * An object to be used when creating the global {@link Ext.Viewport} instance. Please refer to the {@link Ext.Viewport}
  8282. * documentation for more information.
  8283. *
  8284. * Ext.application({
  8285. * viewport: {
  8286. * layout: 'vbox'
  8287. * },
  8288. * launch: function() {
  8289. * Ext.Viewport.add({
  8290. * flex: 1,
  8291. * html: 'top (flex: 1)'
  8292. * });
  8293. *
  8294. * Ext.Viewport.add({
  8295. * flex: 4,
  8296. * html: 'bottom (flex: 4)'
  8297. * });
  8298. * }
  8299. * });
  8300. *
  8301. * @param {String/Object} config.icon
  8302. * Specifies a set of URLs to the application icon for different device form factors. This icon is displayed
  8303. * when the application is added to the device's Home Screen.
  8304. *
  8305. * Ext.application({
  8306. * icon: {
  8307. * 57: 'resources/icons/Icon.png',
  8308. * 72: 'resources/icons/Icon~ipad.png',
  8309. * 114: 'resources/icons/Icon@2x.png',
  8310. * 144: 'resources/icons/Icon~ipad@2x.png'
  8311. * },
  8312. * launch: function() {
  8313. * // ...
  8314. * }
  8315. * });
  8316. *
  8317. * Each key represents the dimension of the icon as a square shape. For example: '57' is the key for a 57 x 57
  8318. * icon image. Here is the breakdown of each dimension and its device target:
  8319. *
  8320. * - 57: Non-retina iPhone, iPod touch, and all Android devices
  8321. * - 72: Retina iPhone and iPod touch
  8322. * - 114: Non-retina iPad (first and second generation)
  8323. * - 144: Retina iPad (third generation)
  8324. *
  8325. * Note that the dimensions of the icon images must be exactly 57x57, 72x72, 114x114 and 144x144 respectively.
  8326. *
  8327. * It is highly recommended that you provide all these different sizes to accommodate a full range of
  8328. * devices currently available. However if you only have one icon in one size, make it 57x57 in size and
  8329. * specify it as a string value. This same icon will be used on all supported devices.
  8330. *
  8331. * Ext.setup({
  8332. * icon: 'resources/icons/Icon.png',
  8333. * onReady: function() {
  8334. * // ...
  8335. * }
  8336. * });
  8337. *
  8338. * @param {Object} config.startupImage
  8339. * Specifies a set of URLs to the application startup images for different device form factors. This image is
  8340. * displayed when the application is being launched from the Home Screen icon. Note that this currently only applies
  8341. * to iOS devices.
  8342. *
  8343. * Ext.application({
  8344. * startupImage: {
  8345. * '320x460': 'resources/startup/320x460.jpg',
  8346. * '640x920': 'resources/startup/640x920.png',
  8347. * '640x1096': 'resources/startup/640x1096.png',
  8348. * '768x1004': 'resources/startup/768x1004.png',
  8349. * '748x1024': 'resources/startup/748x1024.png',
  8350. * '1536x2008': 'resources/startup/1536x2008.png',
  8351. * '1496x2048': 'resources/startup/1496x2048.png'
  8352. * },
  8353. * launch: function() {
  8354. * // ...
  8355. * }
  8356. * });
  8357. *
  8358. * Each key represents the dimension of the image. For example: '320x460' is the key for a 320px x 460px image.
  8359. * Here is the breakdown of each dimension and its device target:
  8360. *
  8361. * - 320x460: Non-retina iPhone, iPod touch, and all Android devices
  8362. * - 640x920: Retina iPhone and iPod touch
  8363. * - 640x1096: iPhone 5 and iPod touch (fifth generation)
  8364. * - 768x1004: Non-retina iPad (first and second generation) in portrait orientation
  8365. * - 748x1024: Non-retina iPad (first and second generation) in landscape orientation
  8366. * - 1536x2008: Retina iPad (third generation) in portrait orientation
  8367. * - 1496x2048: Retina iPad (third generation) in landscape orientation
  8368. *
  8369. * Please note that there's no automatic fallback mechanism for the startup images. In other words, if you don't specify
  8370. * a valid image for a certain device, nothing will be displayed while the application is being launched on that device.
  8371. *
  8372. * @param {Boolean} config.isIconPrecomposed
  8373. * True to not having a glossy effect added to the icon by the OS, which will preserve its exact look. This currently
  8374. * only applies to iOS devices.
  8375. *
  8376. * @param {String} config.statusBarStyle
  8377. * The style of status bar to be shown on applications added to the iOS home screen. Valid options are:
  8378. *
  8379. * * `default`
  8380. * * `black`
  8381. * * `black-translucent`
  8382. *
  8383. * @param {String[]} config.requires
  8384. * An array of required classes for your application which will be automatically loaded if {@link Ext.Loader#enabled} is set
  8385. * to `true`. Please refer to {@link Ext.Loader} and {@link Ext.Loader#require} for more information.
  8386. *
  8387. * Ext.application({
  8388. * requires: ['Ext.Button', 'Ext.tab.Panel'],
  8389. * launch: function() {
  8390. * // ...
  8391. * }
  8392. * });
  8393. *
  8394. * @param {Object} config.eventPublishers
  8395. * Sencha Touch, by default, includes various {@link Ext.event.recognizer.Recognizer} subclasses to recognize events fired
  8396. * in your application. The list of default recognizers can be found in the documentation for {@link Ext.event.recognizer.Recognizer}.
  8397. *
  8398. * To change the default recognizers, you can use the following syntax:
  8399. *
  8400. * Ext.application({
  8401. * eventPublishers: {
  8402. * touchGesture: {
  8403. * recognizers: {
  8404. * swipe: {
  8405. * // this will include both vertical and horizontal swipe recognizers
  8406. * xclass: 'Ext.event.recognizer.Swipe'
  8407. * }
  8408. * }
  8409. * }
  8410. * },
  8411. * launch: function() {
  8412. * // ...
  8413. * }
  8414. * });
  8415. *
  8416. * You can also disable recognizers using this syntax:
  8417. *
  8418. * Ext.application({
  8419. * eventPublishers: {
  8420. * touchGesture: {
  8421. * recognizers: {
  8422. * swipe: null,
  8423. * pinch: null,
  8424. * rotate: null
  8425. * }
  8426. * }
  8427. * },
  8428. * launch: function() {
  8429. * // ...
  8430. * }
  8431. * });
  8432. */
  8433. application: function(config) {
  8434. var appName = config.name,
  8435. onReady, scope, requires;
  8436. if (!config) {
  8437. config = {};
  8438. }
  8439. if (!Ext.Loader.config.paths[appName]) {
  8440. Ext.Loader.setPath(appName, config.appFolder || 'app');
  8441. }
  8442. requires = Ext.Array.from(config.requires);
  8443. config.requires = ['Ext.app.Application'];
  8444. onReady = config.onReady;
  8445. scope = config.scope;
  8446. config.onReady = function() {
  8447. config.requires = requires;
  8448. new Ext.app.Application(config);
  8449. if (onReady) {
  8450. onReady.call(scope);
  8451. }
  8452. };
  8453. Ext.setup(config);
  8454. },
  8455. /**
  8456. * @private
  8457. * @param config
  8458. * @param callback
  8459. * @member Ext
  8460. */
  8461. factoryConfig: function(config, callback) {
  8462. var isSimpleObject = Ext.isSimpleObject(config);
  8463. if (isSimpleObject && config.xclass) {
  8464. var className = config.xclass;
  8465. delete config.xclass;
  8466. Ext.require(className, function() {
  8467. Ext.factoryConfig(config, function(cfg) {
  8468. callback(Ext.create(className, cfg));
  8469. });
  8470. });
  8471. return;
  8472. }
  8473. var isArray = Ext.isArray(config),
  8474. keys = [],
  8475. key, value, i, ln;
  8476. if (isSimpleObject || isArray) {
  8477. if (isSimpleObject) {
  8478. for (key in config) {
  8479. if (config.hasOwnProperty(key)) {
  8480. value = config[key];
  8481. if (Ext.isSimpleObject(value) || Ext.isArray(value)) {
  8482. keys.push(key);
  8483. }
  8484. }
  8485. }
  8486. }
  8487. else {
  8488. for (i = 0,ln = config.length; i < ln; i++) {
  8489. value = config[i];
  8490. if (Ext.isSimpleObject(value) || Ext.isArray(value)) {
  8491. keys.push(i);
  8492. }
  8493. }
  8494. }
  8495. i = 0;
  8496. ln = keys.length;
  8497. if (ln === 0) {
  8498. callback(config);
  8499. return;
  8500. }
  8501. function fn(value) {
  8502. config[key] = value;
  8503. i++;
  8504. factory();
  8505. }
  8506. function factory() {
  8507. if (i >= ln) {
  8508. callback(config);
  8509. return;
  8510. }
  8511. key = keys[i];
  8512. value = config[key];
  8513. Ext.factoryConfig(value, fn);
  8514. }
  8515. factory();
  8516. return;
  8517. }
  8518. callback(config);
  8519. },
  8520. /**
  8521. * A global factory method to instantiate a class from a config object. For example, these two calls are equivalent:
  8522. *
  8523. * Ext.factory({ text: 'My Button' }, 'Ext.Button');
  8524. * Ext.create('Ext.Button', { text: 'My Button' });
  8525. *
  8526. * If an existing instance is also specified, it will be updated with the supplied config object. This is useful
  8527. * if you need to either create or update an object, depending on if an instance already exists. For example:
  8528. *
  8529. * var button;
  8530. * button = Ext.factory({ text: 'New Button' }, 'Ext.Button', button); // Button created
  8531. * button = Ext.factory({ text: 'Updated Button' }, 'Ext.Button', button); // Button updated
  8532. *
  8533. * @param {Object} config The config object to instantiate or update an instance with.
  8534. * @param {String} classReference The class to instantiate from.
  8535. * @param {Object} [instance] The instance to update.
  8536. * @param [aliasNamespace]
  8537. * @member Ext
  8538. */
  8539. factory: function(config, classReference, instance, aliasNamespace) {
  8540. var manager = Ext.ClassManager,
  8541. newInstance;
  8542. // If config is falsy or a valid instance, destroy the current instance
  8543. // (if it exists) and replace with the new one
  8544. if (!config || config.isInstance) {
  8545. if (instance && instance !== config) {
  8546. instance.destroy();
  8547. }
  8548. return config;
  8549. }
  8550. if (aliasNamespace) {
  8551. // If config is a string value, treat it as an alias
  8552. if (typeof config == 'string') {
  8553. return manager.instantiateByAlias(aliasNamespace + '.' + config);
  8554. }
  8555. // Same if 'type' is given in config
  8556. else if (Ext.isObject(config) && 'type' in config) {
  8557. return manager.instantiateByAlias(aliasNamespace + '.' + config.type, config);
  8558. }
  8559. }
  8560. if (config === true) {
  8561. return instance || manager.instantiate(classReference);
  8562. }
  8563. //<debug error>
  8564. if (!Ext.isObject(config)) {
  8565. Ext.Logger.error("Invalid config, must be a valid config object");
  8566. }
  8567. //</debug>
  8568. if ('xtype' in config) {
  8569. newInstance = manager.instantiateByAlias('widget.' + config.xtype, config);
  8570. }
  8571. else if ('xclass' in config) {
  8572. newInstance = manager.instantiate(config.xclass, config);
  8573. }
  8574. if (newInstance) {
  8575. if (instance) {
  8576. instance.destroy();
  8577. }
  8578. return newInstance;
  8579. }
  8580. if (instance) {
  8581. return instance.setConfig(config);
  8582. }
  8583. return manager.instantiate(classReference, config);
  8584. },
  8585. /**
  8586. * @private
  8587. * @member Ext
  8588. */
  8589. deprecateClassMember: function(cls, oldName, newName, message) {
  8590. return this.deprecateProperty(cls.prototype, oldName, newName, message);
  8591. },
  8592. /**
  8593. * @private
  8594. * @member Ext
  8595. */
  8596. deprecateClassMembers: function(cls, members) {
  8597. var prototype = cls.prototype,
  8598. oldName, newName;
  8599. for (oldName in members) {
  8600. if (members.hasOwnProperty(oldName)) {
  8601. newName = members[oldName];
  8602. this.deprecateProperty(prototype, oldName, newName);
  8603. }
  8604. }
  8605. },
  8606. /**
  8607. * @private
  8608. * @member Ext
  8609. */
  8610. deprecateProperty: function(object, oldName, newName, message) {
  8611. if (!message) {
  8612. message = "'" + oldName + "' is deprecated";
  8613. }
  8614. if (newName) {
  8615. message += ", please use '" + newName + "' instead";
  8616. }
  8617. if (newName) {
  8618. Ext.Object.defineProperty(object, oldName, {
  8619. get: function() {
  8620. //<debug warn>
  8621. Ext.Logger.deprecate(message, 1);
  8622. //</debug>
  8623. return this[newName];
  8624. },
  8625. set: function(value) {
  8626. //<debug warn>
  8627. Ext.Logger.deprecate(message, 1);
  8628. //</debug>
  8629. this[newName] = value;
  8630. },
  8631. configurable: true
  8632. });
  8633. }
  8634. },
  8635. /**
  8636. * @private
  8637. * @member Ext
  8638. */
  8639. deprecatePropertyValue: function(object, name, value, message) {
  8640. Ext.Object.defineProperty(object, name, {
  8641. get: function() {
  8642. //<debug warn>
  8643. Ext.Logger.deprecate(message, 1);
  8644. //</debug>
  8645. return value;
  8646. },
  8647. configurable: true
  8648. });
  8649. },
  8650. /**
  8651. * @private
  8652. * @member Ext
  8653. */
  8654. deprecateMethod: function(object, name, method, message) {
  8655. object[name] = function() {
  8656. //<debug warn>
  8657. Ext.Logger.deprecate(message, 2);
  8658. //</debug>
  8659. if (method) {
  8660. return method.apply(this, arguments);
  8661. }
  8662. };
  8663. },
  8664. /**
  8665. * @private
  8666. * @member Ext
  8667. */
  8668. deprecateClassMethod: function(cls, name, method, message) {
  8669. if (typeof name != 'string') {
  8670. var from, to;
  8671. for (from in name) {
  8672. if (name.hasOwnProperty(from)) {
  8673. to = name[from];
  8674. Ext.deprecateClassMethod(cls, from, to);
  8675. }
  8676. }
  8677. return;
  8678. }
  8679. var isLateBinding = typeof method == 'string',
  8680. member;
  8681. if (!message) {
  8682. message = "'" + name + "()' is deprecated, please use '" + (isLateBinding ? method : method.name) +
  8683. "()' instead";
  8684. }
  8685. if (isLateBinding) {
  8686. member = function() {
  8687. //<debug warn>
  8688. Ext.Logger.deprecate(message, this);
  8689. //</debug>
  8690. return this[method].apply(this, arguments);
  8691. };
  8692. }
  8693. else {
  8694. member = function() {
  8695. //<debug warn>
  8696. Ext.Logger.deprecate(message, this);
  8697. //</debug>
  8698. return method.apply(this, arguments);
  8699. };
  8700. }
  8701. if (name in cls.prototype) {
  8702. Ext.Object.defineProperty(cls.prototype, name, {
  8703. value: null,
  8704. writable: true,
  8705. configurable: true
  8706. });
  8707. }
  8708. cls.addMember(name, member);
  8709. },
  8710. //<debug>
  8711. /**
  8712. * Useful snippet to show an exact, narrowed-down list of top-level Components that are not yet destroyed.
  8713. * @private
  8714. */
  8715. showLeaks: function() {
  8716. var map = Ext.ComponentManager.all.map,
  8717. leaks = [],
  8718. parent;
  8719. Ext.Object.each(map, function(id, component) {
  8720. while ((parent = component.getParent()) && map.hasOwnProperty(parent.getId())) {
  8721. component = parent;
  8722. }
  8723. if (leaks.indexOf(component) === -1) {
  8724. leaks.push(component);
  8725. }
  8726. });
  8727. console.log(leaks);
  8728. },
  8729. //</debug>
  8730. /**
  8731. * True when the document is fully initialized and ready for action
  8732. * @type Boolean
  8733. * @member Ext
  8734. * @private
  8735. */
  8736. isReady : false,
  8737. /**
  8738. * @private
  8739. * @member Ext
  8740. */
  8741. readyListeners: [],
  8742. /**
  8743. * @private
  8744. * @member Ext
  8745. */
  8746. triggerReady: function() {
  8747. var listeners = Ext.readyListeners,
  8748. i, ln, listener;
  8749. if (!Ext.isReady) {
  8750. Ext.isReady = true;
  8751. for (i = 0,ln = listeners.length; i < ln; i++) {
  8752. listener = listeners[i];
  8753. listener.fn.call(listener.scope);
  8754. }
  8755. delete Ext.readyListeners;
  8756. }
  8757. },
  8758. /**
  8759. * @private
  8760. * @member Ext
  8761. */
  8762. onDocumentReady: function(fn, scope) {
  8763. if (Ext.isReady) {
  8764. fn.call(scope);
  8765. }
  8766. else {
  8767. var triggerFn = Ext.triggerReady;
  8768. Ext.readyListeners.push({
  8769. fn: fn,
  8770. scope: scope
  8771. });
  8772. if (Ext.browser.is.PhoneGap && !Ext.os.is.Desktop) {
  8773. if (!Ext.readyListenerAttached) {
  8774. Ext.readyListenerAttached = true;
  8775. document.addEventListener('deviceready', triggerFn, false);
  8776. }
  8777. }
  8778. else {
  8779. if (document.readyState.match(/interactive|complete|loaded/) !== null) {
  8780. triggerFn();
  8781. }
  8782. else if (!Ext.readyListenerAttached) {
  8783. Ext.readyListenerAttached = true;
  8784. window.addEventListener('DOMContentLoaded', triggerFn, false);
  8785. }
  8786. }
  8787. }
  8788. },
  8789. /**
  8790. * Calls function after specified delay, or right away when delay == 0.
  8791. * @param {Function} callback The callback to execute.
  8792. * @param {Object} scope (optional) The scope to execute in.
  8793. * @param {Array} args (optional) The arguments to pass to the function.
  8794. * @param {Number} delay (optional) Pass a number to delay the call by a number of milliseconds.
  8795. * @member Ext
  8796. */
  8797. callback: function(callback, scope, args, delay) {
  8798. if (Ext.isFunction(callback)) {
  8799. args = args || [];
  8800. scope = scope || window;
  8801. if (delay) {
  8802. Ext.defer(callback, delay, scope, args);
  8803. } else {
  8804. callback.apply(scope, args);
  8805. }
  8806. }
  8807. }
  8808. });
  8809. //<debug>
  8810. Ext.Object.defineProperty(Ext, 'Msg', {
  8811. get: function() {
  8812. Ext.Logger.error("Using Ext.Msg without requiring Ext.MessageBox");
  8813. return null;
  8814. },
  8815. set: function(value) {
  8816. Ext.Object.defineProperty(Ext, 'Msg', {
  8817. value: value
  8818. });
  8819. return value;
  8820. },
  8821. configurable: true
  8822. });
  8823. //</debug>
  8824. //@tag dom,core
  8825. //@require Ext-more
  8826. /**
  8827. * Provides information about browser.
  8828. *
  8829. * Should not be manually instantiated unless for unit-testing.
  8830. * Access the global instance stored in {@link Ext.browser} instead.
  8831. * @private
  8832. */
  8833. Ext.define('Ext.env.Browser', {
  8834. requires: ['Ext.Version'],
  8835. statics: {
  8836. browserNames: {
  8837. ie: 'IE',
  8838. firefox: 'Firefox',
  8839. safari: 'Safari',
  8840. chrome: 'Chrome',
  8841. opera: 'Opera',
  8842. dolfin: 'Dolfin',
  8843. webosbrowser: 'webOSBrowser',
  8844. chromeMobile: 'ChromeMobile',
  8845. silk: 'Silk',
  8846. other: 'Other'
  8847. },
  8848. engineNames: {
  8849. webkit: 'WebKit',
  8850. gecko: 'Gecko',
  8851. presto: 'Presto',
  8852. trident: 'Trident',
  8853. other: 'Other'
  8854. },
  8855. enginePrefixes: {
  8856. webkit: 'AppleWebKit/',
  8857. gecko: 'Gecko/',
  8858. presto: 'Presto/',
  8859. trident: 'Trident/'
  8860. },
  8861. browserPrefixes: {
  8862. ie: 'MSIE ',
  8863. firefox: 'Firefox/',
  8864. chrome: 'Chrome/',
  8865. safari: 'Version/',
  8866. opera: 'Opera/',
  8867. dolfin: 'Dolfin/',
  8868. webosbrowser: 'wOSBrowser/',
  8869. chromeMobile: 'CrMo/',
  8870. silk: 'Silk/'
  8871. }
  8872. },
  8873. styleDashPrefixes: {
  8874. WebKit: '-webkit-',
  8875. Gecko: '-moz-',
  8876. Trident: '-ms-',
  8877. Presto: '-o-',
  8878. Other: ''
  8879. },
  8880. stylePrefixes: {
  8881. WebKit: 'Webkit',
  8882. Gecko: 'Moz',
  8883. Trident: 'ms',
  8884. Presto: 'O',
  8885. Other: ''
  8886. },
  8887. propertyPrefixes: {
  8888. WebKit: 'webkit',
  8889. Gecko: 'moz',
  8890. Trident: 'ms',
  8891. Presto: 'o',
  8892. Other: ''
  8893. },
  8894. // scope: Ext.env.Browser.prototype
  8895. /**
  8896. * A "hybrid" property, can be either accessed as a method call, for example:
  8897. *
  8898. * if (Ext.browser.is('IE')) {
  8899. * // ...
  8900. * }
  8901. *
  8902. * Or as an object with Boolean properties, for example:
  8903. *
  8904. * if (Ext.browser.is.IE) {
  8905. * // ...
  8906. * }
  8907. *
  8908. * Versions can be conveniently checked as well. For example:
  8909. *
  8910. * if (Ext.browser.is.IE6) {
  8911. * // Equivalent to (Ext.browser.is.IE && Ext.browser.version.equals(6))
  8912. * }
  8913. *
  8914. * __Note:__ Only {@link Ext.Version#getMajor major component} and {@link Ext.Version#getShortVersion simplified}
  8915. * value of the version are available via direct property checking.
  8916. *
  8917. * Supported values are:
  8918. *
  8919. * - IE
  8920. * - Firefox
  8921. * - Safari
  8922. * - Chrome
  8923. * - Opera
  8924. * - WebKit
  8925. * - Gecko
  8926. * - Presto
  8927. * - Trident
  8928. * - WebView
  8929. * - Other
  8930. *
  8931. * @param {String} value The OS name to check.
  8932. * @return {Boolean}
  8933. */
  8934. is: Ext.emptyFn,
  8935. /**
  8936. * The full name of the current browser.
  8937. * Possible values are:
  8938. *
  8939. * - IE
  8940. * - Firefox
  8941. * - Safari
  8942. * - Chrome
  8943. * - Opera
  8944. * - Other
  8945. * @type String
  8946. * @readonly
  8947. */
  8948. name: null,
  8949. /**
  8950. * Refer to {@link Ext.Version}.
  8951. * @type Ext.Version
  8952. * @readonly
  8953. */
  8954. version: null,
  8955. /**
  8956. * The full name of the current browser's engine.
  8957. * Possible values are:
  8958. *
  8959. * - WebKit
  8960. * - Gecko
  8961. * - Presto
  8962. * - Trident
  8963. * - Other
  8964. * @type String
  8965. * @readonly
  8966. */
  8967. engineName: null,
  8968. /**
  8969. * Refer to {@link Ext.Version}.
  8970. * @type Ext.Version
  8971. * @readonly
  8972. */
  8973. engineVersion: null,
  8974. setFlag: function(name, value) {
  8975. if (typeof value == 'undefined') {
  8976. value = true;
  8977. }
  8978. this.is[name] = value;
  8979. this.is[name.toLowerCase()] = value;
  8980. return this;
  8981. },
  8982. constructor: function(userAgent) {
  8983. /**
  8984. * @property {String}
  8985. * Browser User Agent string.
  8986. */
  8987. this.userAgent = userAgent;
  8988. is = this.is = function(name) {
  8989. return is[name] === true;
  8990. };
  8991. var statics = this.statics(),
  8992. browserMatch = userAgent.match(new RegExp('((?:' + Ext.Object.getValues(statics.browserPrefixes).join(')|(?:') + '))([\\w\\._]+)')),
  8993. engineMatch = userAgent.match(new RegExp('((?:' + Ext.Object.getValues(statics.enginePrefixes).join(')|(?:') + '))([\\w\\._]+)')),
  8994. browserNames = statics.browserNames,
  8995. browserName = browserNames.other,
  8996. engineNames = statics.engineNames,
  8997. engineName = engineNames.other,
  8998. browserVersion = '',
  8999. engineVersion = '',
  9000. isWebView = false,
  9001. is, i, name;
  9002. if (browserMatch) {
  9003. browserName = browserNames[Ext.Object.getKey(statics.browserPrefixes, browserMatch[1])];
  9004. browserVersion = new Ext.Version(browserMatch[2]);
  9005. }
  9006. if (engineMatch) {
  9007. engineName = engineNames[Ext.Object.getKey(statics.enginePrefixes, engineMatch[1])];
  9008. engineVersion = new Ext.Version(engineMatch[2]);
  9009. }
  9010. // Facebook changes the userAgent when you view a website within their iOS app. For some reason, the strip out information
  9011. // about the browser, so we have to detect that and fake it...
  9012. if (userAgent.match(/FB/) && browserName == "Other") {
  9013. browserName = browserNames.safari;
  9014. engineName = engineNames.webkit;
  9015. }
  9016. if (userAgent.match(/Android.*Chrome/g)) {
  9017. browserName = 'ChromeMobile';
  9018. }
  9019. Ext.apply(this, {
  9020. engineName: engineName,
  9021. engineVersion: engineVersion,
  9022. name: browserName,
  9023. version: browserVersion
  9024. });
  9025. this.setFlag(browserName);
  9026. if (browserVersion) {
  9027. this.setFlag(browserName + (browserVersion.getMajor() || ''));
  9028. this.setFlag(browserName + browserVersion.getShortVersion());
  9029. }
  9030. for (i in browserNames) {
  9031. if (browserNames.hasOwnProperty(i)) {
  9032. name = browserNames[i];
  9033. this.setFlag(name, browserName === name);
  9034. }
  9035. }
  9036. this.setFlag(name);
  9037. if (engineVersion) {
  9038. this.setFlag(engineName + (engineVersion.getMajor() || ''));
  9039. this.setFlag(engineName + engineVersion.getShortVersion());
  9040. }
  9041. for (i in engineNames) {
  9042. if (engineNames.hasOwnProperty(i)) {
  9043. name = engineNames[i];
  9044. this.setFlag(name, engineName === name);
  9045. }
  9046. }
  9047. this.setFlag('Standalone', !!navigator.standalone);
  9048. if (typeof window.PhoneGap != 'undefined' || typeof window.Cordova != 'undefined' || typeof window.cordova != 'undefined') {
  9049. isWebView = true;
  9050. this.setFlag('PhoneGap');
  9051. }
  9052. else if (!!window.isNK) {
  9053. isWebView = true;
  9054. this.setFlag('Sencha');
  9055. }
  9056. // Check if running in UIWebView
  9057. if (/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)(?!.*FBAN)/i.test(userAgent)) {
  9058. isWebView = true;
  9059. }
  9060. // Flag to check if it we are in the WebView
  9061. this.setFlag('WebView', isWebView);
  9062. /**
  9063. * @property {Boolean}
  9064. * `true` if browser is using strict mode.
  9065. */
  9066. this.isStrict = document.compatMode == "CSS1Compat";
  9067. /**
  9068. * @property {Boolean}
  9069. * `true` if page is running over SSL.
  9070. */
  9071. this.isSecure = /^https/i.test(window.location.protocol);
  9072. return this;
  9073. },
  9074. getStyleDashPrefix: function() {
  9075. return this.styleDashPrefixes[this.engineName];
  9076. },
  9077. getStylePrefix: function() {
  9078. return this.stylePrefixes[this.engineName];
  9079. },
  9080. getVendorProperyName: function(name) {
  9081. var prefix = this.propertyPrefixes[this.engineName];
  9082. if (prefix.length > 0) {
  9083. return prefix + Ext.String.capitalize(name);
  9084. }
  9085. return name;
  9086. }
  9087. }, function() {
  9088. /**
  9089. * @class Ext.browser
  9090. * @extends Ext.env.Browser
  9091. * @singleton
  9092. * Provides useful information about the current browser.
  9093. *
  9094. * Example:
  9095. *
  9096. * if (Ext.browser.is.IE) {
  9097. * // IE specific code here
  9098. * }
  9099. *
  9100. * if (Ext.browser.is.WebKit) {
  9101. * // WebKit specific code here
  9102. * }
  9103. *
  9104. * console.log("Version " + Ext.browser.version);
  9105. *
  9106. * For a full list of supported values, refer to {@link #is} property/method.
  9107. *
  9108. * @aside guide environment_package
  9109. */
  9110. var browserEnv = Ext.browser = new this(Ext.global.navigator.userAgent);
  9111. });
  9112. //@tag dom,core
  9113. //@require Ext.env.Browser
  9114. /**
  9115. * Provides information about operating system environment.
  9116. *
  9117. * Should not be manually instantiated unless for unit-testing.
  9118. * Access the global instance stored in {@link Ext.os} instead.
  9119. * @private
  9120. */
  9121. Ext.define('Ext.env.OS', {
  9122. requires: ['Ext.Version'],
  9123. statics: {
  9124. names: {
  9125. ios: 'iOS',
  9126. android: 'Android',
  9127. webos: 'webOS',
  9128. blackberry: 'BlackBerry',
  9129. rimTablet: 'RIMTablet',
  9130. mac: 'MacOS',
  9131. win: 'Windows',
  9132. linux: 'Linux',
  9133. bada: 'Bada',
  9134. other: 'Other'
  9135. },
  9136. prefixes: {
  9137. ios: 'i(?:Pad|Phone|Pod)(?:.*)CPU(?: iPhone)? OS ',
  9138. android: '(Android |HTC_|Silk/)', // Some HTC devices ship with an OSX userAgent by default,
  9139. // so we need to add a direct check for HTC_
  9140. blackberry: 'BlackBerry(?:.*)Version\/',
  9141. rimTablet: 'RIM Tablet OS ',
  9142. webos: '(?:webOS|hpwOS)\/',
  9143. bada: 'Bada\/'
  9144. }
  9145. },
  9146. /**
  9147. * A "hybrid" property, can be either accessed as a method call, i.e:
  9148. *
  9149. * if (Ext.os.is('Android')) {
  9150. * // ...
  9151. * }
  9152. *
  9153. * or as an object with boolean properties, i.e:
  9154. *
  9155. * if (Ext.os.is.Android) {
  9156. * // ...
  9157. * }
  9158. *
  9159. * Versions can be conveniently checked as well. For example:
  9160. *
  9161. * if (Ext.os.is.Android2) {
  9162. * // Equivalent to (Ext.os.is.Android && Ext.os.version.equals(2))
  9163. * }
  9164. *
  9165. * if (Ext.os.is.iOS32) {
  9166. * // Equivalent to (Ext.os.is.iOS && Ext.os.version.equals(3.2))
  9167. * }
  9168. *
  9169. * Note that only {@link Ext.Version#getMajor major component} and {@link Ext.Version#getShortVersion simplified}
  9170. * value of the version are available via direct property checking. Supported values are:
  9171. *
  9172. * - iOS
  9173. * - iPad
  9174. * - iPhone
  9175. * - iPhone5 (also true for 4in iPods).
  9176. * - iPod
  9177. * - Android
  9178. * - WebOS
  9179. * - BlackBerry
  9180. * - Bada
  9181. * - MacOS
  9182. * - Windows
  9183. * - Linux
  9184. * - Other
  9185. * @param {String} value The OS name to check.
  9186. * @return {Boolean}
  9187. */
  9188. is: Ext.emptyFn,
  9189. /**
  9190. * @property {String} [name=null]
  9191. * @readonly
  9192. * The full name of the current operating system. Possible values are:
  9193. *
  9194. * - iOS
  9195. * - Android
  9196. * - WebOS
  9197. * - BlackBerry,
  9198. * - MacOS
  9199. * - Windows
  9200. * - Linux
  9201. * - Other
  9202. */
  9203. name: null,
  9204. /**
  9205. * @property {Ext.Version} [version=null]
  9206. * Refer to {@link Ext.Version}
  9207. * @readonly
  9208. */
  9209. version: null,
  9210. setFlag: function(name, value) {
  9211. if (typeof value == 'undefined') {
  9212. value = true;
  9213. }
  9214. this.is[name] = value;
  9215. this.is[name.toLowerCase()] = value;
  9216. return this;
  9217. },
  9218. constructor: function(userAgent, platform) {
  9219. var statics = this.statics(),
  9220. names = statics.names,
  9221. prefixes = statics.prefixes,
  9222. name,
  9223. version = '',
  9224. i, prefix, match, item, is;
  9225. is = this.is = function(name) {
  9226. return this.is[name] === true;
  9227. };
  9228. for (i in prefixes) {
  9229. if (prefixes.hasOwnProperty(i)) {
  9230. prefix = prefixes[i];
  9231. match = userAgent.match(new RegExp('(?:'+prefix+')([^\\s;]+)'));
  9232. if (match) {
  9233. name = names[i];
  9234. // This is here because some HTC android devices show an OSX Snow Leopard userAgent by default.
  9235. // And the Kindle Fire doesn't have any indicator of Android as the OS in its User Agent
  9236. if (match[1] && (match[1] == "HTC_" || match[1] == "Silk/")) {
  9237. version = new Ext.Version("2.3");
  9238. } else {
  9239. version = new Ext.Version(match[match.length - 1]);
  9240. }
  9241. break;
  9242. }
  9243. }
  9244. }
  9245. if (!name) {
  9246. name = names[(userAgent.toLowerCase().match(/mac|win|linux/) || ['other'])[0]];
  9247. version = new Ext.Version('');
  9248. }
  9249. this.name = name;
  9250. this.version = version;
  9251. if (platform) {
  9252. this.setFlag(platform.replace(/ simulator$/i, ''));
  9253. }
  9254. this.setFlag(name);
  9255. if (version) {
  9256. this.setFlag(name + (version.getMajor() || ''));
  9257. this.setFlag(name + version.getShortVersion());
  9258. }
  9259. for (i in names) {
  9260. if (names.hasOwnProperty(i)) {
  9261. item = names[i];
  9262. if (!is.hasOwnProperty(name)) {
  9263. this.setFlag(item, (name === item));
  9264. }
  9265. }
  9266. }
  9267. // Detect if the device is the iPhone 5.
  9268. if (this.name == "iOS" && window.screen.height == 568) {
  9269. this.setFlag('iPhone5');
  9270. }
  9271. return this;
  9272. }
  9273. }, function() {
  9274. var navigation = Ext.global.navigator,
  9275. userAgent = navigation.userAgent,
  9276. osEnv, osName, deviceType;
  9277. /**
  9278. * @class Ext.os
  9279. * @extends Ext.env.OS
  9280. * @singleton
  9281. * Provides useful information about the current operating system environment.
  9282. *
  9283. * Example:
  9284. *
  9285. * if (Ext.os.is.Windows) {
  9286. * // Windows specific code here
  9287. * }
  9288. *
  9289. * if (Ext.os.is.iOS) {
  9290. * // iPad, iPod, iPhone, etc.
  9291. * }
  9292. *
  9293. * console.log("Version " + Ext.os.version);
  9294. *
  9295. * For a full list of supported values, refer to the {@link #is} property/method.
  9296. *
  9297. * @aside guide environment_package
  9298. */
  9299. Ext.os = osEnv = new this(userAgent, navigation.platform);
  9300. osName = osEnv.name;
  9301. var search = window.location.search.match(/deviceType=(Tablet|Phone)/),
  9302. nativeDeviceType = window.deviceType;
  9303. // Override deviceType by adding a get variable of deviceType. NEEDED FOR DOCS APP.
  9304. // E.g: example/kitchen-sink.html?deviceType=Phone
  9305. if (search && search[1]) {
  9306. deviceType = search[1];
  9307. }
  9308. else if (nativeDeviceType === 'iPhone') {
  9309. deviceType = 'Phone';
  9310. }
  9311. else if (nativeDeviceType === 'iPad') {
  9312. deviceType = 'Tablet';
  9313. }
  9314. else {
  9315. if (!osEnv.is.Android && !osEnv.is.iOS && /Windows|Linux|MacOS/.test(osName)) {
  9316. deviceType = 'Desktop';
  9317. // always set it to false when you are on a desktop
  9318. Ext.browser.is.WebView = false;
  9319. }
  9320. else if (osEnv.is.iPad || osEnv.is.Android3 || (osEnv.is.Android4 && userAgent.search(/mobile/i) == -1)) {
  9321. deviceType = 'Tablet';
  9322. }
  9323. else {
  9324. deviceType = 'Phone';
  9325. }
  9326. }
  9327. /**
  9328. * @property {String} deviceType
  9329. * The generic type of the current device.
  9330. *
  9331. * Possible values:
  9332. *
  9333. * - Phone
  9334. * - Tablet
  9335. * - Desktop
  9336. *
  9337. * For testing purposes the deviceType can be overridden by adding
  9338. * a deviceType parameter to the URL of the page, like so:
  9339. *
  9340. * http://localhost/mypage.html?deviceType=Tablet
  9341. *
  9342. */
  9343. osEnv.setFlag(deviceType, true);
  9344. osEnv.deviceType = deviceType;
  9345. /**
  9346. * @class Ext.is
  9347. * Used to detect if the current browser supports a certain feature, and the type of the current browser.
  9348. * @deprecated 2.0.0
  9349. * Please refer to the {@link Ext.browser}, {@link Ext.os} and {@link Ext.feature} classes instead.
  9350. */
  9351. });
  9352. //@tag dom,core
  9353. /**
  9354. * Provides information about browser.
  9355. *
  9356. * Should not be manually instantiated unless for unit-testing.
  9357. * Access the global instance stored in {@link Ext.browser} instead.
  9358. * @private
  9359. */
  9360. Ext.define('Ext.env.Feature', {
  9361. requires: ['Ext.env.Browser', 'Ext.env.OS'],
  9362. constructor: function() {
  9363. this.testElements = {};
  9364. this.has = function(name) {
  9365. return !!this.has[name];
  9366. };
  9367. return this;
  9368. },
  9369. getTestElement: function(tag, createNew) {
  9370. if (tag === undefined) {
  9371. tag = 'div';
  9372. }
  9373. else if (typeof tag !== 'string') {
  9374. return tag;
  9375. }
  9376. if (createNew) {
  9377. return document.createElement(tag);
  9378. }
  9379. if (!this.testElements[tag]) {
  9380. this.testElements[tag] = document.createElement(tag);
  9381. }
  9382. return this.testElements[tag];
  9383. },
  9384. isStyleSupported: function(name, tag) {
  9385. var elementStyle = this.getTestElement(tag).style,
  9386. cName = Ext.String.capitalize(name);
  9387. if (typeof elementStyle[name] !== 'undefined'
  9388. || typeof elementStyle[Ext.browser.getStylePrefix(name) + cName] !== 'undefined') {
  9389. return true;
  9390. }
  9391. return false;
  9392. },
  9393. isEventSupported: function(name, tag) {
  9394. if (tag === undefined) {
  9395. tag = window;
  9396. }
  9397. var element = this.getTestElement(tag),
  9398. eventName = 'on' + name.toLowerCase(),
  9399. isSupported = (eventName in element);
  9400. if (!isSupported) {
  9401. if (element.setAttribute && element.removeAttribute) {
  9402. element.setAttribute(eventName, '');
  9403. isSupported = typeof element[eventName] === 'function';
  9404. if (typeof element[eventName] !== 'undefined') {
  9405. element[eventName] = undefined;
  9406. }
  9407. element.removeAttribute(eventName);
  9408. }
  9409. }
  9410. return isSupported;
  9411. },
  9412. getSupportedPropertyName: function(object, name) {
  9413. var vendorName = Ext.browser.getVendorProperyName(name);
  9414. if (vendorName in object) {
  9415. return vendorName;
  9416. }
  9417. else if (name in object) {
  9418. return name;
  9419. }
  9420. return null;
  9421. },
  9422. registerTest: Ext.Function.flexSetter(function(name, fn) {
  9423. this.has[name] = fn.call(this);
  9424. return this;
  9425. })
  9426. }, function() {
  9427. /**
  9428. * @class Ext.feature
  9429. * @extend Ext.env.Feature
  9430. * @singleton
  9431. *
  9432. * A simple class to verify if a browser feature exists or not on the current device.
  9433. *
  9434. * if (Ext.feature.has.Canvas) {
  9435. * // do some cool things with canvas here
  9436. * }
  9437. *
  9438. * See the {@link #has} property/method for details of the features that can be detected.
  9439. *
  9440. * @aside guide environment_package
  9441. */
  9442. Ext.feature = new this;
  9443. var has = Ext.feature.has;
  9444. /**
  9445. * @method has
  9446. * @member Ext.feature
  9447. * Verifies if a browser feature exists or not on the current device.
  9448. *
  9449. * A "hybrid" property, can be either accessed as a method call, i.e:
  9450. *
  9451. * if (Ext.feature.has('Canvas')) {
  9452. * // ...
  9453. * }
  9454. *
  9455. * or as an object with boolean properties, i.e:
  9456. *
  9457. * if (Ext.feature.has.Canvas) {
  9458. * // ...
  9459. * }
  9460. *
  9461. * Possible properties/parameter values:
  9462. *
  9463. * - Canvas
  9464. * - Svg
  9465. * - Vml
  9466. * - Touch - supports touch events (`touchstart`).
  9467. * - Orientation - supports different orientations.
  9468. * - OrientationChange - supports the `orientationchange` event.
  9469. * - DeviceMotion - supports the `devicemotion` event.
  9470. * - Geolocation
  9471. * - SqlDatabase
  9472. * - WebSockets
  9473. * - Range - supports [DOM document fragments.][1]
  9474. * - CreateContextualFragment - supports HTML fragment parsing using [range.createContextualFragment()][2].
  9475. * - History - supports history management with [history.pushState()][3].
  9476. * - CssTransforms
  9477. * - Css3dTransforms
  9478. * - CssAnimations
  9479. * - CssTransitions
  9480. * - Audio - supports the `<audio>` tag.
  9481. * - Video - supports the `<video>` tag.
  9482. * - ClassList - supports the HTML5 classList API.
  9483. * - LocalStorage - LocalStorage is supported and can be written to.
  9484. *
  9485. * [1]: https://developer.mozilla.org/en/DOM/range
  9486. * [2]: https://developer.mozilla.org/en/DOM/range.createContextualFragment
  9487. * [3]: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history#The_pushState().C2.A0method
  9488. *
  9489. * @param {String} value The feature name to check.
  9490. * @return {Boolean}
  9491. */
  9492. Ext.feature.registerTest({
  9493. Canvas: function() {
  9494. var element = this.getTestElement('canvas');
  9495. return !!(element && element.getContext && element.getContext('2d'));
  9496. },
  9497. Svg: function() {
  9498. var doc = document;
  9499. return !!(doc.createElementNS && !!doc.createElementNS("http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect);
  9500. },
  9501. Vml: function() {
  9502. var element = this.getTestElement(),
  9503. ret = false;
  9504. element.innerHTML = "<!--[if vml]><br><![endif]-->";
  9505. ret = (element.childNodes.length === 1);
  9506. element.innerHTML = "";
  9507. return ret;
  9508. },
  9509. Touch: function() {
  9510. return this.isEventSupported('touchstart') && !(Ext.os && Ext.os.name.match(/Windows|MacOS|Linux/) && !Ext.os.is.BlackBerry6);
  9511. },
  9512. Orientation: function() {
  9513. return ('orientation' in window) && this.isEventSupported('orientationchange');
  9514. },
  9515. OrientationChange: function() {
  9516. return this.isEventSupported('orientationchange');
  9517. },
  9518. DeviceMotion: function() {
  9519. return this.isEventSupported('devicemotion');
  9520. },
  9521. Geolocation: function() {
  9522. return 'geolocation' in window.navigator;
  9523. },
  9524. SqlDatabase: function() {
  9525. return 'openDatabase' in window;
  9526. },
  9527. WebSockets: function() {
  9528. return 'WebSocket' in window;
  9529. },
  9530. Range: function() {
  9531. return !!document.createRange;
  9532. },
  9533. CreateContextualFragment: function() {
  9534. var range = !!document.createRange ? document.createRange() : false;
  9535. return range && !!range.createContextualFragment;
  9536. },
  9537. History: function() {
  9538. return ('history' in window && 'pushState' in window.history);
  9539. },
  9540. CssTransforms: function() {
  9541. return this.isStyleSupported('transform');
  9542. },
  9543. Css3dTransforms: function() {
  9544. // See https://sencha.jira.com/browse/TOUCH-1544
  9545. return this.has('CssTransforms') && this.isStyleSupported('perspective') && !Ext.os.is.Android2;
  9546. },
  9547. CssAnimations: function() {
  9548. return this.isStyleSupported('animationName');
  9549. },
  9550. CssTransitions: function() {
  9551. return this.isStyleSupported('transitionProperty');
  9552. },
  9553. Audio: function() {
  9554. return !!this.getTestElement('audio').canPlayType;
  9555. },
  9556. Video: function() {
  9557. return !!this.getTestElement('video').canPlayType;
  9558. },
  9559. ClassList: function() {
  9560. return "classList" in this.getTestElement();
  9561. },
  9562. LocalStorage : function() {
  9563. var supported = false;
  9564. try {
  9565. if ('localStorage' in window && window['localStorage'] !== null) {
  9566. //this should throw an error in private browsing mode in iOS
  9567. localStorage.setItem('sencha-localstorage-test', 'test success');
  9568. //clean up if setItem worked
  9569. localStorage.removeItem('sencha-localstorage-test');
  9570. supported = true;
  9571. }
  9572. } catch ( e ) {}
  9573. return supported;
  9574. }
  9575. });
  9576. });
  9577. //@tag dom,core
  9578. //@define Ext.DomQuery
  9579. //@define Ext.core.DomQuery
  9580. //@require Ext.env.Feature
  9581. /**
  9582. * @class Ext.DomQuery
  9583. * @alternateClassName Ext.dom.Query
  9584. *
  9585. * Provides functionality to select elements on the page based on a CSS selector. Delegates to
  9586. * document.querySelectorAll. More information can be found at
  9587. * [http://www.w3.org/TR/css3-selectors/](http://www.w3.org/TR/css3-selectors/)
  9588. *
  9589. * All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example
  9590. * `div.foo:nth-child(odd)[@foo=bar].bar:first` would be a perfectly valid selector.
  9591. *
  9592. * ## Element Selectors:
  9593. *
  9594. * * \* any element
  9595. * * E an element with the tag E
  9596. * * E F All descendant elements of E that have the tag F
  9597. * * E > F or E/F all direct children elements of E that have the tag F
  9598. * * E + F all elements with the tag F that are immediately preceded by an element with the tag E
  9599. * * E ~ F all elements with the tag F that are preceded by a sibling element with the tag E
  9600. *
  9601. * ## Attribute Selectors:
  9602. *
  9603. * The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.
  9604. *
  9605. * * E[foo] has an attribute "foo"
  9606. * * E[foo=bar] has an attribute "foo" that equals "bar"
  9607. * * E[foo^=bar] has an attribute "foo" that starts with "bar"
  9608. * * E[foo$=bar] has an attribute "foo" that ends with "bar"
  9609. * * E[foo*=bar] has an attribute "foo" that contains the substring "bar"
  9610. * * E[foo%=2] has an attribute "foo" that is evenly divisible by 2
  9611. * * E[foo!=bar] has an attribute "foo" that does not equal "bar"
  9612. *
  9613. * ## Pseudo Classes:
  9614. *
  9615. * * E:first-child E is the first child of its parent
  9616. * * E:last-child E is the last child of its parent
  9617. * * E:nth-child(n) E is the nth child of its parent (1 based as per the spec)
  9618. * * E:nth-child(odd) E is an odd child of its parent
  9619. * * E:nth-child(even) E is an even child of its parent
  9620. * * E:only-child E is the only child of its parent
  9621. * * E:checked E is an element that is has a checked attribute that is true (e.g. a radio or checkbox)
  9622. * * E:first the first E in the resultset
  9623. * * E:last the last E in the resultset
  9624. * * E:nth(n) the nth E in the resultset (1 based)
  9625. * * E:odd shortcut for :nth-child(odd)
  9626. * * E:even shortcut for :nth-child(even)
  9627. * * E:not(S) an E element that does not match simple selector S
  9628. * * E:has(S) an E element that has a descendant that matches simple selector S
  9629. * * E:next(S) an E element whose next sibling matches simple selector S
  9630. * * E:prev(S) an E element whose previous sibling matches simple selector S
  9631. * * E:any(S1|S2|S2) an E element which matches any of the simple selectors S1, S2 or S3//\\
  9632. *
  9633. * ## CSS Value Selectors:
  9634. *
  9635. * * E{display=none} CSS value "display" that equals "none"
  9636. * * E{display^=none} CSS value "display" that starts with "none"
  9637. * * E{display$=none} CSS value "display" that ends with "none"
  9638. * * E{display*=none} CSS value "display" that contains the substring "none"
  9639. * * E{display%=2} CSS value "display" that is evenly divisible by 2
  9640. * * E{display!=none} CSS value "display" that does not equal "none"
  9641. */
  9642. Ext.define('Ext.dom.Query', {
  9643. /**
  9644. * Selects a group of elements.
  9645. * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
  9646. * @param {HTMLElement/String} [root] The start of the query (defaults to document).
  9647. * @return {HTMLElement[]} An Array of DOM elements which match the selector. If there are
  9648. * no matches, and empty Array is returned.
  9649. */
  9650. select: function(q, root) {
  9651. var results = [],
  9652. nodes,
  9653. i,
  9654. j,
  9655. qlen,
  9656. nlen;
  9657. root = root || document;
  9658. if (typeof root == 'string') {
  9659. root = document.getElementById(root);
  9660. }
  9661. q = q.split(",");
  9662. for (i = 0,qlen = q.length; i < qlen; i++) {
  9663. if (typeof q[i] == 'string') {
  9664. //support for node attribute selection
  9665. if (q[i][0] == '@') {
  9666. nodes = root.getAttributeNode(q[i].substring(1));
  9667. results.push(nodes);
  9668. }
  9669. else {
  9670. nodes = root.querySelectorAll(q[i]);
  9671. for (j = 0,nlen = nodes.length; j < nlen; j++) {
  9672. results.push(nodes[j]);
  9673. }
  9674. }
  9675. }
  9676. }
  9677. return results;
  9678. },
  9679. /**
  9680. * Selects a single element.
  9681. * @param {String} selector The selector/xpath query
  9682. * @param {HTMLElement/String} [root] The start of the query (defaults to document).
  9683. * @return {HTMLElement} The DOM element which matched the selector.
  9684. */
  9685. selectNode: function(q, root) {
  9686. return this.select(q, root)[0];
  9687. },
  9688. /**
  9689. * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
  9690. * @param {String/HTMLElement/Array} el An element id, element or array of elements
  9691. * @param {String} selector The simple selector to test
  9692. * @return {Boolean}
  9693. */
  9694. is: function(el, q) {
  9695. if (typeof el == "string") {
  9696. el = document.getElementById(el);
  9697. }
  9698. return this.select(q).indexOf(el) !== -1;
  9699. },
  9700. isXml: function(el) {
  9701. var docEl = (el ? el.ownerDocument || el : 0).documentElement;
  9702. return docEl ? docEl.nodeName !== "HTML" : false;
  9703. }
  9704. }, function() {
  9705. Ext.ns('Ext.core');
  9706. Ext.core.DomQuery = Ext.DomQuery = new this();
  9707. Ext.query = Ext.Function.alias(Ext.DomQuery, 'select');
  9708. });
  9709. //@tag dom,core
  9710. //@define Ext.DomHelper
  9711. //@require Ext.dom.Query
  9712. /**
  9713. * @class Ext.DomHelper
  9714. * @alternateClassName Ext.dom.Helper
  9715. *
  9716. * The DomHelper class provides a layer of abstraction from DOM and transparently supports creating elements via DOM or
  9717. * using HTML fragments. It also has the ability to create HTML fragment templates from your DOM building code.
  9718. *
  9719. * ## DomHelper element specification object
  9720. *
  9721. * A specification object is used when creating elements. Attributes of this object are assumed to be element
  9722. * attributes, except for 4 special attributes:
  9723. *
  9724. * * **tag**: The tag name of the element
  9725. * * **children (or cn)**: An array of the same kind of element definition objects to be created and appended. These
  9726. * can be nested as deep as you want.
  9727. * * **cls**: The class attribute of the element. This will end up being either the "class" attribute on a HTML
  9728. * fragment or className for a DOM node, depending on whether DomHelper is using fragments or DOM.
  9729. * * **html**: The innerHTML for the element
  9730. *
  9731. * ## Insertion methods
  9732. *
  9733. * Commonly used insertion methods:
  9734. *
  9735. * * {@link #append}
  9736. * * {@link #insertBefore}
  9737. * * {@link #insertAfter}
  9738. * * {@link #overwrite}
  9739. * * {@link #insertHtml}
  9740. *
  9741. * ## Example
  9742. *
  9743. * This is an example, where an unordered list with 3 children items is appended to an existing element with id
  9744. * 'my-div':
  9745. *
  9746. * var dh = Ext.DomHelper; // create shorthand alias
  9747. * // specification object
  9748. * var spec = {
  9749. * id: 'my-ul',
  9750. * tag: 'ul',
  9751. * cls: 'my-list',
  9752. * // append children after creating
  9753. * children: [ // may also specify 'cn' instead of 'children'
  9754. * {tag: 'li', id: 'item0', html: 'List Item 0'},
  9755. * {tag: 'li', id: 'item1', html: 'List Item 1'},
  9756. * {tag: 'li', id: 'item2', html: 'List Item 2'}
  9757. * ]
  9758. * };
  9759. * var list = dh.append(
  9760. * 'my-div', // the context element 'my-div' can either be the id or the actual node
  9761. * spec // the specification object
  9762. * );
  9763. *
  9764. * Element creation specification parameters in this class may also be passed as an Array of specification objects.
  9765. * This can be used to insert multiple sibling nodes into an existing container very efficiently. For example, to add
  9766. * more list items to the example above:
  9767. *
  9768. * dh.append('my-ul', [
  9769. * {tag: 'li', id: 'item3', html: 'List Item 3'},
  9770. * {tag: 'li', id: 'item4', html: 'List Item 4'}
  9771. * ]);
  9772. *
  9773. * ## Templating
  9774. *
  9775. * The real power is in the built-in templating. Instead of creating or appending any elements, createTemplate returns
  9776. * a Template object which can be used over and over to insert new elements. Revisiting the example above, we could
  9777. * utilize templating this time:
  9778. *
  9779. * // create the node
  9780. * var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});
  9781. * // get template
  9782. * var tpl = dh.createTemplate({tag: 'li', id: 'item{0}', html: 'List Item {0}'});
  9783. *
  9784. * for(var i = 0; i < 5; i++){
  9785. * tpl.append(list, i); // use template to append to the actual node
  9786. * }
  9787. *
  9788. * An example using a template:
  9789. *
  9790. * var html = '"{0}" href="{1}" class="nav">{2}';
  9791. *
  9792. * var tpl = new Ext.DomHelper.createTemplate(html);
  9793. * tpl.append('blog-roll', ['link1', 'http://www.tommymaintz.com/', "Tommy's Site"]);
  9794. * tpl.append('blog-roll', ['link2', 'http://www.avins.org/', "Jamie's Site"]);
  9795. *
  9796. * The same example using named parameters:
  9797. *
  9798. * var html = '"{id}" href="{url}" class="nav">{text}';
  9799. *
  9800. * var tpl = new Ext.DomHelper.createTemplate(html);
  9801. * tpl.append('blog-roll', {
  9802. * id: 'link1',
  9803. * url: 'http://www.tommymaintz.com/',
  9804. * text: "Tommy's Site"
  9805. * });
  9806. * tpl.append('blog-roll', {
  9807. * id: 'link2',
  9808. * url: 'http://www.avins.org/',
  9809. * text: "Jamie's Site"
  9810. * });
  9811. *
  9812. * ## Compiling Templates
  9813. *
  9814. * Templates are applied using regular expressions. The performance is great, but if you are adding a bunch of DOM
  9815. * elements using the same template, you can increase performance even further by "compiling" the template. The way
  9816. * "compile()" works is the template is parsed and broken up at the different variable points and a dynamic function is
  9817. * created and eval'ed. The generated function performs string concatenation of these parts and the passed variables
  9818. * instead of using regular expressions.
  9819. *
  9820. * var html = '"{id}" href="{url}" class="nav">{text}';
  9821. *
  9822. * var tpl = new Ext.DomHelper.createTemplate(html);
  9823. * tpl.compile();
  9824. *
  9825. * // ... use template like normal
  9826. *
  9827. * ## Performance Boost
  9828. *
  9829. * DomHelper will transparently create HTML fragments when it can. Using HTML fragments instead of DOM can
  9830. * significantly boost performance.
  9831. *
  9832. * Element creation specification parameters may also be strings. If useDom is false, then the string is used as
  9833. * innerHTML. If useDom is true, a string specification results in the creation of a text node. Usage:
  9834. *
  9835. * Ext.DomHelper.useDom = true; // force it to use DOM; reduces performance
  9836. *
  9837. */
  9838. Ext.define('Ext.dom.Helper', {
  9839. emptyTags : /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
  9840. confRe : /tag|children|cn|html|tpl|tplData$/i,
  9841. endRe : /end/i,
  9842. attribXlat: { cls : 'class', htmlFor : 'for' },
  9843. closeTags: {},
  9844. decamelizeName : function () {
  9845. var camelCaseRe = /([a-z])([A-Z])/g,
  9846. cache = {};
  9847. function decamel (match, p1, p2) {
  9848. return p1 + '-' + p2.toLowerCase();
  9849. }
  9850. return function (s) {
  9851. return cache[s] || (cache[s] = s.replace(camelCaseRe, decamel));
  9852. };
  9853. }(),
  9854. generateMarkup: function(spec, buffer) {
  9855. var me = this,
  9856. attr, val, tag, i, closeTags;
  9857. if (typeof spec == "string") {
  9858. buffer.push(spec);
  9859. } else if (Ext.isArray(spec)) {
  9860. for (i = 0; i < spec.length; i++) {
  9861. if (spec[i]) {
  9862. me.generateMarkup(spec[i], buffer);
  9863. }
  9864. }
  9865. } else {
  9866. tag = spec.tag || 'div';
  9867. buffer.push('<', tag);
  9868. for (attr in spec) {
  9869. if (spec.hasOwnProperty(attr)) {
  9870. val = spec[attr];
  9871. if (!me.confRe.test(attr)) {
  9872. if (typeof val == "object") {
  9873. buffer.push(' ', attr, '="');
  9874. me.generateStyles(val, buffer).push('"');
  9875. } else {
  9876. buffer.push(' ', me.attribXlat[attr] || attr, '="', val, '"');
  9877. }
  9878. }
  9879. }
  9880. }
  9881. // Now either just close the tag or try to add children and close the tag.
  9882. if (me.emptyTags.test(tag)) {
  9883. buffer.push('/>');
  9884. } else {
  9885. buffer.push('>');
  9886. // Apply the tpl html, and cn specifications
  9887. if ((val = spec.tpl)) {
  9888. val.applyOut(spec.tplData, buffer);
  9889. }
  9890. if ((val = spec.html)) {
  9891. buffer.push(val);
  9892. }
  9893. if ((val = spec.cn || spec.children)) {
  9894. me.generateMarkup(val, buffer);
  9895. }
  9896. // we generate a lot of close tags, so cache them rather than push 3 parts
  9897. closeTags = me.closeTags;
  9898. buffer.push(closeTags[tag] || (closeTags[tag] = '</' + tag + '>'));
  9899. }
  9900. }
  9901. return buffer;
  9902. },
  9903. /**
  9904. * Converts the styles from the given object to text. The styles are CSS style names
  9905. * with their associated value.
  9906. *
  9907. * The basic form of this method returns a string:
  9908. *
  9909. * var s = Ext.DomHelper.generateStyles({
  9910. * backgroundColor: 'red'
  9911. * });
  9912. *
  9913. * // s = 'background-color:red;'
  9914. *
  9915. * Alternatively, this method can append to an output array.
  9916. *
  9917. * var buf = [];
  9918. *
  9919. * // ...
  9920. *
  9921. * Ext.DomHelper.generateStyles({
  9922. * backgroundColor: 'red'
  9923. * }, buf);
  9924. *
  9925. * In this case, the style text is pushed on to the array and the array is returned.
  9926. *
  9927. * @param {Object} styles The object describing the styles.
  9928. * @param {String[]} [buffer] The output buffer.
  9929. * @return {String/String[]} If buffer is passed, it is returned. Otherwise the style
  9930. * string is returned.
  9931. */
  9932. generateStyles: function (styles, buffer) {
  9933. var a = buffer || [],
  9934. name;
  9935. for (name in styles) {
  9936. if (styles.hasOwnProperty(name)) {
  9937. a.push(this.decamelizeName(name), ':', styles[name], ';');
  9938. }
  9939. }
  9940. return buffer || a.join('');
  9941. },
  9942. /**
  9943. * Returns the markup for the passed Element(s) config.
  9944. * @param {Object} spec The DOM object spec (and children).
  9945. * @return {String}
  9946. */
  9947. markup: function(spec) {
  9948. if (typeof spec == "string") {
  9949. return spec;
  9950. }
  9951. var buf = this.generateMarkup(spec, []);
  9952. return buf.join('');
  9953. },
  9954. /**
  9955. * Applies a style specification to an element.
  9956. * @param {String/HTMLElement} el The element to apply styles to
  9957. * @param {String/Object/Function} styles A style specification string e.g. 'width:100px', or object in the form {width:'100px'}, or
  9958. * a function which returns such a specification.
  9959. */
  9960. applyStyles: function(el, styles) {
  9961. Ext.fly(el).applyStyles(styles);
  9962. },
  9963. /**
  9964. * @private
  9965. * Fix for browsers which no longer support createContextualFragment
  9966. */
  9967. createContextualFragment: function(html){
  9968. var div = document.createElement("div"),
  9969. fragment = document.createDocumentFragment(),
  9970. i = 0,
  9971. length, childNodes;
  9972. div.innerHTML = html;
  9973. childNodes = div.childNodes;
  9974. length = childNodes.length;
  9975. for (; i < length; i++) {
  9976. fragment.appendChild(childNodes[i].cloneNode(true));
  9977. }
  9978. return fragment;
  9979. },
  9980. /**
  9981. * Inserts an HTML fragment into the DOM.
  9982. * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
  9983. *
  9984. * For example take the following HTML: `<div>Contents</div>`
  9985. *
  9986. * Using different `where` values inserts element to the following places:
  9987. *
  9988. * - beforeBegin: `<HERE><div>Contents</div>`
  9989. * - afterBegin: `<div><HERE>Contents</div>`
  9990. * - beforeEnd: `<div>Contents<HERE></div>`
  9991. * - afterEnd: `<div>Contents</div><HERE>`
  9992. *
  9993. * @param {HTMLElement/TextNode} el The context element
  9994. * @param {String} html The HTML fragment
  9995. * @return {HTMLElement} The new node
  9996. */
  9997. insertHtml: function(where, el, html) {
  9998. var setStart, range, frag, rangeEl, isBeforeBegin, isAfterBegin;
  9999. where = where.toLowerCase();
  10000. if (Ext.isTextNode(el)) {
  10001. if (where == 'afterbegin' ) {
  10002. where = 'beforebegin';
  10003. }
  10004. else if (where == 'beforeend') {
  10005. where = 'afterend';
  10006. }
  10007. }
  10008. isBeforeBegin = where == 'beforebegin';
  10009. isAfterBegin = where == 'afterbegin';
  10010. range = Ext.feature.has.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
  10011. setStart = 'setStart' + (this.endRe.test(where) ? 'After' : 'Before');
  10012. if (isBeforeBegin || where == 'afterend') {
  10013. if (range) {
  10014. range[setStart](el);
  10015. frag = range.createContextualFragment(html);
  10016. }
  10017. else {
  10018. frag = this.createContextualFragment(html);
  10019. }
  10020. el.parentNode.insertBefore(frag, isBeforeBegin ? el : el.nextSibling);
  10021. return el[(isBeforeBegin ? 'previous' : 'next') + 'Sibling'];
  10022. }
  10023. else {
  10024. rangeEl = (isAfterBegin ? 'first' : 'last') + 'Child';
  10025. if (el.firstChild) {
  10026. if (range) {
  10027. range[setStart](el[rangeEl]);
  10028. frag = range.createContextualFragment(html);
  10029. } else {
  10030. frag = this.createContextualFragment(html);
  10031. }
  10032. if (isAfterBegin) {
  10033. el.insertBefore(frag, el.firstChild);
  10034. } else {
  10035. el.appendChild(frag);
  10036. }
  10037. } else {
  10038. el.innerHTML = html;
  10039. }
  10040. return el[rangeEl];
  10041. }
  10042. },
  10043. /**
  10044. * Creates new DOM element(s) and inserts them before el.
  10045. * @param {String/HTMLElement/Ext.Element} el The context element
  10046. * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  10047. * @param {Boolean} [returnElement] true to return a Ext.Element
  10048. * @return {HTMLElement/Ext.Element} The new node
  10049. */
  10050. insertBefore: function(el, o, returnElement) {
  10051. return this.doInsert(el, o, returnElement, 'beforebegin');
  10052. },
  10053. /**
  10054. * Creates new DOM element(s) and inserts them after el.
  10055. * @param {String/HTMLElement/Ext.Element} el The context element
  10056. * @param {Object} o The DOM object spec (and children)
  10057. * @param {Boolean} [returnElement] true to return a Ext.Element
  10058. * @return {HTMLElement/Ext.Element} The new node
  10059. */
  10060. insertAfter: function(el, o, returnElement) {
  10061. return this.doInsert(el, o, returnElement, 'afterend');
  10062. },
  10063. /**
  10064. * Creates new DOM element(s) and inserts them as the first child of el.
  10065. * @param {String/HTMLElement/Ext.Element} el The context element
  10066. * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  10067. * @param {Boolean} [returnElement] true to return a Ext.Element
  10068. * @return {HTMLElement/Ext.Element} The new node
  10069. */
  10070. insertFirst: function(el, o, returnElement) {
  10071. return this.doInsert(el, o, returnElement, 'afterbegin');
  10072. },
  10073. /**
  10074. * Creates new DOM element(s) and appends them to el.
  10075. * @param {String/HTMLElement/Ext.Element} el The context element
  10076. * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  10077. * @param {Boolean} [returnElement] true to return a Ext.Element
  10078. * @return {HTMLElement/Ext.Element} The new node
  10079. */
  10080. append: function(el, o, returnElement) {
  10081. return this.doInsert(el, o, returnElement, 'beforeend');
  10082. },
  10083. /**
  10084. * Creates new DOM element(s) and overwrites the contents of el with them.
  10085. * @param {String/HTMLElement/Ext.Element} el The context element
  10086. * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  10087. * @param {Boolean} [returnElement] true to return a Ext.Element
  10088. * @return {HTMLElement/Ext.Element} The new node
  10089. */
  10090. overwrite: function(el, o, returnElement) {
  10091. el = Ext.getDom(el);
  10092. el.innerHTML = this.markup(o);
  10093. return returnElement ? Ext.get(el.firstChild) : el.firstChild;
  10094. },
  10095. doInsert: function(el, o, returnElement, pos) {
  10096. var newNode = this.insertHtml(pos, Ext.getDom(el), this.markup(o));
  10097. return returnElement ? Ext.get(newNode, true) : newNode;
  10098. },
  10099. /**
  10100. * Creates a new Ext.Template from the DOM object spec.
  10101. * @param {Object} o The DOM object spec (and children)
  10102. * @return {Ext.Template} The new template
  10103. */
  10104. createTemplate: function(o) {
  10105. var html = this.markup(o);
  10106. return new Ext.Template(html);
  10107. }
  10108. }, function() {
  10109. Ext.ns('Ext.core');
  10110. Ext.core.DomHelper = Ext.DomHelper = new this;
  10111. });
  10112. //@tag dom,core
  10113. //@require Ext.dom.Helper
  10114. /**
  10115. * An Identifiable mixin.
  10116. * @private
  10117. */
  10118. Ext.define('Ext.mixin.Identifiable', {
  10119. statics: {
  10120. uniqueIds: {}
  10121. },
  10122. isIdentifiable: true,
  10123. mixinId: 'identifiable',
  10124. idCleanRegex: /\.|[^\w\-]/g,
  10125. defaultIdPrefix: 'ext-',
  10126. defaultIdSeparator: '-',
  10127. getOptimizedId: function() {
  10128. return this.id;
  10129. },
  10130. getUniqueId: function() {
  10131. var id = this.id,
  10132. prototype, separator, xtype, uniqueIds, prefix;
  10133. if (!id) {
  10134. prototype = this.self.prototype;
  10135. separator = this.defaultIdSeparator;
  10136. uniqueIds = Ext.mixin.Identifiable.uniqueIds;
  10137. if (!prototype.hasOwnProperty('identifiablePrefix')) {
  10138. xtype = this.xtype;
  10139. if (xtype) {
  10140. prefix = this.defaultIdPrefix + xtype + separator;
  10141. }
  10142. else {
  10143. prefix = prototype.$className.replace(this.idCleanRegex, separator).toLowerCase() + separator;
  10144. }
  10145. prototype.identifiablePrefix = prefix;
  10146. }
  10147. prefix = this.identifiablePrefix;
  10148. if (!uniqueIds.hasOwnProperty(prefix)) {
  10149. uniqueIds[prefix] = 0;
  10150. }
  10151. id = this.id = prefix + (++uniqueIds[prefix]);
  10152. }
  10153. this.getUniqueId = this.getOptimizedId;
  10154. return id;
  10155. },
  10156. setId: function(id) {
  10157. this.id = id;
  10158. },
  10159. /**
  10160. * Retrieves the id of this component. Will autogenerate an id if one has not already been set.
  10161. * @return {String} id
  10162. */
  10163. getId: function() {
  10164. var id = this.id;
  10165. if (!id) {
  10166. id = this.getUniqueId();
  10167. }
  10168. this.getId = this.getOptimizedId;
  10169. return id;
  10170. }
  10171. });
  10172. //@tag dom,core
  10173. //@define Ext.Element-all
  10174. //@define Ext.Element
  10175. /**
  10176. * Encapsulates a DOM element, adding simple DOM manipulation facilities, normalizing for browser differences.
  10177. *
  10178. * All instances of this class inherit the methods of Ext.Fx making visual effects easily available to all DOM elements.
  10179. *
  10180. * Note that the events documented in this class are not Ext events, they encapsulate browser events. To access the
  10181. * underlying browser event, see {@link Ext.EventObject#browserEvent}. Some older browsers may not support the full range of
  10182. * events. Which events are supported is beyond the control of Sencha Touch.
  10183. *
  10184. * ## Usage
  10185. *
  10186. * // by id
  10187. * var el = Ext.get("my-div");
  10188. *
  10189. * // by DOM element reference
  10190. * var el = Ext.get(myDivElement);
  10191. *
  10192. * ## Composite (Collections of) Elements
  10193. *
  10194. * For working with collections of Elements, see {@link Ext.CompositeElement}.
  10195. *
  10196. * @mixins Ext.mixin.Observable
  10197. */
  10198. Ext.define('Ext.dom.Element', {
  10199. alternateClassName: 'Ext.Element',
  10200. mixins: [
  10201. 'Ext.mixin.Identifiable'
  10202. ],
  10203. requires: [
  10204. 'Ext.dom.Query',
  10205. 'Ext.dom.Helper'
  10206. ],
  10207. observableType: 'element',
  10208. xtype: 'element',
  10209. statics: {
  10210. CREATE_ATTRIBUTES: {
  10211. style: 'style',
  10212. className: 'className',
  10213. cls: 'cls',
  10214. classList: 'classList',
  10215. text: 'text',
  10216. hidden: 'hidden',
  10217. html: 'html',
  10218. children: 'children'
  10219. },
  10220. create: function(attributes, domNode) {
  10221. var ATTRIBUTES = this.CREATE_ATTRIBUTES,
  10222. element, elementStyle, tag, value, name, i, ln;
  10223. if (!attributes) {
  10224. attributes = {};
  10225. }
  10226. if (attributes.isElement) {
  10227. return attributes.dom;
  10228. }
  10229. else if ('nodeType' in attributes) {
  10230. return attributes;
  10231. }
  10232. if (typeof attributes == 'string') {
  10233. return document.createTextNode(attributes);
  10234. }
  10235. tag = attributes.tag;
  10236. if (!tag) {
  10237. tag = 'div';
  10238. }
  10239. if (attributes.namespace) {
  10240. element = document.createElementNS(attributes.namespace, tag);
  10241. } else {
  10242. element = document.createElement(tag);
  10243. }
  10244. elementStyle = element.style;
  10245. for (name in attributes) {
  10246. if (name != 'tag') {
  10247. value = attributes[name];
  10248. switch (name) {
  10249. case ATTRIBUTES.style:
  10250. if (typeof value == 'string') {
  10251. element.setAttribute(name, value);
  10252. }
  10253. else {
  10254. for (i in value) {
  10255. if (value.hasOwnProperty(i)) {
  10256. elementStyle[i] = value[i];
  10257. }
  10258. }
  10259. }
  10260. break;
  10261. case ATTRIBUTES.className:
  10262. case ATTRIBUTES.cls:
  10263. element.className = value;
  10264. break;
  10265. case ATTRIBUTES.classList:
  10266. element.className = value.join(' ');
  10267. break;
  10268. case ATTRIBUTES.text:
  10269. element.textContent = value;
  10270. break;
  10271. case ATTRIBUTES.hidden:
  10272. if (value) {
  10273. element.style.display = 'none';
  10274. }
  10275. break;
  10276. case ATTRIBUTES.html:
  10277. element.innerHTML = value;
  10278. break;
  10279. case ATTRIBUTES.children:
  10280. for (i = 0,ln = value.length; i < ln; i++) {
  10281. element.appendChild(this.create(value[i], true));
  10282. }
  10283. break;
  10284. default:
  10285. element.setAttribute(name, value);
  10286. }
  10287. }
  10288. }
  10289. if (domNode) {
  10290. return element;
  10291. }
  10292. else {
  10293. return this.get(element);
  10294. }
  10295. },
  10296. documentElement: null,
  10297. cache: {},
  10298. /**
  10299. * Retrieves Ext.dom.Element objects. {@link Ext#get} is alias for {@link Ext.dom.Element#get}.
  10300. *
  10301. * **This method does not retrieve {@link Ext.Element Element}s.** This method retrieves Ext.dom.Element
  10302. * objects which encapsulate DOM elements. To retrieve a Element by its ID, use {@link Ext.ElementManager#get}.
  10303. *
  10304. * Uses simple caching to consistently return the same object. Automatically fixes if an object was recreated with
  10305. * the same id via AJAX or DOM.
  10306. *
  10307. * @param {String/HTMLElement/Ext.Element} el The `id` of the node, a DOM Node or an existing Element.
  10308. * @return {Ext.dom.Element} The Element object (or `null` if no matching element was found).
  10309. * @static
  10310. * @inheritable
  10311. */
  10312. get: function(element) {
  10313. var cache = this.cache,
  10314. instance, dom, id;
  10315. if (!element) {
  10316. return null;
  10317. }
  10318. if (typeof element == 'string') {
  10319. if (cache.hasOwnProperty(element)) {
  10320. return cache[element];
  10321. }
  10322. if (!(dom = document.getElementById(element))) {
  10323. return null;
  10324. }
  10325. cache[element] = instance = new this(dom);
  10326. return instance;
  10327. }
  10328. if ('tagName' in element) { // dom element
  10329. id = element.id;
  10330. if (cache.hasOwnProperty(id)) {
  10331. return cache[id];
  10332. }
  10333. instance = new this(element);
  10334. cache[instance.getId()] = instance;
  10335. return instance;
  10336. }
  10337. if (element.isElement) {
  10338. return element;
  10339. }
  10340. if (element.isComposite) {
  10341. return element;
  10342. }
  10343. if (Ext.isArray(element)) {
  10344. return this.select(element);
  10345. }
  10346. if (element === document) {
  10347. // create a bogus element object representing the document object
  10348. if (!this.documentElement) {
  10349. this.documentElement = new this(document.documentElement);
  10350. this.documentElement.setId('ext-application');
  10351. }
  10352. return this.documentElement;
  10353. }
  10354. return null;
  10355. },
  10356. data: function(element, key, value) {
  10357. var cache = Ext.cache,
  10358. id, data;
  10359. element = this.get(element);
  10360. if (!element) {
  10361. return null;
  10362. }
  10363. id = element.id;
  10364. data = cache[id].data;
  10365. if (!data) {
  10366. cache[id].data = data = {};
  10367. }
  10368. if (arguments.length == 2) {
  10369. return data[key];
  10370. }
  10371. else {
  10372. return (data[key] = value);
  10373. }
  10374. }
  10375. },
  10376. isElement: true,
  10377. /**
  10378. * @event painted
  10379. * Fires whenever this Element actually becomes visible (painted) on the screen. This is useful when you need to
  10380. * perform 'read' operations on the DOM element, i.e: calculating natural sizes and positioning.
  10381. *
  10382. * __Note:__ This event is not available to be used with event delegation. Instead `painted` only fires if you explicitly
  10383. * add at least one listener to it, for performance reasons.
  10384. *
  10385. * @param {Ext.Element} this The component instance.
  10386. */
  10387. /**
  10388. * @event resize
  10389. * Important note: For the best performance on mobile devices, use this only when you absolutely need to monitor
  10390. * a Element's size.
  10391. *
  10392. * __Note:__ This event is not available to be used with event delegation. Instead `resize` only fires if you explicitly
  10393. * add at least one listener to it, for performance reasons.
  10394. *
  10395. * @param {Ext.Element} this The component instance.
  10396. */
  10397. constructor: function(dom) {
  10398. if (typeof dom == 'string') {
  10399. dom = document.getElementById(dom);
  10400. }
  10401. if (!dom) {
  10402. throw new Error("Invalid domNode reference or an id of an existing domNode: " + dom);
  10403. }
  10404. /**
  10405. * The DOM element
  10406. * @property dom
  10407. * @type HTMLElement
  10408. */
  10409. this.dom = dom;
  10410. this.getUniqueId();
  10411. },
  10412. attach: function (dom) {
  10413. this.dom = dom;
  10414. this.id = dom.id;
  10415. return this;
  10416. },
  10417. getUniqueId: function() {
  10418. var id = this.id,
  10419. dom;
  10420. if (!id) {
  10421. dom = this.dom;
  10422. if (dom.id.length > 0) {
  10423. this.id = id = dom.id;
  10424. }
  10425. else {
  10426. dom.id = id = this.mixins.identifiable.getUniqueId.call(this);
  10427. }
  10428. this.self.cache[id] = this;
  10429. }
  10430. return id;
  10431. },
  10432. setId: function(id) {
  10433. var currentId = this.id,
  10434. cache = this.self.cache;
  10435. if (currentId) {
  10436. delete cache[currentId];
  10437. }
  10438. this.dom.id = id;
  10439. /**
  10440. * The DOM element ID
  10441. * @property id
  10442. * @type String
  10443. */
  10444. this.id = id;
  10445. cache[id] = this;
  10446. return this;
  10447. },
  10448. /**
  10449. * Sets the `innerHTML` of this element.
  10450. * @param {String} html The new HTML.
  10451. */
  10452. setHtml: function(html) {
  10453. this.dom.innerHTML = html;
  10454. },
  10455. /**
  10456. * Returns the `innerHTML` of an element.
  10457. * @return {String}
  10458. */
  10459. getHtml: function() {
  10460. return this.dom.innerHTML;
  10461. },
  10462. setText: function(text) {
  10463. this.dom.textContent = text;
  10464. },
  10465. redraw: function() {
  10466. var dom = this.dom,
  10467. domStyle = dom.style;
  10468. domStyle.display = 'none';
  10469. dom.offsetHeight;
  10470. domStyle.display = '';
  10471. },
  10472. isPainted: function() {
  10473. var dom = this.dom;
  10474. return Boolean(dom && dom.offsetParent);
  10475. },
  10476. /**
  10477. * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function).
  10478. * @param {Object} attributes The object with the attributes.
  10479. * @param {Boolean} [useSet=true] `false` to override the default `setAttribute` to use expandos.
  10480. * @return {Ext.dom.Element} this
  10481. */
  10482. set: function(attributes, useSet) {
  10483. var dom = this.dom,
  10484. attribute, value;
  10485. for (attribute in attributes) {
  10486. if (attributes.hasOwnProperty(attribute)) {
  10487. value = attributes[attribute];
  10488. if (attribute == 'style') {
  10489. this.applyStyles(value);
  10490. }
  10491. else if (attribute == 'cls') {
  10492. dom.className = value;
  10493. }
  10494. else if (useSet !== false) {
  10495. if (value === undefined) {
  10496. dom.removeAttribute(attribute);
  10497. } else {
  10498. dom.setAttribute(attribute, value);
  10499. }
  10500. }
  10501. else {
  10502. dom[attribute] = value;
  10503. }
  10504. }
  10505. }
  10506. return this;
  10507. },
  10508. /**
  10509. * Returns `true` if this element matches the passed simple selector (e.g. 'div.some-class' or 'span:first-child').
  10510. * @param {String} selector The simple selector to test.
  10511. * @return {Boolean} `true` if this element matches the selector, else `false`.
  10512. */
  10513. is: function(selector) {
  10514. return Ext.DomQuery.is(this.dom, selector);
  10515. },
  10516. /**
  10517. * Returns the value of the `value` attribute.
  10518. * @param {Boolean} asNumber `true` to parse the value as a number.
  10519. * @return {String/Number}
  10520. */
  10521. getValue: function(asNumber) {
  10522. var value = this.dom.value;
  10523. return asNumber ? parseInt(value, 10) : value;
  10524. },
  10525. /**
  10526. * Returns the value of an attribute from the element's underlying DOM node.
  10527. * @param {String} name The attribute name.
  10528. * @param {String} [namespace] The namespace in which to look for the attribute.
  10529. * @return {String} The attribute value.
  10530. */
  10531. getAttribute: function(name, namespace) {
  10532. var dom = this.dom;
  10533. return dom.getAttributeNS(namespace, name) || dom.getAttribute(namespace + ":" + name)
  10534. || dom.getAttribute(name) || dom[name];
  10535. },
  10536. setSizeState: function(state) {
  10537. var classes = ['x-sized', 'x-unsized', 'x-stretched'],
  10538. states = [true, false, null],
  10539. index = states.indexOf(state),
  10540. addedClass;
  10541. if (index !== -1) {
  10542. addedClass = classes[index];
  10543. classes.splice(index, 1);
  10544. this.addCls(addedClass);
  10545. }
  10546. this.removeCls(classes);
  10547. return this;
  10548. },
  10549. /**
  10550. * Removes this element's DOM reference. Note that event and cache removal is handled at {@link Ext#removeNode}
  10551. */
  10552. destroy: function() {
  10553. this.isDestroyed = true;
  10554. var cache = Ext.Element.cache,
  10555. dom = this.dom;
  10556. if (dom && dom.parentNode && dom.tagName != 'BODY') {
  10557. dom.parentNode.removeChild(dom);
  10558. }
  10559. delete cache[this.id];
  10560. delete this.dom;
  10561. }
  10562. }, function(Element) {
  10563. Ext.elements = Ext.cache = Element.cache;
  10564. this.addStatics({
  10565. Fly: new Ext.Class({
  10566. extend: Element,
  10567. constructor: function(dom) {
  10568. this.dom = dom;
  10569. }
  10570. }),
  10571. _flyweights: {},
  10572. /**
  10573. * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference
  10574. * to this element - the dom node can be overwritten by other code. {@link Ext#fly} is alias for
  10575. * {@link Ext.dom.Element#fly}.
  10576. *
  10577. * Use this to make one-time references to DOM elements which are not going to be accessed again either by
  10578. * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link
  10579. * Ext#get Ext.get} will be more appropriate to take advantage of the caching provided by the {@link Ext.dom.Element}
  10580. * class.
  10581. *
  10582. * @param {String/HTMLElement} element The DOM node or `id`.
  10583. * @param {String} [named] Allows for creation of named reusable flyweights to prevent conflicts (e.g.
  10584. * internally Ext uses "_global").
  10585. * @return {Ext.dom.Element} The shared Element object (or `null` if no matching element was found).
  10586. * @static
  10587. */
  10588. fly: function(element, named) {
  10589. var fly = null,
  10590. flyweights = Element._flyweights,
  10591. cachedElement;
  10592. named = named || '_global';
  10593. element = Ext.getDom(element);
  10594. if (element) {
  10595. fly = flyweights[named] || (flyweights[named] = new Element.Fly());
  10596. fly.dom = element;
  10597. fly.isSynchronized = false;
  10598. cachedElement = Ext.cache[element.id];
  10599. if (cachedElement && cachedElement.isElement) {
  10600. cachedElement.isSynchronized = false;
  10601. }
  10602. }
  10603. return fly;
  10604. }
  10605. });
  10606. /**
  10607. * @member Ext
  10608. * @method get
  10609. * @alias Ext.dom.Element#get
  10610. */
  10611. Ext.get = function(element) {
  10612. return Element.get.call(Element, element);
  10613. };
  10614. /**
  10615. * @member Ext
  10616. * @method fly
  10617. * @alias Ext.dom.Element#fly
  10618. */
  10619. Ext.fly = function() {
  10620. return Element.fly.apply(Element, arguments);
  10621. };
  10622. Ext.ClassManager.onCreated(function() {
  10623. Element.mixin('observable', Ext.mixin.Observable);
  10624. }, null, 'Ext.mixin.Observable');
  10625. });
  10626. //@tag dom,core
  10627. //@define Ext.Element-all
  10628. //@define Ext.Element-static
  10629. //@require Ext.Element
  10630. /**
  10631. * @class Ext.dom.Element
  10632. */
  10633. Ext.dom.Element.addStatics({
  10634. numberRe: /\d+$/,
  10635. unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
  10636. camelRe: /(-[a-z])/gi,
  10637. cssRe: /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
  10638. opacityRe: /alpha\(opacity=(.*)\)/i,
  10639. propertyCache: {},
  10640. defaultUnit: "px",
  10641. borders: {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'},
  10642. paddings: {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'},
  10643. margins: {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'},
  10644. /**
  10645. * Test if size has a unit, otherwise appends the passed unit string, or the default for this Element.
  10646. * @param {Object} size The size to set.
  10647. * @param {String} units The units to append to a numeric size value.
  10648. * @return {String}
  10649. * @private
  10650. * @static
  10651. */
  10652. addUnits: function(size, units) {
  10653. // Size set to a value which means "auto"
  10654. if (size === "" || size == "auto" || size === undefined || size === null) {
  10655. return size || '';
  10656. }
  10657. // Otherwise, warn if it's not a valid CSS measurement
  10658. if (Ext.isNumber(size) || this.numberRe.test(size)) {
  10659. return size + (units || this.defaultUnit || 'px');
  10660. }
  10661. else if (!this.unitRe.test(size)) {
  10662. //<debug>
  10663. Ext.Logger.warn("Warning, size detected (" + size + ") not a valid property value on Element.addUnits.");
  10664. //</debug>
  10665. return size || '';
  10666. }
  10667. return size;
  10668. },
  10669. /**
  10670. * @static
  10671. * @return {Boolean}
  10672. * @private
  10673. */
  10674. isAncestor: function(p, c) {
  10675. var ret = false;
  10676. p = Ext.getDom(p);
  10677. c = Ext.getDom(c);
  10678. if (p && c) {
  10679. if (p.contains) {
  10680. return p.contains(c);
  10681. } else if (p.compareDocumentPosition) {
  10682. return !!(p.compareDocumentPosition(c) & 16);
  10683. } else {
  10684. while ((c = c.parentNode)) {
  10685. ret = c == p || ret;
  10686. }
  10687. }
  10688. }
  10689. return ret;
  10690. },
  10691. /**
  10692. * Parses a number or string representing margin sizes into an object. Supports CSS-style margin declarations
  10693. * (e.g. 10, "10", "10 10", "10 10 10" and "10 10 10 10" are all valid options and would return the same result)
  10694. * @static
  10695. * @param {Number/String} box The encoded margins
  10696. * @return {Object} An object with margin sizes for top, right, bottom and left containing the unit
  10697. */
  10698. parseBox: function(box) {
  10699. if (typeof box != 'string') {
  10700. box = box.toString();
  10701. }
  10702. var parts = box.split(' '),
  10703. ln = parts.length;
  10704. if (ln == 1) {
  10705. parts[1] = parts[2] = parts[3] = parts[0];
  10706. }
  10707. else if (ln == 2) {
  10708. parts[2] = parts[0];
  10709. parts[3] = parts[1];
  10710. }
  10711. else if (ln == 3) {
  10712. parts[3] = parts[1];
  10713. }
  10714. return {
  10715. top: parts[0] || 0,
  10716. right: parts[1] || 0,
  10717. bottom: parts[2] || 0,
  10718. left: parts[3] || 0
  10719. };
  10720. },
  10721. /**
  10722. * Parses a number or string representing margin sizes into an object. Supports CSS-style margin declarations
  10723. * (e.g. 10, "10", "10 10", "10 10 10" and "10 10 10 10" are all valid options and would return the same result)
  10724. * @static
  10725. * @param {Number/String} box The encoded margins
  10726. * @param {String} units The type of units to add
  10727. * @return {String} An string with unitized (px if units is not specified) metrics for top, right, bottom and left
  10728. */
  10729. unitizeBox: function(box, units) {
  10730. var me = this;
  10731. box = me.parseBox(box);
  10732. return me.addUnits(box.top, units) + ' ' +
  10733. me.addUnits(box.right, units) + ' ' +
  10734. me.addUnits(box.bottom, units) + ' ' +
  10735. me.addUnits(box.left, units);
  10736. },
  10737. // @private
  10738. camelReplaceFn: function(m, a) {
  10739. return a.charAt(1).toUpperCase();
  10740. },
  10741. /**
  10742. * Normalizes CSS property keys from dash delimited to camel case JavaScript Syntax.
  10743. * For example:
  10744. *
  10745. * - border-width -> borderWidth
  10746. * - padding-top -> paddingTop
  10747. *
  10748. * @static
  10749. * @param {String} prop The property to normalize
  10750. * @return {String} The normalized string
  10751. */
  10752. normalize: function(prop) {
  10753. // TODO: Mobile optimization?
  10754. // if (prop == 'float') {
  10755. // prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';
  10756. // }
  10757. return this.propertyCache[prop] || (this.propertyCache[prop] = prop.replace(this.camelRe, this.camelReplaceFn));
  10758. },
  10759. /**
  10760. * Returns the top Element that is located at the passed coordinates
  10761. * @static
  10762. * @param {Number} x The x coordinate
  10763. * @param {Number} y The y coordinate
  10764. * @return {String} The found Element
  10765. */
  10766. fromPoint: function(x, y) {
  10767. return Ext.get(document.elementFromPoint(x, y));
  10768. },
  10769. /**
  10770. * Converts a CSS string into an object with a property for each style.
  10771. *
  10772. * The sample code below would return an object with 2 properties, one
  10773. * for background-color and one for color.
  10774. *
  10775. * var css = 'background-color: red;color: blue; ';
  10776. * console.log(Ext.dom.Element.parseStyles(css));
  10777. *
  10778. * @static
  10779. * @param {String} styles A CSS string
  10780. * @return {Object} styles
  10781. */
  10782. parseStyles: function(styles) {
  10783. var out = {},
  10784. cssRe = this.cssRe,
  10785. matches;
  10786. if (styles) {
  10787. // Since we're using the g flag on the regex, we need to set the lastIndex.
  10788. // This automatically happens on some implementations, but not others, see:
  10789. // http://stackoverflow.com/questions/2645273/javascript-regular-expression-literal-persists-between-function-calls
  10790. // http://blog.stevenlevithan.com/archives/fixing-javascript-regexp
  10791. cssRe.lastIndex = 0;
  10792. while ((matches = cssRe.exec(styles))) {
  10793. out[matches[1]] = matches[2];
  10794. }
  10795. }
  10796. return out;
  10797. }
  10798. });
  10799. //@tag dom,core
  10800. //@define Ext.Element-all
  10801. //@define Ext.Element-alignment
  10802. //@require Ext.Element-static
  10803. /**
  10804. * @class Ext.dom.Element
  10805. */
  10806. //@tag dom,core
  10807. //@define Ext.Element-all
  10808. //@define Ext.Element-insertion
  10809. //@require Ext.Element-alignment
  10810. /**
  10811. * @class Ext.dom.Element
  10812. */
  10813. Ext.dom.Element.addMembers({
  10814. /**
  10815. * Appends the passed element(s) to this element.
  10816. * @param {HTMLElement/Ext.dom.Element} element a DOM Node or an existing Element.
  10817. * @return {Ext.dom.Element} This element.
  10818. */
  10819. appendChild: function(element) {
  10820. this.dom.appendChild(Ext.getDom(element));
  10821. return this;
  10822. },
  10823. removeChild: function(element) {
  10824. this.dom.removeChild(Ext.getDom(element));
  10825. return this;
  10826. },
  10827. append: function() {
  10828. this.appendChild.apply(this, arguments);
  10829. },
  10830. /**
  10831. * Appends this element to the passed element.
  10832. * @param {String/HTMLElement/Ext.dom.Element} el The new parent element.
  10833. * The id of the node, a DOM Node or an existing Element.
  10834. * @return {Ext.dom.Element} This element.
  10835. */
  10836. appendTo: function(el) {
  10837. Ext.getDom(el).appendChild(this.dom);
  10838. return this;
  10839. },
  10840. /**
  10841. * Inserts this element before the passed element in the DOM.
  10842. * @param {String/HTMLElement/Ext.dom.Element} el The element before which this element will be inserted.
  10843. * The id of the node, a DOM Node or an existing Element.
  10844. * @return {Ext.dom.Element} This element.
  10845. */
  10846. insertBefore: function(el) {
  10847. el = Ext.getDom(el);
  10848. el.parentNode.insertBefore(this.dom, el);
  10849. return this;
  10850. },
  10851. /**
  10852. * Inserts this element after the passed element in the DOM.
  10853. * @param {String/HTMLElement/Ext.dom.Element} el The element to insert after.
  10854. * The `id` of the node, a DOM Node or an existing Element.
  10855. * @return {Ext.dom.Element} This element.
  10856. */
  10857. insertAfter: function(el) {
  10858. el = Ext.getDom(el);
  10859. el.parentNode.insertBefore(this.dom, el.nextSibling);
  10860. return this;
  10861. },
  10862. /**
  10863. * Inserts an element as the first child of this element.
  10864. * @param {String/HTMLElement/Ext.dom.Element} element The `id` or element to insert.
  10865. * @return {Ext.dom.Element} this
  10866. */
  10867. insertFirst: function(element) {
  10868. var elementDom = Ext.getDom(element),
  10869. dom = this.dom,
  10870. firstChild = dom.firstChild;
  10871. if (!firstChild) {
  10872. dom.appendChild(elementDom);
  10873. }
  10874. else {
  10875. dom.insertBefore(elementDom, firstChild);
  10876. }
  10877. return this;
  10878. },
  10879. /**
  10880. * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
  10881. * @param {String/HTMLElement/Ext.dom.Element/Object/Array} el The id, element to insert or a DomHelper config
  10882. * to create and insert *or* an array of any of those.
  10883. * @param {String} [where=before] (optional) 'before' or 'after'.
  10884. * @param {Boolean} returnDom (optional) `true` to return the raw DOM element instead of Ext.dom.Element.
  10885. * @return {Ext.dom.Element} The inserted Element. If an array is passed, the last inserted element is returned.
  10886. */
  10887. insertSibling: function(el, where, returnDom) {
  10888. var me = this, rt,
  10889. isAfter = (where || 'before').toLowerCase() == 'after',
  10890. insertEl;
  10891. if (Ext.isArray(el)) {
  10892. insertEl = me;
  10893. Ext.each(el, function(e) {
  10894. rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
  10895. if (isAfter) {
  10896. insertEl = rt;
  10897. }
  10898. });
  10899. return rt;
  10900. }
  10901. el = el || {};
  10902. if (el.nodeType || el.dom) {
  10903. rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom);
  10904. if (!returnDom) {
  10905. rt = Ext.get(rt);
  10906. }
  10907. } else {
  10908. if (isAfter && !me.dom.nextSibling) {
  10909. rt = Ext.core.DomHelper.append(me.dom.parentNode, el, !returnDom);
  10910. } else {
  10911. rt = Ext.core.DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
  10912. }
  10913. }
  10914. return rt;
  10915. },
  10916. /**
  10917. * Replaces the passed element with this element.
  10918. * @param {String/HTMLElement/Ext.dom.Element} el The element to replace.
  10919. * The id of the node, a DOM Node or an existing Element.
  10920. * @return {Ext.dom.Element} This element.
  10921. */
  10922. replace: function(element) {
  10923. element = Ext.getDom(element);
  10924. element.parentNode.replaceChild(this.dom, element);
  10925. return this;
  10926. },
  10927. /**
  10928. * Replaces this element with the passed element.
  10929. * @param {String/HTMLElement/Ext.dom.Element/Object} el The new element (id of the node, a DOM Node
  10930. * or an existing Element) or a DomHelper config of an element to create.
  10931. * @return {Ext.dom.Element} This element.
  10932. */
  10933. replaceWith: function(el) {
  10934. var me = this;
  10935. if (el.nodeType || el.dom || typeof el == 'string') {
  10936. el = Ext.get(el);
  10937. me.dom.parentNode.insertBefore(el, me.dom);
  10938. } else {
  10939. el = Ext.core.DomHelper.insertBefore(me.dom, el);
  10940. }
  10941. delete Ext.cache[me.id];
  10942. Ext.removeNode(me.dom);
  10943. me.id = Ext.id(me.dom = el);
  10944. Ext.dom.Element.addToCache(me.isFlyweight ? new Ext.dom.Element(me.dom) : me);
  10945. return me;
  10946. },
  10947. doReplaceWith: function(element) {
  10948. var dom = this.dom;
  10949. dom.parentNode.replaceChild(Ext.getDom(element), dom);
  10950. },
  10951. /**
  10952. * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
  10953. * @param {Object} config DomHelper element config object. If no tag is specified (e.g., `{tag:'input'}`) then a div will be
  10954. * automatically generated with the specified attributes.
  10955. * @param {HTMLElement} insertBefore (optional) a child element of this element.
  10956. * @param {Boolean} returnDom (optional) `true` to return the dom node instead of creating an Element.
  10957. * @return {Ext.dom.Element} The new child element.
  10958. */
  10959. createChild: function(config, insertBefore, returnDom) {
  10960. config = config || {tag: 'div'};
  10961. if (insertBefore) {
  10962. return Ext.core.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
  10963. }
  10964. else {
  10965. return Ext.core.DomHelper[!this.dom.firstChild ? 'insertFirst' : 'append'](this.dom, config, returnDom !== true);
  10966. }
  10967. },
  10968. /**
  10969. * Creates and wraps this element with another element.
  10970. * @param {Object} [config] (optional) DomHelper element config object for the wrapper element or `null` for an empty div
  10971. * @param {Boolean} [domNode] (optional) `true` to return the raw DOM element instead of Ext.dom.Element.
  10972. * @return {HTMLElement/Ext.dom.Element} The newly created wrapper element.
  10973. */
  10974. wrap: function(config, domNode) {
  10975. var dom = this.dom,
  10976. wrapper = this.self.create(config, domNode),
  10977. wrapperDom = (domNode) ? wrapper : wrapper.dom,
  10978. parentNode = dom.parentNode;
  10979. if (parentNode) {
  10980. parentNode.insertBefore(wrapperDom, dom);
  10981. }
  10982. wrapperDom.appendChild(dom);
  10983. return wrapper;
  10984. },
  10985. wrapAllChildren: function(config) {
  10986. var dom = this.dom,
  10987. children = dom.childNodes,
  10988. wrapper = this.self.create(config),
  10989. wrapperDom = wrapper.dom;
  10990. while (children.length > 0) {
  10991. wrapperDom.appendChild(dom.firstChild);
  10992. }
  10993. dom.appendChild(wrapperDom);
  10994. return wrapper;
  10995. },
  10996. unwrapAllChildren: function() {
  10997. var dom = this.dom,
  10998. children = dom.childNodes,
  10999. parentNode = dom.parentNode;
  11000. if (parentNode) {
  11001. while (children.length > 0) {
  11002. parentNode.insertBefore(dom, dom.firstChild);
  11003. }
  11004. this.destroy();
  11005. }
  11006. },
  11007. unwrap: function() {
  11008. var dom = this.dom,
  11009. parentNode = dom.parentNode,
  11010. grandparentNode;
  11011. if (parentNode) {
  11012. grandparentNode = parentNode.parentNode;
  11013. grandparentNode.insertBefore(dom, parentNode);
  11014. grandparentNode.removeChild(parentNode);
  11015. }
  11016. else {
  11017. grandparentNode = document.createDocumentFragment();
  11018. grandparentNode.appendChild(dom);
  11019. }
  11020. return this;
  11021. },
  11022. detach: function() {
  11023. var dom = this.dom;
  11024. if (dom && dom.parentNode && dom.tagName !== 'BODY') {
  11025. dom.parentNode.removeChild(dom);
  11026. }
  11027. return this;
  11028. },
  11029. /**
  11030. * Inserts an HTML fragment into this element.
  11031. * @param {String} where Where to insert the HTML in relation to this element - 'beforeBegin', 'afterBegin', 'beforeEnd', 'afterEnd'.
  11032. * See {@link Ext.DomHelper#insertHtml} for details.
  11033. * @param {String} html The HTML fragment
  11034. * @param {Boolean} [returnEl=false] (optional) `true` to return an Ext.dom.Element.
  11035. * @return {HTMLElement/Ext.dom.Element} The inserted node (or nearest related if more than 1 inserted).
  11036. */
  11037. insertHtml: function(where, html, returnEl) {
  11038. var el = Ext.core.DomHelper.insertHtml(where, this.dom, html);
  11039. return returnEl ? Ext.get(el) : el;
  11040. }
  11041. });
  11042. //@tag dom,core
  11043. //@define Ext.Element-all
  11044. //@define Ext.Element-position
  11045. //@require Ext.Element-insertion
  11046. /**
  11047. * @class Ext.dom.Element
  11048. */
  11049. Ext.dom.Element.override({
  11050. /**
  11051. * Gets the current X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (`display:none` or elements not appended return `false`).
  11052. * @return {Number} The X position of the element
  11053. */
  11054. getX: function(el) {
  11055. return this.getXY(el)[0];
  11056. },
  11057. /**
  11058. * Gets the current Y position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (`display:none` or elements not appended return `false`).
  11059. * @return {Number} The Y position of the element
  11060. */
  11061. getY: function(el) {
  11062. return this.getXY(el)[1];
  11063. },
  11064. /**
  11065. * Gets the current position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (`display:none` or elements not appended return `false`).
  11066. * @return {Array} The XY position of the element
  11067. */
  11068. getXY: function() {
  11069. var rect = this.dom.getBoundingClientRect(),
  11070. round = Math.round;
  11071. return [round(rect.left + window.pageXOffset), round(rect.top + window.pageYOffset)];
  11072. },
  11073. /**
  11074. * Returns the offsets of this element from the passed element. Both element must be part of the DOM tree
  11075. * and not have `display:none` to have page coordinates.
  11076. * @param {Mixed} element The element to get the offsets from.
  11077. * @return {Array} The XY page offsets (e.g. [100, -200])
  11078. */
  11079. getOffsetsTo: function(el) {
  11080. var o = this.getXY(),
  11081. e = Ext.fly(el, '_internal').getXY();
  11082. return [o[0] - e[0], o[1] - e[1]];
  11083. },
  11084. /**
  11085. * Sets the X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (`display:none` or elements not appended return `false`).
  11086. * @param {Number} The X position of the element
  11087. * @param {Boolean/Object} animate (optional) `true` for the default animation, or a standard Element animation config object.
  11088. * @return {Ext.dom.Element} this
  11089. */
  11090. setX: function(x) {
  11091. return this.setXY([x, this.getY()]);
  11092. },
  11093. /**
  11094. * Sets the Y position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (`display:none` or elements not appended return `false`).
  11095. * @param {Number} The Y position of the element.
  11096. * @param {Boolean/Object} animate (optional) `true` for the default animation, or a standard Element animation config object.
  11097. * @return {Ext.dom.Element} this
  11098. */
  11099. setY: function(y) {
  11100. return this.setXY([this.getX(), y]);
  11101. },
  11102. /**
  11103. * Sets the position of the element in page coordinates, regardless of how the element is positioned.
  11104. * The element must be part of the DOM tree to have page coordinates (`display:none` or elements not appended return `false`).
  11105. * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based).
  11106. * @param {Boolean/Object} animate (optional) `true` for the default animation, or a standard Element animation config object.
  11107. * @return {Ext.dom.Element} this
  11108. */
  11109. setXY: function(pos) {
  11110. var me = this;
  11111. if (arguments.length > 1) {
  11112. pos = [pos, arguments[1]];
  11113. }
  11114. // me.position();
  11115. var pts = me.translatePoints(pos),
  11116. style = me.dom.style;
  11117. for (pos in pts) {
  11118. if (!pts.hasOwnProperty(pos)) {
  11119. continue;
  11120. }
  11121. if (!isNaN(pts[pos])) style[pos] = pts[pos] + "px";
  11122. }
  11123. return me;
  11124. },
  11125. /**
  11126. * Gets the left X coordinate.
  11127. * @return {Number}
  11128. */
  11129. getLeft: function() {
  11130. return parseInt(this.getStyle('left'), 10) || 0;
  11131. },
  11132. /**
  11133. * Gets the right X coordinate of the element (element X position + element width).
  11134. * @return {Number}
  11135. */
  11136. getRight: function() {
  11137. return parseInt(this.getStyle('right'), 10) || 0;
  11138. },
  11139. /**
  11140. * Gets the top Y coordinate.
  11141. * @return {Number}
  11142. */
  11143. getTop: function() {
  11144. return parseInt(this.getStyle('top'), 10) || 0;
  11145. },
  11146. /**
  11147. * Gets the bottom Y coordinate of the element (element Y position + element height).
  11148. * @return {Number}
  11149. */
  11150. getBottom: function() {
  11151. return parseInt(this.getStyle('bottom'), 10) || 0;
  11152. },
  11153. /**
  11154. * Translates the passed page coordinates into left/top CSS values for this element.
  11155. * @param {Number/Array} x The page `x` or an array containing [x, y].
  11156. * @param {Number} y (optional) The page `y`, required if `x` is not an array.
  11157. * @return {Object} An object with `left` and `top` properties. e.g. `{left: (value), top: (value)}`.
  11158. */
  11159. translatePoints: function(x, y) {
  11160. y = isNaN(x[1]) ? y : x[1];
  11161. x = isNaN(x[0]) ? x : x[0];
  11162. var me = this,
  11163. relative = me.isStyle('position', 'relative'),
  11164. o = me.getXY(),
  11165. l = parseInt(me.getStyle('left'), 10),
  11166. t = parseInt(me.getStyle('top'), 10);
  11167. l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
  11168. t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);
  11169. return {left: (x - o[0] + l), top: (y - o[1] + t)};
  11170. },
  11171. /**
  11172. * Sets the element's box. Use {@link #getBox} on another element to get a box object.
  11173. * @param {Object} box The box to fill, for example:
  11174. *
  11175. * {
  11176. * left: ...,
  11177. * top: ...,
  11178. * width: ...,
  11179. * height: ...
  11180. * }
  11181. *
  11182. * @return {Ext.dom.Element} this
  11183. */
  11184. setBox: function(box) {
  11185. var me = this,
  11186. width = box.width,
  11187. height = box.height,
  11188. top = box.top,
  11189. left = box.left;
  11190. if (left !== undefined) {
  11191. me.setLeft(left);
  11192. }
  11193. if (top !== undefined) {
  11194. me.setTop(top);
  11195. }
  11196. if (width !== undefined) {
  11197. me.setWidth(width);
  11198. }
  11199. if (height !== undefined) {
  11200. me.setHeight(height);
  11201. }
  11202. return this;
  11203. },
  11204. /**
  11205. * Return an object defining the area of this Element which can be passed to {@link #setBox} to
  11206. * set another Element's size/location to match this element.
  11207. *
  11208. * The returned object may also be addressed as an Array where index 0 contains the X position
  11209. * and index 1 contains the Y position. So the result may also be used for {@link #setXY}.
  11210. *
  11211. * @param {Boolean} contentBox (optional) If `true` a box for the content of the element is returned.
  11212. * @param {Boolean} local (optional) If `true` the element's left and top are returned instead of page x/y.
  11213. * @return {Object} An object in the format
  11214. * @return {Number} return.x The element's X position.
  11215. * @return {Number} return.y The element's Y position.
  11216. * @return {Number} return.width The element's width.
  11217. * @return {Number} return.height The element's height.
  11218. * @return {Number} return.bottom The element's lower bound.
  11219. * @return {Number} return.right The element's rightmost bound.
  11220. */
  11221. getBox: function(contentBox, local) {
  11222. var me = this,
  11223. dom = me.dom,
  11224. width = dom.offsetWidth,
  11225. height = dom.offsetHeight,
  11226. xy, box, l, r, t, b;
  11227. if (!local) {
  11228. xy = me.getXY();
  11229. }
  11230. else if (contentBox) {
  11231. xy = [0, 0];
  11232. }
  11233. else {
  11234. xy = [parseInt(me.getStyle("left"), 10) || 0, parseInt(me.getStyle("top"), 10) || 0];
  11235. }
  11236. if (!contentBox) {
  11237. box = {
  11238. x: xy[0],
  11239. y: xy[1],
  11240. 0: xy[0],
  11241. 1: xy[1],
  11242. width: width,
  11243. height: height
  11244. };
  11245. }
  11246. else {
  11247. l = me.getBorderWidth.call(me, "l") + me.getPadding.call(me, "l");
  11248. r = me.getBorderWidth.call(me, "r") + me.getPadding.call(me, "r");
  11249. t = me.getBorderWidth.call(me, "t") + me.getPadding.call(me, "t");
  11250. b = me.getBorderWidth.call(me, "b") + me.getPadding.call(me, "b");
  11251. box = {
  11252. x: xy[0] + l,
  11253. y: xy[1] + t,
  11254. 0: xy[0] + l,
  11255. 1: xy[1] + t,
  11256. width: width - (l + r),
  11257. height: height - (t + b)
  11258. };
  11259. }
  11260. box.left = box.x;
  11261. box.top = box.y;
  11262. box.right = box.x + box.width;
  11263. box.bottom = box.y + box.height;
  11264. return box;
  11265. },
  11266. /**
  11267. * Return an object defining the area of this Element which can be passed to {@link #setBox} to
  11268. * set another Element's size/location to match this element.
  11269. * @param {Boolean} asRegion (optional) If `true` an {@link Ext.util.Region} will be returned.
  11270. * @return {Object} box An object in the format:
  11271. *
  11272. * {
  11273. * x: <Element's X position>,
  11274. * y: <Element's Y position>,
  11275. * width: <Element's width>,
  11276. * height: <Element's height>,
  11277. * bottom: <Element's lower bound>,
  11278. * right: <Element's rightmost bound>
  11279. * }
  11280. *
  11281. * The returned object may also be addressed as an Array where index 0 contains the X position
  11282. * and index 1 contains the Y position. So the result may also be used for {@link #setXY}.
  11283. */
  11284. getPageBox: function(getRegion) {
  11285. var me = this,
  11286. el = me.dom,
  11287. w = el.offsetWidth,
  11288. h = el.offsetHeight,
  11289. xy = me.getXY(),
  11290. t = xy[1],
  11291. r = xy[0] + w,
  11292. b = xy[1] + h,
  11293. l = xy[0];
  11294. if (!el) {
  11295. return new Ext.util.Region();
  11296. }
  11297. if (getRegion) {
  11298. return new Ext.util.Region(t, r, b, l);
  11299. }
  11300. else {
  11301. return {
  11302. left: l,
  11303. top: t,
  11304. width: w,
  11305. height: h,
  11306. right: r,
  11307. bottom: b
  11308. };
  11309. }
  11310. }
  11311. });
  11312. //@tag dom,core
  11313. //@define Ext.Element-all
  11314. //@define Ext.Element-style
  11315. //@require Ext.Element-position
  11316. /**
  11317. * @class Ext.dom.Element
  11318. */
  11319. Ext.dom.Element.addMembers({
  11320. WIDTH: 'width',
  11321. HEIGHT: 'height',
  11322. MIN_WIDTH: 'min-width',
  11323. MIN_HEIGHT: 'min-height',
  11324. MAX_WIDTH: 'max-width',
  11325. MAX_HEIGHT: 'max-height',
  11326. TOP: 'top',
  11327. RIGHT: 'right',
  11328. BOTTOM: 'bottom',
  11329. LEFT: 'left',
  11330. /**
  11331. * @property VISIBILITY
  11332. * Visibility mode constant for use with {@link #setVisibilityMode}. Use `visibility` to hide element.
  11333. */
  11334. VISIBILITY: 1,
  11335. /**
  11336. * @property DISPLAY
  11337. * Visibility mode constant for use with {@link #setVisibilityMode}. Use `display` to hide element.
  11338. */
  11339. DISPLAY: 2,
  11340. /**
  11341. * @property OFFSETS
  11342. * Visibility mode constant for use with {@link #setVisibilityMode}. Use offsets to hide element.
  11343. */
  11344. OFFSETS: 3,
  11345. SEPARATOR: '-',
  11346. trimRe: /^\s+|\s+$/g,
  11347. wordsRe: /\w/g,
  11348. spacesRe: /\s+/,
  11349. styleSplitRe: /\s*(?::|;)\s*/,
  11350. transparentRe: /^(?:transparent|(?:rgba[(](?:\s*\d+\s*[,]){3}\s*0\s*[)]))$/i,
  11351. classNameSplitRegex: /[\s]+/,
  11352. borders: {
  11353. t: 'border-top-width',
  11354. r: 'border-right-width',
  11355. b: 'border-bottom-width',
  11356. l: 'border-left-width'
  11357. },
  11358. paddings: {
  11359. t: 'padding-top',
  11360. r: 'padding-right',
  11361. b: 'padding-bottom',
  11362. l: 'padding-left'
  11363. },
  11364. margins: {
  11365. t: 'margin-top',
  11366. r: 'margin-right',
  11367. b: 'margin-bottom',
  11368. l: 'margin-left'
  11369. },
  11370. /**
  11371. * @property {String} defaultUnit
  11372. * The default unit to append to CSS values where a unit isn't provided.
  11373. */
  11374. defaultUnit: "px",
  11375. isSynchronized: false,
  11376. /**
  11377. * @private
  11378. */
  11379. synchronize: function() {
  11380. var dom = this.dom,
  11381. hasClassMap = {},
  11382. className = dom.className,
  11383. classList, i, ln, name;
  11384. if (className.length > 0) {
  11385. classList = dom.className.split(this.classNameSplitRegex);
  11386. for (i = 0, ln = classList.length; i < ln; i++) {
  11387. name = classList[i];
  11388. hasClassMap[name] = true;
  11389. }
  11390. }
  11391. else {
  11392. classList = [];
  11393. }
  11394. this.classList = classList;
  11395. this.hasClassMap = hasClassMap;
  11396. this.isSynchronized = true;
  11397. return this;
  11398. },
  11399. /**
  11400. * Adds the given CSS class(es) to this Element.
  11401. * @param {String} names The CSS class(es) to add to this element.
  11402. * @param {String} [prefix] (optional) Prefix to prepend to each class.
  11403. * @param {String} [suffix] (optional) Suffix to append to each class.
  11404. */
  11405. addCls: function(names, prefix, suffix) {
  11406. if (!names) {
  11407. return this;
  11408. }
  11409. if (!this.isSynchronized) {
  11410. this.synchronize();
  11411. }
  11412. var dom = this.dom,
  11413. map = this.hasClassMap,
  11414. classList = this.classList,
  11415. SEPARATOR = this.SEPARATOR,
  11416. i, ln, name;
  11417. prefix = prefix ? prefix + SEPARATOR : '';
  11418. suffix = suffix ? SEPARATOR + suffix : '';
  11419. if (typeof names == 'string') {
  11420. names = names.split(this.spacesRe);
  11421. }
  11422. for (i = 0, ln = names.length; i < ln; i++) {
  11423. name = prefix + names[i] + suffix;
  11424. if (!map[name]) {
  11425. map[name] = true;
  11426. classList.push(name);
  11427. }
  11428. }
  11429. dom.className = classList.join(' ');
  11430. return this;
  11431. },
  11432. /**
  11433. * Removes the given CSS class(es) from this Element.
  11434. * @param {String} names The CSS class(es) to remove from this element.
  11435. * @param {String} [prefix=''] (optional) Prefix to prepend to each class to be removed.
  11436. * @param {String} [suffix=''] (optional) Suffix to append to each class to be removed.
  11437. */
  11438. removeCls: function(names, prefix, suffix) {
  11439. if (!names) {
  11440. return this;
  11441. }
  11442. if (!this.isSynchronized) {
  11443. this.synchronize();
  11444. }
  11445. if (!suffix) {
  11446. suffix = '';
  11447. }
  11448. var dom = this.dom,
  11449. map = this.hasClassMap,
  11450. classList = this.classList,
  11451. SEPARATOR = this.SEPARATOR,
  11452. i, ln, name;
  11453. prefix = prefix ? prefix + SEPARATOR : '';
  11454. suffix = suffix ? SEPARATOR + suffix : '';
  11455. if (typeof names == 'string') {
  11456. names = names.split(this.spacesRe);
  11457. }
  11458. for (i = 0, ln = names.length; i < ln; i++) {
  11459. name = prefix + names[i] + suffix;
  11460. if (map[name]) {
  11461. delete map[name];
  11462. Ext.Array.remove(classList, name);
  11463. }
  11464. }
  11465. dom.className = classList.join(' ');
  11466. return this;
  11467. },
  11468. /**
  11469. * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
  11470. * @param {String} oldClassName The CSS class to replace.
  11471. * @param {String} newClassName The replacement CSS class.
  11472. * @return {Ext.dom.Element} this
  11473. */
  11474. replaceCls: function(oldName, newName, prefix, suffix) {
  11475. return this.removeCls(oldName, prefix, suffix).addCls(newName, prefix, suffix);
  11476. },
  11477. /**
  11478. * Checks if the specified CSS class exists on this element's DOM node.
  11479. * @param {String} className The CSS class to check for.
  11480. * @return {Boolean} `true` if the class exists, else `false`.
  11481. */
  11482. hasCls: function(name) {
  11483. if (!this.isSynchronized) {
  11484. this.synchronize();
  11485. }
  11486. return this.hasClassMap.hasOwnProperty(name);
  11487. },
  11488. /**
  11489. * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
  11490. * @param {String} className The CSS class to toggle.
  11491. * @return {Ext.dom.Element} this
  11492. */
  11493. toggleCls: function(className, force){
  11494. if (typeof force !== 'boolean') {
  11495. force = !this.hasCls(className);
  11496. }
  11497. return (force) ? this.addCls(className) : this.removeCls(className);
  11498. },
  11499. /**
  11500. * @private
  11501. * @param firstClass
  11502. * @param secondClass
  11503. * @param flag
  11504. * @param prefix
  11505. * @return {Mixed}
  11506. */
  11507. swapCls: function(firstClass, secondClass, flag, prefix) {
  11508. if (flag === undefined) {
  11509. flag = true;
  11510. }
  11511. var addedClass = flag ? firstClass : secondClass,
  11512. removedClass = flag ? secondClass : firstClass;
  11513. if (removedClass) {
  11514. this.removeCls(prefix ? prefix + '-' + removedClass : removedClass);
  11515. }
  11516. if (addedClass) {
  11517. this.addCls(prefix ? prefix + '-' + addedClass : addedClass);
  11518. }
  11519. return this;
  11520. },
  11521. /**
  11522. * Set the width of this Element.
  11523. * @param {Number/String} width The new width.
  11524. * @return {Ext.dom.Element} this
  11525. */
  11526. setWidth: function(width) {
  11527. return this.setLengthValue(this.WIDTH, width);
  11528. },
  11529. /**
  11530. * Set the height of this Element.
  11531. * @param {Number/String} height The new height.
  11532. * @return {Ext.dom.Element} this
  11533. */
  11534. setHeight: function(height) {
  11535. return this.setLengthValue(this.HEIGHT, height);
  11536. },
  11537. /**
  11538. * Set the size of this Element.
  11539. *
  11540. * @param {Number/String} width The new width. This may be one of:
  11541. *
  11542. * - A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).
  11543. * - A String used to set the CSS width style. Animation may **not** be used.
  11544. * - A size object in the format `{width: widthValue, height: heightValue}`.
  11545. *
  11546. * @param {Number/String} height The new height. This may be one of:
  11547. *
  11548. * - A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels).
  11549. * - A String used to set the CSS height style. Animation may **not** be used.
  11550. * @return {Ext.dom.Element} this
  11551. */
  11552. setSize: function(width, height) {
  11553. if (Ext.isObject(width)) {
  11554. // in case of object from getSize()
  11555. height = width.height;
  11556. width = width.width;
  11557. }
  11558. this.setWidth(width);
  11559. this.setHeight(height);
  11560. return this;
  11561. },
  11562. /**
  11563. * Set the minimum width of this Element.
  11564. * @param {Number/String} width The new minimum width.
  11565. * @return {Ext.dom.Element} this
  11566. */
  11567. setMinWidth: function(width) {
  11568. return this.setLengthValue(this.MIN_WIDTH, width);
  11569. },
  11570. /**
  11571. * Set the minimum height of this Element.
  11572. * @param {Number/String} height The new minimum height.
  11573. * @return {Ext.dom.Element} this
  11574. */
  11575. setMinHeight: function(height) {
  11576. return this.setLengthValue(this.MIN_HEIGHT, height);
  11577. },
  11578. /**
  11579. * Set the maximum width of this Element.
  11580. * @param {Number/String} width The new maximum width.
  11581. * @return {Ext.dom.Element} this
  11582. */
  11583. setMaxWidth: function(width) {
  11584. return this.setLengthValue(this.MAX_WIDTH, width);
  11585. },
  11586. /**
  11587. * Set the maximum height of this Element.
  11588. * @param {Number/String} height The new maximum height.
  11589. * @return {Ext.dom.Element} this
  11590. */
  11591. setMaxHeight: function(height) {
  11592. return this.setLengthValue(this.MAX_HEIGHT, height);
  11593. },
  11594. /**
  11595. * Sets the element's top position directly using CSS style (instead of {@link #setY}).
  11596. * @param {String} top The top CSS property value.
  11597. * @return {Ext.dom.Element} this
  11598. */
  11599. setTop: function(top) {
  11600. return this.setLengthValue(this.TOP, top);
  11601. },
  11602. /**
  11603. * Sets the element's CSS right style.
  11604. * @param {String} right The right CSS property value.
  11605. * @return {Ext.dom.Element} this
  11606. */
  11607. setRight: function(right) {
  11608. return this.setLengthValue(this.RIGHT, right);
  11609. },
  11610. /**
  11611. * Sets the element's CSS bottom style.
  11612. * @param {String} bottom The bottom CSS property value.
  11613. * @return {Ext.dom.Element} this
  11614. */
  11615. setBottom: function(bottom) {
  11616. return this.setLengthValue(this.BOTTOM, bottom);
  11617. },
  11618. /**
  11619. * Sets the element's left position directly using CSS style (instead of {@link #setX}).
  11620. * @param {String} left The left CSS property value.
  11621. * @return {Ext.dom.Element} this
  11622. */
  11623. setLeft: function(left) {
  11624. return this.setLengthValue(this.LEFT, left);
  11625. },
  11626. setMargin: function(margin) {
  11627. var domStyle = this.dom.style;
  11628. if (margin || margin === 0) {
  11629. margin = this.self.unitizeBox((margin === true) ? 5 : margin);
  11630. domStyle.setProperty('margin', margin, 'important');
  11631. }
  11632. else {
  11633. domStyle.removeProperty('margin-top');
  11634. domStyle.removeProperty('margin-right');
  11635. domStyle.removeProperty('margin-bottom');
  11636. domStyle.removeProperty('margin-left');
  11637. }
  11638. },
  11639. setPadding: function(padding) {
  11640. var domStyle = this.dom.style;
  11641. if (padding || padding === 0) {
  11642. padding = this.self.unitizeBox((padding === true) ? 5 : padding);
  11643. domStyle.setProperty('padding', padding, 'important');
  11644. }
  11645. else {
  11646. domStyle.removeProperty('padding-top');
  11647. domStyle.removeProperty('padding-right');
  11648. domStyle.removeProperty('padding-bottom');
  11649. domStyle.removeProperty('padding-left');
  11650. }
  11651. },
  11652. setBorder: function(border) {
  11653. var domStyle = this.dom.style;
  11654. if (border || border === 0) {
  11655. border = this.self.unitizeBox((border === true) ? 1 : border);
  11656. domStyle.setProperty('border-width', border, 'important');
  11657. }
  11658. else {
  11659. domStyle.removeProperty('border-top-width');
  11660. domStyle.removeProperty('border-right-width');
  11661. domStyle.removeProperty('border-bottom-width');
  11662. domStyle.removeProperty('border-left-width');
  11663. }
  11664. },
  11665. setLengthValue: function(name, value) {
  11666. var domStyle = this.dom.style;
  11667. if (value === null) {
  11668. domStyle.removeProperty(name);
  11669. return this;
  11670. }
  11671. if (typeof value == 'number') {
  11672. value = value + 'px';
  11673. }
  11674. domStyle.setProperty(name, value, 'important');
  11675. return this;
  11676. },
  11677. /**
  11678. * Sets the visibility of the element (see details). If the `visibilityMode` is set to `Element.DISPLAY`, it will use
  11679. * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the `visibility` property.
  11680. * @param {Boolean} visible Whether the element is visible.
  11681. * @return {Ext.Element} this
  11682. */
  11683. setVisible: function(visible) {
  11684. var mode = this.getVisibilityMode(),
  11685. method = visible ? 'removeCls' : 'addCls';
  11686. switch (mode) {
  11687. case this.VISIBILITY:
  11688. this.removeCls(['x-hidden-display', 'x-hidden-offsets']);
  11689. this[method]('x-hidden-visibility');
  11690. break;
  11691. case this.DISPLAY:
  11692. this.removeCls(['x-hidden-visibility', 'x-hidden-offsets']);
  11693. this[method]('x-hidden-display');
  11694. break;
  11695. case this.OFFSETS:
  11696. this.removeCls(['x-hidden-visibility', 'x-hidden-display']);
  11697. this[method]('x-hidden-offsets');
  11698. break;
  11699. }
  11700. return this;
  11701. },
  11702. getVisibilityMode: function() {
  11703. var dom = this.dom,
  11704. mode = Ext.dom.Element.data(dom, 'visibilityMode');
  11705. if (mode === undefined) {
  11706. Ext.dom.Element.data(dom, 'visibilityMode', mode = this.DISPLAY);
  11707. }
  11708. return mode;
  11709. },
  11710. /**
  11711. * Use this to change the visibility mode between {@link #VISIBILITY}, {@link #DISPLAY} or {@link #OFFSETS}.
  11712. */
  11713. setVisibilityMode: function(mode) {
  11714. this.self.data(this.dom, 'visibilityMode', mode);
  11715. return this;
  11716. },
  11717. /**
  11718. * Shows this element.
  11719. * Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
  11720. */
  11721. show: function() {
  11722. var dom = this.dom;
  11723. if (dom) {
  11724. dom.style.removeProperty('display');
  11725. }
  11726. },
  11727. /**
  11728. * Hides this element.
  11729. * Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
  11730. */
  11731. hide: function() {
  11732. this.dom.style.setProperty('display', 'none', 'important');
  11733. },
  11734. setVisibility: function(isVisible) {
  11735. var domStyle = this.dom.style;
  11736. if (isVisible) {
  11737. domStyle.removeProperty('visibility');
  11738. }
  11739. else {
  11740. domStyle.setProperty('visibility', 'hidden', 'important');
  11741. }
  11742. },
  11743. /**
  11744. * This shared object is keyed by style name (e.g., 'margin-left' or 'marginLeft'). The
  11745. * values are objects with the following properties:
  11746. *
  11747. * * `name` (String) : The actual name to be presented to the DOM. This is typically the value
  11748. * returned by {@link #normalize}.
  11749. * * `get` (Function) : A hook function that will perform the get on this style. These
  11750. * functions receive "(dom, el)" arguments. The `dom` parameter is the DOM Element
  11751. * from which to get the style. The `el` argument (may be `null`) is the Ext.Element.
  11752. * * `set` (Function) : A hook function that will perform the set on this style. These
  11753. * functions receive "(dom, value, el)" arguments. The `dom` parameter is the DOM Element
  11754. * from which to get this style. The `value` parameter is the new value for the style. The
  11755. * `el` argument (may be `null`) is the Ext.Element.
  11756. *
  11757. * The `this` pointer is the object that contains `get` or `set`, which means that
  11758. * `this.name` can be accessed if needed. The hook functions are both optional.
  11759. * @private
  11760. */
  11761. styleHooks: {},
  11762. // @private
  11763. addStyles: function(sides, styles) {
  11764. var totalSize = 0,
  11765. sidesArr = sides.match(this.wordsRe),
  11766. i = 0,
  11767. len = sidesArr.length,
  11768. side, size;
  11769. for (; i < len; i++) {
  11770. side = sidesArr[i];
  11771. size = side && parseInt(this.getStyle(styles[side]), 10);
  11772. if (size) {
  11773. totalSize += Math.abs(size);
  11774. }
  11775. }
  11776. return totalSize;
  11777. },
  11778. /**
  11779. * Checks if the current value of a style is equal to a given value.
  11780. * @param {String} style property whose value is returned.
  11781. * @param {String} value to check against.
  11782. * @return {Boolean} `true` for when the current value equals the given value.
  11783. */
  11784. isStyle: function(style, val) {
  11785. return this.getStyle(style) == val;
  11786. },
  11787. getStyleValue: function(name) {
  11788. return this.dom.style.getPropertyValue(name);
  11789. },
  11790. /**
  11791. * Normalizes `currentStyle` and `computedStyle`.
  11792. * @param {String} prop The style property whose value is returned.
  11793. * @return {String} The current value of the style property for this element.
  11794. */
  11795. getStyle: function(prop) {
  11796. var me = this,
  11797. dom = me.dom,
  11798. hook = me.styleHooks[prop],
  11799. cs, result;
  11800. if (dom == document) {
  11801. return null;
  11802. }
  11803. if (!hook) {
  11804. me.styleHooks[prop] = hook = { name: Ext.dom.Element.normalize(prop) };
  11805. }
  11806. if (hook.get) {
  11807. return hook.get(dom, me);
  11808. }
  11809. cs = window.getComputedStyle(dom, '');
  11810. // why the dom.style lookup? It is not true that "style == computedStyle" as
  11811. // well as the fact that 0/false are valid answers...
  11812. result = (cs && cs[hook.name]); // || dom.style[hook.name];
  11813. // WebKit returns rgb values for transparent, how does this work n IE9+
  11814. // if (!supportsTransparentColor && result == 'rgba(0, 0, 0, 0)') {
  11815. // result = 'transparent';
  11816. // }
  11817. return result;
  11818. },
  11819. /**
  11820. * Wrapper for setting style properties, also takes single object parameter of multiple styles.
  11821. * @param {String/Object} property The style property to be set, or an object of multiple styles.
  11822. * @param {String} [value] The value to apply to the given property, or `null` if an object was passed.
  11823. * @return {Ext.dom.Element} this
  11824. */
  11825. setStyle: function(prop, value) {
  11826. var me = this,
  11827. dom = me.dom,
  11828. hooks = me.styleHooks,
  11829. style = dom.style,
  11830. valueFrom = Ext.valueFrom,
  11831. name, hook;
  11832. // we don't promote the 2-arg form to object-form to avoid the overhead...
  11833. if (typeof prop == 'string') {
  11834. hook = hooks[prop];
  11835. if (!hook) {
  11836. hooks[prop] = hook = { name: Ext.dom.Element.normalize(prop) };
  11837. }
  11838. value = valueFrom(value, '');
  11839. if (hook.set) {
  11840. hook.set(dom, value, me);
  11841. } else {
  11842. style[hook.name] = value;
  11843. }
  11844. }
  11845. else {
  11846. for (name in prop) {
  11847. if (prop.hasOwnProperty(name)) {
  11848. hook = hooks[name];
  11849. if (!hook) {
  11850. hooks[name] = hook = { name: Ext.dom.Element.normalize(name) };
  11851. }
  11852. value = valueFrom(prop[name], '');
  11853. if (hook.set) {
  11854. hook.set(dom, value, me);
  11855. }
  11856. else {
  11857. style[hook.name] = value;
  11858. }
  11859. }
  11860. }
  11861. }
  11862. return me;
  11863. },
  11864. /**
  11865. * Returns the offset height of the element.
  11866. * @param {Boolean} [contentHeight] `true` to get the height minus borders and padding.
  11867. * @return {Number} The element's height.
  11868. */
  11869. getHeight: function(contentHeight) {
  11870. var dom = this.dom,
  11871. height = contentHeight ? (dom.clientHeight - this.getPadding("tb")) : dom.offsetHeight;
  11872. return height > 0 ? height : 0;
  11873. },
  11874. /**
  11875. * Returns the offset width of the element.
  11876. * @param {Boolean} [contentWidth] `true` to get the width minus borders and padding.
  11877. * @return {Number} The element's width.
  11878. */
  11879. getWidth: function(contentWidth) {
  11880. var dom = this.dom,
  11881. width = contentWidth ? (dom.clientWidth - this.getPadding("lr")) : dom.offsetWidth;
  11882. return width > 0 ? width : 0;
  11883. },
  11884. /**
  11885. * Gets the width of the border(s) for the specified side(s)
  11886. * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
  11887. * passing `'lr'` would get the border **l**eft width + the border **r**ight width.
  11888. * @return {Number} The width of the sides passed added together
  11889. */
  11890. getBorderWidth: function(side) {
  11891. return this.addStyles(side, this.borders);
  11892. },
  11893. /**
  11894. * Gets the width of the padding(s) for the specified side(s).
  11895. * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
  11896. * passing `'lr'` would get the padding **l**eft + the padding **r**ight.
  11897. * @return {Number} The padding of the sides passed added together.
  11898. */
  11899. getPadding: function(side) {
  11900. return this.addStyles(side, this.paddings);
  11901. },
  11902. /**
  11903. * More flexible version of {@link #setStyle} for setting style properties.
  11904. * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form `{width:"100px"}`, or
  11905. * a function which returns such a specification.
  11906. * @return {Ext.dom.Element} this
  11907. */
  11908. applyStyles: function(styles) {
  11909. if (styles) {
  11910. var dom = this.dom,
  11911. styleType, i, len;
  11912. if (typeof styles == 'function') {
  11913. styles = styles.call();
  11914. }
  11915. styleType = typeof styles;
  11916. if (styleType == 'string') {
  11917. styles = Ext.util.Format.trim(styles).split(this.styleSplitRe);
  11918. for (i = 0, len = styles.length; i < len;) {
  11919. dom.style[Ext.dom.Element.normalize(styles[i++])] = styles[i++];
  11920. }
  11921. }
  11922. else if (styleType == 'object') {
  11923. this.setStyle(styles);
  11924. }
  11925. }
  11926. },
  11927. /**
  11928. * Returns the size of the element.
  11929. * @param {Boolean} [contentSize] `true` to get the width/size minus borders and padding.
  11930. * @return {Object} An object containing the element's size:
  11931. * @return {Number} return.width
  11932. * @return {Number} return.height
  11933. */
  11934. getSize: function(contentSize) {
  11935. var dom = this.dom;
  11936. return {
  11937. width: Math.max(0, contentSize ? (dom.clientWidth - this.getPadding("lr")) : dom.offsetWidth),
  11938. height: Math.max(0, contentSize ? (dom.clientHeight - this.getPadding("tb")) : dom.offsetHeight)
  11939. };
  11940. },
  11941. /**
  11942. * Forces the browser to repaint this element.
  11943. * @return {Ext.dom.Element} this
  11944. */
  11945. repaint: function() {
  11946. var dom = this.dom;
  11947. this.addCls(Ext.baseCSSPrefix + 'repaint');
  11948. setTimeout(function() {
  11949. Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
  11950. }, 1);
  11951. return this;
  11952. },
  11953. /**
  11954. * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
  11955. * then it returns the calculated width of the sides (see {@link #getPadding}).
  11956. * @param {String} [sides] Any combination of 'l', 'r', 't', 'b' to get the sum of those sides.
  11957. * @return {Object/Number}
  11958. */
  11959. getMargin: function(side) {
  11960. var me = this,
  11961. hash = {t: "top", l: "left", r: "right", b: "bottom"},
  11962. o = {},
  11963. key;
  11964. if (!side) {
  11965. for (key in me.margins) {
  11966. o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
  11967. }
  11968. return o;
  11969. } else {
  11970. return me.addStyles.call(me, side, me.margins);
  11971. }
  11972. }
  11973. });
  11974. //@tag dom,core
  11975. //@define Ext.Element-all
  11976. //@define Ext.Element-traversal
  11977. //@require Ext.Element-style
  11978. /**
  11979. * @class Ext.dom.Element
  11980. */
  11981. Ext.dom.Element.addMembers({
  11982. getParent: function() {
  11983. return Ext.get(this.dom.parentNode);
  11984. },
  11985. getFirstChild: function() {
  11986. return Ext.get(this.dom.firstElementChild);
  11987. },
  11988. /**
  11989. * Returns `true` if this element is an ancestor of the passed element.
  11990. * @param {HTMLElement/String} element The element to check.
  11991. * @return {Boolean} `true` if this element is an ancestor of `el`, else `false`.
  11992. */
  11993. contains: function(element) {
  11994. if (!element) {
  11995. return false;
  11996. }
  11997. var dom = Ext.getDom(element);
  11998. // we need el-contains-itself logic here because isAncestor does not do that:
  11999. return (dom === this.dom) || this.self.isAncestor(this.dom, dom);
  12000. },
  12001. /**
  12002. * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. 'div.some-class' or 'span:first-child')
  12003. * @param {String} selector The simple selector to test.
  12004. * @param {Number/String/HTMLElement/Ext.Element} maxDepth (optional)
  12005. * The max depth to search as a number or element (defaults to `50 || document.body`)
  12006. * @param {Boolean} returnEl (optional) `true` to return a Ext.Element object instead of DOM node.
  12007. * @return {HTMLElement/null} The matching DOM node (or `null` if no match was found).
  12008. */
  12009. findParent: function(simpleSelector, maxDepth, returnEl) {
  12010. var p = this.dom,
  12011. b = document.body,
  12012. depth = 0,
  12013. stopEl;
  12014. maxDepth = maxDepth || 50;
  12015. if (isNaN(maxDepth)) {
  12016. stopEl = Ext.getDom(maxDepth);
  12017. maxDepth = Number.MAX_VALUE;
  12018. }
  12019. while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
  12020. if (Ext.DomQuery.is(p, simpleSelector)) {
  12021. return returnEl ? Ext.get(p) : p;
  12022. }
  12023. depth++;
  12024. p = p.parentNode;
  12025. }
  12026. return null;
  12027. },
  12028. /**
  12029. * Looks at parent nodes for a match of the passed simple selector (e.g. 'div.some-class' or 'span:first-child').
  12030. * @param {String} selector The simple selector to test.
  12031. * @param {Number/String/HTMLElement/Ext.Element} maxDepth (optional)
  12032. * The max depth to search as a number or element (defaults to `10 || document.body`).
  12033. * @param {Boolean} returnEl (optional) `true` to return a Ext.Element object instead of DOM node.
  12034. * @return {HTMLElement/null} The matching DOM node (or `null` if no match was found).
  12035. */
  12036. findParentNode: function(simpleSelector, maxDepth, returnEl) {
  12037. var p = Ext.fly(this.dom.parentNode, '_internal');
  12038. return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
  12039. },
  12040. /**
  12041. * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. 'div.some-class' or 'span:first-child').
  12042. * This is a shortcut for `findParentNode()` that always returns an Ext.dom.Element.
  12043. * @param {String} selector The simple selector to test
  12044. * @param {Number/String/HTMLElement/Ext.Element} maxDepth (optional)
  12045. * The max depth to search as a number or element (defaults to `10 || document.body`).
  12046. * @return {Ext.dom.Element/null} The matching DOM node (or `null` if no match was found).
  12047. */
  12048. up: function(simpleSelector, maxDepth) {
  12049. return this.findParentNode(simpleSelector, maxDepth, true);
  12050. },
  12051. select: function(selector, composite) {
  12052. return Ext.dom.Element.select(selector, this.dom, composite);
  12053. },
  12054. /**
  12055. * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
  12056. * @param {String} selector The CSS selector.
  12057. * @return {HTMLElement[]} An array of the matched nodes.
  12058. */
  12059. query: function(selector) {
  12060. return Ext.DomQuery.select(selector, this.dom);
  12061. },
  12062. /**
  12063. * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
  12064. * @param {String} selector The CSS selector.
  12065. * @param {Boolean} [returnDom=false] (optional) `true` to return the DOM node instead of Ext.dom.Element.
  12066. * @return {HTMLElement/Ext.dom.Element} The child Ext.dom.Element (or DOM node if `returnDom` is `true`).
  12067. */
  12068. down: function(selector, returnDom) {
  12069. var n = Ext.DomQuery.selectNode(selector, this.dom);
  12070. return returnDom ? n : Ext.get(n);
  12071. },
  12072. /**
  12073. * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
  12074. * @param {String} selector The CSS selector.
  12075. * @param {Boolean} [returnDom=false] (optional) `true` to return the DOM node instead of Ext.dom.Element.
  12076. * @return {HTMLElement/Ext.dom.Element} The child Ext.dom.Element (or DOM node if `returnDom` is `true`)
  12077. */
  12078. child: function(selector, returnDom) {
  12079. var node,
  12080. me = this,
  12081. id;
  12082. id = Ext.get(me).id;
  12083. // Escape . or :
  12084. id = id.replace(/[\.:]/g, "\\$0");
  12085. node = Ext.DomQuery.selectNode('#' + id + " > " + selector, me.dom);
  12086. return returnDom ? node : Ext.get(node);
  12087. },
  12088. /**
  12089. * Gets the parent node for this element, optionally chaining up trying to match a selector.
  12090. * @param {String} selector (optional) Find a parent node that matches the passed simple selector.
  12091. * @param {Boolean} returnDom (optional) `true` to return a raw DOM node instead of an Ext.dom.Element.
  12092. * @return {Ext.dom.Element/HTMLElement/null} The parent node or `null`.
  12093. */
  12094. parent: function(selector, returnDom) {
  12095. return this.matchNode('parentNode', 'parentNode', selector, returnDom);
  12096. },
  12097. /**
  12098. * Gets the next sibling, skipping text nodes.
  12099. * @param {String} selector (optional) Find the next sibling that matches the passed simple selector.
  12100. * @param {Boolean} returnDom (optional) `true` to return a raw dom node instead of an Ext.dom.Element.
  12101. * @return {Ext.dom.Element/HTMLElement/null} The next sibling or `null`.
  12102. */
  12103. next: function(selector, returnDom) {
  12104. return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
  12105. },
  12106. /**
  12107. * Gets the previous sibling, skipping text nodes.
  12108. * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector.
  12109. * @param {Boolean} returnDom (optional) `true` to return a raw DOM node instead of an Ext.dom.Element
  12110. * @return {Ext.dom.Element/HTMLElement/null} The previous sibling or `null`.
  12111. */
  12112. prev: function(selector, returnDom) {
  12113. return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
  12114. },
  12115. /**
  12116. * Gets the first child, skipping text nodes.
  12117. * @param {String} selector (optional) Find the next sibling that matches the passed simple selector.
  12118. * @param {Boolean} returnDom (optional) `true` to return a raw DOM node instead of an Ext.dom.Element.
  12119. * @return {Ext.dom.Element/HTMLElement/null} The first child or `null`.
  12120. */
  12121. first: function(selector, returnDom) {
  12122. return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
  12123. },
  12124. /**
  12125. * Gets the last child, skipping text nodes.
  12126. * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector.
  12127. * @param {Boolean} returnDom (optional) `true` to return a raw DOM node instead of an Ext.dom.Element.
  12128. * @return {Ext.dom.Element/HTMLElement/null} The last child or `null`.
  12129. */
  12130. last: function(selector, returnDom) {
  12131. return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
  12132. },
  12133. matchNode: function(dir, start, selector, returnDom) {
  12134. if (!this.dom) {
  12135. return null;
  12136. }
  12137. var n = this.dom[start];
  12138. while (n) {
  12139. if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) {
  12140. return !returnDom ? Ext.get(n) : n;
  12141. }
  12142. n = n[dir];
  12143. }
  12144. return null;
  12145. },
  12146. isAncestor: function(element) {
  12147. return this.self.isAncestor.call(this.self, this.dom, element);
  12148. }
  12149. });
  12150. //@tag dom,core
  12151. //@require Ext.Element-all
  12152. /**
  12153. * This class encapsulates a *collection* of DOM elements, providing methods to filter members, or to perform collective
  12154. * actions upon the whole set.
  12155. *
  12156. * Although they are not listed, this class supports all of the methods of {@link Ext.dom.Element} and
  12157. * {@link Ext.Anim}. The methods from these classes will be performed on all the elements in this collection.
  12158. *
  12159. * Example:
  12160. *
  12161. * var els = Ext.select("#some-el div.some-class");
  12162. * // or select directly from an existing element
  12163. * var el = Ext.get('some-el');
  12164. * el.select('div.some-class');
  12165. *
  12166. * els.setWidth(100); // all elements become 100 width
  12167. * els.hide(true); // all elements fade out and hide
  12168. * // or
  12169. * els.setWidth(100).hide(true);
  12170. *
  12171. * @mixins Ext.dom.Element
  12172. */
  12173. Ext.define('Ext.dom.CompositeElementLite', {
  12174. alternateClassName: ['Ext.CompositeElementLite', 'Ext.CompositeElement'],
  12175. requires: ['Ext.dom.Element'],
  12176. // We use the @mixins tag above to document that CompositeElement has
  12177. // all the same methods as Element, but the @mixins tag also pulls in
  12178. // configs and properties which we don't want, so hide them explicitly:
  12179. /** @cfg bubbleEvents @hide */
  12180. /** @cfg listeners @hide */
  12181. /** @property DISPLAY @hide */
  12182. /** @property OFFSETS @hide */
  12183. /** @property VISIBILITY @hide */
  12184. /** @property defaultUnit @hide */
  12185. /** @property dom @hide */
  12186. /** @property id @hide */
  12187. // Also hide the static #get method that also gets inherited
  12188. /** @method get @static @hide */
  12189. statics: {
  12190. /**
  12191. * @private
  12192. * @static
  12193. * Copies all of the functions from Ext.dom.Element's prototype onto CompositeElementLite's prototype.
  12194. */
  12195. importElementMethods: function() {
  12196. }
  12197. },
  12198. constructor: function(elements, root) {
  12199. /**
  12200. * @property {HTMLElement[]} elements
  12201. * @readonly
  12202. * The Array of DOM elements which this CompositeElement encapsulates.
  12203. *
  12204. * This will not *usually* be accessed in developers' code, but developers wishing to augment the capabilities
  12205. * of the CompositeElementLite class may use it when adding methods to the class.
  12206. *
  12207. * For example to add the `nextAll` method to the class to **add** all following siblings of selected elements,
  12208. * the code would be
  12209. *
  12210. * Ext.override(Ext.dom.CompositeElementLite, {
  12211. * nextAll: function() {
  12212. * var elements = this.elements, i, l = elements.length, n, r = [], ri = -1;
  12213. *
  12214. * // Loop through all elements in this Composite, accumulating
  12215. * // an Array of all siblings.
  12216. * for (i = 0; i < l; i++) {
  12217. * for (n = elements[i].nextSibling; n; n = n.nextSibling) {
  12218. * r[++ri] = n;
  12219. * }
  12220. * }
  12221. *
  12222. * // Add all found siblings to this Composite
  12223. * return this.add(r);
  12224. * }
  12225. * });
  12226. */
  12227. this.elements = [];
  12228. this.add(elements, root);
  12229. this.el = new Ext.dom.Element.Fly();
  12230. },
  12231. isComposite: true,
  12232. // @private
  12233. getElement: function(el) {
  12234. // Set the shared flyweight dom property to the current element
  12235. return this.el.attach(el).synchronize();
  12236. },
  12237. // @private
  12238. transformElement: function(el) {
  12239. return Ext.getDom(el);
  12240. },
  12241. /**
  12242. * Returns the number of elements in this Composite.
  12243. * @return {Number}
  12244. */
  12245. getCount: function() {
  12246. return this.elements.length;
  12247. },
  12248. /**
  12249. * Adds elements to this Composite object.
  12250. * @param {HTMLElement[]/Ext.dom.CompositeElementLite} els Either an Array of DOM elements to add, or another Composite
  12251. * object who's elements should be added.
  12252. * @param {HTMLElement/String} [root] The root element of the query or id of the root.
  12253. * @return {Ext.dom.CompositeElementLite} This Composite object.
  12254. */
  12255. add: function(els, root) {
  12256. var elements = this.elements,
  12257. i, ln;
  12258. if (!els) {
  12259. return this;
  12260. }
  12261. if (typeof els == "string") {
  12262. els = Ext.dom.Element.selectorFunction(els, root);
  12263. }
  12264. else if (els.isComposite) {
  12265. els = els.elements;
  12266. }
  12267. else if (!Ext.isIterable(els)) {
  12268. els = [els];
  12269. }
  12270. for (i = 0, ln = els.length; i < ln; ++i) {
  12271. elements.push(this.transformElement(els[i]));
  12272. }
  12273. return this;
  12274. },
  12275. invoke: function(fn, args) {
  12276. var elements = this.elements,
  12277. ln = elements.length,
  12278. element,
  12279. i;
  12280. for (i = 0; i < ln; i++) {
  12281. element = elements[i];
  12282. if (element) {
  12283. Ext.dom.Element.prototype[fn].apply(this.getElement(element), args);
  12284. }
  12285. }
  12286. return this;
  12287. },
  12288. /**
  12289. * Returns a flyweight Element of the dom element object at the specified index.
  12290. * @param {Number} index
  12291. * @return {Ext.dom.Element}
  12292. */
  12293. item: function(index) {
  12294. var el = this.elements[index],
  12295. out = null;
  12296. if (el) {
  12297. out = this.getElement(el);
  12298. }
  12299. return out;
  12300. },
  12301. // fixes scope with flyweight.
  12302. addListener: function(eventName, handler, scope, opt) {
  12303. var els = this.elements,
  12304. len = els.length,
  12305. i, e;
  12306. for (i = 0; i < len; i++) {
  12307. e = els[i];
  12308. if (e) {
  12309. e.on(eventName, handler, scope || e, opt);
  12310. }
  12311. }
  12312. return this;
  12313. },
  12314. /**
  12315. * Calls the passed function for each element in this composite.
  12316. * @param {Function} fn The function to call.
  12317. * @param {Ext.dom.Element} fn.el The current Element in the iteration. **This is the flyweight
  12318. * (shared) Ext.dom.Element instance, so if you require a a reference to the dom node, use el.dom.**
  12319. * @param {Ext.dom.CompositeElementLite} fn.c This Composite object.
  12320. * @param {Number} fn.index The zero-based index in the iteration.
  12321. * @param {Object} [scope] The scope (this reference) in which the function is executed.
  12322. * Defaults to the Element.
  12323. * @return {Ext.dom.CompositeElementLite} this
  12324. */
  12325. each: function(fn, scope) {
  12326. var me = this,
  12327. els = me.elements,
  12328. len = els.length,
  12329. i, e;
  12330. for (i = 0; i < len; i++) {
  12331. e = els[i];
  12332. if (e) {
  12333. e = this.getElement(e);
  12334. if (fn.call(scope || e, e, me, i) === false) {
  12335. break;
  12336. }
  12337. }
  12338. }
  12339. return me;
  12340. },
  12341. /**
  12342. * Clears this Composite and adds the elements passed.
  12343. * @param {HTMLElement[]/Ext.dom.CompositeElementLite} els Either an array of DOM elements, or another Composite from which
  12344. * to fill this Composite.
  12345. * @return {Ext.dom.CompositeElementLite} this
  12346. */
  12347. fill: function(els) {
  12348. var me = this;
  12349. me.elements = [];
  12350. me.add(els);
  12351. return me;
  12352. },
  12353. /**
  12354. * Filters this composite to only elements that match the passed selector.
  12355. * @param {String/Function} selector A string CSS selector or a comparison function. The comparison function will be
  12356. * called with the following arguments:
  12357. * @param {Ext.dom.Element} selector.el The current DOM element.
  12358. * @param {Number} selector.index The current index within the collection.
  12359. * @return {Ext.dom.CompositeElementLite} this
  12360. */
  12361. filter: function(selector) {
  12362. var els = [],
  12363. me = this,
  12364. fn = Ext.isFunction(selector) ? selector
  12365. : function(el) {
  12366. return el.is(selector);
  12367. };
  12368. me.each(function(el, self, i) {
  12369. if (fn(el, i) !== false) {
  12370. els[els.length] = me.transformElement(el);
  12371. }
  12372. });
  12373. me.elements = els;
  12374. return me;
  12375. },
  12376. /**
  12377. * Find the index of the passed element within the composite collection.
  12378. * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, or an Ext.dom.Element, or an HtmlElement
  12379. * to find within the composite collection.
  12380. * @return {Number} The index of the passed Ext.dom.Element in the composite collection, or -1 if not found.
  12381. */
  12382. indexOf: function(el) {
  12383. return Ext.Array.indexOf(this.elements, this.transformElement(el));
  12384. },
  12385. /**
  12386. * Replaces the specified element with the passed element.
  12387. * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, the Element itself, the index of the
  12388. * element in this composite to replace.
  12389. * @param {String/Ext.Element} replacement The id of an element or the Element itself.
  12390. * @param {Boolean} [domReplace] `true` to remove and replace the element in the document too.
  12391. * @return {Ext.dom.CompositeElementLite} this
  12392. */
  12393. replaceElement: function(el, replacement, domReplace) {
  12394. var index = !isNaN(el) ? el : this.indexOf(el),
  12395. d;
  12396. if (index > -1) {
  12397. replacement = Ext.getDom(replacement);
  12398. if (domReplace) {
  12399. d = this.elements[index];
  12400. d.parentNode.insertBefore(replacement, d);
  12401. Ext.removeNode(d);
  12402. }
  12403. Ext.Array.splice(this.elements, index, 1, replacement);
  12404. }
  12405. return this;
  12406. },
  12407. /**
  12408. * Removes all elements.
  12409. */
  12410. clear: function() {
  12411. this.elements = [];
  12412. },
  12413. addElements: function(els, root) {
  12414. if (!els) {
  12415. return this;
  12416. }
  12417. if (typeof els == "string") {
  12418. els = Ext.dom.Element.selectorFunction(els, root);
  12419. }
  12420. var yels = this.elements;
  12421. Ext.each(els, function(e) {
  12422. yels.push(Ext.get(e));
  12423. });
  12424. return this;
  12425. },
  12426. /**
  12427. * Returns the first Element
  12428. * @return {Ext.dom.Element}
  12429. */
  12430. first: function() {
  12431. return this.item(0);
  12432. },
  12433. /**
  12434. * Returns the last Element
  12435. * @return {Ext.dom.Element}
  12436. */
  12437. last: function() {
  12438. return this.item(this.getCount() - 1);
  12439. },
  12440. /**
  12441. * Returns `true` if this composite contains the passed element
  12442. * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, or an Ext.Element, or an HtmlElement to
  12443. * find within the composite collection.
  12444. * @return {Boolean}
  12445. */
  12446. contains: function(el) {
  12447. return this.indexOf(el) != -1;
  12448. },
  12449. /**
  12450. * Removes the specified element(s).
  12451. * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, the Element itself, the index of the
  12452. * element in this composite or an array of any of those.
  12453. * @param {Boolean} [removeDom] `true` to also remove the element from the document
  12454. * @return {Ext.dom.CompositeElementLite} this
  12455. */
  12456. removeElement: function(keys, removeDom) {
  12457. var me = this,
  12458. elements = this.elements,
  12459. el;
  12460. Ext.each(keys, function(val) {
  12461. if ((el = (elements[val] || elements[val = me.indexOf(val)]))) {
  12462. if (removeDom) {
  12463. if (el.dom) {
  12464. el.remove();
  12465. }
  12466. else {
  12467. Ext.removeNode(el);
  12468. }
  12469. }
  12470. Ext.Array.erase(elements, val, 1);
  12471. }
  12472. });
  12473. return this;
  12474. }
  12475. }, function() {
  12476. var Element = Ext.dom.Element,
  12477. elementPrototype = Element.prototype,
  12478. prototype = this.prototype,
  12479. name;
  12480. for (name in elementPrototype) {
  12481. if (typeof elementPrototype[name] == 'function'){
  12482. (function(key) {
  12483. prototype[key] = prototype[key] || function() {
  12484. return this.invoke(key, arguments);
  12485. };
  12486. }).call(prototype, name);
  12487. }
  12488. }
  12489. prototype.on = prototype.addListener;
  12490. if (Ext.DomQuery){
  12491. Element.selectorFunction = Ext.DomQuery.select;
  12492. }
  12493. /**
  12494. * Selects elements based on the passed CSS selector to enable {@link Ext.Element Element} methods
  12495. * to be applied to many related elements in one statement through the returned
  12496. * {@link Ext.dom.CompositeElementLite CompositeElementLite} object.
  12497. * @param {String/HTMLElement[]} selector The CSS selector or an array of elements
  12498. * @param {HTMLElement/String} [root] The root element of the query or id of the root
  12499. * @return {Ext.dom.CompositeElementLite}
  12500. * @member Ext.dom.Element
  12501. * @method select
  12502. */
  12503. Element.select = function(selector, root) {
  12504. var elements;
  12505. if (typeof selector == "string") {
  12506. elements = Element.selectorFunction(selector, root);
  12507. }
  12508. else if (selector.length !== undefined) {
  12509. elements = selector;
  12510. }
  12511. else {
  12512. //<debug>
  12513. throw new Error("[Ext.select] Invalid selector specified: " + selector);
  12514. //</debug>
  12515. }
  12516. return new Ext.CompositeElementLite(elements);
  12517. };
  12518. /**
  12519. * @member Ext
  12520. * @method select
  12521. * @alias Ext.dom.Element#select
  12522. */
  12523. Ext.select = function() {
  12524. return Element.select.apply(Element, arguments);
  12525. };
  12526. });
  12527. Ext.ClassManager.addNameAlternateMappings({
  12528. "Ext.app.Profile": [],
  12529. "Ext.event.recognizer.MultiTouch": [],
  12530. "Ext.fx.Runner": [],
  12531. "Ext.chart.grid.CircularGrid": [],
  12532. "Ext.mixin.Templatable": [],
  12533. "Ext.event.recognizer.Pinch": [],
  12534. "Ext.util.Format": [],
  12535. "Ext.direct.JsonProvider": [],
  12536. "Ext.data.identifier.Simple": [],
  12537. "Ext.dataview.DataView": [
  12538. "Ext.DataView"
  12539. ],
  12540. "Ext.field.Hidden": [
  12541. "Ext.form.Hidden"
  12542. ],
  12543. "Ext.env.Feature": [],
  12544. "Ext.field.Number": [
  12545. "Ext.form.Number"
  12546. ],
  12547. "Ext.chart.series.CandleStick": [],
  12548. "Ext.device.Connection": [],
  12549. "Ext.data.Model": [
  12550. "Ext.data.Record"
  12551. ],
  12552. "Ext.data.reader.Reader": [
  12553. "Ext.data.Reader",
  12554. "Ext.data.DataReader"
  12555. ],
  12556. "Ext.Sheet": [],
  12557. "Ext.tab.Tab": [
  12558. "Ext.Tab"
  12559. ],
  12560. "Ext.chart.series.sprite.StackedCartesian": [],
  12561. "Ext.util.Grouper": [],
  12562. "Ext.util.translatable.CssPosition": [],
  12563. "Ext.util.paintmonitor.Abstract": [],
  12564. "Ext.direct.RemotingProvider": [],
  12565. "Ext.data.NodeInterface": [
  12566. "Ext.data.Node"
  12567. ],
  12568. "Ext.env.OS": [],
  12569. "Ext.chart.interactions.PanZoom": [],
  12570. "Ext.util.PositionMap": [],
  12571. "Ext.chart.series.ItemPublisher": [],
  12572. "Ext.util.Sortable": [],
  12573. "Ext.chart.series.sprite.AbstractRadial": [],
  12574. "Ext.fx.runner.Css": [],
  12575. "Ext.fx.runner.CssTransition": [],
  12576. "Ext.draw.Group": [],
  12577. "Ext.XTemplateCompiler": [],
  12578. "Ext.util.Wrapper": [],
  12579. "Ext.app.Router": [],
  12580. "Ext.direct.Transaction": [
  12581. "Ext.Direct.Transaction"
  12582. ],
  12583. "Ext.util.Offset": [],
  12584. "Ext.dom.Element": [
  12585. "Ext.Element"
  12586. ],
  12587. "Ext.device.device.Abstract": [],
  12588. "Ext.mixin.Mixin": [],
  12589. "Ext.fx.animation.FadeOut": [],
  12590. "Ext.util.Geolocation": [
  12591. "Ext.util.GeoLocation"
  12592. ],
  12593. "Ext.ComponentManager": [
  12594. "Ext.ComponentMgr"
  12595. ],
  12596. "Ext.util.sizemonitor.OverflowChange": [],
  12597. "Ext.event.publisher.ElementSize": [],
  12598. "Ext.tab.Bar": [
  12599. "Ext.TabBar"
  12600. ],
  12601. "Ext.event.Dom": [],
  12602. "Ext.app.Application": [],
  12603. "Ext.dataview.List": [
  12604. "Ext.List"
  12605. ],
  12606. "Ext.util.translatable.Dom": [],
  12607. "Ext.fx.layout.card.Scroll": [],
  12608. "Ext.draw.LimitedCache": [],
  12609. "Ext.device.geolocation.Sencha": [],
  12610. "Ext.dataview.ListItemHeader": [],
  12611. "Ext.event.publisher.TouchGesture": [],
  12612. "Ext.data.SortTypes": [],
  12613. "Ext.device.contacts.Abstract": [],
  12614. "Ext.device.push.Sencha": [],
  12615. "Ext.fx.animation.WipeOut": [],
  12616. "Ext.slider.Slider": [],
  12617. "Ext.Component": [
  12618. "Ext.lib.Component"
  12619. ],
  12620. "Ext.device.communicator.Default": [],
  12621. "Ext.fx.runner.CssAnimation": [],
  12622. "Ext.chart.axis.Axis": [],
  12623. "Ext.fx.animation.Cube": [],
  12624. "Ext.chart.Markers": [],
  12625. "Ext.chart.series.sprite.Radar": [],
  12626. "Ext.device.device.Simulator": [],
  12627. "Ext.Ajax": [],
  12628. "Ext.dataview.component.ListItem": [],
  12629. "Ext.util.Filter": [],
  12630. "Ext.layout.wrapper.Inner": [],
  12631. "Ext.draw.Animator": [],
  12632. "Ext.device.geolocation.Simulator": [],
  12633. "Ext.data.association.BelongsTo": [
  12634. "Ext.data.BelongsToAssociation"
  12635. ],
  12636. "Ext.draw.Surface": [],
  12637. "Ext.dom.Query": [],
  12638. "Ext.scroll.indicator.ScrollPosition": [],
  12639. "Ext.field.Email": [
  12640. "Ext.form.Email"
  12641. ],
  12642. "Ext.fx.layout.card.Abstract": [],
  12643. "Ext.event.Controller": [],
  12644. "Ext.dataview.component.Container": [],
  12645. "Ext.log.writer.Remote": [],
  12646. "Ext.fx.layout.card.Style": [],
  12647. "Ext.device.purchases.Sencha": [],
  12648. "Ext.chart.axis.segmenter.Segmenter": [],
  12649. "Ext.viewport.Android": [],
  12650. "Ext.log.formatter.Identity": [],
  12651. "Ext.chart.interactions.ItemHighlight": [],
  12652. "Ext.picker.Picker": [
  12653. "Ext.Picker"
  12654. ],
  12655. "Ext.data.Batch": [],
  12656. "Ext.draw.modifier.Animation": [],
  12657. "Ext.chart.AbstractChart": [],
  12658. "Ext.tab.Panel": [
  12659. "Ext.TabPanel"
  12660. ],
  12661. "Ext.draw.Path": [],
  12662. "Ext.scroll.indicator.Throttled": [],
  12663. "Ext.fx.animation.SlideOut": [],
  12664. "Ext.device.connection.Sencha": [],
  12665. "Ext.fx.layout.card.Pop": [],
  12666. "Ext.chart.axis.layout.Discrete": [],
  12667. "Ext.data.Field": [],
  12668. "Ext.chart.series.Gauge": [],
  12669. "Ext.data.StoreManager": [
  12670. "Ext.StoreMgr",
  12671. "Ext.data.StoreMgr",
  12672. "Ext.StoreManager"
  12673. ],
  12674. "Ext.fx.animation.PopOut": [],
  12675. "Ext.chart.label.Callout": [],
  12676. "Ext.device.push.Abstract": [],
  12677. "Ext.util.DelayedTask": [],
  12678. "Ext.fx.easing.Momentum": [],
  12679. "Ext.fx.easing.Abstract": [],
  12680. "Ext.Title": [],
  12681. "Ext.event.recognizer.Drag": [],
  12682. "Ext.field.TextArea": [
  12683. "Ext.form.TextArea"
  12684. ],
  12685. "Ext.fx.Easing": [],
  12686. "Ext.chart.series.sprite.Scatter": [],
  12687. "Ext.picker.Date": [
  12688. "Ext.DatePicker"
  12689. ],
  12690. "Ext.data.reader.Array": [
  12691. "Ext.data.ArrayReader"
  12692. ],
  12693. "Ext.data.proxy.JsonP": [
  12694. "Ext.data.ScriptTagProxy"
  12695. ],
  12696. "Ext.device.communicator.Android": [],
  12697. "Ext.chart.series.Area": [],
  12698. "Ext.device.device.PhoneGap": [],
  12699. "Ext.field.Checkbox": [
  12700. "Ext.form.Checkbox"
  12701. ],
  12702. "Ext.chart.Legend": [],
  12703. "Ext.Media": [],
  12704. "Ext.TitleBar": [],
  12705. "Ext.chart.interactions.RotatePie3D": [],
  12706. "Ext.draw.gradient.Linear": [],
  12707. "Ext.util.TapRepeater": [],
  12708. "Ext.event.Touch": [],
  12709. "Ext.mixin.Bindable": [],
  12710. "Ext.data.proxy.Server": [
  12711. "Ext.data.ServerProxy"
  12712. ],
  12713. "Ext.chart.series.Cartesian": [],
  12714. "Ext.util.sizemonitor.Scroll": [],
  12715. "Ext.data.ResultSet": [],
  12716. "Ext.data.association.HasMany": [
  12717. "Ext.data.HasManyAssociation"
  12718. ],
  12719. "Ext.draw.TimingFunctions": [],
  12720. "Ext.draw.engine.Canvas": [],
  12721. "Ext.data.proxy.Ajax": [
  12722. "Ext.data.HttpProxy",
  12723. "Ext.data.AjaxProxy"
  12724. ],
  12725. "Ext.layout.Default": [],
  12726. "Ext.fx.animation.Fade": [
  12727. "Ext.fx.animation.FadeIn"
  12728. ],
  12729. "Ext.util.paintmonitor.CssAnimation": [],
  12730. "Ext.data.writer.Writer": [
  12731. "Ext.data.DataWriter",
  12732. "Ext.data.Writer"
  12733. ],
  12734. "Ext.event.recognizer.Recognizer": [],
  12735. "Ext.form.FieldSet": [],
  12736. "Ext.scroll.Indicator": [
  12737. "Ext.util.Indicator"
  12738. ],
  12739. "Ext.XTemplateParser": [],
  12740. "Ext.behavior.Scrollable": [],
  12741. "Ext.chart.series.sprite.CandleStick": [],
  12742. "Ext.data.JsonP": [
  12743. "Ext.util.JSONP"
  12744. ],
  12745. "Ext.device.connection.PhoneGap": [],
  12746. "Ext.event.publisher.Dom": [],
  12747. "Ext.fx.layout.card.Fade": [],
  12748. "Ext.app.Controller": [],
  12749. "Ext.fx.State": [],
  12750. "Ext.layout.wrapper.BoxDock": [],
  12751. "Ext.chart.series.sprite.Pie3DPart": [],
  12752. "Ext.viewport.Default": [],
  12753. "Ext.layout.HBox": [],
  12754. "Ext.ux.auth.model.Session": [],
  12755. "Ext.scroll.indicator.Default": [],
  12756. "Ext.data.ModelManager": [
  12757. "Ext.ModelMgr",
  12758. "Ext.ModelManager"
  12759. ],
  12760. "Ext.data.Validations": [
  12761. "Ext.data.validations"
  12762. ],
  12763. "Ext.util.translatable.Abstract": [],
  12764. "Ext.scroll.indicator.Abstract": [],
  12765. "Ext.Button": [],
  12766. "Ext.field.Radio": [
  12767. "Ext.form.Radio"
  12768. ],
  12769. "Ext.util.HashMap": [],
  12770. "Ext.field.Input": [],
  12771. "Ext.device.Camera": [],
  12772. "Ext.mixin.Filterable": [],
  12773. "Ext.draw.TextMeasurer": [],
  12774. "Ext.dataview.element.Container": [],
  12775. "Ext.chart.series.sprite.PieSlice": [],
  12776. "Ext.data.Connection": [],
  12777. "Ext.direct.ExceptionEvent": [],
  12778. "Ext.Panel": [
  12779. "Ext.lib.Panel"
  12780. ],
  12781. "Ext.data.association.HasOne": [
  12782. "Ext.data.HasOneAssociation"
  12783. ],
  12784. "Ext.device.geolocation.Abstract": [],
  12785. "Ext.ActionSheet": [],
  12786. "Ext.layout.Box": [],
  12787. "Ext.bb.CrossCut": [],
  12788. "Ext.Video": [],
  12789. "Ext.ux.auth.Session": [],
  12790. "Ext.chart.series.Line": [],
  12791. "Ext.fx.layout.card.Cube": [],
  12792. "Ext.event.recognizer.HorizontalSwipe": [],
  12793. "Ext.data.writer.Json": [
  12794. "Ext.data.JsonWriter"
  12795. ],
  12796. "Ext.layout.Fit": [],
  12797. "Ext.fx.animation.Slide": [
  12798. "Ext.fx.animation.SlideIn"
  12799. ],
  12800. "Ext.device.Purchases.Purchase": [],
  12801. "Ext.table.Row": [],
  12802. "Ext.log.formatter.Formatter": [],
  12803. "Ext.Container": [
  12804. "Ext.lib.Container"
  12805. ],
  12806. "Ext.fx.animation.Pop": [
  12807. "Ext.fx.animation.PopIn"
  12808. ],
  12809. "Ext.draw.sprite.Circle": [],
  12810. "Ext.fx.layout.card.Reveal": [],
  12811. "Ext.fx.layout.card.Cover": [],
  12812. "Ext.log.Base": [],
  12813. "Ext.data.reader.Xml": [
  12814. "Ext.data.XmlReader"
  12815. ],
  12816. "Ext.event.publisher.ElementPaint": [],
  12817. "Ext.chart.axis.Category": [],
  12818. "Ext.data.reader.Json": [
  12819. "Ext.data.JsonReader"
  12820. ],
  12821. "Ext.Decorator": [],
  12822. "Ext.data.TreeStore": [],
  12823. "Ext.device.Purchases": [],
  12824. "Ext.device.orientation.HTML5": [],
  12825. "Ext.draw.gradient.Gradient": [],
  12826. "Ext.event.recognizer.DoubleTap": [],
  12827. "Ext.log.Logger": [],
  12828. "Ext.picker.Slot": [
  12829. "Ext.Picker.Slot"
  12830. ],
  12831. "Ext.device.notification.Simulator": [],
  12832. "Ext.field.Field": [
  12833. "Ext.form.Field"
  12834. ],
  12835. "Ext.log.filter.Priority": [],
  12836. "Ext.util.sizemonitor.Abstract": [],
  12837. "Ext.chart.series.sprite.Polar": [],
  12838. "Ext.util.paintmonitor.OverflowChange": [],
  12839. "Ext.util.LineSegment": [],
  12840. "Ext.SegmentedButton": [],
  12841. "Ext.Sortable": [],
  12842. "Ext.fx.easing.Linear": [],
  12843. "Ext.chart.series.sprite.Aggregative": [],
  12844. "Ext.dom.CompositeElement": [
  12845. "Ext.CompositeElement"
  12846. ],
  12847. "Ext.data.identifier.Uuid": [],
  12848. "Ext.data.proxy.Client": [
  12849. "Ext.proxy.ClientProxy"
  12850. ],
  12851. "Ext.fx.easing.Bounce": [],
  12852. "Ext.data.Types": [],
  12853. "Ext.chart.series.sprite.Cartesian": [],
  12854. "Ext.app.Action": [],
  12855. "Ext.util.Translatable": [],
  12856. "Ext.device.camera.PhoneGap": [],
  12857. "Ext.draw.sprite.Path": [],
  12858. "Ext.LoadMask": [],
  12859. "Ext.data.association.Association": [
  12860. "Ext.data.Association"
  12861. ],
  12862. "Ext.chart.axis.sprite.Axis": [],
  12863. "Ext.behavior.Draggable": [],
  12864. "Ext.chart.grid.RadialGrid": [],
  12865. "Ext.util.TranslatableGroup": [],
  12866. "Ext.fx.Animation": [],
  12867. "Ext.draw.sprite.Ellipse": [],
  12868. "Ext.util.Inflector": [],
  12869. "Ext.Map": [],
  12870. "Ext.XTemplate": [],
  12871. "Ext.data.NodeStore": [],
  12872. "Ext.draw.sprite.AttributeParser": [],
  12873. "Ext.form.Panel": [
  12874. "Ext.form.FormPanel"
  12875. ],
  12876. "Ext.chart.series.Series": [],
  12877. "Ext.data.Request": [],
  12878. "Ext.draw.sprite.Text": [],
  12879. "Ext.layout.Float": [],
  12880. "Ext.dom.CompositeElementLite": [
  12881. "Ext.CompositeElementLite",
  12882. "Ext.CompositeElement"
  12883. ],
  12884. "Ext.dataview.component.DataItem": [],
  12885. "Ext.chart.CartesianChart": [
  12886. "Ext.chart.Chart"
  12887. ],
  12888. "Ext.data.proxy.WebStorage": [
  12889. "Ext.data.WebStorageProxy"
  12890. ],
  12891. "Ext.log.writer.Writer": [],
  12892. "Ext.device.Communicator": [],
  12893. "Ext.fx.animation.Flip": [],
  12894. "Ext.util.Point": [],
  12895. "Ext.chart.series.StackedCartesian": [],
  12896. "Ext.fx.layout.card.Slide": [],
  12897. "Ext.Anim": [],
  12898. "Ext.data.DirectStore": [],
  12899. "Ext.dataview.NestedList": [
  12900. "Ext.NestedList"
  12901. ],
  12902. "Ext.app.Route": [],
  12903. "Ext.device.connection.Simulator": [],
  12904. "Ext.chart.PolarChart": [],
  12905. "Ext.event.publisher.ComponentSize": [],
  12906. "Ext.slider.Toggle": [],
  12907. "Ext.data.identifier.Sequential": [],
  12908. "Ext.AbstractComponent": [],
  12909. "Ext.Template": [],
  12910. "Ext.device.Push": [],
  12911. "Ext.fx.easing.BoundMomentum": [],
  12912. "Ext.viewport.Viewport": [],
  12913. "Ext.event.recognizer.VerticalSwipe": [],
  12914. "Ext.chart.series.Polar": [],
  12915. "Ext.event.Event": [
  12916. "Ext.EventObject"
  12917. ],
  12918. "Ext.behavior.Behavior": [],
  12919. "Ext.chart.grid.VerticalGrid": [],
  12920. "Ext.chart.label.Label": [],
  12921. "Ext.draw.sprite.EllipticalArc": [],
  12922. "Ext.fx.easing.EaseOut": [],
  12923. "Ext.Toolbar": [],
  12924. "Ext.event.recognizer.LongPress": [],
  12925. "Ext.device.notification.Sencha": [],
  12926. "Ext.chart.series.sprite.Line": [],
  12927. "Ext.data.ArrayStore": [],
  12928. "Ext.data.proxy.SQL": [],
  12929. "Ext.event.recognizer.Rotate": [],
  12930. "Ext.mixin.Sortable": [],
  12931. "Ext.fx.layout.card.Flip": [],
  12932. "Ext.chart.interactions.CrossZoom": [],
  12933. "Ext.event.publisher.ComponentPaint": [],
  12934. "Ext.util.TranslatableList": [],
  12935. "Ext.carousel.Item": [],
  12936. "Ext.event.recognizer.Swipe": [],
  12937. "Ext.mixin.Identifiable": [],
  12938. "Ext.util.translatable.ScrollPosition": [],
  12939. "Ext.device.camera.Simulator": [],
  12940. "Ext.chart.series.sprite.Area": [],
  12941. "Ext.event.recognizer.Touch": [],
  12942. "Ext.plugin.ListPaging": [],
  12943. "Ext.draw.sprite.Sector": [],
  12944. "Ext.chart.axis.segmenter.Names": [],
  12945. "Ext.mixin.Observable": [
  12946. "Ext.util.Observable"
  12947. ],
  12948. "Ext.carousel.Infinite": [],
  12949. "Ext.draw.Matrix": [],
  12950. "Ext.Mask": [],
  12951. "Ext.event.publisher.Publisher": [],
  12952. "Ext.layout.wrapper.Dock": [],
  12953. "Ext.app.History": [],
  12954. "Ext.data.proxy.Direct": [
  12955. "Ext.data.DirectProxy"
  12956. ],
  12957. "Ext.chart.axis.layout.Continuous": [],
  12958. "Ext.table.Cell": [],
  12959. "Ext.fx.layout.card.ScrollCover": [],
  12960. "Ext.device.orientation.Sencha": [],
  12961. "Ext.util.Droppable": [],
  12962. "Ext.draw.sprite.Composite": [],
  12963. "Ext.chart.series.Pie": [],
  12964. "Ext.device.Purchases.Product": [],
  12965. "Ext.device.Orientation": [],
  12966. "Ext.direct.Provider": [],
  12967. "Ext.draw.sprite.Arc": [],
  12968. "Ext.chart.axis.segmenter.Time": [],
  12969. "Ext.util.Draggable": [],
  12970. "Ext.device.contacts.Sencha": [],
  12971. "Ext.dom.Helper": [],
  12972. "Ext.chart.grid.HorizontalGrid": [],
  12973. "Ext.mixin.Traversable": [],
  12974. "Ext.util.AbstractMixedCollection": [],
  12975. "Ext.data.JsonStore": [],
  12976. "Ext.draw.SegmentTree": [],
  12977. "Ext.direct.RemotingEvent": [],
  12978. "Ext.plugin.PullRefresh": [],
  12979. "Ext.log.writer.Console": [],
  12980. "Ext.field.Spinner": [
  12981. "Ext.form.Spinner"
  12982. ],
  12983. "Ext.chart.axis.segmenter.Numeric": [],
  12984. "Ext.data.proxy.LocalStorage": [
  12985. "Ext.data.LocalStorageProxy"
  12986. ],
  12987. "Ext.fx.animation.Wipe": [
  12988. "Ext.fx.animation.WipeIn"
  12989. ],
  12990. "Ext.fx.layout.Card": [],
  12991. "Ext.TaskQueue": [],
  12992. "Ext.Label": [],
  12993. "Ext.util.translatable.CssTransform": [],
  12994. "Ext.viewport.Ios": [],
  12995. "Ext.Spacer": [],
  12996. "Ext.mixin.Selectable": [],
  12997. "Ext.draw.sprite.Image": [],
  12998. "Ext.data.proxy.Rest": [
  12999. "Ext.data.RestProxy"
  13000. ],
  13001. "Ext.Img": [],
  13002. "Ext.chart.series.sprite.Bar": [],
  13003. "Ext.log.writer.DocumentTitle": [],
  13004. "Ext.data.Error": [],
  13005. "Ext.util.Sorter": [],
  13006. "Ext.draw.gradient.Radial": [],
  13007. "Ext.layout.Abstract": [],
  13008. "Ext.device.notification.Abstract": [],
  13009. "Ext.log.filter.Filter": [],
  13010. "Ext.device.camera.Sencha": [],
  13011. "Ext.draw.sprite.Sprite": [],
  13012. "Ext.draw.Color": [],
  13013. "Ext.chart.series.Bar": [],
  13014. "Ext.field.Slider": [
  13015. "Ext.form.Slider"
  13016. ],
  13017. "Ext.field.Search": [
  13018. "Ext.form.Search"
  13019. ],
  13020. "Ext.chart.series.Scatter": [],
  13021. "Ext.device.Device": [],
  13022. "Ext.event.Dispatcher": [],
  13023. "Ext.data.Store": [],
  13024. "Ext.draw.modifier.Highlight": [],
  13025. "Ext.behavior.Translatable": [],
  13026. "Ext.direct.Manager": [
  13027. "Ext.Direct"
  13028. ],
  13029. "Ext.env.Browser": [],
  13030. "Ext.data.proxy.Proxy": [
  13031. "Ext.data.DataProxy",
  13032. "Ext.data.Proxy"
  13033. ],
  13034. "Ext.draw.modifier.Modifier": [],
  13035. "Ext.navigation.View": [
  13036. "Ext.NavigationView"
  13037. ],
  13038. "Ext.draw.modifier.Target": [],
  13039. "Ext.draw.sprite.AttributeDefinition": [],
  13040. "Ext.device.Notification": [],
  13041. "Ext.draw.Component": [],
  13042. "Ext.layout.VBox": [],
  13043. "Ext.slider.Thumb": [],
  13044. "Ext.MessageBox": [],
  13045. "Ext.ux.Faker": [],
  13046. "Ext.dataview.IndexBar": [
  13047. "Ext.IndexBar"
  13048. ],
  13049. "Ext.dataview.element.List": [],
  13050. "Ext.layout.FlexBox": [],
  13051. "Ext.field.Url": [
  13052. "Ext.form.Url"
  13053. ],
  13054. "Ext.draw.Solver": [],
  13055. "Ext.data.proxy.Memory": [
  13056. "Ext.data.MemoryProxy"
  13057. ],
  13058. "Ext.chart.axis.Time": [],
  13059. "Ext.layout.Card": [],
  13060. "Ext.ComponentQuery": [],
  13061. "Ext.chart.series.Pie3D": [],
  13062. "Ext.device.camera.Abstract": [],
  13063. "Ext.device.device.Sencha": [],
  13064. "Ext.scroll.View": [
  13065. "Ext.util.ScrollView"
  13066. ],
  13067. "Ext.draw.sprite.Rect": [],
  13068. "Ext.util.Region": [],
  13069. "Ext.field.Select": [
  13070. "Ext.form.Select"
  13071. ],
  13072. "Ext.draw.Draw": [],
  13073. "Ext.ItemCollection": [],
  13074. "Ext.log.formatter.Default": [],
  13075. "Ext.navigation.Bar": [],
  13076. "Ext.chart.axis.layout.CombineDuplicate": [],
  13077. "Ext.device.Geolocation": [],
  13078. "Ext.chart.SpaceFillingChart": [],
  13079. "Ext.data.proxy.SessionStorage": [
  13080. "Ext.data.SessionStorageProxy"
  13081. ],
  13082. "Ext.fx.easing.EaseIn": [],
  13083. "Ext.draw.sprite.AnimationParser": [],
  13084. "Ext.field.Password": [
  13085. "Ext.form.Password"
  13086. ],
  13087. "Ext.device.connection.Abstract": [],
  13088. "Ext.direct.Event": [],
  13089. "Ext.direct.RemotingMethod": [],
  13090. "Ext.Evented": [
  13091. "Ext.EventedBase"
  13092. ],
  13093. "Ext.carousel.Indicator": [
  13094. "Ext.Carousel.Indicator"
  13095. ],
  13096. "Ext.util.Collection": [],
  13097. "Ext.chart.interactions.ItemInfo": [],
  13098. "Ext.chart.MarkerHolder": [],
  13099. "Ext.carousel.Carousel": [
  13100. "Ext.Carousel"
  13101. ],
  13102. "Ext.Audio": [],
  13103. "Ext.device.Contacts": [],
  13104. "Ext.table.Table": [],
  13105. "Ext.draw.engine.SvgContext.Gradient": [],
  13106. "Ext.chart.axis.layout.Layout": [],
  13107. "Ext.data.Errors": [],
  13108. "Ext.field.Text": [
  13109. "Ext.form.Text"
  13110. ],
  13111. "Ext.field.TextAreaInput": [],
  13112. "Ext.field.DatePicker": [
  13113. "Ext.form.DatePicker"
  13114. ],
  13115. "Ext.draw.engine.Svg": [],
  13116. "Ext.event.recognizer.Tap": [],
  13117. "Ext.device.orientation.Abstract": [],
  13118. "Ext.AbstractManager": [],
  13119. "Ext.chart.series.Radar": [],
  13120. "Ext.chart.interactions.Abstract": [],
  13121. "Ext.scroll.indicator.CssTransform": [],
  13122. "Ext.util.PaintMonitor": [],
  13123. "Ext.direct.PollingProvider": [],
  13124. "Ext.device.notification.PhoneGap": [],
  13125. "Ext.data.writer.Xml": [
  13126. "Ext.data.XmlWriter"
  13127. ],
  13128. "Ext.event.recognizer.SingleTouch": [],
  13129. "Ext.draw.sprite.Instancing": [],
  13130. "Ext.event.publisher.ComponentDelegation": [],
  13131. "Ext.chart.axis.Numeric": [],
  13132. "Ext.field.Toggle": [
  13133. "Ext.form.Toggle"
  13134. ],
  13135. "Ext.fx.layout.card.ScrollReveal": [],
  13136. "Ext.data.Operation": [],
  13137. "Ext.fx.animation.Abstract": [],
  13138. "Ext.chart.interactions.Rotate": [],
  13139. "Ext.draw.engine.SvgContext": [],
  13140. "Ext.scroll.Scroller": [],
  13141. "Ext.util.SizeMonitor": [],
  13142. "Ext.event.ListenerStack": [],
  13143. "Ext.util.MixedCollection": []
  13144. });Ext.ClassManager.addNameAliasMappings({
  13145. "Ext.app.Profile": [],
  13146. "Ext.event.recognizer.MultiTouch": [],
  13147. "Ext.fx.Runner": [],
  13148. "Ext.chart.grid.CircularGrid": [
  13149. "grid.circular"
  13150. ],
  13151. "Ext.mixin.Templatable": [],
  13152. "Ext.event.recognizer.Pinch": [],
  13153. "Ext.util.Format": [],
  13154. "Ext.direct.JsonProvider": [
  13155. "direct.jsonprovider"
  13156. ],
  13157. "Ext.data.identifier.Simple": [
  13158. "data.identifier.simple"
  13159. ],
  13160. "Ext.dataview.DataView": [
  13161. "widget.dataview"
  13162. ],
  13163. "Ext.field.Hidden": [
  13164. "widget.hiddenfield"
  13165. ],
  13166. "Ext.env.Feature": [],
  13167. "Ext.field.Number": [
  13168. "widget.numberfield"
  13169. ],
  13170. "Ext.chart.series.CandleStick": [
  13171. "series.candlestick"
  13172. ],
  13173. "Ext.device.Connection": [],
  13174. "Ext.data.Model": [],
  13175. "Ext.data.reader.Reader": [],
  13176. "Ext.Sheet": [
  13177. "widget.sheet"
  13178. ],
  13179. "Ext.tab.Tab": [
  13180. "widget.tab"
  13181. ],
  13182. "Ext.chart.series.sprite.StackedCartesian": [],
  13183. "Ext.util.Grouper": [],
  13184. "Ext.util.translatable.CssPosition": [],
  13185. "Ext.util.paintmonitor.Abstract": [],
  13186. "Ext.direct.RemotingProvider": [
  13187. "direct.remotingprovider"
  13188. ],
  13189. "Ext.data.NodeInterface": [],
  13190. "Ext.env.OS": [],
  13191. "Ext.chart.interactions.PanZoom": [
  13192. "interaction.panzoom"
  13193. ],
  13194. "Ext.util.PositionMap": [],
  13195. "Ext.chart.series.ItemPublisher": [],
  13196. "Ext.util.Sortable": [],
  13197. "Ext.chart.series.sprite.AbstractRadial": [],
  13198. "Ext.fx.runner.Css": [],
  13199. "Ext.fx.runner.CssTransition": [],
  13200. "Ext.draw.Group": [],
  13201. "Ext.XTemplateCompiler": [],
  13202. "Ext.util.Wrapper": [],
  13203. "Ext.app.Router": [],
  13204. "Ext.direct.Transaction": [
  13205. "direct.transaction"
  13206. ],
  13207. "Ext.util.Offset": [],
  13208. "Ext.dom.Element": [
  13209. "widget.element"
  13210. ],
  13211. "Ext.device.device.Abstract": [],
  13212. "Ext.mixin.Mixin": [],
  13213. "Ext.fx.animation.FadeOut": [
  13214. "animation.fadeOut"
  13215. ],
  13216. "Ext.util.Geolocation": [],
  13217. "Ext.ComponentManager": [],
  13218. "Ext.util.sizemonitor.OverflowChange": [],
  13219. "Ext.event.publisher.ElementSize": [],
  13220. "Ext.tab.Bar": [
  13221. "widget.tabbar"
  13222. ],
  13223. "Ext.event.Dom": [],
  13224. "Ext.app.Application": [],
  13225. "Ext.dataview.List": [
  13226. "widget.list"
  13227. ],
  13228. "Ext.util.translatable.Dom": [],
  13229. "Ext.fx.layout.card.Scroll": [
  13230. "fx.layout.card.scroll"
  13231. ],
  13232. "Ext.draw.LimitedCache": [],
  13233. "Ext.device.geolocation.Sencha": [],
  13234. "Ext.dataview.ListItemHeader": [
  13235. "widget.listitemheader"
  13236. ],
  13237. "Ext.event.publisher.TouchGesture": [],
  13238. "Ext.data.SortTypes": [],
  13239. "Ext.device.contacts.Abstract": [],
  13240. "Ext.device.push.Sencha": [],
  13241. "Ext.fx.animation.WipeOut": [],
  13242. "Ext.slider.Slider": [
  13243. "widget.slider"
  13244. ],
  13245. "Ext.Component": [
  13246. "widget.component"
  13247. ],
  13248. "Ext.device.communicator.Default": [],
  13249. "Ext.fx.runner.CssAnimation": [],
  13250. "Ext.chart.axis.Axis": [
  13251. "widget.axis"
  13252. ],
  13253. "Ext.fx.animation.Cube": [
  13254. "animation.cube"
  13255. ],
  13256. "Ext.chart.Markers": [],
  13257. "Ext.chart.series.sprite.Radar": [
  13258. "sprite.radar"
  13259. ],
  13260. "Ext.device.device.Simulator": [],
  13261. "Ext.Ajax": [],
  13262. "Ext.dataview.component.ListItem": [
  13263. "widget.listitem"
  13264. ],
  13265. "Ext.util.Filter": [],
  13266. "Ext.layout.wrapper.Inner": [],
  13267. "Ext.draw.Animator": [],
  13268. "Ext.device.geolocation.Simulator": [],
  13269. "Ext.data.association.BelongsTo": [
  13270. "association.belongsto"
  13271. ],
  13272. "Ext.draw.Surface": [
  13273. "widget.surface"
  13274. ],
  13275. "Ext.dom.Query": [],
  13276. "Ext.scroll.indicator.ScrollPosition": [],
  13277. "Ext.field.Email": [
  13278. "widget.emailfield"
  13279. ],
  13280. "Ext.fx.layout.card.Abstract": [],
  13281. "Ext.event.Controller": [],
  13282. "Ext.dataview.component.Container": [],
  13283. "Ext.log.writer.Remote": [],
  13284. "Ext.fx.layout.card.Style": [],
  13285. "Ext.device.purchases.Sencha": [],
  13286. "Ext.chart.axis.segmenter.Segmenter": [],
  13287. "Ext.viewport.Android": [],
  13288. "Ext.log.formatter.Identity": [],
  13289. "Ext.chart.interactions.ItemHighlight": [
  13290. "interaction.itemhighlight"
  13291. ],
  13292. "Ext.picker.Picker": [
  13293. "widget.picker"
  13294. ],
  13295. "Ext.data.Batch": [],
  13296. "Ext.draw.modifier.Animation": [
  13297. "modifier.animation"
  13298. ],
  13299. "Ext.chart.AbstractChart": [],
  13300. "Ext.tab.Panel": [
  13301. "widget.tabpanel"
  13302. ],
  13303. "Ext.draw.Path": [],
  13304. "Ext.scroll.indicator.Throttled": [],
  13305. "Ext.fx.animation.SlideOut": [
  13306. "animation.slideOut"
  13307. ],
  13308. "Ext.device.connection.Sencha": [],
  13309. "Ext.fx.layout.card.Pop": [
  13310. "fx.layout.card.pop"
  13311. ],
  13312. "Ext.chart.axis.layout.Discrete": [
  13313. "axisLayout.discrete"
  13314. ],
  13315. "Ext.data.Field": [
  13316. "data.field"
  13317. ],
  13318. "Ext.chart.series.Gauge": [
  13319. "series.gauge"
  13320. ],
  13321. "Ext.data.StoreManager": [],
  13322. "Ext.fx.animation.PopOut": [
  13323. "animation.popOut"
  13324. ],
  13325. "Ext.chart.label.Callout": [],
  13326. "Ext.device.push.Abstract": [],
  13327. "Ext.util.DelayedTask": [],
  13328. "Ext.fx.easing.Momentum": [],
  13329. "Ext.fx.easing.Abstract": [],
  13330. "Ext.Title": [
  13331. "widget.title"
  13332. ],
  13333. "Ext.event.recognizer.Drag": [],
  13334. "Ext.field.TextArea": [
  13335. "widget.textareafield"
  13336. ],
  13337. "Ext.fx.Easing": [],
  13338. "Ext.chart.series.sprite.Scatter": [
  13339. "sprite.scatterSeries"
  13340. ],
  13341. "Ext.picker.Date": [
  13342. "widget.datepicker"
  13343. ],
  13344. "Ext.data.reader.Array": [
  13345. "reader.array"
  13346. ],
  13347. "Ext.data.proxy.JsonP": [
  13348. "proxy.jsonp",
  13349. "proxy.scripttag"
  13350. ],
  13351. "Ext.device.communicator.Android": [],
  13352. "Ext.chart.series.Area": [
  13353. "series.area"
  13354. ],
  13355. "Ext.device.device.PhoneGap": [],
  13356. "Ext.field.Checkbox": [
  13357. "widget.checkboxfield"
  13358. ],
  13359. "Ext.chart.Legend": [
  13360. "widget.legend"
  13361. ],
  13362. "Ext.Media": [
  13363. "widget.media"
  13364. ],
  13365. "Ext.TitleBar": [
  13366. "widget.titlebar"
  13367. ],
  13368. "Ext.chart.interactions.RotatePie3D": [
  13369. "interaction.rotatePie3d"
  13370. ],
  13371. "Ext.draw.gradient.Linear": [],
  13372. "Ext.util.TapRepeater": [],
  13373. "Ext.event.Touch": [],
  13374. "Ext.mixin.Bindable": [],
  13375. "Ext.data.proxy.Server": [
  13376. "proxy.server"
  13377. ],
  13378. "Ext.chart.series.Cartesian": [],
  13379. "Ext.util.sizemonitor.Scroll": [],
  13380. "Ext.data.ResultSet": [],
  13381. "Ext.data.association.HasMany": [
  13382. "association.hasmany"
  13383. ],
  13384. "Ext.draw.TimingFunctions": [],
  13385. "Ext.draw.engine.Canvas": [],
  13386. "Ext.data.proxy.Ajax": [
  13387. "proxy.ajax"
  13388. ],
  13389. "Ext.layout.Default": [
  13390. "layout.default",
  13391. "layout.auto"
  13392. ],
  13393. "Ext.fx.animation.Fade": [
  13394. "animation.fade",
  13395. "animation.fadeIn"
  13396. ],
  13397. "Ext.util.paintmonitor.CssAnimation": [],
  13398. "Ext.data.writer.Writer": [
  13399. "writer.base"
  13400. ],
  13401. "Ext.event.recognizer.Recognizer": [],
  13402. "Ext.form.FieldSet": [
  13403. "widget.fieldset"
  13404. ],
  13405. "Ext.scroll.Indicator": [],
  13406. "Ext.XTemplateParser": [],
  13407. "Ext.behavior.Scrollable": [],
  13408. "Ext.chart.series.sprite.CandleStick": [
  13409. "sprite.candlestickSeries"
  13410. ],
  13411. "Ext.data.JsonP": [],
  13412. "Ext.device.connection.PhoneGap": [],
  13413. "Ext.event.publisher.Dom": [],
  13414. "Ext.fx.layout.card.Fade": [
  13415. "fx.layout.card.fade"
  13416. ],
  13417. "Ext.app.Controller": [],
  13418. "Ext.fx.State": [],
  13419. "Ext.layout.wrapper.BoxDock": [],
  13420. "Ext.chart.series.sprite.Pie3DPart": [
  13421. "sprite.pie3dPart"
  13422. ],
  13423. "Ext.viewport.Default": [
  13424. "widget.viewport"
  13425. ],
  13426. "Ext.layout.HBox": [
  13427. "layout.hbox"
  13428. ],
  13429. "Ext.ux.auth.model.Session": [],
  13430. "Ext.scroll.indicator.Default": [],
  13431. "Ext.data.ModelManager": [],
  13432. "Ext.data.Validations": [],
  13433. "Ext.util.translatable.Abstract": [],
  13434. "Ext.scroll.indicator.Abstract": [],
  13435. "Ext.Button": [
  13436. "widget.button"
  13437. ],
  13438. "Ext.field.Radio": [
  13439. "widget.radiofield"
  13440. ],
  13441. "Ext.util.HashMap": [],
  13442. "Ext.field.Input": [
  13443. "widget.input"
  13444. ],
  13445. "Ext.device.Camera": [],
  13446. "Ext.mixin.Filterable": [],
  13447. "Ext.draw.TextMeasurer": [],
  13448. "Ext.dataview.element.Container": [],
  13449. "Ext.chart.series.sprite.PieSlice": [
  13450. "sprite.pieslice"
  13451. ],
  13452. "Ext.data.Connection": [],
  13453. "Ext.direct.ExceptionEvent": [
  13454. "direct.exception"
  13455. ],
  13456. "Ext.Panel": [
  13457. "widget.panel"
  13458. ],
  13459. "Ext.data.association.HasOne": [
  13460. "association.hasone"
  13461. ],
  13462. "Ext.device.geolocation.Abstract": [],
  13463. "Ext.ActionSheet": [
  13464. "widget.actionsheet"
  13465. ],
  13466. "Ext.layout.Box": [
  13467. "layout.tablebox"
  13468. ],
  13469. "Ext.bb.CrossCut": [
  13470. "widget.crosscut"
  13471. ],
  13472. "Ext.Video": [
  13473. "widget.video"
  13474. ],
  13475. "Ext.ux.auth.Session": [],
  13476. "Ext.chart.series.Line": [
  13477. "series.line"
  13478. ],
  13479. "Ext.fx.layout.card.Cube": [
  13480. "fx.layout.card.cube"
  13481. ],
  13482. "Ext.event.recognizer.HorizontalSwipe": [],
  13483. "Ext.data.writer.Json": [
  13484. "writer.json"
  13485. ],
  13486. "Ext.layout.Fit": [
  13487. "layout.fit"
  13488. ],
  13489. "Ext.fx.animation.Slide": [
  13490. "animation.slide",
  13491. "animation.slideIn"
  13492. ],
  13493. "Ext.device.Purchases.Purchase": [],
  13494. "Ext.table.Row": [
  13495. "widget.tablerow"
  13496. ],
  13497. "Ext.log.formatter.Formatter": [],
  13498. "Ext.Container": [
  13499. "widget.container"
  13500. ],
  13501. "Ext.fx.animation.Pop": [
  13502. "animation.pop",
  13503. "animation.popIn"
  13504. ],
  13505. "Ext.draw.sprite.Circle": [
  13506. "sprite.circle"
  13507. ],
  13508. "Ext.fx.layout.card.Reveal": [
  13509. "fx.layout.card.reveal"
  13510. ],
  13511. "Ext.fx.layout.card.Cover": [
  13512. "fx.layout.card.cover"
  13513. ],
  13514. "Ext.log.Base": [],
  13515. "Ext.data.reader.Xml": [
  13516. "reader.xml"
  13517. ],
  13518. "Ext.event.publisher.ElementPaint": [],
  13519. "Ext.chart.axis.Category": [
  13520. "axis.category"
  13521. ],
  13522. "Ext.data.reader.Json": [
  13523. "reader.json"
  13524. ],
  13525. "Ext.Decorator": [],
  13526. "Ext.data.TreeStore": [
  13527. "store.tree"
  13528. ],
  13529. "Ext.device.Purchases": [],
  13530. "Ext.device.orientation.HTML5": [],
  13531. "Ext.draw.gradient.Gradient": [],
  13532. "Ext.event.recognizer.DoubleTap": [],
  13533. "Ext.log.Logger": [],
  13534. "Ext.picker.Slot": [
  13535. "widget.pickerslot"
  13536. ],
  13537. "Ext.device.notification.Simulator": [],
  13538. "Ext.field.Field": [
  13539. "widget.field"
  13540. ],
  13541. "Ext.log.filter.Priority": [],
  13542. "Ext.util.sizemonitor.Abstract": [],
  13543. "Ext.chart.series.sprite.Polar": [],
  13544. "Ext.util.paintmonitor.OverflowChange": [],
  13545. "Ext.util.LineSegment": [],
  13546. "Ext.SegmentedButton": [
  13547. "widget.segmentedbutton"
  13548. ],
  13549. "Ext.Sortable": [],
  13550. "Ext.fx.easing.Linear": [
  13551. "easing.linear"
  13552. ],
  13553. "Ext.chart.series.sprite.Aggregative": [],
  13554. "Ext.dom.CompositeElement": [],
  13555. "Ext.data.identifier.Uuid": [
  13556. "data.identifier.uuid"
  13557. ],
  13558. "Ext.data.proxy.Client": [],
  13559. "Ext.fx.easing.Bounce": [],
  13560. "Ext.data.Types": [],
  13561. "Ext.chart.series.sprite.Cartesian": [],
  13562. "Ext.app.Action": [],
  13563. "Ext.util.Translatable": [],
  13564. "Ext.device.camera.PhoneGap": [],
  13565. "Ext.draw.sprite.Path": [
  13566. "sprite.path"
  13567. ],
  13568. "Ext.LoadMask": [
  13569. "widget.loadmask"
  13570. ],
  13571. "Ext.data.association.Association": [],
  13572. "Ext.chart.axis.sprite.Axis": [],
  13573. "Ext.behavior.Draggable": [],
  13574. "Ext.chart.grid.RadialGrid": [
  13575. "grid.radial"
  13576. ],
  13577. "Ext.util.TranslatableGroup": [],
  13578. "Ext.fx.Animation": [],
  13579. "Ext.draw.sprite.Ellipse": [
  13580. "sprite.ellipse"
  13581. ],
  13582. "Ext.util.Inflector": [],
  13583. "Ext.Map": [
  13584. "widget.map"
  13585. ],
  13586. "Ext.XTemplate": [],
  13587. "Ext.data.NodeStore": [
  13588. "store.node"
  13589. ],
  13590. "Ext.draw.sprite.AttributeParser": [],
  13591. "Ext.form.Panel": [
  13592. "widget.formpanel"
  13593. ],
  13594. "Ext.chart.series.Series": [],
  13595. "Ext.data.Request": [],
  13596. "Ext.draw.sprite.Text": [
  13597. "sprite.text"
  13598. ],
  13599. "Ext.layout.Float": [
  13600. "layout.float"
  13601. ],
  13602. "Ext.dom.CompositeElementLite": [],
  13603. "Ext.dataview.component.DataItem": [
  13604. "widget.dataitem"
  13605. ],
  13606. "Ext.chart.CartesianChart": [
  13607. "widget.chart",
  13608. "Ext.chart.Chart"
  13609. ],
  13610. "Ext.data.proxy.WebStorage": [],
  13611. "Ext.log.writer.Writer": [],
  13612. "Ext.device.Communicator": [],
  13613. "Ext.fx.animation.Flip": [
  13614. "animation.flip"
  13615. ],
  13616. "Ext.util.Point": [],
  13617. "Ext.chart.series.StackedCartesian": [],
  13618. "Ext.fx.layout.card.Slide": [
  13619. "fx.layout.card.slide"
  13620. ],
  13621. "Ext.Anim": [],
  13622. "Ext.data.DirectStore": [
  13623. "store.direct"
  13624. ],
  13625. "Ext.dataview.NestedList": [
  13626. "widget.nestedlist"
  13627. ],
  13628. "Ext.app.Route": [],
  13629. "Ext.device.connection.Simulator": [],
  13630. "Ext.chart.PolarChart": [
  13631. "widget.polar"
  13632. ],
  13633. "Ext.event.publisher.ComponentSize": [],
  13634. "Ext.slider.Toggle": [],
  13635. "Ext.data.identifier.Sequential": [
  13636. "data.identifier.sequential"
  13637. ],
  13638. "Ext.AbstractComponent": [],
  13639. "Ext.Template": [],
  13640. "Ext.device.Push": [],
  13641. "Ext.fx.easing.BoundMomentum": [],
  13642. "Ext.viewport.Viewport": [],
  13643. "Ext.event.recognizer.VerticalSwipe": [],
  13644. "Ext.chart.series.Polar": [],
  13645. "Ext.event.Event": [],
  13646. "Ext.behavior.Behavior": [],
  13647. "Ext.chart.grid.VerticalGrid": [
  13648. "grid.vertical"
  13649. ],
  13650. "Ext.chart.label.Label": [],
  13651. "Ext.draw.sprite.EllipticalArc": [
  13652. "sprite.ellipticalArc"
  13653. ],
  13654. "Ext.fx.easing.EaseOut": [
  13655. "easing.ease-out"
  13656. ],
  13657. "Ext.Toolbar": [
  13658. "widget.toolbar"
  13659. ],
  13660. "Ext.event.recognizer.LongPress": [],
  13661. "Ext.device.notification.Sencha": [],
  13662. "Ext.chart.series.sprite.Line": [
  13663. "sprite.lineSeries"
  13664. ],
  13665. "Ext.data.ArrayStore": [
  13666. "store.array"
  13667. ],
  13668. "Ext.data.proxy.SQL": [
  13669. "proxy.sql"
  13670. ],
  13671. "Ext.event.recognizer.Rotate": [],
  13672. "Ext.mixin.Sortable": [],
  13673. "Ext.fx.layout.card.Flip": [
  13674. "fx.layout.card.flip"
  13675. ],
  13676. "Ext.chart.interactions.CrossZoom": [
  13677. "interaction.crosszoom"
  13678. ],
  13679. "Ext.event.publisher.ComponentPaint": [],
  13680. "Ext.util.TranslatableList": [],
  13681. "Ext.carousel.Item": [],
  13682. "Ext.event.recognizer.Swipe": [],
  13683. "Ext.mixin.Identifiable": [],
  13684. "Ext.util.translatable.ScrollPosition": [],
  13685. "Ext.device.camera.Simulator": [],
  13686. "Ext.chart.series.sprite.Area": [
  13687. "sprite.areaSeries"
  13688. ],
  13689. "Ext.event.recognizer.Touch": [],
  13690. "Ext.plugin.ListPaging": [
  13691. "plugin.listpaging"
  13692. ],
  13693. "Ext.draw.sprite.Sector": [
  13694. "sprite.sector"
  13695. ],
  13696. "Ext.chart.axis.segmenter.Names": [
  13697. "segmenter.names"
  13698. ],
  13699. "Ext.mixin.Observable": [],
  13700. "Ext.carousel.Infinite": [],
  13701. "Ext.draw.Matrix": [],
  13702. "Ext.Mask": [
  13703. "widget.mask"
  13704. ],
  13705. "Ext.event.publisher.Publisher": [],
  13706. "Ext.layout.wrapper.Dock": [],
  13707. "Ext.app.History": [],
  13708. "Ext.data.proxy.Direct": [
  13709. "proxy.direct"
  13710. ],
  13711. "Ext.chart.axis.layout.Continuous": [
  13712. "axisLayout.continuous"
  13713. ],
  13714. "Ext.table.Cell": [
  13715. "widget.tablecell"
  13716. ],
  13717. "Ext.fx.layout.card.ScrollCover": [
  13718. "fx.layout.card.scrollcover"
  13719. ],
  13720. "Ext.device.orientation.Sencha": [],
  13721. "Ext.util.Droppable": [],
  13722. "Ext.draw.sprite.Composite": [
  13723. "sprite.composite"
  13724. ],
  13725. "Ext.chart.series.Pie": [
  13726. "series.pie"
  13727. ],
  13728. "Ext.device.Purchases.Product": [],
  13729. "Ext.device.Orientation": [],
  13730. "Ext.direct.Provider": [
  13731. "direct.provider"
  13732. ],
  13733. "Ext.draw.sprite.Arc": [
  13734. "sprite.arc"
  13735. ],
  13736. "Ext.chart.axis.segmenter.Time": [
  13737. "segmenter.time"
  13738. ],
  13739. "Ext.util.Draggable": [],
  13740. "Ext.device.contacts.Sencha": [],
  13741. "Ext.dom.Helper": [],
  13742. "Ext.chart.grid.HorizontalGrid": [
  13743. "grid.horizontal"
  13744. ],
  13745. "Ext.mixin.Traversable": [],
  13746. "Ext.util.AbstractMixedCollection": [],
  13747. "Ext.data.JsonStore": [
  13748. "store.json"
  13749. ],
  13750. "Ext.draw.SegmentTree": [],
  13751. "Ext.direct.RemotingEvent": [
  13752. "direct.rpc"
  13753. ],
  13754. "Ext.plugin.PullRefresh": [
  13755. "plugin.pullrefresh"
  13756. ],
  13757. "Ext.log.writer.Console": [],
  13758. "Ext.field.Spinner": [
  13759. "widget.spinnerfield"
  13760. ],
  13761. "Ext.chart.axis.segmenter.Numeric": [
  13762. "segmenter.numeric"
  13763. ],
  13764. "Ext.data.proxy.LocalStorage": [
  13765. "proxy.localstorage"
  13766. ],
  13767. "Ext.fx.animation.Wipe": [],
  13768. "Ext.fx.layout.Card": [],
  13769. "Ext.TaskQueue": [],
  13770. "Ext.Label": [
  13771. "widget.label"
  13772. ],
  13773. "Ext.util.translatable.CssTransform": [],
  13774. "Ext.viewport.Ios": [],
  13775. "Ext.Spacer": [
  13776. "widget.spacer"
  13777. ],
  13778. "Ext.mixin.Selectable": [],
  13779. "Ext.draw.sprite.Image": [
  13780. "sprite.image"
  13781. ],
  13782. "Ext.data.proxy.Rest": [
  13783. "proxy.rest"
  13784. ],
  13785. "Ext.Img": [
  13786. "widget.img",
  13787. "widget.image"
  13788. ],
  13789. "Ext.chart.series.sprite.Bar": [
  13790. "sprite.barSeries"
  13791. ],
  13792. "Ext.log.writer.DocumentTitle": [],
  13793. "Ext.data.Error": [],
  13794. "Ext.util.Sorter": [],
  13795. "Ext.draw.gradient.Radial": [],
  13796. "Ext.layout.Abstract": [],
  13797. "Ext.device.notification.Abstract": [],
  13798. "Ext.log.filter.Filter": [],
  13799. "Ext.device.camera.Sencha": [],
  13800. "Ext.draw.sprite.Sprite": [
  13801. "sprite.sprite"
  13802. ],
  13803. "Ext.draw.Color": [],
  13804. "Ext.chart.series.Bar": [
  13805. "series.bar"
  13806. ],
  13807. "Ext.field.Slider": [
  13808. "widget.sliderfield"
  13809. ],
  13810. "Ext.field.Search": [
  13811. "widget.searchfield"
  13812. ],
  13813. "Ext.chart.series.Scatter": [
  13814. "series.scatter"
  13815. ],
  13816. "Ext.device.Device": [],
  13817. "Ext.event.Dispatcher": [],
  13818. "Ext.data.Store": [
  13819. "store.store"
  13820. ],
  13821. "Ext.draw.modifier.Highlight": [
  13822. "modifier.highlight"
  13823. ],
  13824. "Ext.behavior.Translatable": [],
  13825. "Ext.direct.Manager": [],
  13826. "Ext.env.Browser": [],
  13827. "Ext.data.proxy.Proxy": [
  13828. "proxy.proxy"
  13829. ],
  13830. "Ext.draw.modifier.Modifier": [],
  13831. "Ext.navigation.View": [
  13832. "widget.navigationview"
  13833. ],
  13834. "Ext.draw.modifier.Target": [
  13835. "modifier.target"
  13836. ],
  13837. "Ext.draw.sprite.AttributeDefinition": [],
  13838. "Ext.device.Notification": [],
  13839. "Ext.draw.Component": [
  13840. "widget.draw"
  13841. ],
  13842. "Ext.layout.VBox": [
  13843. "layout.vbox"
  13844. ],
  13845. "Ext.slider.Thumb": [
  13846. "widget.thumb"
  13847. ],
  13848. "Ext.MessageBox": [],
  13849. "Ext.ux.Faker": [],
  13850. "Ext.dataview.IndexBar": [],
  13851. "Ext.dataview.element.List": [],
  13852. "Ext.layout.FlexBox": [
  13853. "layout.box"
  13854. ],
  13855. "Ext.field.Url": [
  13856. "widget.urlfield"
  13857. ],
  13858. "Ext.draw.Solver": [],
  13859. "Ext.data.proxy.Memory": [
  13860. "proxy.memory"
  13861. ],
  13862. "Ext.chart.axis.Time": [
  13863. "axis.time"
  13864. ],
  13865. "Ext.layout.Card": [
  13866. "layout.card"
  13867. ],
  13868. "Ext.ComponentQuery": [],
  13869. "Ext.chart.series.Pie3D": [
  13870. "series.pie3d"
  13871. ],
  13872. "Ext.device.camera.Abstract": [],
  13873. "Ext.device.device.Sencha": [],
  13874. "Ext.scroll.View": [],
  13875. "Ext.draw.sprite.Rect": [
  13876. "sprite.rect"
  13877. ],
  13878. "Ext.util.Region": [],
  13879. "Ext.field.Select": [
  13880. "widget.selectfield"
  13881. ],
  13882. "Ext.draw.Draw": [],
  13883. "Ext.ItemCollection": [],
  13884. "Ext.log.formatter.Default": [],
  13885. "Ext.navigation.Bar": [],
  13886. "Ext.chart.axis.layout.CombineDuplicate": [
  13887. "axisLayout.combineDuplicate"
  13888. ],
  13889. "Ext.device.Geolocation": [],
  13890. "Ext.chart.SpaceFillingChart": [
  13891. "widget.spacefilling"
  13892. ],
  13893. "Ext.data.proxy.SessionStorage": [
  13894. "proxy.sessionstorage"
  13895. ],
  13896. "Ext.fx.easing.EaseIn": [
  13897. "easing.ease-in"
  13898. ],
  13899. "Ext.draw.sprite.AnimationParser": [],
  13900. "Ext.field.Password": [
  13901. "widget.passwordfield"
  13902. ],
  13903. "Ext.device.connection.Abstract": [],
  13904. "Ext.direct.Event": [
  13905. "direct.event"
  13906. ],
  13907. "Ext.direct.RemotingMethod": [],
  13908. "Ext.Evented": [],
  13909. "Ext.carousel.Indicator": [
  13910. "widget.carouselindicator"
  13911. ],
  13912. "Ext.util.Collection": [],
  13913. "Ext.chart.interactions.ItemInfo": [
  13914. "interaction.iteminfo"
  13915. ],
  13916. "Ext.chart.MarkerHolder": [],
  13917. "Ext.carousel.Carousel": [
  13918. "widget.carousel"
  13919. ],
  13920. "Ext.Audio": [
  13921. "widget.audio"
  13922. ],
  13923. "Ext.device.Contacts": [],
  13924. "Ext.table.Table": [
  13925. "widget.table"
  13926. ],
  13927. "Ext.draw.engine.SvgContext.Gradient": [],
  13928. "Ext.chart.axis.layout.Layout": [],
  13929. "Ext.data.Errors": [],
  13930. "Ext.field.Text": [
  13931. "widget.textfield"
  13932. ],
  13933. "Ext.field.TextAreaInput": [
  13934. "widget.textareainput"
  13935. ],
  13936. "Ext.field.DatePicker": [
  13937. "widget.datepickerfield"
  13938. ],
  13939. "Ext.draw.engine.Svg": [],
  13940. "Ext.event.recognizer.Tap": [],
  13941. "Ext.device.orientation.Abstract": [],
  13942. "Ext.AbstractManager": [],
  13943. "Ext.chart.series.Radar": [
  13944. "series.radar"
  13945. ],
  13946. "Ext.chart.interactions.Abstract": [
  13947. "widget.interaction"
  13948. ],
  13949. "Ext.scroll.indicator.CssTransform": [],
  13950. "Ext.util.PaintMonitor": [],
  13951. "Ext.direct.PollingProvider": [
  13952. "direct.pollingprovider"
  13953. ],
  13954. "Ext.device.notification.PhoneGap": [],
  13955. "Ext.data.writer.Xml": [
  13956. "writer.xml"
  13957. ],
  13958. "Ext.event.recognizer.SingleTouch": [],
  13959. "Ext.draw.sprite.Instancing": [
  13960. "sprite.instancing"
  13961. ],
  13962. "Ext.event.publisher.ComponentDelegation": [],
  13963. "Ext.chart.axis.Numeric": [
  13964. "axis.numeric"
  13965. ],
  13966. "Ext.field.Toggle": [
  13967. "widget.togglefield"
  13968. ],
  13969. "Ext.fx.layout.card.ScrollReveal": [
  13970. "fx.layout.card.scrollreveal"
  13971. ],
  13972. "Ext.data.Operation": [],
  13973. "Ext.fx.animation.Abstract": [],
  13974. "Ext.chart.interactions.Rotate": [
  13975. "interaction.rotate"
  13976. ],
  13977. "Ext.draw.engine.SvgContext": [],
  13978. "Ext.scroll.Scroller": [],
  13979. "Ext.util.SizeMonitor": [],
  13980. "Ext.event.ListenerStack": [],
  13981. "Ext.util.MixedCollection": []
  13982. });