1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624 |
- (function(){
- /*!*************************************************************
- *
- * Firebug Lite 1.3.2
- *
- * Copyright (c) 2007, Parakey Inc.
- * Released under BSD license.
- * More information: http://getfirebug.com/firebuglite
- *
- **************************************************************/
- /*!
- * CSS selectors powered by:
- *
- * Sizzle CSS Selector Engine - v1.0
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
- /** @namespace describe lib */
- var FBL = {};
- /** @name ns @namespace */
- ( /** @scope ns-lib @this FBL */ function() {
- // ************************************************************************************************
- // ************************************************************************************************
- // Constants
- var productionDir = "http://getfirebug.com/releases/lite/";
- var bookmarkletVersion = 4;
- // ************************************************************************************************
- var reNotWhitespace = /[^\s]/;
- var reSplitFile = /:\/{1,3}(.*?)\/([^\/]*?)\/?($|\?.*)/;
- // Globals
- this.reJavascript = /\s*javascript:\s*(.*)/;
- this.reChrome = /chrome:\/\/([^\/]*)\//;
- this.reFile = /file:\/\/([^\/]*)\//;
- // ************************************************************************************************
- // properties
- var userAgent = navigator.userAgent.toLowerCase();
- this.isFirefox = /firefox/.test(userAgent);
- this.isOpera = /opera/.test(userAgent);
- this.isSafari = /webkit/.test(userAgent);
- this.isIE = /msie/.test(userAgent) && !/opera/.test(userAgent);
- this.isIE6 = /msie 6/i.test(navigator.appVersion);
- this.browserVersion = (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1];
- this.isIElt8 = this.isIE && (this.browserVersion-0 < 8);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.NS = null;
- this.pixelsPerInch = null;
- // ************************************************************************************************
- // Namespaces
- var namespaces = [];
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.ns = function(fn)
- {
- var ns = {};
- namespaces.push(fn, ns);
- return ns;
- };
- var FBTrace = null;
- this.initialize = function()
- {
- // Firebug Lite is already running in persistent mode so we just quit
- if (window.firebug && firebug.firebuglite || window.console && console.firebuglite)
- return;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // initialize environment
- // point the FBTrace object to the local variable
- if (FBL.FBTrace)
- FBTrace = FBL.FBTrace;
- else
- FBTrace = FBL.FBTrace = {};
- FBL.Ajax.initialize();
- // check if the actual window is a persisted chrome context
- var isChromeContext = window.Firebug && typeof window.Firebug.SharedEnv == "object";
- // chrome context of the persistent application
- if (isChromeContext)
- {
- // TODO: xxxpedro persist - make a better synchronization
- sharedEnv = window.Firebug.SharedEnv;
- delete window.Firebug.SharedEnv;
- FBL.Env = sharedEnv;
- FBL.Env.isChromeContext = true;
- FBTrace.messageQueue = FBL.Env.traceMessageQueue;
- }
- // non-persistent application
- else
- {
- FBL.NS = document.documentElement.namespaceURI;
- FBL.Env.browser = window;
- FBL.Env.destroy = destroyEnvironment;
- if (document.documentElement.getAttribute("debug") == "true")
- FBL.Env.Options.startOpened = true;
- // find the URL location of the loaded application
- findLocation();
- // TODO: get preferences here...
- var prefs = eval("(" + FBL.readCookie("FirebugLite") + ")");
- if (prefs)
- {
- FBL.Env.Options.startOpened = prefs.startOpened;
- FBL.Env.Options.enableTrace = prefs.enableTrace;
- FBL.Env.Options.enablePersistent = prefs.enablePersistent;
- FBL.Env.Options.disableXHRListener = prefs.disableXHRListener;
- }
- if (FBL.isFirefox &&
- typeof FBL.Env.browser.console == "object" &&
- FBL.Env.browser.console.firebug &&
- FBL.Env.Options.disableWhenFirebugActive)
- return;
- }
- // exposes the FBL to the global namespace when in debug mode
- if (FBL.Env.isDebugMode)
- {
- FBL.Env.browser.FBL = FBL;
- }
- // check browser compatibilities
- this.isQuiksMode = FBL.Env.browser.document.compatMode == "BackCompat";
- this.isIEQuiksMode = this.isIE && this.isQuiksMode;
- this.isIEStantandMode = this.isIE && !this.isQuiksMode;
- this.noFixedPosition = this.isIE6 || this.isIEQuiksMode;
- // after creating/synchronizing the environment, initialize the FBTrace module
- if (FBL.Env.Options.enableTrace) FBTrace.initialize();
- if (FBTrace.DBG_INITIALIZE && isChromeContext) FBTrace.sysout("FBL.initialize - persistent application", "initialize chrome context");
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // initialize namespaces
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FBL.initialize", namespaces.length/2+" namespaces BEGIN");
- for (var i = 0; i < namespaces.length; i += 2)
- {
- var fn = namespaces[i];
- var ns = namespaces[i+1];
- fn.apply(ns);
- }
- if (FBTrace.DBG_INITIALIZE) {
- FBTrace.sysout("FBL.initialize", namespaces.length/2+" namespaces END");
- FBTrace.sysout("FBL waitForDocument", "waiting document load");
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // finish environment initialization
- FBL.Firebug.loadPrefs(prefs);
- if (FBL.Env.Options.enablePersistent)
- {
- // TODO: xxxpedro persist - make a better synchronization
- if (isChromeContext)
- {
- FBL.FirebugChrome.clone(FBL.Env.FirebugChrome);
- }
- else
- {
- FBL.Env.FirebugChrome = FBL.FirebugChrome;
- FBL.Env.traceMessageQueue = FBTrace.messageQueue;
- }
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // wait document load
- waitForDocument();
- };
- var waitForDocument = function waitForDocument()
- {
- // document.body not available in XML+XSL documents in Firefox
- var doc = FBL.Env.browser.document;
- var body = doc.getElementsByTagName("body")[0];
- if (body)
- {
- calculatePixelsPerInch(doc, body);
- onDocumentLoad();
- }
- else
- setTimeout(waitForDocument, 50);
- };
- var onDocumentLoad = function onDocumentLoad()
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FBL onDocumentLoad", "document loaded");
- // fix IE6 problem with cache of background images, causing a lot of flickering
- if (FBL.isIE6)
- fixIE6BackgroundImageCache();
- // chrome context of the persistent application
- if (FBL.Env.Options.enablePersistent && FBL.Env.isChromeContext)
- {
- // finally, start the application in the chrome context
- FBL.Firebug.initialize();
- // if is not development mode, remove the shared environment cache object
- // used to synchronize the both persistent contexts
- if (!FBL.Env.isDevelopmentMode)
- {
- sharedEnv.destroy();
- sharedEnv = null;
- }
- }
- // non-persistent application
- else
- {
- FBL.FirebugChrome.create();
- }
- };
- // ************************************************************************************************
- // Env
- var sharedEnv;
- this.Env =
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Env Options (will be transported to Firebug options)
- Options:
- {
- saveCookies: false,
- saveWindowPosition: false,
- saveCommandLineHistory: false,
- startOpened: false,
- startInNewWindow: false,
- showIconWhenHidden: true,
- overrideConsole: true,
- ignoreFirebugElements: true,
- disableWhenFirebugActive: true,
- disableXHRListener: false,
- enableTrace: false,
- enablePersistent: false
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Library location
- Location:
- {
- sourceDir: null,
- baseDir: null,
- skinDir: null,
- skin: null,
- app: null
- },
- skin: "xp",
- useLocalSkin: false,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Env states
- isDevelopmentMode: false,
- isDebugMode: false,
- isChromeContext: false,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Env references
- browser: null,
- chrome: null
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var destroyEnvironment = function destroyEnvironment()
- {
- setTimeout(function()
- {
- FBL = null;
- }, 100);
- };
- // ************************************************************************************************
- // Library location
- var findLocation = function findLocation()
- {
- var reFirebugFile = /(firebug-lite(?:-\w+)?(?:\.js|\.jgz))(?:#(.+))?$/;
- var rePath = /^(.*\/)/;
- var reProtocol = /^\w+:\/\//;
- var path = null;
- var doc = document;
- // Firebug Lite 1.3.0 bookmarklet identification
- var script = doc.getElementById("FirebugLite");
- if (script)
- {
- file = reFirebugFile.exec(script.src);
- var version = script.getAttribute("FirebugLite");
- var number = version ? parseInt(version) : 0;
- if (!version || !number || number < bookmarkletVersion)
- {
- FBL.Env.bookmarkletOutdated = true;
- }
- }
- else
- {
- for(var i=0, s=doc.getElementsByTagName("script"), si; si=s[i]; i++)
- {
- var file = null;
- if ( si.nodeName.toLowerCase() == "script" && (file = reFirebugFile.exec(si.src)) )
- {
- script = si;
- break;
- }
- }
- }
- if (script)
- script.firebugIgnore = true;
- if (file)
- {
- var fileName = file[1];
- var fileOptions = file[2];
- // absolute path
- if (reProtocol.test(script.src)) {
- path = rePath.exec(script.src)[1];
- }
- // relative path
- else
- {
- var r = rePath.exec(script.src);
- var src = r ? r[1] : script.src;
- var backDir = /^((?:\.\.\/)+)(.*)/.exec(src);
- var reLastDir = /^(.*\/)[^\/]+\/$/;
- path = rePath.exec(location.href)[1];
- // "../some/path"
- if (backDir)
- {
- var j = backDir[1].length/3;
- var p;
- while (j-- > 0)
- path = reLastDir.exec(path)[1];
- path += backDir[2];
- }
- else if(src.indexOf("/") != -1)
- {
- // "./some/path"
- if(/^\.\/./.test(src))
- {
- path += src.substring(2);
- }
- // "/some/path"
- else if(/^\/./.test(src))
- {
- var domain = /^(\w+:\/\/[^\/]+)/.exec(path);
- path = domain[1] + src;
- }
- // "some/path"
- else
- {
- path += src;
- }
- }
- }
- }
- FBL.Env.isChromeExtension = script && script.getAttribute("extension") == "Chrome";
- if (FBL.Env.isChromeExtension)
- {
- path = productionDir;
- FBL.Env.bookmarkletOutdated = false;
- script = {innerHTML: "{showIconWhenHidden:false}"};
- }
- var m = path && path.match(/([^\/]+)\/$/) || null;
- if (path && m)
- {
- var Env = FBL.Env;
- // Always use the local skin when running in the same domain
- // See Issue 3554: Firebug Lite should use local images when loaded locally
- Env.useLocalSkin = path.indexOf(location.protocol + "//" + location.host + "/") == 0;
- // detecting development and debug modes via file name
- if (fileName == "firebug-lite-dev.js")
- {
- Env.isDevelopmentMode = true;
- Env.isDebugMode = true;
- }
- else if (fileName == "firebug-lite-debug.js")
- {
- Env.isDebugMode = true;
- }
- // process the <html debug="true">
- if (Env.browser.document.documentElement.getAttribute("debug") == "true")
- {
- Env.Options.startOpened = true;
- }
- // process the Script URL Options
- if (fileOptions)
- {
- var options = fileOptions.split(",");
- for (var i = 0, length = options.length; i < length; i++)
- {
- var option = options[i];
- var name, value;
- if (option.indexOf("=") != -1)
- {
- var parts = option.split("=");
- name = parts[0];
- value = eval(unescape(parts[1]));
- }
- else
- {
- name = option;
- value = true;
- }
- if (name == "debug")
- {
- Env.isDebugMode = !!value;
- }
- else if (name in Env.Options)
- {
- Env.Options[name] = value;
- }
- else
- {
- Env[name] = value;
- }
- }
- }
- // process the Script JSON Options
- var innerOptions = FBL.trim(script.innerHTML);
- if (innerOptions)
- {
- var innerOptionsObject = eval("(" + innerOptions + ")");
- for (var name in innerOptionsObject)
- {
- var value = innerOptionsObject[name];
- if (name == "debug")
- {
- Env.isDebugMode = !!value;
- }
- else if (name in Env.Options)
- {
- Env.Options[name] = value;
- }
- else
- {
- Env[name] = value;
- }
- }
- }
- // process the Debug Mode
- if (Env.isDebugMode)
- {
- Env.Options.startOpened = true;
- Env.Options.enableTrace = true;
- Env.Options.disableWhenFirebugActive = false;
- }
- var loc = Env.Location;
- var isProductionRelease = path.indexOf(productionDir) != -1;
- loc.sourceDir = path;
- loc.baseDir = path.substr(0, path.length - m[1].length - 1);
- loc.skinDir = (isProductionRelease ? path : loc.baseDir) + "skin/" + Env.skin + "/";
- loc.skin = loc.skinDir + "firebug.html";
- loc.app = path + fileName;
- }
- else
- {
- throw new Error("Firebug Error: Library path not found");
- }
- };
- // ************************************************************************************************
- // Basics
- this.bind = function() // fn, thisObject, args => thisObject.fn(args, arguments);
- {
- var args = cloneArray(arguments), fn = args.shift(), object = args.shift();
- return function() { return fn.apply(object, arrayInsert(cloneArray(args), 0, arguments)); };
- };
- this.bindFixed = function() // fn, thisObject, args => thisObject.fn(args);
- {
- var args = cloneArray(arguments), fn = args.shift(), object = args.shift();
- return function() { return fn.apply(object, args); };
- };
- this.extend = function(l, r)
- {
- var newOb = {};
- for (var n in l)
- newOb[n] = l[n];
- for (var n in r)
- newOb[n] = r[n];
- return newOb;
- };
- this.descend = function(prototypeParent, childProperties)
- {
- function protoSetter() {};
- protoSetter.prototype = prototypeParent;
- var newOb = new protoSetter();
- for (var n in childProperties)
- newOb[n] = childProperties[n];
- return newOb;
- };
- this.append = function(l, r)
- {
- for (var n in r)
- l[n] = r[n];
- return l;
- };
- this.keys = function(map) // At least sometimes the keys will be on user-level window objects
- {
- var keys = [];
- try
- {
- for (var name in map) // enumeration is safe
- keys.push(name); // name is string, safe
- }
- catch (exc)
- {
- // Sometimes we get exceptions trying to iterate properties
- }
- return keys; // return is safe
- };
- this.values = function(map)
- {
- var values = [];
- try
- {
- for (var name in map)
- {
- try
- {
- values.push(map[name]);
- }
- catch (exc)
- {
- // Sometimes we get exceptions trying to access properties
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("lib.values FAILED ", exc);
- }
- }
- }
- catch (exc)
- {
- // Sometimes we get exceptions trying to iterate properties
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("lib.values FAILED ", exc);
- }
- return values;
- };
- this.remove = function(list, item)
- {
- for (var i = 0; i < list.length; ++i)
- {
- if (list[i] == item)
- {
- list.splice(i, 1);
- break;
- }
- }
- };
- this.sliceArray = function(array, index)
- {
- var slice = [];
- for (var i = index; i < array.length; ++i)
- slice.push(array[i]);
- return slice;
- };
- function cloneArray(array, fn)
- {
- var newArray = [];
- if (fn)
- for (var i = 0; i < array.length; ++i)
- newArray.push(fn(array[i]));
- else
- for (var i = 0; i < array.length; ++i)
- newArray.push(array[i]);
- return newArray;
- }
- function extendArray(array, array2)
- {
- var newArray = [];
- newArray.push.apply(newArray, array);
- newArray.push.apply(newArray, array2);
- return newArray;
- }
- this.extendArray = extendArray;
- this.cloneArray = cloneArray;
- function arrayInsert(array, index, other)
- {
- for (var i = 0; i < other.length; ++i)
- array.splice(i+index, 0, other[i]);
- return array;
- }
- // ************************************************************************************************
- this.createStyleSheet = function(doc, url)
- {
- //TODO: xxxpedro
- //var style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style");
- var style = this.createElement("link");
- style.setAttribute("charset","utf-8");
- style.firebugIgnore = true;
- style.setAttribute("rel", "stylesheet");
- style.setAttribute("type", "text/css");
- style.setAttribute("href", url);
- //TODO: xxxpedro
- //style.innerHTML = this.getResource(url);
- return style;
- };
- this.addStyleSheet = function(doc, style)
- {
- var heads = doc.getElementsByTagName("head");
- if (heads.length)
- heads[0].appendChild(style);
- else
- doc.documentElement.appendChild(style);
- };
- this.appendStylesheet = function(doc, uri)
- {
- // Make sure the stylesheet is not appended twice.
- if (this.$(uri, doc))
- return;
- var styleSheet = this.createStyleSheet(doc, uri);
- styleSheet.setAttribute("id", uri);
- this.addStyleSheet(doc, styleSheet);
- };
- this.addScript = function(doc, id, src)
- {
- var element = doc.createElementNS("http://www.w3.org/1999/xhtml", "html:script");
- element.setAttribute("type", "text/javascript");
- element.setAttribute("id", id);
- if (!FBTrace.DBG_CONSOLE)
- FBL.unwrapObject(element).firebugIgnore = true;
- element.innerHTML = src;
- if (doc.documentElement)
- doc.documentElement.appendChild(element);
- else
- {
- // See issue 1079, the svg test case gives this error
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("lib.addScript doc has no documentElement:", doc);
- }
- return element;
- };
- // ************************************************************************************************
- this.getStyle = this.isIE ?
- function(el, name)
- {
- return el.currentStyle[name] || el.style[name] || undefined;
- }
- :
- function(el, name)
- {
- return el.ownerDocument.defaultView.getComputedStyle(el,null)[name]
- || el.style[name] || undefined;
- };
- // ************************************************************************************************
- // Whitespace and Entity conversions
- var entityConversionLists = this.entityConversionLists = {
- normal : {
- whitespace : {
- '\t' : '\u200c\u2192',
- '\n' : '\u200c\u00b6',
- '\r' : '\u200c\u00ac',
- ' ' : '\u200c\u00b7'
- }
- },
- reverse : {
- whitespace : {
- '	' : '\t',
- '
' : '\n',
- '\u200c\u2192' : '\t',
- '\u200c\u00b6' : '\n',
- '\u200c\u00ac' : '\r',
- '\u200c\u00b7' : ' '
- }
- }
- };
- var normal = entityConversionLists.normal,
- reverse = entityConversionLists.reverse;
- function addEntityMapToList(ccode, entity)
- {
- var lists = Array.prototype.slice.call(arguments, 2),
- len = lists.length,
- ch = String.fromCharCode(ccode);
- for (var i = 0; i < len; i++)
- {
- var list = lists[i];
- normal[list]=normal[list] || {};
- normal[list][ch] = '&' + entity + ';';
- reverse[list]=reverse[list] || {};
- reverse[list]['&' + entity + ';'] = ch;
- }
- };
- var e = addEntityMapToList,
- white = 'whitespace',
- text = 'text',
- attr = 'attributes',
- css = 'css',
- editor = 'editor';
- e(0x0022, 'quot', attr, css);
- e(0x0026, 'amp', attr, text, css);
- e(0x0027, 'apos', css);
- e(0x003c, 'lt', attr, text, css);
- e(0x003e, 'gt', attr, text, css);
- e(0xa9, 'copy', text, editor);
- e(0xae, 'reg', text, editor);
- e(0x2122, 'trade', text, editor);
- // See http://en.wikipedia.org/wiki/Dash
- e(0x2012, '#8210', attr, text, editor); // figure dash
- e(0x2013, 'ndash', attr, text, editor); // en dash
- e(0x2014, 'mdash', attr, text, editor); // em dash
- e(0x2015, '#8213', attr, text, editor); // horizontal bar
- e(0x00a0, 'nbsp', attr, text, white, editor);
- e(0x2002, 'ensp', attr, text, white, editor);
- e(0x2003, 'emsp', attr, text, white, editor);
- e(0x2009, 'thinsp', attr, text, white, editor);
- e(0x200c, 'zwnj', attr, text, white, editor);
- e(0x200d, 'zwj', attr, text, white, editor);
- e(0x200e, 'lrm', attr, text, white, editor);
- e(0x200f, 'rlm', attr, text, white, editor);
- e(0x200b, '#8203', attr, text, white, editor); // zero-width space (ZWSP)
- //************************************************************************************************
- // Entity escaping
- var entityConversionRegexes = {
- normal : {},
- reverse : {}
- };
- var escapeEntitiesRegEx = {
- normal : function(list)
- {
- var chars = [];
- for ( var ch in list)
- {
- chars.push(ch);
- }
- return new RegExp('([' + chars.join('') + '])', 'gm');
- },
- reverse : function(list)
- {
- var chars = [];
- for ( var ch in list)
- {
- chars.push(ch);
- }
- return new RegExp('(' + chars.join('|') + ')', 'gm');
- }
- };
- function getEscapeRegexp(direction, lists)
- {
- var name = '', re;
- var groups = [].concat(lists);
- for (i = 0; i < groups.length; i++)
- {
- name += groups[i].group;
- }
- re = entityConversionRegexes[direction][name];
- if (!re)
- {
- var list = {};
- if (groups.length > 1)
- {
- for ( var i = 0; i < groups.length; i++)
- {
- var aList = entityConversionLists[direction][groups[i].group];
- for ( var item in aList)
- list[item] = aList[item];
- }
- } else if (groups.length==1)
- {
- list = entityConversionLists[direction][groups[0].group]; // faster for special case
- } else {
- list = {}; // perhaps should print out an error here?
- }
- re = entityConversionRegexes[direction][name] = escapeEntitiesRegEx[direction](list);
- }
- return re;
- };
- function createSimpleEscape(name, direction)
- {
- return function(value)
- {
- var list = entityConversionLists[direction][name];
- return String(value).replace(
- getEscapeRegexp(direction, {
- group : name,
- list : list
- }),
- function(ch)
- {
- return list[ch];
- }
- );
- };
- };
- function escapeGroupsForEntities(str, lists)
- {
- lists = [].concat(lists);
- var re = getEscapeRegexp('normal', lists),
- split = String(str).split(re),
- len = split.length,
- results = [],
- cur, r, i, ri = 0, l, list, last = '';
- if (!len)
- return [ {
- str : String(str),
- group : '',
- name : ''
- } ];
- for (i = 0; i < len; i++)
- {
- cur = split[i];
- if (cur == '')
- continue;
- for (l = 0; l < lists.length; l++)
- {
- list = lists[l];
- r = entityConversionLists.normal[list.group][cur];
- // if (cur == ' ' && list.group == 'whitespace' && last == ' ') // only show for runs of more than one space
- // r = ' ';
- if (r)
- {
- results[ri] = {
- 'str' : r,
- 'class' : list['class'],
- 'extra' : list.extra[cur] ? list['class']
- + list.extra[cur] : ''
- };
- break;
- }
- }
- // last=cur;
- if (!r)
- results[ri] = {
- 'str' : cur,
- 'class' : '',
- 'extra' : ''
- };
- ri++;
- }
- return results;
- };
- this.escapeGroupsForEntities = escapeGroupsForEntities;
- function unescapeEntities(str, lists)
- {
- var re = getEscapeRegexp('reverse', lists),
- split = String(str).split(re),
- len = split.length,
- results = [],
- cur, r, i, ri = 0, l, list;
- if (!len)
- return str;
- lists = [].concat(lists);
- for (i = 0; i < len; i++)
- {
- cur = split[i];
- if (cur == '')
- continue;
- for (l = 0; l < lists.length; l++)
- {
- list = lists[l];
- r = entityConversionLists.reverse[list.group][cur];
- if (r)
- {
- results[ri] = r;
- break;
- }
- }
- if (!r)
- results[ri] = cur;
- ri++;
- }
- return results.join('') || '';
- };
- // ************************************************************************************************
- // String escaping
- var escapeForTextNode = this.escapeForTextNode = createSimpleEscape('text', 'normal');
- var escapeForHtmlEditor = this.escapeForHtmlEditor = createSimpleEscape('editor', 'normal');
- var escapeForElementAttribute = this.escapeForElementAttribute = createSimpleEscape('attributes', 'normal');
- var escapeForCss = this.escapeForCss = createSimpleEscape('css', 'normal');
- // deprecated compatibility functions
- //this.deprecateEscapeHTML = createSimpleEscape('text', 'normal');
- //this.deprecatedUnescapeHTML = createSimpleEscape('text', 'reverse');
- //this.escapeHTML = deprecated("use appropriate escapeFor... function", this.deprecateEscapeHTML);
- //this.unescapeHTML = deprecated("use appropriate unescapeFor... function", this.deprecatedUnescapeHTML);
- var escapeForSourceLine = this.escapeForSourceLine = createSimpleEscape('text', 'normal');
- var unescapeWhitespace = createSimpleEscape('whitespace', 'reverse');
- this.unescapeForTextNode = function(str)
- {
- if (Firebug.showTextNodesWithWhitespace)
- str = unescapeWhitespace(str);
- if (!Firebug.showTextNodesWithEntities)
- str = escapeForElementAttribute(str);
- return str;
- };
- this.escapeNewLines = function(value)
- {
- return value.replace(/\r/g, "\\r").replace(/\n/g, "\\n");
- };
- this.stripNewLines = function(value)
- {
- return typeof(value) == "string" ? value.replace(/[\r\n]/g, " ") : value;
- };
- this.escapeJS = function(value)
- {
- return value.replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace('"', '\\"', "g");
- };
- function escapeHTMLAttribute(value)
- {
- function replaceChars(ch)
- {
- switch (ch)
- {
- case "&":
- return "&";
- case "'":
- return apos;
- case '"':
- return quot;
- }
- return "?";
- };
- var apos = "'", quot = """, around = '"';
- if( value.indexOf('"') == -1 ) {
- quot = '"';
- apos = "'";
- } else if( value.indexOf("'") == -1 ) {
- quot = '"';
- around = "'";
- }
- return around + (String(value).replace(/[&'"]/g, replaceChars)) + around;
- }
- function escapeHTML(value)
- {
- function replaceChars(ch)
- {
- switch (ch)
- {
- case "<":
- return "<";
- case ">":
- return ">";
- case "&":
- return "&";
- case "'":
- return "'";
- case '"':
- return """;
- }
- return "?";
- };
- return String(value).replace(/[<>&"']/g, replaceChars);
- }
- this.escapeHTML = escapeHTML;
- this.cropString = function(text, limit)
- {
- text = text + "";
- if (!limit)
- var halfLimit = 50;
- else
- var halfLimit = limit / 2;
- if (text.length > limit)
- return this.escapeNewLines(text.substr(0, halfLimit) + "..." + text.substr(text.length-halfLimit));
- else
- return this.escapeNewLines(text);
- };
- this.isWhitespace = function(text)
- {
- return !reNotWhitespace.exec(text);
- };
- this.splitLines = function(text)
- {
- var reSplitLines2 = /.*(:?\r\n|\n|\r)?/mg;
- var lines;
- if (text.match)
- {
- lines = text.match(reSplitLines2);
- }
- else
- {
- var str = text+"";
- lines = str.match(reSplitLines2);
- }
- lines.pop();
- return lines;
- };
- // ************************************************************************************************
- this.safeToString = function(ob)
- {
- if (this.isIE)
- return ob + "";
- try
- {
- if (ob && "toString" in ob && typeof ob.toString == "function")
- return ob.toString();
- }
- catch (exc)
- {
- // xxxpedro it is not safe to use ob+""?
- return ob + "";
- ///return "[an object with no toString() function]";
- }
- };
- // ************************************************************************************************
- this.hasProperties = function(ob)
- {
- try
- {
- for (var name in ob)
- return true;
- } catch (exc) {}
- return false;
- };
- // ************************************************************************************************
- // String Util
- var reTrim = /^\s+|\s+$/g;
- this.trim = function(s)
- {
- return s.replace(reTrim, "");
- };
- // ************************************************************************************************
- // Empty
- this.emptyFn = function(){};
- // ************************************************************************************************
- // Visibility
- this.isVisible = function(elt)
- {
- /*
- if (elt instanceof XULElement)
- {
- //FBTrace.sysout("isVisible elt.offsetWidth: "+elt.offsetWidth+" offsetHeight:"+ elt.offsetHeight+" localName:"+ elt.localName+" nameSpace:"+elt.nameSpaceURI+"\n");
- return (!elt.hidden && !elt.collapsed);
- }
- /**/
- return this.getStyle(elt, "visibility") != "hidden" &&
- ( elt.offsetWidth > 0 || elt.offsetHeight > 0
- || elt.tagName in invisibleTags
- || elt.namespaceURI == "http://www.w3.org/2000/svg"
- || elt.namespaceURI == "http://www.w3.org/1998/Math/MathML" );
- };
- this.collapse = function(elt, collapsed)
- {
- // IE6 doesn't support the [collapsed] CSS selector. IE7 does support the selector,
- // but it is causing a bug (the element disappears when you set the "collapsed"
- // attribute, but it doesn't appear when you remove the attribute. So, for those
- // cases, we need to use the class attribute.
- if (this.isIElt8)
- {
- if (collapsed)
- this.setClass(elt, "collapsed");
- else
- this.removeClass(elt, "collapsed");
- }
- else
- elt.setAttribute("collapsed", collapsed ? "true" : "false");
- };
- this.obscure = function(elt, obscured)
- {
- if (obscured)
- this.setClass(elt, "obscured");
- else
- this.removeClass(elt, "obscured");
- };
- this.hide = function(elt, hidden)
- {
- elt.style.visibility = hidden ? "hidden" : "visible";
- };
- this.clearNode = function(node)
- {
- var nodeName = " " + node.nodeName.toLowerCase() + " ";
- var ignoreTags = " table tbody thead tfoot th tr td ";
- // IE can't use innerHTML of table elements
- if (this.isIE && ignoreTags.indexOf(nodeName) != -1)
- this.eraseNode(node);
- else
- node.innerHTML = "";
- };
- this.eraseNode = function(node)
- {
- while (node.lastChild)
- node.removeChild(node.lastChild);
- };
- // ************************************************************************************************
- // Window iteration
- this.iterateWindows = function(win, handler)
- {
- if (!win || !win.document)
- return;
- handler(win);
- if (win == top || !win.frames) return; // XXXjjb hack for chromeBug
- for (var i = 0; i < win.frames.length; ++i)
- {
- var subWin = win.frames[i];
- if (subWin != win)
- this.iterateWindows(subWin, handler);
- }
- };
- this.getRootWindow = function(win)
- {
- for (; win; win = win.parent)
- {
- if (!win.parent || win == win.parent || !this.instanceOf(win.parent, "Window"))
- return win;
- }
- return null;
- };
- // ************************************************************************************************
- // Graphics
- this.getClientOffset = function(elt)
- {
- var addOffset = function addOffset(elt, coords, view)
- {
- var p = elt.offsetParent;
- var style = isIE ? elt.currentStyle : view.getComputedStyle(elt, "");
- if (elt.offsetLeft)
- coords.x += elt.offsetLeft + parseInt(style.borderLeftWidth);
- if (elt.offsetTop)
- coords.y += elt.offsetTop + parseInt(style.borderTopWidth);
- if (p)
- {
- if (p.nodeType == 1)
- addOffset(p, coords, view);
- }
- else
- {
- var otherView = isIE ? elt.ownerDocument.parentWindow : elt.ownerDocument.defaultView;
- if (otherView.frameElement)
- addOffset(otherView.frameElement, coords, otherView);
- }
- };
- var isIE = this.isIE;
- var coords = {x: 0, y: 0};
- if (elt)
- {
- var view = isIE ? elt.ownerDocument.parentWindow : elt.ownerDocument.defaultView;
- addOffset(elt, coords, view);
- }
- return coords;
- };
- this.getViewOffset = function(elt, singleFrame)
- {
- function addOffset(elt, coords, view)
- {
- var p = elt.offsetParent;
- coords.x += elt.offsetLeft - (p ? p.scrollLeft : 0);
- coords.y += elt.offsetTop - (p ? p.scrollTop : 0);
- if (p)
- {
- if (p.nodeType == 1)
- {
- var parentStyle = view.getComputedStyle(p, "");
- if (parentStyle.position != "static")
- {
- coords.x += parseInt(parentStyle.borderLeftWidth);
- coords.y += parseInt(parentStyle.borderTopWidth);
- if (p.localName == "TABLE")
- {
- coords.x += parseInt(parentStyle.paddingLeft);
- coords.y += parseInt(parentStyle.paddingTop);
- }
- else if (p.localName == "BODY")
- {
- var style = view.getComputedStyle(elt, "");
- coords.x += parseInt(style.marginLeft);
- coords.y += parseInt(style.marginTop);
- }
- }
- else if (p.localName == "BODY")
- {
- coords.x += parseInt(parentStyle.borderLeftWidth);
- coords.y += parseInt(parentStyle.borderTopWidth);
- }
- var parent = elt.parentNode;
- while (p != parent)
- {
- coords.x -= parent.scrollLeft;
- coords.y -= parent.scrollTop;
- parent = parent.parentNode;
- }
- addOffset(p, coords, view);
- }
- }
- else
- {
- if (elt.localName == "BODY")
- {
- var style = view.getComputedStyle(elt, "");
- coords.x += parseInt(style.borderLeftWidth);
- coords.y += parseInt(style.borderTopWidth);
- var htmlStyle = view.getComputedStyle(elt.parentNode, "");
- coords.x -= parseInt(htmlStyle.paddingLeft);
- coords.y -= parseInt(htmlStyle.paddingTop);
- }
- if (elt.scrollLeft)
- coords.x += elt.scrollLeft;
- if (elt.scrollTop)
- coords.y += elt.scrollTop;
- var win = elt.ownerDocument.defaultView;
- if (win && (!singleFrame && win.frameElement))
- addOffset(win.frameElement, coords, win);
- }
- }
- var coords = {x: 0, y: 0};
- if (elt)
- addOffset(elt, coords, elt.ownerDocument.defaultView);
- return coords;
- };
- this.getLTRBWH = function(elt)
- {
- var bcrect,
- dims = {"left": 0, "top": 0, "right": 0, "bottom": 0, "width": 0, "height": 0};
- if (elt)
- {
- bcrect = elt.getBoundingClientRect();
- dims.left = bcrect.left;
- dims.top = bcrect.top;
- dims.right = bcrect.right;
- dims.bottom = bcrect.bottom;
- if(bcrect.width)
- {
- dims.width = bcrect.width;
- dims.height = bcrect.height;
- }
- else
- {
- dims.width = dims.right - dims.left;
- dims.height = dims.bottom - dims.top;
- }
- }
- return dims;
- };
- this.applyBodyOffsets = function(elt, clientRect)
- {
- var od = elt.ownerDocument;
- if (!od.body)
- return clientRect;
- var style = od.defaultView.getComputedStyle(od.body, null);
- var pos = style.getPropertyValue('position');
- if(pos === 'absolute' || pos === 'relative')
- {
- var borderLeft = parseInt(style.getPropertyValue('border-left-width').replace('px', ''),10) || 0;
- var borderTop = parseInt(style.getPropertyValue('border-top-width').replace('px', ''),10) || 0;
- var paddingLeft = parseInt(style.getPropertyValue('padding-left').replace('px', ''),10) || 0;
- var paddingTop = parseInt(style.getPropertyValue('padding-top').replace('px', ''),10) || 0;
- var marginLeft = parseInt(style.getPropertyValue('margin-left').replace('px', ''),10) || 0;
- var marginTop = parseInt(style.getPropertyValue('margin-top').replace('px', ''),10) || 0;
- var offsetX = borderLeft + paddingLeft + marginLeft;
- var offsetY = borderTop + paddingTop + marginTop;
- clientRect.left -= offsetX;
- clientRect.top -= offsetY;
- clientRect.right -= offsetX;
- clientRect.bottom -= offsetY;
- }
- return clientRect;
- };
- this.getOffsetSize = function(elt)
- {
- return {width: elt.offsetWidth, height: elt.offsetHeight};
- };
- this.getOverflowParent = function(element)
- {
- for (var scrollParent = element.parentNode; scrollParent; scrollParent = scrollParent.offsetParent)
- {
- if (scrollParent.scrollHeight > scrollParent.offsetHeight)
- return scrollParent;
- }
- };
- this.isScrolledToBottom = function(element)
- {
- var onBottom = (element.scrollTop + element.offsetHeight) == element.scrollHeight;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("isScrolledToBottom offsetHeight: "+element.offsetHeight +" onBottom:"+onBottom);
- return onBottom;
- };
- this.scrollToBottom = function(element)
- {
- element.scrollTop = element.scrollHeight;
- if (FBTrace.DBG_CONSOLE)
- {
- FBTrace.sysout("scrollToBottom reset scrollTop "+element.scrollTop+" = "+element.scrollHeight);
- if (element.scrollHeight == element.offsetHeight)
- FBTrace.sysout("scrollToBottom attempt to scroll non-scrollable element "+element, element);
- }
- return (element.scrollTop == element.scrollHeight);
- };
- this.move = function(element, x, y)
- {
- element.style.left = x + "px";
- element.style.top = y + "px";
- };
- this.resize = function(element, w, h)
- {
- element.style.width = w + "px";
- element.style.height = h + "px";
- };
- this.linesIntoCenterView = function(element, scrollBox) // {before: int, after: int}
- {
- if (!scrollBox)
- scrollBox = this.getOverflowParent(element);
- if (!scrollBox)
- return;
- var offset = this.getClientOffset(element);
- var topSpace = offset.y - scrollBox.scrollTop;
- var bottomSpace = (scrollBox.scrollTop + scrollBox.clientHeight)
- - (offset.y + element.offsetHeight);
- if (topSpace < 0 || bottomSpace < 0)
- {
- var split = (scrollBox.clientHeight/2);
- var centerY = offset.y - split;
- scrollBox.scrollTop = centerY;
- topSpace = split;
- bottomSpace = split - element.offsetHeight;
- }
- return {before: Math.round((topSpace/element.offsetHeight) + 0.5),
- after: Math.round((bottomSpace/element.offsetHeight) + 0.5) };
- };
- this.scrollIntoCenterView = function(element, scrollBox, notX, notY)
- {
- if (!element)
- return;
- if (!scrollBox)
- scrollBox = this.getOverflowParent(element);
- if (!scrollBox)
- return;
- var offset = this.getClientOffset(element);
- if (!notY)
- {
- var topSpace = offset.y - scrollBox.scrollTop;
- var bottomSpace = (scrollBox.scrollTop + scrollBox.clientHeight)
- - (offset.y + element.offsetHeight);
- if (topSpace < 0 || bottomSpace < 0)
- {
- var centerY = offset.y - (scrollBox.clientHeight/2);
- scrollBox.scrollTop = centerY;
- }
- }
- if (!notX)
- {
- var leftSpace = offset.x - scrollBox.scrollLeft;
- var rightSpace = (scrollBox.scrollLeft + scrollBox.clientWidth)
- - (offset.x + element.clientWidth);
- if (leftSpace < 0 || rightSpace < 0)
- {
- var centerX = offset.x - (scrollBox.clientWidth/2);
- scrollBox.scrollLeft = centerX;
- }
- }
- if (FBTrace.DBG_SOURCEFILES)
- FBTrace.sysout("lib.scrollIntoCenterView ","Element:"+element.innerHTML);
- };
- // ************************************************************************************************
- // CSS
- var cssKeywordMap = null;
- var cssPropNames = null;
- var cssColorNames = null;
- var imageRules = null;
- this.getCSSKeywordsByProperty = function(propName)
- {
- if (!cssKeywordMap)
- {
- cssKeywordMap = {};
- for (var name in this.cssInfo)
- {
- var list = [];
- var types = this.cssInfo[name];
- for (var i = 0; i < types.length; ++i)
- {
- var keywords = this.cssKeywords[types[i]];
- if (keywords)
- list.push.apply(list, keywords);
- }
- cssKeywordMap[name] = list;
- }
- }
- return propName in cssKeywordMap ? cssKeywordMap[propName] : [];
- };
- this.getCSSPropertyNames = function()
- {
- if (!cssPropNames)
- {
- cssPropNames = [];
- for (var name in this.cssInfo)
- cssPropNames.push(name);
- }
- return cssPropNames;
- };
- this.isColorKeyword = function(keyword)
- {
- if (keyword == "transparent")
- return false;
- if (!cssColorNames)
- {
- cssColorNames = [];
- var colors = this.cssKeywords["color"];
- for (var i = 0; i < colors.length; ++i)
- cssColorNames.push(colors[i].toLowerCase());
- var systemColors = this.cssKeywords["systemColor"];
- for (var i = 0; i < systemColors.length; ++i)
- cssColorNames.push(systemColors[i].toLowerCase());
- }
- return cssColorNames.indexOf ? // Array.indexOf is not available in IE
- cssColorNames.indexOf(keyword.toLowerCase()) != -1 :
- (" " + cssColorNames.join(" ") + " ").indexOf(" " + keyword.toLowerCase() + " ") != -1;
- };
- this.isImageRule = function(rule)
- {
- if (!imageRules)
- {
- imageRules = [];
- for (var i in this.cssInfo)
- {
- var r = i.toLowerCase();
- var suffix = "image";
- if (r.match(suffix + "$") == suffix || r == "background")
- imageRules.push(r);
- }
- }
- return imageRules.indexOf ? // Array.indexOf is not available in IE
- imageRules.indexOf(rule.toLowerCase()) != -1 :
- (" " + imageRules.join(" ") + " ").indexOf(" " + rule.toLowerCase() + " ") != -1;
- };
- this.copyTextStyles = function(fromNode, toNode, style)
- {
- var view = this.isIE ?
- fromNode.ownerDocument.parentWindow :
- fromNode.ownerDocument.defaultView;
- if (view)
- {
- if (!style)
- style = this.isIE ? fromNode.currentStyle : view.getComputedStyle(fromNode, "");
- toNode.style.fontFamily = style.fontFamily;
- // TODO: xxxpedro need to create a FBL.getComputedStyle() because IE
- // returns wrong computed styles for inherited properties (like font-*)
- //
- // Also would be good to create a FBL.getStyle()
- toNode.style.fontSize = style.fontSize;
- toNode.style.fontWeight = style.fontWeight;
- toNode.style.fontStyle = style.fontStyle;
- return style;
- }
- };
- this.copyBoxStyles = function(fromNode, toNode, style)
- {
- var view = this.isIE ?
- fromNode.ownerDocument.parentWindow :
- fromNode.ownerDocument.defaultView;
- if (view)
- {
- if (!style)
- style = this.isIE ? fromNode.currentStyle : view.getComputedStyle(fromNode, "");
- toNode.style.marginTop = style.marginTop;
- toNode.style.marginRight = style.marginRight;
- toNode.style.marginBottom = style.marginBottom;
- toNode.style.marginLeft = style.marginLeft;
- toNode.style.borderTopWidth = style.borderTopWidth;
- toNode.style.borderRightWidth = style.borderRightWidth;
- toNode.style.borderBottomWidth = style.borderBottomWidth;
- toNode.style.borderLeftWidth = style.borderLeftWidth;
- return style;
- }
- };
- this.readBoxStyles = function(style)
- {
- var styleNames = {
- "margin-top": "marginTop", "margin-right": "marginRight",
- "margin-left": "marginLeft", "margin-bottom": "marginBottom",
- "border-top-width": "borderTop", "border-right-width": "borderRight",
- "border-left-width": "borderLeft", "border-bottom-width": "borderBottom",
- "padding-top": "paddingTop", "padding-right": "paddingRight",
- "padding-left": "paddingLeft", "padding-bottom": "paddingBottom",
- "z-index": "zIndex"
- };
- var styles = {};
- for (var styleName in styleNames)
- styles[styleNames[styleName]] = parseInt(style.getPropertyCSSValue(styleName).cssText) || 0;
- if (FBTrace.DBG_INSPECT)
- FBTrace.sysout("readBoxStyles ", styles);
- return styles;
- };
- this.getBoxFromStyles = function(style, element)
- {
- var args = this.readBoxStyles(style);
- args.width = element.offsetWidth
- - (args.paddingLeft+args.paddingRight+args.borderLeft+args.borderRight);
- args.height = element.offsetHeight
- - (args.paddingTop+args.paddingBottom+args.borderTop+args.borderBottom);
- return args;
- };
- this.getElementCSSSelector = function(element)
- {
- var label = element.localName.toLowerCase();
- if (element.id)
- label += "#" + element.id;
- if (element.hasAttribute("class"))
- label += "." + element.getAttribute("class").split(" ")[0];
- return label;
- };
- this.getURLForStyleSheet= function(styleSheet)
- {
- //http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet. For inline style sheets, the value of this attribute is null.
- return (styleSheet.href ? styleSheet.href : styleSheet.ownerNode.ownerDocument.URL);
- };
- this.getDocumentForStyleSheet = function(styleSheet)
- {
- while (styleSheet.parentStyleSheet && !styleSheet.ownerNode)
- {
- styleSheet = styleSheet.parentStyleSheet;
- }
- if (styleSheet.ownerNode)
- return styleSheet.ownerNode.ownerDocument;
- };
- /**
- * Retrieves the instance number for a given style sheet. The instance number
- * is sheet's index within the set of all other sheets whose URL is the same.
- */
- this.getInstanceForStyleSheet = function(styleSheet, ownerDocument)
- {
- // System URLs are always unique (or at least we are making this assumption)
- if (FBL.isSystemStyleSheet(styleSheet))
- return 0;
- // ownerDocument is an optional hint for performance
- if (FBTrace.DBG_CSS) FBTrace.sysout("getInstanceForStyleSheet: " + styleSheet.href + " " + styleSheet.media.mediaText + " " + (styleSheet.ownerNode && FBL.getElementXPath(styleSheet.ownerNode)), ownerDocument);
- ownerDocument = ownerDocument || FBL.getDocumentForStyleSheet(styleSheet);
- var ret = 0,
- styleSheets = ownerDocument.styleSheets,
- href = styleSheet.href;
- for (var i = 0; i < styleSheets.length; i++)
- {
- var curSheet = styleSheets[i];
- if (FBTrace.DBG_CSS) FBTrace.sysout("getInstanceForStyleSheet: compare href " + i + " " + curSheet.href + " " + curSheet.media.mediaText + " " + (curSheet.ownerNode && FBL.getElementXPath(curSheet.ownerNode)));
- if (curSheet == styleSheet)
- break;
- if (curSheet.href == href)
- ret++;
- }
- return ret;
- };
- // ************************************************************************************************
- // HTML and XML Serialization
- var getElementType = this.getElementType = function(node)
- {
- if (isElementXUL(node))
- return 'xul';
- else if (isElementSVG(node))
- return 'svg';
- else if (isElementMathML(node))
- return 'mathml';
- else if (isElementXHTML(node))
- return 'xhtml';
- else if (isElementHTML(node))
- return 'html';
- }
- var getElementSimpleType = this.getElementSimpleType = function(node)
- {
- if (isElementSVG(node))
- return 'svg';
- else if (isElementMathML(node))
- return 'mathml';
- else
- return 'html';
- }
- var isElementHTML = this.isElementHTML = function(node)
- {
- return node.nodeName == node.nodeName.toUpperCase();
- }
- var isElementXHTML = this.isElementXHTML = function(node)
- {
- return node.nodeName == node.nodeName.toLowerCase();
- }
- var isElementMathML = this.isElementMathML = function(node)
- {
- return node.namespaceURI == 'http://www.w3.org/1998/Math/MathML';
- }
- var isElementSVG = this.isElementSVG = function(node)
- {
- return node.namespaceURI == 'http://www.w3.org/2000/svg';
- }
- var isElementXUL = this.isElementXUL = function(node)
- {
- return node instanceof XULElement;
- }
- this.isSelfClosing = function(element)
- {
- if (isElementSVG(element) || isElementMathML(element))
- return true;
- var tag = element.localName.toLowerCase();
- return (this.selfClosingTags.hasOwnProperty(tag));
- };
- this.getElementHTML = function(element)
- {
- var self=this;
- function toHTML(elt)
- {
- if (elt.nodeType == Node.ELEMENT_NODE)
- {
- if (unwrapObject(elt).firebugIgnore)
- return;
- html.push('<', elt.nodeName.toLowerCase());
- for (var i = 0; i < elt.attributes.length; ++i)
- {
- var attr = elt.attributes[i];
- // Hide attributes set by Firebug
- if (attr.localName.indexOf("firebug-") == 0)
- continue;
- // MathML
- if (attr.localName.indexOf("-moz-math") == 0)
- {
- // just hide for now
- continue;
- }
- html.push(' ', attr.nodeName, '="', escapeForElementAttribute(attr.nodeValue),'"');
- }
- if (elt.firstChild)
- {
- html.push('>');
- var pureText=true;
- for (var child = element.firstChild; child; child = child.nextSibling)
- pureText=pureText && (child.nodeType == Node.TEXT_NODE);
- if (pureText)
- html.push(escapeForHtmlEditor(elt.textContent));
- else {
- for (var child = elt.firstChild; child; child = child.nextSibling)
- toHTML(child);
- }
- html.push('</', elt.nodeName.toLowerCase(), '>');
- }
- else if (isElementSVG(elt) || isElementMathML(elt))
- {
- html.push('/>');
- }
- else if (self.isSelfClosing(elt))
- {
- html.push((isElementXHTML(elt))?'/>':'>');
- }
- else
- {
- html.push('></', elt.nodeName.toLowerCase(), '>');
- }
- }
- else if (elt.nodeType == Node.TEXT_NODE)
- html.push(escapeForTextNode(elt.textContent));
- else if (elt.nodeType == Node.CDATA_SECTION_NODE)
- html.push('<![CDATA[', elt.nodeValue, ']]>');
- else if (elt.nodeType == Node.COMMENT_NODE)
- html.push('<!--', elt.nodeValue, '-->');
- }
- var html = [];
- toHTML(element);
- return html.join("");
- };
- this.getElementXML = function(element)
- {
- function toXML(elt)
- {
- if (elt.nodeType == Node.ELEMENT_NODE)
- {
- if (unwrapObject(elt).firebugIgnore)
- return;
- xml.push('<', elt.nodeName.toLowerCase());
- for (var i = 0; i < elt.attributes.length; ++i)
- {
- var attr = elt.attributes[i];
- // Hide attributes set by Firebug
- if (attr.localName.indexOf("firebug-") == 0)
- continue;
- // MathML
- if (attr.localName.indexOf("-moz-math") == 0)
- {
- // just hide for now
- continue;
- }
- xml.push(' ', attr.nodeName, '="', escapeForElementAttribute(attr.nodeValue),'"');
- }
- if (elt.firstChild)
- {
- xml.push('>');
- for (var child = elt.firstChild; child; child = child.nextSibling)
- toXML(child);
- xml.push('</', elt.nodeName.toLowerCase(), '>');
- }
- else
- xml.push('/>');
- }
- else if (elt.nodeType == Node.TEXT_NODE)
- xml.push(elt.nodeValue);
- else if (elt.nodeType == Node.CDATA_SECTION_NODE)
- xml.push('<![CDATA[', elt.nodeValue, ']]>');
- else if (elt.nodeType == Node.COMMENT_NODE)
- xml.push('<!--', elt.nodeValue, '-->');
- }
- var xml = [];
- toXML(element);
- return xml.join("");
- };
- // ************************************************************************************************
- // CSS classes
- this.hasClass = function(node, name) // className, className, ...
- {
- // TODO: xxxpedro when lib.hasClass is called with more than 2 arguments?
- // this function can be optimized a lot if assumed 2 arguments only,
- // which seems to be what happens 99% of the time
- if (arguments.length == 2)
- return (' '+node.className+' ').indexOf(' '+name+' ') != -1;
- if (!node || node.nodeType != 1)
- return false;
- else
- {
- for (var i=1; i<arguments.length; ++i)
- {
- var name = arguments[i];
- var re = new RegExp("(^|\\s)"+name+"($|\\s)");
- if (!re.exec(node.className))
- return false;
- }
- return true;
- }
- };
- this.old_hasClass = function(node, name) // className, className, ...
- {
- if (!node || node.nodeType != 1)
- return false;
- else
- {
- for (var i=1; i<arguments.length; ++i)
- {
- var name = arguments[i];
- var re = new RegExp("(^|\\s)"+name+"($|\\s)");
- if (!re.exec(node.className))
- return false;
- }
- return true;
- }
- };
- this.setClass = function(node, name)
- {
- if (node && (' '+node.className+' ').indexOf(' '+name+' ') == -1)
- ///if (node && !this.hasClass(node, name))
- node.className += " " + name;
- };
- this.getClassValue = function(node, name)
- {
- var re = new RegExp(name+"-([^ ]+)");
- var m = re.exec(node.className);
- return m ? m[1] : "";
- };
- this.removeClass = function(node, name)
- {
- if (node && node.className)
- {
- var index = node.className.indexOf(name);
- if (index >= 0)
- {
- var size = name.length;
- node.className = node.className.substr(0,index-1) + node.className.substr(index+size);
- }
- }
- };
- this.toggleClass = function(elt, name)
- {
- if ((' '+elt.className+' ').indexOf(' '+name+' ') != -1)
- ///if (this.hasClass(elt, name))
- this.removeClass(elt, name);
- else
- this.setClass(elt, name);
- };
- this.setClassTimed = function(elt, name, context, timeout)
- {
- if (!timeout)
- timeout = 1300;
- if (elt.__setClassTimeout)
- context.clearTimeout(elt.__setClassTimeout);
- else
- this.setClass(elt, name);
- elt.__setClassTimeout = context.setTimeout(function()
- {
- delete elt.__setClassTimeout;
- FBL.removeClass(elt, name);
- }, timeout);
- };
- this.cancelClassTimed = function(elt, name, context)
- {
- if (elt.__setClassTimeout)
- {
- FBL.removeClass(elt, name);
- context.clearTimeout(elt.__setClassTimeout);
- delete elt.__setClassTimeout;
- }
- };
- // ************************************************************************************************
- // DOM queries
- this.$ = function(id, doc)
- {
- if (doc)
- return doc.getElementById(id);
- else
- {
- return FBL.Firebug.chrome.document.getElementById(id);
- }
- };
- this.$$ = function(selector, doc)
- {
- if (doc || !FBL.Firebug.chrome)
- return FBL.Firebug.Selector(selector, doc);
- else
- {
- return FBL.Firebug.Selector(selector, FBL.Firebug.chrome.document);
- }
- };
- this.getChildByClass = function(node) // ,classname, classname, classname...
- {
- for (var i = 1; i < arguments.length; ++i)
- {
- var className = arguments[i];
- var child = node.firstChild;
- node = null;
- for (; child; child = child.nextSibling)
- {
- if (this.hasClass(child, className))
- {
- node = child;
- break;
- }
- }
- }
- return node;
- };
- this.getAncestorByClass = function(node, className)
- {
- for (var parent = node; parent; parent = parent.parentNode)
- {
- if (this.hasClass(parent, className))
- return parent;
- }
- return null;
- };
- this.getElementsByClass = function(node, className)
- {
- var result = [];
- for (var child = node.firstChild; child; child = child.nextSibling)
- {
- if (this.hasClass(child, className))
- result.push(child);
- }
- return result;
- };
- this.getElementByClass = function(node, className) // className, className, ...
- {
- var args = cloneArray(arguments); args.splice(0, 1);
- for (var child = node.firstChild; child; child = child.nextSibling)
- {
- var args1 = cloneArray(args); args1.unshift(child);
- if (FBL.hasClass.apply(null, args1))
- return child;
- else
- {
- var found = FBL.getElementByClass.apply(null, args1);
- if (found)
- return found;
- }
- }
- return null;
- };
- this.isAncestor = function(node, potentialAncestor)
- {
- for (var parent = node; parent; parent = parent.parentNode)
- {
- if (parent == potentialAncestor)
- return true;
- }
- return false;
- };
- this.getNextElement = function(node)
- {
- while (node && node.nodeType != 1)
- node = node.nextSibling;
- return node;
- };
- this.getPreviousElement = function(node)
- {
- while (node && node.nodeType != 1)
- node = node.previousSibling;
- return node;
- };
- this.getBody = function(doc)
- {
- if (doc.body)
- return doc.body;
- var body = doc.getElementsByTagName("body")[0];
- if (body)
- return body;
- return doc.firstChild; // For non-HTML docs
- };
- this.findNextDown = function(node, criteria)
- {
- if (!node)
- return null;
- for (var child = node.firstChild; child; child = child.nextSibling)
- {
- if (criteria(child))
- return child;
- var next = this.findNextDown(child, criteria);
- if (next)
- return next;
- }
- };
- this.findPreviousUp = function(node, criteria)
- {
- if (!node)
- return null;
- for (var child = node.lastChild; child; child = child.previousSibling)
- {
- var next = this.findPreviousUp(child, criteria);
- if (next)
- return next;
- if (criteria(child))
- return child;
- }
- };
- this.findNext = function(node, criteria, upOnly, maxRoot)
- {
- if (!node)
- return null;
- if (!upOnly)
- {
- var next = this.findNextDown(node, criteria);
- if (next)
- return next;
- }
- for (var sib = node.nextSibling; sib; sib = sib.nextSibling)
- {
- if (criteria(sib))
- return sib;
- var next = this.findNextDown(sib, criteria);
- if (next)
- return next;
- }
- if (node.parentNode && node.parentNode != maxRoot)
- return this.findNext(node.parentNode, criteria, true);
- };
- this.findPrevious = function(node, criteria, downOnly, maxRoot)
- {
- if (!node)
- return null;
- for (var sib = node.previousSibling; sib; sib = sib.previousSibling)
- {
- var prev = this.findPreviousUp(sib, criteria);
- if (prev)
- return prev;
- if (criteria(sib))
- return sib;
- }
- if (!downOnly)
- {
- var next = this.findPreviousUp(node, criteria);
- if (next)
- return next;
- }
- if (node.parentNode && node.parentNode != maxRoot)
- {
- if (criteria(node.parentNode))
- return node.parentNode;
- return this.findPrevious(node.parentNode, criteria, true);
- }
- };
- this.getNextByClass = function(root, state)
- {
- var iter = function iter(node) { return node.nodeType == 1 && FBL.hasClass(node, state); };
- return this.findNext(root, iter);
- };
- this.getPreviousByClass = function(root, state)
- {
- var iter = function iter(node) { return node.nodeType == 1 && FBL.hasClass(node, state); };
- return this.findPrevious(root, iter);
- };
- this.isElement = function(o)
- {
- try {
- return o && this.instanceOf(o, "Element");
- }
- catch (ex) {
- return false;
- }
- };
- // ************************************************************************************************
- // DOM Modification
- // TODO: xxxpedro use doc fragments in Context API
- var appendFragment = null;
- this.appendInnerHTML = function(element, html, referenceElement)
- {
- // if undefined, we must convert it to null otherwise it will throw an error in IE
- // when executing element.insertBefore(firstChild, referenceElement)
- referenceElement = referenceElement || null;
- var doc = element.ownerDocument;
- // doc.createRange not available in IE
- if (doc.createRange)
- {
- var range = doc.createRange(); // a helper object
- range.selectNodeContents(element); // the environment to interpret the html
- var fragment = range.createContextualFragment(html); // parse
- var firstChild = fragment.firstChild;
- element.insertBefore(fragment, referenceElement);
- }
- else
- {
- if (!appendFragment || appendFragment.ownerDocument != doc)
- appendFragment = doc.createDocumentFragment();
- var div = doc.createElement("div");
- div.innerHTML = html;
- var firstChild = div.firstChild;
- while (div.firstChild)
- appendFragment.appendChild(div.firstChild);
- element.insertBefore(appendFragment, referenceElement);
- div = null;
- }
- return firstChild;
- };
- // ************************************************************************************************
- // DOM creation
- this.createElement = function(tagName, properties)
- {
- properties = properties || {};
- var doc = properties.document || FBL.Firebug.chrome.document;
- var element = doc.createElement(tagName);
- for(var name in properties)
- {
- if (name != "document")
- {
- element[name] = properties[name];
- }
- }
- return element;
- };
- this.createGlobalElement = function(tagName, properties)
- {
- properties = properties || {};
- var doc = FBL.Env.browser.document;
- var element = this.NS && doc.createElementNS ?
- doc.createElementNS(FBL.NS, tagName) :
- doc.createElement(tagName);
- for(var name in properties)
- {
- var propname = name;
- if (FBL.isIE && name == "class") propname = "className";
- if (name != "document")
- {
- element.setAttribute(propname, properties[name]);
- }
- }
- return element;
- };
- //************************************************************************************************
- this.safeGetWindowLocation = function(window)
- {
- try
- {
- if (window)
- {
- if (window.closed)
- return "(window.closed)";
- if ("location" in window)
- return window.location+"";
- else
- return "(no window.location)";
- }
- else
- return "(no context.window)";
- }
- catch(exc)
- {
- if (FBTrace.DBG_WINDOWS || FBTrace.DBG_ERRORS)
- FBTrace.sysout("TabContext.getWindowLocation failed "+exc, exc);
- FBTrace.sysout("TabContext.getWindowLocation failed window:", window);
- return "(getWindowLocation: "+exc+")";
- }
- };
- // ************************************************************************************************
- // Events
- this.isLeftClick = function(event)
- {
- return (this.isIE && event.type != "click" && event.type != "dblclick" ?
- event.button == 1 : // IE "click" and "dblclick" button model
- event.button == 0) && // others
- this.noKeyModifiers(event);
- };
- this.isMiddleClick = function(event)
- {
- return (this.isIE && event.type != "click" && event.type != "dblclick" ?
- event.button == 4 : // IE "click" and "dblclick" button model
- event.button == 1) &&
- this.noKeyModifiers(event);
- };
- this.isRightClick = function(event)
- {
- return (this.isIE && event.type != "click" && event.type != "dblclick" ?
- event.button == 2 : // IE "click" and "dblclick" button model
- event.button == 2) &&
- this.noKeyModifiers(event);
- };
- this.noKeyModifiers = function(event)
- {
- return !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey;
- };
- this.isControlClick = function(event)
- {
- return (this.isIE && event.type != "click" && event.type != "dblclick" ?
- event.button == 1 : // IE "click" and "dblclick" button model
- event.button == 0) &&
- this.isControl(event);
- };
- this.isShiftClick = function(event)
- {
- return (this.isIE && event.type != "click" && event.type != "dblclick" ?
- event.button == 1 : // IE "click" and "dblclick" button model
- event.button == 0) &&
- this.isShift(event);
- };
- this.isControl = function(event)
- {
- return (event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey;
- };
- this.isAlt = function(event)
- {
- return event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey;
- };
- this.isAltClick = function(event)
- {
- return (this.isIE && event.type != "click" && event.type != "dblclick" ?
- event.button == 1 : // IE "click" and "dblclick" button model
- event.button == 0) &&
- this.isAlt(event);
- };
- this.isControlShift = function(event)
- {
- return (event.metaKey || event.ctrlKey) && event.shiftKey && !event.altKey;
- };
- this.isShift = function(event)
- {
- return event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey;
- };
- this.addEvent = function(object, name, handler, useCapture)
- {
- if (object.addEventListener)
- object.addEventListener(name, handler, useCapture);
- else
- object.attachEvent("on"+name, handler);
- };
- this.removeEvent = function(object, name, handler, useCapture)
- {
- try
- {
- if (object.removeEventListener)
- object.removeEventListener(name, handler, useCapture);
- else
- object.detachEvent("on"+name, handler);
- }
- catch(e)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("FBL.removeEvent error: ", object, name);
- }
- };
- this.cancelEvent = function(e, preventDefault)
- {
- if (!e) return;
- if (preventDefault)
- {
- if (e.preventDefault)
- e.preventDefault();
- else
- e.returnValue = false;
- }
- if (e.stopPropagation)
- e.stopPropagation();
- else
- e.cancelBubble = true;
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.addGlobalEvent = function(name, handler)
- {
- var doc = this.Firebug.browser.document;
- var frames = this.Firebug.browser.window.frames;
- this.addEvent(doc, name, handler);
- if (this.Firebug.chrome.type == "popup")
- this.addEvent(this.Firebug.chrome.document, name, handler);
- for (var i = 0, frame; frame = frames[i]; i++)
- {
- try
- {
- this.addEvent(frame.document, name, handler);
- }
- catch(E)
- {
- // Avoid acess denied
- }
- }
- };
- this.removeGlobalEvent = function(name, handler)
- {
- var doc = this.Firebug.browser.document;
- var frames = this.Firebug.browser.window.frames;
- this.removeEvent(doc, name, handler);
- if (this.Firebug.chrome.type == "popup")
- this.removeEvent(this.Firebug.chrome.document, name, handler);
- for (var i = 0, frame; frame = frames[i]; i++)
- {
- try
- {
- this.removeEvent(frame.document, name, handler);
- }
- catch(E)
- {
- // Avoid acess denied
- }
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.dispatch = function(listeners, name, args)
- {
- if (!listeners) return;
- try
- {/**/
- if (typeof listeners.length != "undefined")
- {
- if (FBTrace.DBG_DISPATCH) FBTrace.sysout("FBL.dispatch", name+" to "+listeners.length+" listeners");
- for (var i = 0; i < listeners.length; ++i)
- {
- var listener = listeners[i];
- if ( listener[name] )
- listener[name].apply(listener, args);
- }
- }
- else
- {
- if (FBTrace.DBG_DISPATCH) FBTrace.sysout("FBL.dispatch", name+" to listeners of an object");
- for (var prop in listeners)
- {
- var listener = listeners[prop];
- if ( listener[name] )
- listener[name].apply(listener, args);
- }
- }
- }
- catch (exc)
- {
- if (FBTrace.DBG_ERRORS)
- {
- FBTrace.sysout(" Exception in lib.dispatch "+ name, exc);
- //FBTrace.dumpProperties(" Exception in lib.dispatch listener", listener);
- }
- }
- /**/
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var disableTextSelectionHandler = function(event)
- {
- FBL.cancelEvent(event, true);
- return false;
- };
- this.disableTextSelection = function(e)
- {
- if (typeof e.onselectstart != "undefined") // IE
- this.addEvent(e, "selectstart", disableTextSelectionHandler);
- else // others
- {
- e.style.cssText = "user-select: none; -khtml-user-select: none; -moz-user-select: none;";
- // canceling the event in FF will prevent the menu popups to close when clicking over
- // text-disabled elements
- if (!this.isFirefox)
- this.addEvent(e, "mousedown", disableTextSelectionHandler);
- }
- e.style.cursor = "default";
- };
- this.restoreTextSelection = function(e)
- {
- if (typeof e.onselectstart != "undefined") // IE
- this.removeEvent(e, "selectstart", disableTextSelectionHandler);
- else // others
- {
- e.style.cssText = "cursor: default;";
- // canceling the event in FF will prevent the menu popups to close when clicking over
- // text-disabled elements
- if (!this.isFirefox)
- this.removeEvent(e, "mousedown", disableTextSelectionHandler);
- }
- };
- // ************************************************************************************************
- // DOM Events
- var eventTypes =
- {
- composition: [
- "composition",
- "compositionstart",
- "compositionend" ],
- contextmenu: [
- "contextmenu" ],
- drag: [
- "dragenter",
- "dragover",
- "dragexit",
- "dragdrop",
- "draggesture" ],
- focus: [
- "focus",
- "blur" ],
- form: [
- "submit",
- "reset",
- "change",
- "select",
- "input" ],
- key: [
- "keydown",
- "keyup",
- "keypress" ],
- load: [
- "load",
- "beforeunload",
- "unload",
- "abort",
- "error" ],
- mouse: [
- "mousedown",
- "mouseup",
- "click",
- "dblclick",
- "mouseover",
- "mouseout",
- "mousemove" ],
- mutation: [
- "DOMSubtreeModified",
- "DOMNodeInserted",
- "DOMNodeRemoved",
- "DOMNodeRemovedFromDocument",
- "DOMNodeInsertedIntoDocument",
- "DOMAttrModified",
- "DOMCharacterDataModified" ],
- paint: [
- "paint",
- "resize",
- "scroll" ],
- scroll: [
- "overflow",
- "underflow",
- "overflowchanged" ],
- text: [
- "text" ],
- ui: [
- "DOMActivate",
- "DOMFocusIn",
- "DOMFocusOut" ],
- xul: [
- "popupshowing",
- "popupshown",
- "popuphiding",
- "popuphidden",
- "close",
- "command",
- "broadcast",
- "commandupdate" ]
- };
- this.getEventFamily = function(eventType)
- {
- if (!this.families)
- {
- this.families = {};
- for (var family in eventTypes)
- {
- var types = eventTypes[family];
- for (var i = 0; i < types.length; ++i)
- this.families[types[i]] = family;
- }
- }
- return this.families[eventType];
- };
- // ************************************************************************************************
- // URLs
- this.getFileName = function(url)
- {
- var split = this.splitURLBase(url);
- return split.name;
- };
- this.splitURLBase = function(url)
- {
- if (this.isDataURL(url))
- return this.splitDataURL(url);
- return this.splitURLTrue(url);
- };
- this.splitDataURL = function(url)
- {
- var mark = url.indexOf(':', 3);
- if (mark != 4)
- return false; // the first 5 chars must be 'data:'
- var point = url.indexOf(',', mark+1);
- if (point < mark)
- return false; // syntax error
- var props = { encodedContent: url.substr(point+1) };
- var metadataBuffer = url.substr(mark+1, point);
- var metadata = metadataBuffer.split(';');
- for (var i = 0; i < metadata.length; i++)
- {
- var nv = metadata[i].split('=');
- if (nv.length == 2)
- props[nv[0]] = nv[1];
- }
- // Additional Firebug-specific properties
- if (props.hasOwnProperty('fileName'))
- {
- var caller_URL = decodeURIComponent(props['fileName']);
- var caller_split = this.splitURLTrue(caller_URL);
- if (props.hasOwnProperty('baseLineNumber')) // this means it's probably an eval()
- {
- props['path'] = caller_split.path;
- props['line'] = props['baseLineNumber'];
- var hint = decodeURIComponent(props['encodedContent'].substr(0,200)).replace(/\s*$/, "");
- props['name'] = 'eval->'+hint;
- }
- else
- {
- props['name'] = caller_split.name;
- props['path'] = caller_split.path;
- }
- }
- else
- {
- if (!props.hasOwnProperty('path'))
- props['path'] = "data:";
- if (!props.hasOwnProperty('name'))
- props['name'] = decodeURIComponent(props['encodedContent'].substr(0,200)).replace(/\s*$/, "");
- }
- return props;
- };
- this.splitURLTrue = function(url)
- {
- var m = reSplitFile.exec(url);
- if (!m)
- return {name: url, path: url};
- else if (!m[2])
- return {path: m[1], name: m[1]};
- else
- return {path: m[1], name: m[2]+m[3]};
- };
- this.getFileExtension = function(url)
- {
- if (!url)
- return null;
- // Remove query string from the URL if any.
- var queryString = url.indexOf("?");
- if (queryString != -1)
- url = url.substr(0, queryString);
- // Now get the file extension.
- var lastDot = url.lastIndexOf(".");
- return url.substr(lastDot+1);
- };
- this.isSystemURL = function(url)
- {
- if (!url) return true;
- if (url.length == 0) return true;
- if (url[0] == 'h') return false;
- if (url.substr(0, 9) == "resource:")
- return true;
- else if (url.substr(0, 16) == "chrome://firebug")
- return true;
- else if (url == "XPCSafeJSObjectWrapper.cpp")
- return true;
- else if (url.substr(0, 6) == "about:")
- return true;
- else if (url.indexOf("firebug-service.js") != -1)
- return true;
- else
- return false;
- };
- this.isSystemPage = function(win)
- {
- try
- {
- var doc = win.document;
- if (!doc)
- return false;
- // Detect pages for pretty printed XML
- if ((doc.styleSheets.length && doc.styleSheets[0].href
- == "chrome://global/content/xml/XMLPrettyPrint.css")
- || (doc.styleSheets.length > 1 && doc.styleSheets[1].href
- == "chrome://browser/skin/feeds/subscribe.css"))
- return true;
- return FBL.isSystemURL(win.location.href);
- }
- catch (exc)
- {
- // Sometimes documents just aren't ready to be manipulated here, but don't let that
- // gum up the works
- ERROR("tabWatcher.isSystemPage document not ready:"+ exc);
- return false;
- }
- };
- this.isSystemStyleSheet = function(sheet)
- {
- var href = sheet && sheet.href;
- return href && FBL.isSystemURL(href);
- };
- this.getURIHost = function(uri)
- {
- try
- {
- if (uri)
- return uri.host;
- else
- return "";
- }
- catch (exc)
- {
- return "";
- }
- };
- this.isLocalURL = function(url)
- {
- if (url.substr(0, 5) == "file:")
- return true;
- else if (url.substr(0, 8) == "wyciwyg:")
- return true;
- else
- return false;
- };
- this.isDataURL = function(url)
- {
- return (url && url.substr(0,5) == "data:");
- };
- this.getLocalPath = function(url)
- {
- if (this.isLocalURL(url))
- {
- var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler);
- var file = fileHandler.getFileFromURLSpec(url);
- return file.path;
- }
- };
- this.getURLFromLocalFile = function(file)
- {
- var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler);
- var URL = fileHandler.getURLSpecFromFile(file);
- return URL;
- };
- this.getDataURLForContent = function(content, url)
- {
- // data:text/javascript;fileName=x%2Cy.js;baseLineNumber=10,<the-url-encoded-data>
- var uri = "data:text/html;";
- uri += "fileName="+encodeURIComponent(url)+ ",";
- uri += encodeURIComponent(content);
- return uri;
- },
- this.getDomain = function(url)
- {
- var m = /[^:]+:\/{1,3}([^\/]+)/.exec(url);
- return m ? m[1] : "";
- };
- this.getURLPath = function(url)
- {
- var m = /[^:]+:\/{1,3}[^\/]+(\/.*?)$/.exec(url);
- return m ? m[1] : "";
- };
- this.getPrettyDomain = function(url)
- {
- var m = /[^:]+:\/{1,3}(www\.)?([^\/]+)/.exec(url);
- return m ? m[2] : "";
- };
- this.absoluteURL = function(url, baseURL)
- {
- return this.absoluteURLWithDots(url, baseURL).replace("/./", "/", "g");
- };
- this.absoluteURLWithDots = function(url, baseURL)
- {
- if (url[0] == "?")
- return baseURL + url;
- var reURL = /(([^:]+:)\/{1,2}[^\/]*)(.*?)$/;
- var m = reURL.exec(url);
- if (m)
- return url;
- var m = reURL.exec(baseURL);
- if (!m)
- return "";
- var head = m[1];
- var tail = m[3];
- if (url.substr(0, 2) == "//")
- return m[2] + url;
- else if (url[0] == "/")
- {
- return head + url;
- }
- else if (tail[tail.length-1] == "/")
- return baseURL + url;
- else
- {
- var parts = tail.split("/");
- return head + parts.slice(0, parts.length-1).join("/") + "/" + url;
- }
- };
- this.normalizeURL = function(url) // this gets called a lot, any performance improvement welcome
- {
- if (!url)
- return "";
- // Replace one or more characters that are not forward-slash followed by /.., by space.
- if (url.length < 255) // guard against monsters.
- {
- // Replace one or more characters that are not forward-slash followed by /.., by space.
- url = url.replace(/[^\/]+\/\.\.\//, "", "g");
- // Issue 1496, avoid #
- url = url.replace(/#.*/,"");
- // For some reason, JSDS reports file URLs like "file:/" instead of "file:///", so they
- // don't match up with the URLs we get back from the DOM
- url = url.replace(/file:\/([^\/])/g, "file:///$1");
- if (url.indexOf('chrome:')==0)
- {
- var m = reChromeCase.exec(url); // 1 is package name, 2 is path
- if (m)
- {
- url = "chrome://"+m[1].toLowerCase()+"/"+m[2];
- }
- }
- }
- return url;
- };
- this.denormalizeURL = function(url)
- {
- return url.replace(/file:\/\/\//g, "file:/");
- };
- this.parseURLParams = function(url)
- {
- var q = url ? url.indexOf("?") : -1;
- if (q == -1)
- return [];
- var search = url.substr(q+1);
- var h = search.lastIndexOf("#");
- if (h != -1)
- search = search.substr(0, h);
- if (!search)
- return [];
- return this.parseURLEncodedText(search);
- };
- this.parseURLEncodedText = function(text)
- {
- var maxValueLength = 25000;
- var params = [];
- // Unescape '+' characters that are used to encode a space.
- // See section 2.2.in RFC 3986: http://www.ietf.org/rfc/rfc3986.txt
- text = text.replace(/\+/g, " ");
- var args = text.split("&");
- for (var i = 0; i < args.length; ++i)
- {
- try {
- var parts = args[i].split("=");
- if (parts.length == 2)
- {
- if (parts[1].length > maxValueLength)
- parts[1] = this.$STR("LargeData");
- params.push({name: decodeURIComponent(parts[0]), value: decodeURIComponent(parts[1])});
- }
- else
- params.push({name: decodeURIComponent(parts[0]), value: ""});
- }
- catch (e)
- {
- if (FBTrace.DBG_ERRORS)
- {
- FBTrace.sysout("parseURLEncodedText EXCEPTION ", e);
- FBTrace.sysout("parseURLEncodedText EXCEPTION URI", args[i]);
- }
- }
- }
- params.sort(function(a, b) { return a.name <= b.name ? -1 : 1; });
- return params;
- };
- // TODO: xxxpedro lib. why loops in domplate are requiring array in parameters
- // as in response/request headers and get/post parameters in Net module?
- this.parseURLParamsArray = function(url)
- {
- var q = url ? url.indexOf("?") : -1;
- if (q == -1)
- return [];
- var search = url.substr(q+1);
- var h = search.lastIndexOf("#");
- if (h != -1)
- search = search.substr(0, h);
- if (!search)
- return [];
- return this.parseURLEncodedTextArray(search);
- };
- this.parseURLEncodedTextArray = function(text)
- {
- var maxValueLength = 25000;
- var params = [];
- // Unescape '+' characters that are used to encode a space.
- // See section 2.2.in RFC 3986: http://www.ietf.org/rfc/rfc3986.txt
- text = text.replace(/\+/g, " ");
- var args = text.split("&");
- for (var i = 0; i < args.length; ++i)
- {
- try {
- var parts = args[i].split("=");
- if (parts.length == 2)
- {
- if (parts[1].length > maxValueLength)
- parts[1] = this.$STR("LargeData");
- params.push({name: decodeURIComponent(parts[0]), value: [decodeURIComponent(parts[1])]});
- }
- else
- params.push({name: decodeURIComponent(parts[0]), value: [""]});
- }
- catch (e)
- {
- if (FBTrace.DBG_ERRORS)
- {
- FBTrace.sysout("parseURLEncodedText EXCEPTION ", e);
- FBTrace.sysout("parseURLEncodedText EXCEPTION URI", args[i]);
- }
- }
- }
- params.sort(function(a, b) { return a.name <= b.name ? -1 : 1; });
- return params;
- };
- this.reEncodeURL = function(file, text)
- {
- var lines = text.split("\n");
- var params = this.parseURLEncodedText(lines[lines.length-1]);
- var args = [];
- for (var i = 0; i < params.length; ++i)
- args.push(encodeURIComponent(params[i].name)+"="+encodeURIComponent(params[i].value));
- var url = file.href;
- url += (url.indexOf("?") == -1 ? "?" : "&") + args.join("&");
- return url;
- };
- this.getResource = function(aURL)
- {
- try
- {
- var channel=ioService.newChannel(aURL,null,null);
- var input=channel.open();
- return FBL.readFromStream(input);
- }
- catch (e)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("lib.getResource FAILS for "+aURL, e);
- }
- };
- this.parseJSONString = function(jsonString, originURL)
- {
- // See if this is a Prototype style *-secure request.
- var regex = new RegExp(/^\/\*-secure-([\s\S]*)\*\/\s*$/);
- var matches = regex.exec(jsonString);
- if (matches)
- {
- jsonString = matches[1];
- if (jsonString[0] == "\\" && jsonString[1] == "n")
- jsonString = jsonString.substr(2);
- if (jsonString[jsonString.length-2] == "\\" && jsonString[jsonString.length-1] == "n")
- jsonString = jsonString.substr(0, jsonString.length-2);
- }
- if (jsonString.indexOf("&&&START&&&"))
- {
- regex = new RegExp(/&&&START&&& (.+) &&&END&&&/);
- matches = regex.exec(jsonString);
- if (matches)
- jsonString = matches[1];
- }
- // throw on the extra parentheses
- jsonString = "(" + jsonString + ")";
- ///var s = Components.utils.Sandbox(originURL);
- var jsonObject = null;
- try
- {
- ///jsonObject = Components.utils.evalInSandbox(jsonString, s);
- //jsonObject = Firebug.context.eval(jsonString);
- jsonObject = Firebug.context.evaluate(jsonString, null, null, function(){return null;});
- }
- catch(e)
- {
- /***
- if (e.message.indexOf("is not defined"))
- {
- var parts = e.message.split(" ");
- s[parts[0]] = function(str){ return str; };
- try {
- jsonObject = Components.utils.evalInSandbox(jsonString, s);
- } catch(ex) {
- if (FBTrace.DBG_ERRORS || FBTrace.DBG_JSONVIEWER)
- FBTrace.sysout("jsonviewer.parseJSON EXCEPTION", e);
- return null;
- }
- }
- else
- {/**/
- if (FBTrace.DBG_ERRORS || FBTrace.DBG_JSONVIEWER)
- FBTrace.sysout("jsonviewer.parseJSON EXCEPTION", e);
- return null;
- ///}
- }
- return jsonObject;
- };
- // ************************************************************************************************
- this.objectToString = function(object)
- {
- try
- {
- return object+"";
- }
- catch (exc)
- {
- return null;
- }
- };
- // ************************************************************************************************
- // Input Caret Position
- this.setSelectionRange = function(input, start, length)
- {
- if (input.createTextRange)
- {
- var range = input.createTextRange();
- range.moveStart("character", start);
- range.moveEnd("character", length - input.value.length);
- range.select();
- }
- else if (input.setSelectionRange)
- {
- input.setSelectionRange(start, length);
- input.focus();
- }
- };
- // ************************************************************************************************
- // Input Selection Start / Caret Position
- this.getInputSelectionStart = function(input)
- {
- if (document.selection)
- {
- var range = input.ownerDocument.selection.createRange();
- var text = range.text;
- //console.log("range", range.text);
- // if there is a selection, find the start position
- if (text)
- {
- return input.value.indexOf(text);
- }
- // if there is no selection, find the caret position
- else
- {
- range.moveStart("character", -input.value.length);
- return range.text.length;
- }
- }
- else if (typeof input.selectionStart != "undefined")
- return input.selectionStart;
- return 0;
- };
- // ************************************************************************************************
- // Opera Tab Fix
- function onOperaTabBlur(e)
- {
- if (this.lastKey == 9)
- this.focus();
- };
- function onOperaTabKeyDown(e)
- {
- this.lastKey = e.keyCode;
- };
- function onOperaTabFocus(e)
- {
- this.lastKey = null;
- };
- this.fixOperaTabKey = function(el)
- {
- el.onfocus = onOperaTabFocus;
- el.onblur = onOperaTabBlur;
- el.onkeydown = onOperaTabKeyDown;
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.Property = function(object, name)
- {
- this.object = object;
- this.name = name;
- this.getObject = function()
- {
- return object[name];
- };
- };
- this.ErrorCopy = function(message)
- {
- this.message = message;
- };
- function EventCopy(event)
- {
- // Because event objects are destroyed arbitrarily by Gecko, we must make a copy of them to
- // represent them long term in the inspector.
- for (var name in event)
- {
- try {
- this[name] = event[name];
- } catch (exc) { }
- }
- }
- this.EventCopy = EventCopy;
- // ************************************************************************************************
- // Type Checking
- var toString = Object.prototype.toString;
- var reFunction = /^\s*function(\s+[\w_$][\w\d_$]*)?\s*\(/;
- this.isArray = function(object) {
- return toString.call(object) === '[object Array]';
- };
- this.isFunction = function(object) {
- if (!object) return false;
- return toString.call(object) === "[object Function]" ||
- this.isIE && typeof object != "string" && reFunction.test(""+object);
- };
- // ************************************************************************************************
- // Instance Checking
- this.instanceOf = function(object, className)
- {
- if (!object || typeof object != "object")
- return false;
- // Try to use the native instanceof operator. We can only use it when we know
- // exactly the window where the object is located at
- if (object.ownerDocument)
- {
- // find the correct window of the object
- var win = object.ownerDocument.defaultView || object.ownerDocument.parentWindow;
- // if the class is accessible in the window, uses the native instanceof operator
- // if the instanceof evaluates to "true" we can assume it is a instance, but if it
- // evaluates to "false" we must continue with the duck type detection below because
- // the native object may be extended, thus breaking the instanceof result
- // See Issue 3524: Firebug Lite Style Panel doesn't work if the native Element is extended
- if (className in win && object instanceof win[className])
- return true;
- }
- // If the object doesn't have the ownerDocument property, we'll try to look at
- // the current context's window
- else
- {
- // TODO: xxxpedro context
- // Since we're not using yet a Firebug.context, we'll just use the top window
- // (browser) as a reference
- var win = Firebug.browser.window;
- if (className in win)
- return object instanceof win[className];
- }
- // get the duck type model from the cache
- var cache = instanceCheckMap[className];
- if (!cache)
- return false;
- // starts the hacky duck type detection
- for(var n in cache)
- {
- var obj = cache[n];
- var type = typeof obj;
- obj = type == "object" ? obj : [obj];
- for(var name in obj)
- {
- // avoid problems with extended native objects
- // See Issue 3524: Firebug Lite Style Panel doesn't work if the native Element is extended
- if (!obj.hasOwnProperty(name))
- continue;
- var value = obj[name];
- if( n == "property" && !(value in object) ||
- n == "method" && !this.isFunction(object[value]) ||
- n == "value" && (""+object[name]).toLowerCase() != (""+value).toLowerCase() )
- return false;
- }
- }
- return true;
- };
- var instanceCheckMap =
- {
- // DuckTypeCheck:
- // {
- // property: ["window", "document"],
- // method: "setTimeout",
- // value: {nodeType: 1}
- // },
- Window:
- {
- property: ["window", "document"],
- method: "setTimeout"
- },
- Document:
- {
- property: ["body", "cookie"],
- method: "getElementById"
- },
- Node:
- {
- property: "ownerDocument",
- method: "appendChild"
- },
- Element:
- {
- property: "tagName",
- value: {nodeType: 1}
- },
- Location:
- {
- property: ["hostname", "protocol"],
- method: "assign"
- },
- HTMLImageElement:
- {
- property: "useMap",
- value:
- {
- nodeType: 1,
- tagName: "img"
- }
- },
- HTMLAnchorElement:
- {
- property: "hreflang",
- value:
- {
- nodeType: 1,
- tagName: "a"
- }
- },
- HTMLInputElement:
- {
- property: "form",
- value:
- {
- nodeType: 1,
- tagName: "input"
- }
- },
- HTMLButtonElement:
- {
- // ?
- },
- HTMLFormElement:
- {
- method: "submit",
- value:
- {
- nodeType: 1,
- tagName: "form"
- }
- },
- HTMLBodyElement:
- {
- },
- HTMLHtmlElement:
- {
- },
- CSSStyleRule:
- {
- property: ["selectorText", "style"]
- }
- };
- // ************************************************************************************************
- // DOM Constants
- /*
- Problems:
- - IE does not have window.Node, window.Element, etc
- - for (var name in Node.prototype) return nothing on FF
- */
- var domMemberMap2 = {};
- var domMemberMap2Sandbox = null;
- var getDomMemberMap2 = function(name)
- {
- if (!domMemberMap2Sandbox)
- {
- var doc = Firebug.chrome.document;
- var frame = doc.createElement("iframe");
- frame.id = "FirebugSandbox";
- frame.style.display = "none";
- frame.src = "about:blank";
- doc.body.appendChild(frame);
- domMemberMap2Sandbox = frame.window || frame.contentWindow;
- }
- var props = [];
- //var object = domMemberMap2Sandbox[name];
- //object = object.prototype || object;
- var object = null;
- if (name == "Window")
- object = domMemberMap2Sandbox.window;
- else if (name == "Document")
- object = domMemberMap2Sandbox.document;
- else if (name == "HTMLScriptElement")
- object = domMemberMap2Sandbox.document.createElement("script");
- else if (name == "HTMLAnchorElement")
- object = domMemberMap2Sandbox.document.createElement("a");
- else if (name.indexOf("Element") != -1)
- {
- object = domMemberMap2Sandbox.document.createElement("div");
- }
- if (object)
- {
- //object = object.prototype || object;
- //props = 'addEventListener,document,location,navigator,window'.split(',');
- for (var n in object)
- props.push(n);
- }
- /**/
- return props;
- return extendArray(props, domMemberMap[name]);
- };
- // xxxpedro experimental get DOM members
- this.getDOMMembers = function(object)
- {
- if (!domMemberCache)
- {
- FBL.domMemberCache = domMemberCache = {};
- for (var name in domMemberMap)
- {
- var builtins = getDomMemberMap2(name);
- var cache = domMemberCache[name] = {};
- /*
- if (name.indexOf("Element") != -1)
- {
- this.append(cache, this.getDOMMembers("Node"));
- this.append(cache, this.getDOMMembers("Element"));
- }
- /**/
- for (var i = 0; i < builtins.length; ++i)
- cache[builtins[i]] = i;
- }
- }
- try
- {
- if (this.instanceOf(object, "Window"))
- { return domMemberCache.Window; }
- else if (this.instanceOf(object, "Document") || this.instanceOf(object, "XMLDocument"))
- { return domMemberCache.Document; }
- else if (this.instanceOf(object, "Location"))
- { return domMemberCache.Location; }
- else if (this.instanceOf(object, "HTMLImageElement"))
- { return domMemberCache.HTMLImageElement; }
- else if (this.instanceOf(object, "HTMLAnchorElement"))
- { return domMemberCache.HTMLAnchorElement; }
- else if (this.instanceOf(object, "HTMLInputElement"))
- { return domMemberCache.HTMLInputElement; }
- else if (this.instanceOf(object, "HTMLButtonElement"))
- { return domMemberCache.HTMLButtonElement; }
- else if (this.instanceOf(object, "HTMLFormElement"))
- { return domMemberCache.HTMLFormElement; }
- else if (this.instanceOf(object, "HTMLBodyElement"))
- { return domMemberCache.HTMLBodyElement; }
- else if (this.instanceOf(object, "HTMLHtmlElement"))
- { return domMemberCache.HTMLHtmlElement; }
- else if (this.instanceOf(object, "HTMLScriptElement"))
- { return domMemberCache.HTMLScriptElement; }
- else if (this.instanceOf(object, "HTMLTableElement"))
- { return domMemberCache.HTMLTableElement; }
- else if (this.instanceOf(object, "HTMLTableRowElement"))
- { return domMemberCache.HTMLTableRowElement; }
- else if (this.instanceOf(object, "HTMLTableCellElement"))
- { return domMemberCache.HTMLTableCellElement; }
- else if (this.instanceOf(object, "HTMLIFrameElement"))
- { return domMemberCache.HTMLIFrameElement; }
- else if (this.instanceOf(object, "SVGSVGElement"))
- { return domMemberCache.SVGSVGElement; }
- else if (this.instanceOf(object, "SVGElement"))
- { return domMemberCache.SVGElement; }
- else if (this.instanceOf(object, "Element"))
- { return domMemberCache.Element; }
- else if (this.instanceOf(object, "Text") || this.instanceOf(object, "CDATASection"))
- { return domMemberCache.Text; }
- else if (this.instanceOf(object, "Attr"))
- { return domMemberCache.Attr; }
- else if (this.instanceOf(object, "Node"))
- { return domMemberCache.Node; }
- else if (this.instanceOf(object, "Event") || this.instanceOf(object, "EventCopy"))
- { return domMemberCache.Event; }
- else
- return {};
- }
- catch(E)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("lib.getDOMMembers FAILED ", E);
- return {};
- }
- };
- /*
- this.getDOMMembers = function(object)
- {
- if (!domMemberCache)
- {
- domMemberCache = {};
- for (var name in domMemberMap)
- {
- var builtins = domMemberMap[name];
- var cache = domMemberCache[name] = {};
- for (var i = 0; i < builtins.length; ++i)
- cache[builtins[i]] = i;
- }
- }
- try
- {
- if (this.instanceOf(object, "Window"))
- { return domMemberCache.Window; }
- else if (object instanceof Document || object instanceof XMLDocument)
- { return domMemberCache.Document; }
- else if (object instanceof Location)
- { return domMemberCache.Location; }
- else if (object instanceof HTMLImageElement)
- { return domMemberCache.HTMLImageElement; }
- else if (object instanceof HTMLAnchorElement)
- { return domMemberCache.HTMLAnchorElement; }
- else if (object instanceof HTMLInputElement)
- { return domMemberCache.HTMLInputElement; }
- else if (object instanceof HTMLButtonElement)
- { return domMemberCache.HTMLButtonElement; }
- else if (object instanceof HTMLFormElement)
- { return domMemberCache.HTMLFormElement; }
- else if (object instanceof HTMLBodyElement)
- { return domMemberCache.HTMLBodyElement; }
- else if (object instanceof HTMLHtmlElement)
- { return domMemberCache.HTMLHtmlElement; }
- else if (object instanceof HTMLScriptElement)
- { return domMemberCache.HTMLScriptElement; }
- else if (object instanceof HTMLTableElement)
- { return domMemberCache.HTMLTableElement; }
- else if (object instanceof HTMLTableRowElement)
- { return domMemberCache.HTMLTableRowElement; }
- else if (object instanceof HTMLTableCellElement)
- { return domMemberCache.HTMLTableCellElement; }
- else if (object instanceof HTMLIFrameElement)
- { return domMemberCache.HTMLIFrameElement; }
- else if (object instanceof SVGSVGElement)
- { return domMemberCache.SVGSVGElement; }
- else if (object instanceof SVGElement)
- { return domMemberCache.SVGElement; }
- else if (object instanceof Element)
- { return domMemberCache.Element; }
- else if (object instanceof Text || object instanceof CDATASection)
- { return domMemberCache.Text; }
- else if (object instanceof Attr)
- { return domMemberCache.Attr; }
- else if (object instanceof Node)
- { return domMemberCache.Node; }
- else if (object instanceof Event || object instanceof EventCopy)
- { return domMemberCache.Event; }
- else
- return {};
- }
- catch(E)
- {
- return {};
- }
- };
- /**/
- this.isDOMMember = function(object, propName)
- {
- var members = this.getDOMMembers(object);
- return members && propName in members;
- };
- var domMemberCache = null;
- var domMemberMap = {};
- domMemberMap.Window =
- [
- "document",
- "frameElement",
- "innerWidth",
- "innerHeight",
- "outerWidth",
- "outerHeight",
- "screenX",
- "screenY",
- "pageXOffset",
- "pageYOffset",
- "scrollX",
- "scrollY",
- "scrollMaxX",
- "scrollMaxY",
- "status",
- "defaultStatus",
- "parent",
- "opener",
- "top",
- "window",
- "content",
- "self",
- "location",
- "history",
- "frames",
- "navigator",
- "screen",
- "menubar",
- "toolbar",
- "locationbar",
- "personalbar",
- "statusbar",
- "directories",
- "scrollbars",
- "fullScreen",
- "netscape",
- "java",
- "console",
- "Components",
- "controllers",
- "closed",
- "crypto",
- "pkcs11",
- "name",
- "property",
- "length",
- "sessionStorage",
- "globalStorage",
- "setTimeout",
- "setInterval",
- "clearTimeout",
- "clearInterval",
- "addEventListener",
- "removeEventListener",
- "dispatchEvent",
- "getComputedStyle",
- "captureEvents",
- "releaseEvents",
- "routeEvent",
- "enableExternalCapture",
- "disableExternalCapture",
- "moveTo",
- "moveBy",
- "resizeTo",
- "resizeBy",
- "scroll",
- "scrollTo",
- "scrollBy",
- "scrollByLines",
- "scrollByPages",
- "sizeToContent",
- "setResizable",
- "getSelection",
- "open",
- "openDialog",
- "close",
- "alert",
- "confirm",
- "prompt",
- "dump",
- "focus",
- "blur",
- "find",
- "back",
- "forward",
- "home",
- "stop",
- "print",
- "atob",
- "btoa",
- "updateCommands",
- "XPCNativeWrapper",
- "GeckoActiveXObject",
- "applicationCache" // FF3
- ];
- domMemberMap.Location =
- [
- "href",
- "protocol",
- "host",
- "hostname",
- "port",
- "pathname",
- "search",
- "hash",
- "assign",
- "reload",
- "replace"
- ];
- domMemberMap.Node =
- [
- "id",
- "className",
- "nodeType",
- "tagName",
- "nodeName",
- "localName",
- "prefix",
- "namespaceURI",
- "nodeValue",
- "ownerDocument",
- "parentNode",
- "offsetParent",
- "nextSibling",
- "previousSibling",
- "firstChild",
- "lastChild",
- "childNodes",
- "attributes",
- "dir",
- "baseURI",
- "textContent",
- "innerHTML",
- "addEventListener",
- "removeEventListener",
- "dispatchEvent",
- "cloneNode",
- "appendChild",
- "insertBefore",
- "replaceChild",
- "removeChild",
- "compareDocumentPosition",
- "hasAttributes",
- "hasChildNodes",
- "lookupNamespaceURI",
- "lookupPrefix",
- "normalize",
- "isDefaultNamespace",
- "isEqualNode",
- "isSameNode",
- "isSupported",
- "getFeature",
- "getUserData",
- "setUserData"
- ];
- domMemberMap.Document = extendArray(domMemberMap.Node,
- [
- "documentElement",
- "body",
- "title",
- "location",
- "referrer",
- "cookie",
- "contentType",
- "lastModified",
- "characterSet",
- "inputEncoding",
- "xmlEncoding",
- "xmlStandalone",
- "xmlVersion",
- "strictErrorChecking",
- "documentURI",
- "URL",
- "defaultView",
- "doctype",
- "implementation",
- "styleSheets",
- "images",
- "links",
- "forms",
- "anchors",
- "embeds",
- "plugins",
- "applets",
- "width",
- "height",
- "designMode",
- "compatMode",
- "async",
- "preferredStylesheetSet",
- "alinkColor",
- "linkColor",
- "vlinkColor",
- "bgColor",
- "fgColor",
- "domain",
- "addEventListener",
- "removeEventListener",
- "dispatchEvent",
- "captureEvents",
- "releaseEvents",
- "routeEvent",
- "clear",
- "open",
- "close",
- "execCommand",
- "execCommandShowHelp",
- "getElementsByName",
- "getSelection",
- "queryCommandEnabled",
- "queryCommandIndeterm",
- "queryCommandState",
- "queryCommandSupported",
- "queryCommandText",
- "queryCommandValue",
- "write",
- "writeln",
- "adoptNode",
- "appendChild",
- "removeChild",
- "renameNode",
- "cloneNode",
- "compareDocumentPosition",
- "createAttribute",
- "createAttributeNS",
- "createCDATASection",
- "createComment",
- "createDocumentFragment",
- "createElement",
- "createElementNS",
- "createEntityReference",
- "createEvent",
- "createExpression",
- "createNSResolver",
- "createNodeIterator",
- "createProcessingInstruction",
- "createRange",
- "createTextNode",
- "createTreeWalker",
- "domConfig",
- "evaluate",
- "evaluateFIXptr",
- "evaluateXPointer",
- "getAnonymousElementByAttribute",
- "getAnonymousNodes",
- "addBinding",
- "removeBinding",
- "getBindingParent",
- "getBoxObjectFor",
- "setBoxObjectFor",
- "getElementById",
- "getElementsByTagName",
- "getElementsByTagNameNS",
- "hasAttributes",
- "hasChildNodes",
- "importNode",
- "insertBefore",
- "isDefaultNamespace",
- "isEqualNode",
- "isSameNode",
- "isSupported",
- "load",
- "loadBindingDocument",
- "lookupNamespaceURI",
- "lookupPrefix",
- "normalize",
- "normalizeDocument",
- "getFeature",
- "getUserData",
- "setUserData"
- ]);
- domMemberMap.Element = extendArray(domMemberMap.Node,
- [
- "clientWidth",
- "clientHeight",
- "offsetLeft",
- "offsetTop",
- "offsetWidth",
- "offsetHeight",
- "scrollLeft",
- "scrollTop",
- "scrollWidth",
- "scrollHeight",
- "style",
- "tabIndex",
- "title",
- "lang",
- "align",
- "spellcheck",
- "addEventListener",
- "removeEventListener",
- "dispatchEvent",
- "focus",
- "blur",
- "cloneNode",
- "appendChild",
- "insertBefore",
- "replaceChild",
- "removeChild",
- "compareDocumentPosition",
- "getElementsByTagName",
- "getElementsByTagNameNS",
- "getAttribute",
- "getAttributeNS",
- "getAttributeNode",
- "getAttributeNodeNS",
- "setAttribute",
- "setAttributeNS",
- "setAttributeNode",
- "setAttributeNodeNS",
- "removeAttribute",
- "removeAttributeNS",
- "removeAttributeNode",
- "hasAttribute",
- "hasAttributeNS",
- "hasAttributes",
- "hasChildNodes",
- "lookupNamespaceURI",
- "lookupPrefix",
- "normalize",
- "isDefaultNamespace",
- "isEqualNode",
- "isSameNode",
- "isSupported",
- "getFeature",
- "getUserData",
- "setUserData"
- ]);
- domMemberMap.SVGElement = extendArray(domMemberMap.Element,
- [
- "x",
- "y",
- "width",
- "height",
- "rx",
- "ry",
- "transform",
- "href",
- "ownerSVGElement",
- "viewportElement",
- "farthestViewportElement",
- "nearestViewportElement",
- "getBBox",
- "getCTM",
- "getScreenCTM",
- "getTransformToElement",
- "getPresentationAttribute",
- "preserveAspectRatio"
- ]);
- domMemberMap.SVGSVGElement = extendArray(domMemberMap.Element,
- [
- "x",
- "y",
- "width",
- "height",
- "rx",
- "ry",
- "transform",
- "viewBox",
- "viewport",
- "currentView",
- "useCurrentView",
- "pixelUnitToMillimeterX",
- "pixelUnitToMillimeterY",
- "screenPixelToMillimeterX",
- "screenPixelToMillimeterY",
- "currentScale",
- "currentTranslate",
- "zoomAndPan",
- "ownerSVGElement",
- "viewportElement",
- "farthestViewportElement",
- "nearestViewportElement",
- "contentScriptType",
- "contentStyleType",
- "getBBox",
- "getCTM",
- "getScreenCTM",
- "getTransformToElement",
- "getEnclosureList",
- "getIntersectionList",
- "getViewboxToViewportTransform",
- "getPresentationAttribute",
- "getElementById",
- "checkEnclosure",
- "checkIntersection",
- "createSVGAngle",
- "createSVGLength",
- "createSVGMatrix",
- "createSVGNumber",
- "createSVGPoint",
- "createSVGRect",
- "createSVGString",
- "createSVGTransform",
- "createSVGTransformFromMatrix",
- "deSelectAll",
- "preserveAspectRatio",
- "forceRedraw",
- "suspendRedraw",
- "unsuspendRedraw",
- "unsuspendRedrawAll",
- "getCurrentTime",
- "setCurrentTime",
- "animationsPaused",
- "pauseAnimations",
- "unpauseAnimations"
- ]);
- domMemberMap.HTMLImageElement = extendArray(domMemberMap.Element,
- [
- "src",
- "naturalWidth",
- "naturalHeight",
- "width",
- "height",
- "x",
- "y",
- "name",
- "alt",
- "longDesc",
- "lowsrc",
- "border",
- "complete",
- "hspace",
- "vspace",
- "isMap",
- "useMap"
- ]);
- domMemberMap.HTMLAnchorElement = extendArray(domMemberMap.Element,
- [
- "name",
- "target",
- "accessKey",
- "href",
- "protocol",
- "host",
- "hostname",
- "port",
- "pathname",
- "search",
- "hash",
- "hreflang",
- "coords",
- "shape",
- "text",
- "type",
- "rel",
- "rev",
- "charset"
- ]);
- domMemberMap.HTMLIFrameElement = extendArray(domMemberMap.Element,
- [
- "contentDocument",
- "contentWindow",
- "frameBorder",
- "height",
- "longDesc",
- "marginHeight",
- "marginWidth",
- "name",
- "scrolling",
- "src",
- "width"
- ]);
- domMemberMap.HTMLTableElement = extendArray(domMemberMap.Element,
- [
- "bgColor",
- "border",
- "caption",
- "cellPadding",
- "cellSpacing",
- "frame",
- "rows",
- "rules",
- "summary",
- "tBodies",
- "tFoot",
- "tHead",
- "width",
- "createCaption",
- "createTFoot",
- "createTHead",
- "deleteCaption",
- "deleteRow",
- "deleteTFoot",
- "deleteTHead",
- "insertRow"
- ]);
- domMemberMap.HTMLTableRowElement = extendArray(domMemberMap.Element,
- [
- "bgColor",
- "cells",
- "ch",
- "chOff",
- "rowIndex",
- "sectionRowIndex",
- "vAlign",
- "deleteCell",
- "insertCell"
- ]);
- domMemberMap.HTMLTableCellElement = extendArray(domMemberMap.Element,
- [
- "abbr",
- "axis",
- "bgColor",
- "cellIndex",
- "ch",
- "chOff",
- "colSpan",
- "headers",
- "height",
- "noWrap",
- "rowSpan",
- "scope",
- "vAlign",
- "width"
- ]);
- domMemberMap.HTMLScriptElement = extendArray(domMemberMap.Element,
- [
- "src"
- ]);
- domMemberMap.HTMLButtonElement = extendArray(domMemberMap.Element,
- [
- "accessKey",
- "disabled",
- "form",
- "name",
- "type",
- "value",
- "click"
- ]);
- domMemberMap.HTMLInputElement = extendArray(domMemberMap.Element,
- [
- "type",
- "value",
- "checked",
- "accept",
- "accessKey",
- "alt",
- "controllers",
- "defaultChecked",
- "defaultValue",
- "disabled",
- "form",
- "maxLength",
- "name",
- "readOnly",
- "selectionEnd",
- "selectionStart",
- "size",
- "src",
- "textLength",
- "useMap",
- "click",
- "select",
- "setSelectionRange"
- ]);
- domMemberMap.HTMLFormElement = extendArray(domMemberMap.Element,
- [
- "acceptCharset",
- "action",
- "author",
- "elements",
- "encoding",
- "enctype",
- "entry_id",
- "length",
- "method",
- "name",
- "post",
- "target",
- "text",
- "url",
- "reset",
- "submit"
- ]);
- domMemberMap.HTMLBodyElement = extendArray(domMemberMap.Element,
- [
- "aLink",
- "background",
- "bgColor",
- "link",
- "text",
- "vLink"
- ]);
- domMemberMap.HTMLHtmlElement = extendArray(domMemberMap.Element,
- [
- "version"
- ]);
- domMemberMap.Text = extendArray(domMemberMap.Node,
- [
- "data",
- "length",
- "appendData",
- "deleteData",
- "insertData",
- "replaceData",
- "splitText",
- "substringData"
- ]);
- domMemberMap.Attr = extendArray(domMemberMap.Node,
- [
- "name",
- "value",
- "specified",
- "ownerElement"
- ]);
- domMemberMap.Event =
- [
- "type",
- "target",
- "currentTarget",
- "originalTarget",
- "explicitOriginalTarget",
- "relatedTarget",
- "rangeParent",
- "rangeOffset",
- "view",
- "keyCode",
- "charCode",
- "screenX",
- "screenY",
- "clientX",
- "clientY",
- "layerX",
- "layerY",
- "pageX",
- "pageY",
- "detail",
- "button",
- "which",
- "ctrlKey",
- "shiftKey",
- "altKey",
- "metaKey",
- "eventPhase",
- "timeStamp",
- "bubbles",
- "cancelable",
- "cancelBubble",
- "isTrusted",
- "isChar",
- "getPreventDefault",
- "initEvent",
- "initMouseEvent",
- "initKeyEvent",
- "initUIEvent",
- "preventBubble",
- "preventCapture",
- "preventDefault",
- "stopPropagation"
- ];
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.domConstantMap =
- {
- "ELEMENT_NODE": 1,
- "ATTRIBUTE_NODE": 1,
- "TEXT_NODE": 1,
- "CDATA_SECTION_NODE": 1,
- "ENTITY_REFERENCE_NODE": 1,
- "ENTITY_NODE": 1,
- "PROCESSING_INSTRUCTION_NODE": 1,
- "COMMENT_NODE": 1,
- "DOCUMENT_NODE": 1,
- "DOCUMENT_TYPE_NODE": 1,
- "DOCUMENT_FRAGMENT_NODE": 1,
- "NOTATION_NODE": 1,
- "DOCUMENT_POSITION_DISCONNECTED": 1,
- "DOCUMENT_POSITION_PRECEDING": 1,
- "DOCUMENT_POSITION_FOLLOWING": 1,
- "DOCUMENT_POSITION_CONTAINS": 1,
- "DOCUMENT_POSITION_CONTAINED_BY": 1,
- "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC": 1,
- "UNKNOWN_RULE": 1,
- "STYLE_RULE": 1,
- "CHARSET_RULE": 1,
- "IMPORT_RULE": 1,
- "MEDIA_RULE": 1,
- "FONT_FACE_RULE": 1,
- "PAGE_RULE": 1,
- "CAPTURING_PHASE": 1,
- "AT_TARGET": 1,
- "BUBBLING_PHASE": 1,
- "SCROLL_PAGE_UP": 1,
- "SCROLL_PAGE_DOWN": 1,
- "MOUSEUP": 1,
- "MOUSEDOWN": 1,
- "MOUSEOVER": 1,
- "MOUSEOUT": 1,
- "MOUSEMOVE": 1,
- "MOUSEDRAG": 1,
- "CLICK": 1,
- "DBLCLICK": 1,
- "KEYDOWN": 1,
- "KEYUP": 1,
- "KEYPRESS": 1,
- "DRAGDROP": 1,
- "FOCUS": 1,
- "BLUR": 1,
- "SELECT": 1,
- "CHANGE": 1,
- "RESET": 1,
- "SUBMIT": 1,
- "SCROLL": 1,
- "LOAD": 1,
- "UNLOAD": 1,
- "XFER_DONE": 1,
- "ABORT": 1,
- "ERROR": 1,
- "LOCATE": 1,
- "MOVE": 1,
- "RESIZE": 1,
- "FORWARD": 1,
- "HELP": 1,
- "BACK": 1,
- "TEXT": 1,
- "ALT_MASK": 1,
- "CONTROL_MASK": 1,
- "SHIFT_MASK": 1,
- "META_MASK": 1,
- "DOM_VK_TAB": 1,
- "DOM_VK_PAGE_UP": 1,
- "DOM_VK_PAGE_DOWN": 1,
- "DOM_VK_UP": 1,
- "DOM_VK_DOWN": 1,
- "DOM_VK_LEFT": 1,
- "DOM_VK_RIGHT": 1,
- "DOM_VK_CANCEL": 1,
- "DOM_VK_HELP": 1,
- "DOM_VK_BACK_SPACE": 1,
- "DOM_VK_CLEAR": 1,
- "DOM_VK_RETURN": 1,
- "DOM_VK_ENTER": 1,
- "DOM_VK_SHIFT": 1,
- "DOM_VK_CONTROL": 1,
- "DOM_VK_ALT": 1,
- "DOM_VK_PAUSE": 1,
- "DOM_VK_CAPS_LOCK": 1,
- "DOM_VK_ESCAPE": 1,
- "DOM_VK_SPACE": 1,
- "DOM_VK_END": 1,
- "DOM_VK_HOME": 1,
- "DOM_VK_PRINTSCREEN": 1,
- "DOM_VK_INSERT": 1,
- "DOM_VK_DELETE": 1,
- "DOM_VK_0": 1,
- "DOM_VK_1": 1,
- "DOM_VK_2": 1,
- "DOM_VK_3": 1,
- "DOM_VK_4": 1,
- "DOM_VK_5": 1,
- "DOM_VK_6": 1,
- "DOM_VK_7": 1,
- "DOM_VK_8": 1,
- "DOM_VK_9": 1,
- "DOM_VK_SEMICOLON": 1,
- "DOM_VK_EQUALS": 1,
- "DOM_VK_A": 1,
- "DOM_VK_B": 1,
- "DOM_VK_C": 1,
- "DOM_VK_D": 1,
- "DOM_VK_E": 1,
- "DOM_VK_F": 1,
- "DOM_VK_G": 1,
- "DOM_VK_H": 1,
- "DOM_VK_I": 1,
- "DOM_VK_J": 1,
- "DOM_VK_K": 1,
- "DOM_VK_L": 1,
- "DOM_VK_M": 1,
- "DOM_VK_N": 1,
- "DOM_VK_O": 1,
- "DOM_VK_P": 1,
- "DOM_VK_Q": 1,
- "DOM_VK_R": 1,
- "DOM_VK_S": 1,
- "DOM_VK_T": 1,
- "DOM_VK_U": 1,
- "DOM_VK_V": 1,
- "DOM_VK_W": 1,
- "DOM_VK_X": 1,
- "DOM_VK_Y": 1,
- "DOM_VK_Z": 1,
- "DOM_VK_CONTEXT_MENU": 1,
- "DOM_VK_NUMPAD0": 1,
- "DOM_VK_NUMPAD1": 1,
- "DOM_VK_NUMPAD2": 1,
- "DOM_VK_NUMPAD3": 1,
- "DOM_VK_NUMPAD4": 1,
- "DOM_VK_NUMPAD5": 1,
- "DOM_VK_NUMPAD6": 1,
- "DOM_VK_NUMPAD7": 1,
- "DOM_VK_NUMPAD8": 1,
- "DOM_VK_NUMPAD9": 1,
- "DOM_VK_MULTIPLY": 1,
- "DOM_VK_ADD": 1,
- "DOM_VK_SEPARATOR": 1,
- "DOM_VK_SUBTRACT": 1,
- "DOM_VK_DECIMAL": 1,
- "DOM_VK_DIVIDE": 1,
- "DOM_VK_F1": 1,
- "DOM_VK_F2": 1,
- "DOM_VK_F3": 1,
- "DOM_VK_F4": 1,
- "DOM_VK_F5": 1,
- "DOM_VK_F6": 1,
- "DOM_VK_F7": 1,
- "DOM_VK_F8": 1,
- "DOM_VK_F9": 1,
- "DOM_VK_F10": 1,
- "DOM_VK_F11": 1,
- "DOM_VK_F12": 1,
- "DOM_VK_F13": 1,
- "DOM_VK_F14": 1,
- "DOM_VK_F15": 1,
- "DOM_VK_F16": 1,
- "DOM_VK_F17": 1,
- "DOM_VK_F18": 1,
- "DOM_VK_F19": 1,
- "DOM_VK_F20": 1,
- "DOM_VK_F21": 1,
- "DOM_VK_F22": 1,
- "DOM_VK_F23": 1,
- "DOM_VK_F24": 1,
- "DOM_VK_NUM_LOCK": 1,
- "DOM_VK_SCROLL_LOCK": 1,
- "DOM_VK_COMMA": 1,
- "DOM_VK_PERIOD": 1,
- "DOM_VK_SLASH": 1,
- "DOM_VK_BACK_QUOTE": 1,
- "DOM_VK_OPEN_BRACKET": 1,
- "DOM_VK_BACK_SLASH": 1,
- "DOM_VK_CLOSE_BRACKET": 1,
- "DOM_VK_QUOTE": 1,
- "DOM_VK_META": 1,
- "SVG_ZOOMANDPAN_DISABLE": 1,
- "SVG_ZOOMANDPAN_MAGNIFY": 1,
- "SVG_ZOOMANDPAN_UNKNOWN": 1
- };
- this.cssInfo =
- {
- "background": ["bgRepeat", "bgAttachment", "bgPosition", "color", "systemColor", "none"],
- "background-attachment": ["bgAttachment"],
- "background-color": ["color", "systemColor"],
- "background-image": ["none"],
- "background-position": ["bgPosition"],
- "background-repeat": ["bgRepeat"],
- "border": ["borderStyle", "thickness", "color", "systemColor", "none"],
- "border-top": ["borderStyle", "borderCollapse", "color", "systemColor", "none"],
- "border-right": ["borderStyle", "borderCollapse", "color", "systemColor", "none"],
- "border-bottom": ["borderStyle", "borderCollapse", "color", "systemColor", "none"],
- "border-left": ["borderStyle", "borderCollapse", "color", "systemColor", "none"],
- "border-collapse": ["borderCollapse"],
- "border-color": ["color", "systemColor"],
- "border-top-color": ["color", "systemColor"],
- "border-right-color": ["color", "systemColor"],
- "border-bottom-color": ["color", "systemColor"],
- "border-left-color": ["color", "systemColor"],
- "border-spacing": [],
- "border-style": ["borderStyle"],
- "border-top-style": ["borderStyle"],
- "border-right-style": ["borderStyle"],
- "border-bottom-style": ["borderStyle"],
- "border-left-style": ["borderStyle"],
- "border-width": ["thickness"],
- "border-top-width": ["thickness"],
- "border-right-width": ["thickness"],
- "border-bottom-width": ["thickness"],
- "border-left-width": ["thickness"],
- "bottom": ["auto"],
- "caption-side": ["captionSide"],
- "clear": ["clear", "none"],
- "clip": ["auto"],
- "color": ["color", "systemColor"],
- "content": ["content"],
- "counter-increment": ["none"],
- "counter-reset": ["none"],
- "cursor": ["cursor", "none"],
- "direction": ["direction"],
- "display": ["display", "none"],
- "empty-cells": [],
- "float": ["float", "none"],
- "font": ["fontStyle", "fontVariant", "fontWeight", "fontFamily"],
- "font-family": ["fontFamily"],
- "font-size": ["fontSize"],
- "font-size-adjust": [],
- "font-stretch": [],
- "font-style": ["fontStyle"],
- "font-variant": ["fontVariant"],
- "font-weight": ["fontWeight"],
- "height": ["auto"],
- "left": ["auto"],
- "letter-spacing": [],
- "line-height": [],
- "list-style": ["listStyleType", "listStylePosition", "none"],
- "list-style-image": ["none"],
- "list-style-position": ["listStylePosition"],
- "list-style-type": ["listStyleType", "none"],
- "margin": [],
- "margin-top": [],
- "margin-right": [],
- "margin-bottom": [],
- "margin-left": [],
- "marker-offset": ["auto"],
- "min-height": ["none"],
- "max-height": ["none"],
- "min-width": ["none"],
- "max-width": ["none"],
- "outline": ["borderStyle", "color", "systemColor", "none"],
- "outline-color": ["color", "systemColor"],
- "outline-style": ["borderStyle"],
- "outline-width": [],
- "overflow": ["overflow", "auto"],
- "overflow-x": ["overflow", "auto"],
- "overflow-y": ["overflow", "auto"],
- "padding": [],
- "padding-top": [],
- "padding-right": [],
- "padding-bottom": [],
- "padding-left": [],
- "position": ["position"],
- "quotes": ["none"],
- "right": ["auto"],
- "table-layout": ["tableLayout", "auto"],
- "text-align": ["textAlign"],
- "text-decoration": ["textDecoration", "none"],
- "text-indent": [],
- "text-shadow": [],
- "text-transform": ["textTransform", "none"],
- "top": ["auto"],
- "unicode-bidi": [],
- "vertical-align": ["verticalAlign"],
- "white-space": ["whiteSpace"],
- "width": ["auto"],
- "word-spacing": [],
- "z-index": [],
- "-moz-appearance": ["mozAppearance"],
- "-moz-border-radius": [],
- "-moz-border-radius-bottomleft": [],
- "-moz-border-radius-bottomright": [],
- "-moz-border-radius-topleft": [],
- "-moz-border-radius-topright": [],
- "-moz-border-top-colors": ["color", "systemColor"],
- "-moz-border-right-colors": ["color", "systemColor"],
- "-moz-border-bottom-colors": ["color", "systemColor"],
- "-moz-border-left-colors": ["color", "systemColor"],
- "-moz-box-align": ["mozBoxAlign"],
- "-moz-box-direction": ["mozBoxDirection"],
- "-moz-box-flex": [],
- "-moz-box-ordinal-group": [],
- "-moz-box-orient": ["mozBoxOrient"],
- "-moz-box-pack": ["mozBoxPack"],
- "-moz-box-sizing": ["mozBoxSizing"],
- "-moz-opacity": [],
- "-moz-user-focus": ["userFocus", "none"],
- "-moz-user-input": ["userInput"],
- "-moz-user-modify": [],
- "-moz-user-select": ["userSelect", "none"],
- "-moz-background-clip": [],
- "-moz-background-inline-policy": [],
- "-moz-background-origin": [],
- "-moz-binding": [],
- "-moz-column-count": [],
- "-moz-column-gap": [],
- "-moz-column-width": [],
- "-moz-image-region": []
- };
- this.inheritedStyleNames =
- {
- "border-collapse": 1,
- "border-spacing": 1,
- "border-style": 1,
- "caption-side": 1,
- "color": 1,
- "cursor": 1,
- "direction": 1,
- "empty-cells": 1,
- "font": 1,
- "font-family": 1,
- "font-size-adjust": 1,
- "font-size": 1,
- "font-style": 1,
- "font-variant": 1,
- "font-weight": 1,
- "letter-spacing": 1,
- "line-height": 1,
- "list-style": 1,
- "list-style-image": 1,
- "list-style-position": 1,
- "list-style-type": 1,
- "quotes": 1,
- "text-align": 1,
- "text-decoration": 1,
- "text-indent": 1,
- "text-shadow": 1,
- "text-transform": 1,
- "white-space": 1,
- "word-spacing": 1
- };
- this.cssKeywords =
- {
- "appearance":
- [
- "button",
- "button-small",
- "checkbox",
- "checkbox-container",
- "checkbox-small",
- "dialog",
- "listbox",
- "menuitem",
- "menulist",
- "menulist-button",
- "menulist-textfield",
- "menupopup",
- "progressbar",
- "radio",
- "radio-container",
- "radio-small",
- "resizer",
- "scrollbar",
- "scrollbarbutton-down",
- "scrollbarbutton-left",
- "scrollbarbutton-right",
- "scrollbarbutton-up",
- "scrollbartrack-horizontal",
- "scrollbartrack-vertical",
- "separator",
- "statusbar",
- "tab",
- "tab-left-edge",
- "tabpanels",
- "textfield",
- "toolbar",
- "toolbarbutton",
- "toolbox",
- "tooltip",
- "treeheadercell",
- "treeheadersortarrow",
- "treeitem",
- "treetwisty",
- "treetwistyopen",
- "treeview",
- "window"
- ],
- "systemColor":
- [
- "ActiveBorder",
- "ActiveCaption",
- "AppWorkspace",
- "Background",
- "ButtonFace",
- "ButtonHighlight",
- "ButtonShadow",
- "ButtonText",
- "CaptionText",
- "GrayText",
- "Highlight",
- "HighlightText",
- "InactiveBorder",
- "InactiveCaption",
- "InactiveCaptionText",
- "InfoBackground",
- "InfoText",
- "Menu",
- "MenuText",
- "Scrollbar",
- "ThreeDDarkShadow",
- "ThreeDFace",
- "ThreeDHighlight",
- "ThreeDLightShadow",
- "ThreeDShadow",
- "Window",
- "WindowFrame",
- "WindowText",
- "-moz-field",
- "-moz-fieldtext",
- "-moz-workspace",
- "-moz-visitedhyperlinktext",
- "-moz-use-text-color"
- ],
- "color":
- [
- "AliceBlue",
- "AntiqueWhite",
- "Aqua",
- "Aquamarine",
- "Azure",
- "Beige",
- "Bisque",
- "Black",
- "BlanchedAlmond",
- "Blue",
- "BlueViolet",
- "Brown",
- "BurlyWood",
- "CadetBlue",
- "Chartreuse",
- "Chocolate",
- "Coral",
- "CornflowerBlue",
- "Cornsilk",
- "Crimson",
- "Cyan",
- "DarkBlue",
- "DarkCyan",
- "DarkGoldenRod",
- "DarkGray",
- "DarkGreen",
- "DarkKhaki",
- "DarkMagenta",
- "DarkOliveGreen",
- "DarkOrange",
- "DarkOrchid",
- "DarkRed",
- "DarkSalmon",
- "DarkSeaGreen",
- "DarkSlateBlue",
- "DarkSlateGray",
- "DarkTurquoise",
- "DarkViolet",
- "DeepPink",
- "DarkSkyBlue",
- "DimGray",
- "DodgerBlue",
- "Feldspar",
- "FireBrick",
- "FloralWhite",
- "ForestGreen",
- "Fuchsia",
- "Gainsboro",
- "GhostWhite",
- "Gold",
- "GoldenRod",
- "Gray",
- "Green",
- "GreenYellow",
- "HoneyDew",
- "HotPink",
- "IndianRed",
- "Indigo",
- "Ivory",
- "Khaki",
- "Lavender",
- "LavenderBlush",
- "LawnGreen",
- "LemonChiffon",
- "LightBlue",
- "LightCoral",
- "LightCyan",
- "LightGoldenRodYellow",
- "LightGrey",
- "LightGreen",
- "LightPink",
- "LightSalmon",
- "LightSeaGreen",
- "LightSkyBlue",
- "LightSlateBlue",
- "LightSlateGray",
- "LightSteelBlue",
- "LightYellow",
- "Lime",
- "LimeGreen",
- "Linen",
- "Magenta",
- "Maroon",
- "MediumAquaMarine",
- "MediumBlue",
- "MediumOrchid",
- "MediumPurple",
- "MediumSeaGreen",
- "MediumSlateBlue",
- "MediumSpringGreen",
- "MediumTurquoise",
- "MediumVioletRed",
- "MidnightBlue",
- "MintCream",
- "MistyRose",
- "Moccasin",
- "NavajoWhite",
- "Navy",
- "OldLace",
- "Olive",
- "OliveDrab",
- "Orange",
- "OrangeRed",
- "Orchid",
- "PaleGoldenRod",
- "PaleGreen",
- "PaleTurquoise",
- "PaleVioletRed",
- "PapayaWhip",
- "PeachPuff",
- "Peru",
- "Pink",
- "Plum",
- "PowderBlue",
- "Purple",
- "Red",
- "RosyBrown",
- "RoyalBlue",
- "SaddleBrown",
- "Salmon",
- "SandyBrown",
- "SeaGreen",
- "SeaShell",
- "Sienna",
- "Silver",
- "SkyBlue",
- "SlateBlue",
- "SlateGray",
- "Snow",
- "SpringGreen",
- "SteelBlue",
- "Tan",
- "Teal",
- "Thistle",
- "Tomato",
- "Turquoise",
- "Violet",
- "VioletRed",
- "Wheat",
- "White",
- "WhiteSmoke",
- "Yellow",
- "YellowGreen",
- "transparent",
- "invert"
- ],
- "auto":
- [
- "auto"
- ],
- "none":
- [
- "none"
- ],
- "captionSide":
- [
- "top",
- "bottom",
- "left",
- "right"
- ],
- "clear":
- [
- "left",
- "right",
- "both"
- ],
- "cursor":
- [
- "auto",
- "cell",
- "context-menu",
- "crosshair",
- "default",
- "help",
- "pointer",
- "progress",
- "move",
- "e-resize",
- "all-scroll",
- "ne-resize",
- "nw-resize",
- "n-resize",
- "se-resize",
- "sw-resize",
- "s-resize",
- "w-resize",
- "ew-resize",
- "ns-resize",
- "nesw-resize",
- "nwse-resize",
- "col-resize",
- "row-resize",
- "text",
- "vertical-text",
- "wait",
- "alias",
- "copy",
- "move",
- "no-drop",
- "not-allowed",
- "-moz-alias",
- "-moz-cell",
- "-moz-copy",
- "-moz-grab",
- "-moz-grabbing",
- "-moz-contextmenu",
- "-moz-zoom-in",
- "-moz-zoom-out",
- "-moz-spinning"
- ],
- "direction":
- [
- "ltr",
- "rtl"
- ],
- "bgAttachment":
- [
- "scroll",
- "fixed"
- ],
- "bgPosition":
- [
- "top",
- "center",
- "bottom",
- "left",
- "right"
- ],
- "bgRepeat":
- [
- "repeat",
- "repeat-x",
- "repeat-y",
- "no-repeat"
- ],
- "borderStyle":
- [
- "hidden",
- "dotted",
- "dashed",
- "solid",
- "double",
- "groove",
- "ridge",
- "inset",
- "outset",
- "-moz-bg-inset",
- "-moz-bg-outset",
- "-moz-bg-solid"
- ],
- "borderCollapse":
- [
- "collapse",
- "separate"
- ],
- "overflow":
- [
- "visible",
- "hidden",
- "scroll",
- "-moz-scrollbars-horizontal",
- "-moz-scrollbars-none",
- "-moz-scrollbars-vertical"
- ],
- "listStyleType":
- [
- "disc",
- "circle",
- "square",
- "decimal",
- "decimal-leading-zero",
- "lower-roman",
- "upper-roman",
- "lower-greek",
- "lower-alpha",
- "lower-latin",
- "upper-alpha",
- "upper-latin",
- "hebrew",
- "armenian",
- "georgian",
- "cjk-ideographic",
- "hiragana",
- "katakana",
- "hiragana-iroha",
- "katakana-iroha",
- "inherit"
- ],
- "listStylePosition":
- [
- "inside",
- "outside"
- ],
- "content":
- [
- "open-quote",
- "close-quote",
- "no-open-quote",
- "no-close-quote",
- "inherit"
- ],
- "fontStyle":
- [
- "normal",
- "italic",
- "oblique",
- "inherit"
- ],
- "fontVariant":
- [
- "normal",
- "small-caps",
- "inherit"
- ],
- "fontWeight":
- [
- "normal",
- "bold",
- "bolder",
- "lighter",
- "inherit"
- ],
- "fontSize":
- [
- "xx-small",
- "x-small",
- "small",
- "medium",
- "large",
- "x-large",
- "xx-large",
- "smaller",
- "larger"
- ],
- "fontFamily":
- [
- "Arial",
- "Comic Sans MS",
- "Georgia",
- "Tahoma",
- "Verdana",
- "Times New Roman",
- "Trebuchet MS",
- "Lucida Grande",
- "Helvetica",
- "serif",
- "sans-serif",
- "cursive",
- "fantasy",
- "monospace",
- "caption",
- "icon",
- "menu",
- "message-box",
- "small-caption",
- "status-bar",
- "inherit"
- ],
- "display":
- [
- "block",
- "inline",
- "inline-block",
- "list-item",
- "marker",
- "run-in",
- "compact",
- "table",
- "inline-table",
- "table-row-group",
- "table-column",
- "table-column-group",
- "table-header-group",
- "table-footer-group",
- "table-row",
- "table-cell",
- "table-caption",
- "-moz-box",
- "-moz-compact",
- "-moz-deck",
- "-moz-grid",
- "-moz-grid-group",
- "-moz-grid-line",
- "-moz-groupbox",
- "-moz-inline-block",
- "-moz-inline-box",
- "-moz-inline-grid",
- "-moz-inline-stack",
- "-moz-inline-table",
- "-moz-marker",
- "-moz-popup",
- "-moz-runin",
- "-moz-stack"
- ],
- "position":
- [
- "static",
- "relative",
- "absolute",
- "fixed",
- "inherit"
- ],
- "float":
- [
- "left",
- "right"
- ],
- "textAlign":
- [
- "left",
- "right",
- "center",
- "justify"
- ],
- "tableLayout":
- [
- "fixed"
- ],
- "textDecoration":
- [
- "underline",
- "overline",
- "line-through",
- "blink"
- ],
- "textTransform":
- [
- "capitalize",
- "lowercase",
- "uppercase",
- "inherit"
- ],
- "unicodeBidi":
- [
- "normal",
- "embed",
- "bidi-override"
- ],
- "whiteSpace":
- [
- "normal",
- "pre",
- "nowrap"
- ],
- "verticalAlign":
- [
- "baseline",
- "sub",
- "super",
- "top",
- "text-top",
- "middle",
- "bottom",
- "text-bottom",
- "inherit"
- ],
- "thickness":
- [
- "thin",
- "medium",
- "thick"
- ],
- "userFocus":
- [
- "ignore",
- "normal"
- ],
- "userInput":
- [
- "disabled",
- "enabled"
- ],
- "userSelect":
- [
- "normal"
- ],
- "mozBoxSizing":
- [
- "content-box",
- "padding-box",
- "border-box"
- ],
- "mozBoxAlign":
- [
- "start",
- "center",
- "end",
- "baseline",
- "stretch"
- ],
- "mozBoxDirection":
- [
- "normal",
- "reverse"
- ],
- "mozBoxOrient":
- [
- "horizontal",
- "vertical"
- ],
- "mozBoxPack":
- [
- "start",
- "center",
- "end"
- ]
- };
- this.nonEditableTags =
- {
- "HTML": 1,
- "HEAD": 1,
- "html": 1,
- "head": 1
- };
- this.innerEditableTags =
- {
- "BODY": 1,
- "body": 1
- };
- this.selfClosingTags =
- { // End tags for void elements are forbidden http://wiki.whatwg.org/wiki/HTML_vs._XHTML
- "meta": 1,
- "link": 1,
- "area": 1,
- "base": 1,
- "col": 1,
- "input": 1,
- "img": 1,
- "br": 1,
- "hr": 1,
- "param":1,
- "embed":1
- };
- var invisibleTags = this.invisibleTags =
- {
- "HTML": 1,
- "HEAD": 1,
- "TITLE": 1,
- "META": 1,
- "LINK": 1,
- "STYLE": 1,
- "SCRIPT": 1,
- "NOSCRIPT": 1,
- "BR": 1,
- "PARAM": 1,
- "COL": 1,
- "html": 1,
- "head": 1,
- "title": 1,
- "meta": 1,
- "link": 1,
- "style": 1,
- "script": 1,
- "noscript": 1,
- "br": 1,
- "param": 1,
- "col": 1
- /*
- "window": 1,
- "browser": 1,
- "frame": 1,
- "tabbrowser": 1,
- "WINDOW": 1,
- "BROWSER": 1,
- "FRAME": 1,
- "TABBROWSER": 1,
- */
- };
- if (typeof KeyEvent == "undefined") {
- this.KeyEvent = {
- DOM_VK_CANCEL: 3,
- DOM_VK_HELP: 6,
- DOM_VK_BACK_SPACE: 8,
- DOM_VK_TAB: 9,
- DOM_VK_CLEAR: 12,
- DOM_VK_RETURN: 13,
- DOM_VK_ENTER: 14,
- DOM_VK_SHIFT: 16,
- DOM_VK_CONTROL: 17,
- DOM_VK_ALT: 18,
- DOM_VK_PAUSE: 19,
- DOM_VK_CAPS_LOCK: 20,
- DOM_VK_ESCAPE: 27,
- DOM_VK_SPACE: 32,
- DOM_VK_PAGE_UP: 33,
- DOM_VK_PAGE_DOWN: 34,
- DOM_VK_END: 35,
- DOM_VK_HOME: 36,
- DOM_VK_LEFT: 37,
- DOM_VK_UP: 38,
- DOM_VK_RIGHT: 39,
- DOM_VK_DOWN: 40,
- DOM_VK_PRINTSCREEN: 44,
- DOM_VK_INSERT: 45,
- DOM_VK_DELETE: 46,
- DOM_VK_0: 48,
- DOM_VK_1: 49,
- DOM_VK_2: 50,
- DOM_VK_3: 51,
- DOM_VK_4: 52,
- DOM_VK_5: 53,
- DOM_VK_6: 54,
- DOM_VK_7: 55,
- DOM_VK_8: 56,
- DOM_VK_9: 57,
- DOM_VK_SEMICOLON: 59,
- DOM_VK_EQUALS: 61,
- DOM_VK_A: 65,
- DOM_VK_B: 66,
- DOM_VK_C: 67,
- DOM_VK_D: 68,
- DOM_VK_E: 69,
- DOM_VK_F: 70,
- DOM_VK_G: 71,
- DOM_VK_H: 72,
- DOM_VK_I: 73,
- DOM_VK_J: 74,
- DOM_VK_K: 75,
- DOM_VK_L: 76,
- DOM_VK_M: 77,
- DOM_VK_N: 78,
- DOM_VK_O: 79,
- DOM_VK_P: 80,
- DOM_VK_Q: 81,
- DOM_VK_R: 82,
- DOM_VK_S: 83,
- DOM_VK_T: 84,
- DOM_VK_U: 85,
- DOM_VK_V: 86,
- DOM_VK_W: 87,
- DOM_VK_X: 88,
- DOM_VK_Y: 89,
- DOM_VK_Z: 90,
- DOM_VK_CONTEXT_MENU: 93,
- DOM_VK_NUMPAD0: 96,
- DOM_VK_NUMPAD1: 97,
- DOM_VK_NUMPAD2: 98,
- DOM_VK_NUMPAD3: 99,
- DOM_VK_NUMPAD4: 100,
- DOM_VK_NUMPAD5: 101,
- DOM_VK_NUMPAD6: 102,
- DOM_VK_NUMPAD7: 103,
- DOM_VK_NUMPAD8: 104,
- DOM_VK_NUMPAD9: 105,
- DOM_VK_MULTIPLY: 106,
- DOM_VK_ADD: 107,
- DOM_VK_SEPARATOR: 108,
- DOM_VK_SUBTRACT: 109,
- DOM_VK_DECIMAL: 110,
- DOM_VK_DIVIDE: 111,
- DOM_VK_F1: 112,
- DOM_VK_F2: 113,
- DOM_VK_F3: 114,
- DOM_VK_F4: 115,
- DOM_VK_F5: 116,
- DOM_VK_F6: 117,
- DOM_VK_F7: 118,
- DOM_VK_F8: 119,
- DOM_VK_F9: 120,
- DOM_VK_F10: 121,
- DOM_VK_F11: 122,
- DOM_VK_F12: 123,
- DOM_VK_F13: 124,
- DOM_VK_F14: 125,
- DOM_VK_F15: 126,
- DOM_VK_F16: 127,
- DOM_VK_F17: 128,
- DOM_VK_F18: 129,
- DOM_VK_F19: 130,
- DOM_VK_F20: 131,
- DOM_VK_F21: 132,
- DOM_VK_F22: 133,
- DOM_VK_F23: 134,
- DOM_VK_F24: 135,
- DOM_VK_NUM_LOCK: 144,
- DOM_VK_SCROLL_LOCK: 145,
- DOM_VK_COMMA: 188,
- DOM_VK_PERIOD: 190,
- DOM_VK_SLASH: 191,
- DOM_VK_BACK_QUOTE: 192,
- DOM_VK_OPEN_BRACKET: 219,
- DOM_VK_BACK_SLASH: 220,
- DOM_VK_CLOSE_BRACKET: 221,
- DOM_VK_QUOTE: 222,
- DOM_VK_META: 224
- };
- }
- // ************************************************************************************************
- // Ajax
- /**
- * @namespace
- */
- this.Ajax =
- {
- requests: [],
- transport: null,
- states: ["Uninitialized","Loading","Loaded","Interactive","Complete"],
- initialize: function()
- {
- this.transport = this.getXHRObject();
- },
- getXHRObject: function()
- {
- var xhrObj = false;
- try
- {
- xhrObj = new XMLHttpRequest();
- }
- catch(e)
- {
- var progid = [
- "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0",
- "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"
- ];
- for ( var i=0; i < progid.length; ++i ) {
- try
- {
- xhrObj = new ActiveXObject(progid[i]);
- }
- catch(e)
- {
- continue;
- }
- break;
- }
- }
- finally
- {
- return xhrObj;
- }
- },
- /**
- * Create a AJAX request.
- *
- * @name request
- * @param {Object} options request options
- * @param {String} options.url URL to be requested
- * @param {String} options.type Request type ("get" ou "post"). Default is "get".
- * @param {Boolean} options.async Asynchronous flag. Default is "true".
- * @param {String} options.dataType Data type ("text", "html", "xml" or "json"). Default is "text".
- * @param {String} options.contentType Content-type of the data being sent. Default is "application/x-www-form-urlencoded".
- * @param {Function} options.onLoading onLoading callback
- * @param {Function} options.onLoaded onLoaded callback
- * @param {Function} options.onInteractive onInteractive callback
- * @param {Function} options.onComplete onComplete callback
- * @param {Function} options.onUpdate onUpdate callback
- * @param {Function} options.onSuccess onSuccess callback
- * @param {Function} options.onFailure onFailure callback
- */
- request: function(options)
- {
- // process options
- var o = FBL.extend(
- {
- // default values
- type: "get",
- async: true,
- dataType: "text",
- contentType: "application/x-www-form-urlencoded"
- },
- options || {}
- );
- this.requests.push(o);
- var s = this.getState();
- if (s == "Uninitialized" || s == "Complete" || s == "Loaded")
- this.sendRequest();
- },
- serialize: function(data)
- {
- var r = [""], rl = 0;
- if (data) {
- if (typeof data == "string") r[rl++] = data;
- else if (data.innerHTML && data.elements) {
- for (var i=0,el,l=(el=data.elements).length; i < l; i++)
- if (el[i].name) {
- r[rl++] = encodeURIComponent(el[i].name);
- r[rl++] = "=";
- r[rl++] = encodeURIComponent(el[i].value);
- r[rl++] = "&";
- }
- } else
- for(var param in data) {
- r[rl++] = encodeURIComponent(param);
- r[rl++] = "=";
- r[rl++] = encodeURIComponent(data[param]);
- r[rl++] = "&";
- }
- }
- return r.join("").replace(/&$/, "");
- },
- sendRequest: function()
- {
- var t = FBL.Ajax.transport, r = FBL.Ajax.requests.shift(), data;
- // open XHR object
- t.open(r.type, r.url, r.async);
- //setRequestHeaders();
- // indicates that it is a XHR request to the server
- t.setRequestHeader("X-Requested-With", "XMLHttpRequest");
- // if data is being sent, sets the appropriate content-type
- if (data = FBL.Ajax.serialize(r.data))
- t.setRequestHeader("Content-Type", r.contentType);
- /** @ignore */
- // onreadystatechange handler
- t.onreadystatechange = function()
- {
- FBL.Ajax.onStateChange(r);
- };
- // send the request
- t.send(data);
- },
- /**
- * Handles the state change
- */
- onStateChange: function(options)
- {
- var fn, o = options, t = this.transport;
- var state = this.getState(t);
- if (fn = o["on" + state]) fn(this.getResponse(o), o);
- if (state == "Complete")
- {
- var success = t.status == 200, response = this.getResponse(o);
- if (fn = o["onUpdate"])
- fn(response, o);
- if (fn = o["on" + (success ? "Success" : "Failure")])
- fn(response, o);
- t.onreadystatechange = FBL.emptyFn;
- if (this.requests.length > 0)
- setTimeout(this.sendRequest, 10);
- }
- },
- /**
- * gets the appropriate response value according the type
- */
- getResponse: function(options)
- {
- var t = this.transport, type = options.dataType;
- if (t.status != 200) return t.statusText;
- else if (type == "text") return t.responseText;
- else if (type == "html") return t.responseText;
- else if (type == "xml") return t.responseXML;
- else if (type == "json") return eval("(" + t.responseText + ")");
- },
- /**
- * returns the current state of the XHR object
- */
- getState: function()
- {
- return this.states[this.transport.readyState];
- }
- };
- // ************************************************************************************************
- // Cookie, from http://www.quirksmode.org/js/cookies.html
- this.createCookie = function(name,value,days)
- {
- if ('cookie' in document)
- {
- if (days)
- {
- var date = new Date();
- date.setTime(date.getTime()+(days*24*60*60*1000));
- var expires = "; expires="+date.toGMTString();
- }
- else
- var expires = "";
- document.cookie = name+"="+value+expires+"; path=/";
- }
- };
- this.readCookie = function (name)
- {
- if ('cookie' in document)
- {
- var nameEQ = name + "=";
- var ca = document.cookie.split(';');
- for(var i=0; i < ca.length; i++)
- {
- var c = ca[i];
- while (c.charAt(0)==' ') c = c.substring(1,c.length);
- if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
- }
- }
- return null;
- };
- this.removeCookie = function(name)
- {
- this.createCookie(name, "", -1);
- };
- // ************************************************************************************************
- // http://www.mister-pixel.com/#Content__state=is_that_simple
- var fixIE6BackgroundImageCache = function(doc)
- {
- doc = doc || document;
- try
- {
- doc.execCommand("BackgroundImageCache", false, true);
- }
- catch(E)
- {
- }
- };
- // ************************************************************************************************
- // calculatePixelsPerInch
- var resetStyle = "margin:0; padding:0; border:0; position:absolute; overflow:hidden; display:block;";
- var calculatePixelsPerInch = function calculatePixelsPerInch(doc, body)
- {
- var inch = FBL.createGlobalElement("div");
- inch.style.cssText = resetStyle + "width:1in; height:1in; position:absolute; top:-1234px; left:-1234px;";
- body.appendChild(inch);
- FBL.pixelsPerInch = {
- x: inch.offsetWidth,
- y: inch.offsetHeight
- };
- body.removeChild(inch);
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.SourceLink = function(url, line, type, object, instance)
- {
- this.href = url;
- this.instance = instance;
- this.line = line;
- this.type = type;
- this.object = object;
- };
- this.SourceLink.prototype =
- {
- toString: function()
- {
- return this.href;
- },
- toJSON: function() // until 3.1...
- {
- return "{\"href\":\""+this.href+"\", "+
- (this.line?("\"line\":"+this.line+","):"")+
- (this.type?(" \"type\":\""+this.type+"\","):"")+
- "}";
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.SourceText = function(lines, owner)
- {
- this.lines = lines;
- this.owner = owner;
- };
- this.SourceText.getLineAsHTML = function(lineNo)
- {
- return escapeForSourceLine(this.lines[lineNo-1]);
- };
- // ************************************************************************************************
- }).apply(FBL);
- /* See license.txt for terms of usage */
- FBL.ns( /** @scope ns-i18n */ function() { with (FBL) {
- // ************************************************************************************************
- // TODO: xxxpedro localization
- var oSTR =
- {
- "NoMembersWarning": "There are no properties to show for this object.",
- "EmptyStyleSheet": "There are no rules in this stylesheet.",
- "EmptyElementCSS": "This element has no style rules.",
- "AccessRestricted": "Access to restricted URI denied.",
- "net.label.Parameters": "Parameters",
- "net.label.Source": "Source",
- "URLParameters": "Params",
- "EditStyle": "Edit Element Style...",
- "NewRule": "New Rule...",
- "NewProp": "New Property...",
- "EditProp": 'Edit "%s"',
- "DeleteProp": 'Delete "%s"',
- "DisableProp": 'Disable "%s"'
- };
- // ************************************************************************************************
- FBL.$STR = function(name)
- {
- return oSTR.hasOwnProperty(name) ? oSTR[name] : name;
- };
- FBL.$STRF = function(name, args)
- {
- if (!oSTR.hasOwnProperty(name)) return name;
- var format = oSTR[name];
- var objIndex = 0;
- var parts = parseFormat(format);
- var trialIndex = objIndex;
- var objects = args;
- for (var i= 0; i < parts.length; i++)
- {
- var part = parts[i];
- if (part && typeof(part) == "object")
- {
- if (++trialIndex > objects.length) // then too few parameters for format, assume unformatted.
- {
- format = "";
- objIndex = -1;
- parts.length = 0;
- break;
- }
- }
- }
- var result = [];
- for (var i = 0; i < parts.length; ++i)
- {
- var part = parts[i];
- if (part && typeof(part) == "object")
- {
- result.push(""+args.shift());
- }
- else
- result.push(part);
- }
- return result.join("");
- };
- // ************************************************************************************************
- var parseFormat = function parseFormat(format)
- {
- var parts = [];
- if (format.length <= 0)
- return parts;
- var reg = /((^%|.%)(\d+)?(\.)([a-zA-Z]))|((^%|.%)([a-zA-Z]))/;
- for (var m = reg.exec(format); m; m = reg.exec(format))
- {
- if (m[0].substr(0, 2) == "%%")
- {
- parts.push(format.substr(0, m.index));
- parts.push(m[0].substr(1));
- }
- else
- {
- var type = m[8] ? m[8] : m[5];
- var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
- var rep = null;
- switch (type)
- {
- case "s":
- rep = FirebugReps.Text;
- break;
- case "f":
- case "i":
- case "d":
- rep = FirebugReps.Number;
- break;
- case "o":
- rep = null;
- break;
- }
- parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
- parts.push({rep: rep, precision: precision, type: ("%" + type)});
- }
- format = format.substr(m.index+m[0].length);
- }
- parts.push(format);
- return parts;
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns( /** @scope ns-firebug */ function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Globals
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Internals
- var modules = [];
- var panelTypes = [];
- var panelTypeMap = {};
- var reps = [];
- var parentPanelMap = {};
- // ************************************************************************************************
- // Firebug
- /**
- * @namespace describe Firebug
- * @exports window.Firebug as Firebug
- */
- window.Firebug = FBL.Firebug =
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- version: "Firebug Lite 1.3.2",
- revision: "$Revision: 9760 $",
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- modules: modules,
- panelTypes: panelTypes,
- panelTypeMap: panelTypeMap,
- reps: reps,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Initialization
- initialize: function()
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.initialize", "initializing application");
- Firebug.browser = new Context(Env.browser);
- Firebug.context = Firebug.browser;
- // Document must be cached before chrome initialization
- cacheDocument();
- if (Firebug.Inspector)
- Firebug.Inspector.create();
- if (FBL.processAllStyleSheets)
- processAllStyleSheets(Firebug.browser.document);
- FirebugChrome.initialize();
- dispatch(modules, "initialize", []);
- if (Env.onLoad)
- {
- var onLoad = Env.onLoad;
- delete Env.onLoad;
- setTimeout(onLoad, 200);
- }
- },
- shutdown: function()
- {
- if (Firebug.Inspector)
- Firebug.Inspector.destroy();
- dispatch(modules, "shutdown", []);
- var chromeMap = FirebugChrome.chromeMap;
- for (var name in chromeMap)
- {
- if (chromeMap.hasOwnProperty(name))
- {
- chromeMap[name].destroy();
- }
- }
- Firebug.Lite.Cache.Element.clear();
- Firebug.Lite.Cache.StyleSheet.clear();
- Firebug.browser = null;
- Firebug.context = null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Registration
- registerModule: function()
- {
- modules.push.apply(modules, arguments);
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.registerModule");
- },
- registerPanel: function()
- {
- panelTypes.push.apply(panelTypes, arguments);
- for (var i = 0, panelType; panelType = arguments[i]; ++i)
- {
- panelTypeMap[panelType.prototype.name] = arguments[i];
- if (panelType.prototype.parentPanel)
- parentPanelMap[panelType.prototype.parentPanel] = 1;
- }
- if (FBTrace.DBG_INITIALIZE)
- for (var i = 0; i < arguments.length; ++i)
- FBTrace.sysout("Firebug.registerPanel", arguments[i].prototype.name);
- },
- registerRep: function()
- {
- reps.push.apply(reps, arguments);
- },
- unregisterRep: function()
- {
- for (var i = 0; i < arguments.length; ++i)
- remove(reps, arguments[i]);
- },
- setDefaultReps: function(funcRep, rep)
- {
- FBL.defaultRep = rep;
- FBL.defaultFuncRep = funcRep;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Reps
- getRep: function(object)
- {
- var type = typeof object;
- if (isIE && isFunction(object))
- type = "function";
- for (var i = 0; i < reps.length; ++i)
- {
- var rep = reps[i];
- try
- {
- if (rep.supportsObject(object, type))
- {
- if (FBTrace.DBG_DOM)
- FBTrace.sysout("getRep type: "+type+" object: "+object, rep);
- return rep;
- }
- }
- catch (exc)
- {
- if (FBTrace.DBG_ERRORS)
- {
- FBTrace.sysout("firebug.getRep FAILS: ", exc.message || exc);
- FBTrace.sysout("firebug.getRep reps["+i+"/"+reps.length+"]: Rep="+reps[i].className);
- // TODO: xxxpedro add trace to FBTrace logs like in Firebug
- //firebug.trace();
- }
- }
- }
- return (type == 'function') ? defaultFuncRep : defaultRep;
- },
- getRepObject: function(node)
- {
- var target = null;
- for (var child = node; child; child = child.parentNode)
- {
- if (hasClass(child, "repTarget"))
- target = child;
- if (child.repObject)
- {
- if (!target && hasClass(child, "repIgnore"))
- break;
- else
- return child.repObject;
- }
- }
- },
- getRepNode: function(node)
- {
- for (var child = node; child; child = child.parentNode)
- {
- if (child.repObject)
- return child;
- }
- },
- getElementByRepObject: function(element, object)
- {
- for (var child = element.firstChild; child; child = child.nextSibling)
- {
- if (child.repObject == object)
- return child;
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Preferences
- getPref: function(name)
- {
- return Firebug[name];
- },
- setPref: function(name, value)
- {
- Firebug[name] = value;
- this.savePrefs();
- },
- setPrefs: function(prefs)
- {
- for (var name in prefs)
- {
- if (prefs.hasOwnProperty(name))
- Firebug[name] = prefs[name];
- }
- this.savePrefs();
- },
- restorePrefs: function()
- {
- var Options = Env.Options;
- for (var name in Options)
- {
- Firebug[name] = Options[name];
- }
- },
- loadPrefs: function(prefs)
- {
- this.restorePrefs();
- prefs = prefs || eval("(" + readCookie("FirebugLite") + ")");
- for (var name in prefs)
- {
- if (prefs.hasOwnProperty(name))
- Firebug[name] = prefs[name];
- }
- },
- savePrefs: function()
- {
- var json = ['{'], jl = 0;
- var Options = Env.Options;
- for (var name in Options)
- {
- if (Options.hasOwnProperty(name))
- {
- var value = Firebug[name];
- json[++jl] = '"';
- json[++jl] = name;
- var type = typeof value;
- if (type == "boolean" || type == "number")
- {
- json[++jl] = '":';
- json[++jl] = value;
- json[++jl] = ',';
- }
- else
- {
- json[++jl] = '":"';
- json[++jl] = value;
- json[++jl] = '",';
- }
- }
- }
- json.length = jl--;
- json[++jl] = '}';
- createCookie("FirebugLite", json.join(""));
- },
- erasePrefs: function()
- {
- removeCookie("FirebugLite");
- }
- };
- Firebug.restorePrefs();
- if (!Env.Options.enablePersistent ||
- Env.Options.enablePersistent && Env.isChromeContext ||
- Env.isDebugMode)
- Env.browser.window.Firebug = FBL.Firebug;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Other methods
- FBL.cacheDocument = function cacheDocument()
- {
- var ElementCache = Firebug.Lite.Cache.Element;
- var els = Firebug.browser.document.getElementsByTagName("*");
- for (var i=0, l=els.length, el; i<l; i++)
- {
- el = els[i];
- ElementCache(el);
- }
- };
- // ************************************************************************************************
- /**
- * @class
- *
- * Support for listeners registration. This object also extended by Firebug.Module so,
- * all modules supports listening automatically. Notice that array of listeners
- * is created for each intance of a module within initialize method. Thus all derived
- * module classes must ensure that Firebug.Module.initialize method is called for the
- * super class.
- */
- Firebug.Listener = function()
- {
- // The array is created when the first listeners is added.
- // It can't be created here since derived objects would share
- // the same array.
- this.fbListeners = null;
- };
- Firebug.Listener.prototype =
- {
- addListener: function(listener)
- {
- if (!this.fbListeners)
- this.fbListeners = []; // delay the creation until the objects are created so 'this' causes new array for each module
- this.fbListeners.push(listener);
- },
- removeListener: function(listener)
- {
- remove(this.fbListeners, listener); // if this.fbListeners is null, remove is being called with no add
- }
- };
- // ************************************************************************************************
- // ************************************************************************************************
- // Module
- /**
- * @module Base class for all modules. Every derived module object must be registered using
- * <code>Firebug.registerModule</code> method. There is always one instance of a module object
- * per browser window.
- * @extends Firebug.Listener
- */
- Firebug.Module = extend(new Firebug.Listener(),
- /** @extend Firebug.Module */
- {
- /**
- * Called when the window is opened.
- */
- initialize: function()
- {
- },
- /**
- * Called when the window is closed.
- */
- shutdown: function()
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**
- * Called when a new context is created but before the page is loaded.
- */
- initContext: function(context)
- {
- },
- /**
- * Called after a context is detached to a separate window;
- */
- reattachContext: function(browser, context)
- {
- },
- /**
- * Called when a context is destroyed. Module may store info on persistedState for reloaded pages.
- */
- destroyContext: function(context, persistedState)
- {
- },
- // Called when a FF tab is create or activated (user changes FF tab)
- // Called after context is created or with context == null (to abort?)
- showContext: function(browser, context)
- {
- },
- /**
- * Called after a context's page gets DOMContentLoaded
- */
- loadedContext: function(context)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- showPanel: function(browser, panel)
- {
- },
- showSidePanel: function(browser, panel)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- updateOption: function(name, value)
- {
- },
- getObjectByURL: function(context, url)
- {
- }
- });
- // ************************************************************************************************
- // Panel
- /**
- * @panel Base class for all panels. Every derived panel must define a constructor and
- * register with "Firebug.registerPanel" method. An instance of the panel
- * object is created by the framework for each browser tab where Firebug is activated.
- */
- Firebug.Panel =
- {
- name: "HelloWorld",
- title: "Hello World!",
- parentPanel: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- options: {
- hasCommandLine: false,
- hasStatusBar: false,
- hasToolButtons: false,
- // Pre-rendered panels are those included in the skin file (firebug.html)
- isPreRendered: false,
- innerHTMLSync: false
- /*
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // To be used by external extensions
- panelHTML: "",
- panelCSS: "",
- toolButtonsHTML: ""
- /**/
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- tabNode: null,
- panelNode: null,
- sidePanelNode: null,
- statusBarNode: null,
- toolButtonsNode: null,
- panelBarNode: null,
- sidePanelBarBoxNode: null,
- sidePanelBarNode: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- sidePanelBar: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- searchable: false,
- editable: true,
- order: 2147483647,
- statusSeparator: "<",
- create: function(context, doc)
- {
- this.hasSidePanel = parentPanelMap.hasOwnProperty(this.name);
- this.panelBarNode = $("fbPanelBar1");
- this.sidePanelBarBoxNode = $("fbPanelBar2");
- if (this.hasSidePanel)
- {
- this.sidePanelBar = extend({}, PanelBar);
- this.sidePanelBar.create(this);
- }
- var options = this.options = extend(Firebug.Panel.options, this.options);
- var panelId = "fb" + this.name;
- if (options.isPreRendered)
- {
- this.panelNode = $(panelId);
- this.tabNode = $(panelId + "Tab");
- this.tabNode.style.display = "block";
- if (options.hasToolButtons)
- {
- this.toolButtonsNode = $(panelId + "Buttons");
- }
- if (options.hasStatusBar)
- {
- this.statusBarBox = $("fbStatusBarBox");
- this.statusBarNode = $(panelId + "StatusBar");
- }
- }
- else
- {
- var containerSufix = this.parentPanel ? "2" : "1";
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Create Panel
- var panelNode = this.panelNode = createElement("div", {
- id: panelId,
- className: "fbPanel"
- });
- $("fbPanel" + containerSufix).appendChild(panelNode);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Create Panel Tab
- var tabHTML = '<span class="fbTabL"></span><span class="fbTabText">' +
- this.title + '</span><span class="fbTabR"></span>';
- var tabNode = this.tabNode = createElement("a", {
- id: panelId + "Tab",
- className: "fbTab fbHover",
- innerHTML: tabHTML
- });
- if (isIE6)
- {
- tabNode.href = "javascript:void(0)";
- }
- var panelBarNode = this.parentPanel ?
- Firebug.chrome.getPanel(this.parentPanel).sidePanelBarNode :
- this.panelBarNode;
- panelBarNode.appendChild(tabNode);
- tabNode.style.display = "block";
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // create ToolButtons
- if (options.hasToolButtons)
- {
- this.toolButtonsNode = createElement("span", {
- id: panelId + "Buttons",
- className: "fbToolbarButtons"
- });
- $("fbToolbarButtons").appendChild(this.toolButtonsNode);
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // create StatusBar
- if (options.hasStatusBar)
- {
- this.statusBarBox = $("fbStatusBarBox");
- this.statusBarNode = createElement("span", {
- id: panelId + "StatusBar",
- className: "fbToolbarButtons fbStatusBar"
- });
- this.statusBarBox.appendChild(this.statusBarNode);
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // create SidePanel
- }
- this.containerNode = this.panelNode.parentNode;
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.create", this.name);
- // xxxpedro contextMenu
- this.onContextMenu = bind(this.onContextMenu, this);
- /*
- this.context = context;
- this.document = doc;
- this.panelNode = doc.createElement("div");
- this.panelNode.ownerPanel = this;
- setClass(this.panelNode, "panelNode panelNode-"+this.name+" contextUID="+context.uid);
- doc.body.appendChild(this.panelNode);
- if (FBTrace.DBG_INITIALIZE)
- FBTrace.sysout("firebug.initialize panelNode for "+this.name+"\n");
- this.initializeNode(this.panelNode);
- /**/
- },
- destroy: function(state) // Panel may store info on state
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.destroy", this.name);
- if (this.hasSidePanel)
- {
- this.sidePanelBar.destroy();
- this.sidePanelBar = null;
- }
- this.options = null;
- this.name = null;
- this.parentPanel = null;
- this.tabNode = null;
- this.panelNode = null;
- this.containerNode = null;
- this.toolButtonsNode = null;
- this.statusBarBox = null;
- this.statusBarNode = null;
- //if (this.panelNode)
- // delete this.panelNode.ownerPanel;
- //this.destroyNode();
- },
- initialize: function()
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.initialize", this.name);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- if (this.hasSidePanel)
- {
- this.sidePanelBar.initialize();
- }
- var options = this.options = extend(Firebug.Panel.options, this.options);
- var panelId = "fb" + this.name;
- this.panelNode = $(panelId);
- this.tabNode = $(panelId + "Tab");
- this.tabNode.style.display = "block";
- if (options.hasStatusBar)
- {
- this.statusBarBox = $("fbStatusBarBox");
- this.statusBarNode = $(panelId + "StatusBar");
- }
- if (options.hasToolButtons)
- {
- this.toolButtonsNode = $(panelId + "Buttons");
- }
- this.containerNode = this.panelNode.parentNode;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // restore persistent state
- this.containerNode.scrollTop = this.lastScrollTop;
- // xxxpedro contextMenu
- addEvent(this.containerNode, "contextmenu", this.onContextMenu);
- /// TODO: xxxpedro infoTip Hack
- Firebug.chrome.currentPanel =
- Firebug.chrome.selectedPanel && Firebug.chrome.selectedPanel.sidePanelBar ?
- Firebug.chrome.selectedPanel.sidePanelBar.selectedPanel :
- Firebug.chrome.selectedPanel;
- Firebug.showInfoTips = true;
- Firebug.InfoTip.initializeBrowser(Firebug.chrome);
- },
- shutdown: function()
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.shutdown", this.name);
- /// TODO: xxxpedro infoTip Hack
- Firebug.InfoTip.uninitializeBrowser(Firebug.chrome);
- if (Firebug.chrome.largeCommandLineVisible)
- Firebug.chrome.hideLargeCommandLine();
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- if (this.hasSidePanel)
- {
- // TODO: xxxpedro firebug1.3a6
- // new PanelBar mechanism will need to call shutdown to hide the panels (so it
- // doesn't appears in other panel's sidePanelBar. Therefore, we need to implement
- // a "remember selected panel" feature in the sidePanelBar
- //this.sidePanelBar.shutdown();
- }
- // store persistent state
- this.lastScrollTop = this.containerNode.scrollTop;
- // xxxpedro contextMenu
- removeEvent(this.containerNode, "contextmenu", this.onContextMenu);
- },
- detach: function(oldChrome, newChrome)
- {
- if (oldChrome.selectedPanel.name == this.name)
- this.lastScrollTop = oldChrome.selectedPanel.containerNode.scrollTop;
- },
- reattach: function(doc)
- {
- if (this.options.innerHTMLSync)
- this.synchronizeUI();
- },
- synchronizeUI: function()
- {
- this.containerNode.scrollTop = this.lastScrollTop || 0;
- },
- show: function(state)
- {
- var options = this.options;
- if (options.hasStatusBar)
- {
- this.statusBarBox.style.display = "inline";
- this.statusBarNode.style.display = "inline";
- }
- if (options.hasToolButtons)
- {
- this.toolButtonsNode.style.display = "inline";
- }
- this.panelNode.style.display = "block";
- this.visible = true;
- if (!this.parentPanel)
- Firebug.chrome.layout(this);
- },
- hide: function(state)
- {
- var options = this.options;
- if (options.hasStatusBar)
- {
- this.statusBarBox.style.display = "none";
- this.statusBarNode.style.display = "none";
- }
- if (options.hasToolButtons)
- {
- this.toolButtonsNode.style.display = "none";
- }
- this.panelNode.style.display = "none";
- this.visible = false;
- },
- watchWindow: function(win)
- {
- },
- unwatchWindow: function(win)
- {
- },
- updateOption: function(name, value)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**
- * Toolbar helpers
- */
- showToolbarButtons: function(buttonsId, show)
- {
- try
- {
- if (!this.context.browser) // XXXjjb this is bug. Somehow the panel context is not FirebugContext.
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("firebug.Panel showToolbarButtons this.context has no browser, this:", this);
- return;
- }
- var buttons = this.context.browser.chrome.$(buttonsId);
- if (buttons)
- collapse(buttons, show ? "false" : "true");
- }
- catch (exc)
- {
- if (FBTrace.DBG_ERRORS)
- {
- FBTrace.dumpProperties("firebug.Panel showToolbarButtons FAILS", exc);
- if (!this.context.browser)FBTrace.dumpStack("firebug.Panel showToolbarButtons no browser");
- }
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**
- * Returns a number indicating the view's ability to inspect the object.
- *
- * Zero means not supported, and higher numbers indicate specificity.
- */
- supportsObject: function(object)
- {
- return 0;
- },
- hasObject: function(object) // beyond type testing, is this object selectable?
- {
- return false;
- },
- select: function(object, forceUpdate)
- {
- if (!object)
- object = this.getDefaultSelection(this.context);
- if(FBTrace.DBG_PANELS)
- FBTrace.sysout("firebug.select "+this.name+" forceUpdate: "+forceUpdate+" "+object+((object==this.selection)?"==":"!=")+this.selection);
- if (forceUpdate || object != this.selection)
- {
- this.selection = object;
- this.updateSelection(object);
- // TODO: xxxpedro
- // XXXjoe This is kind of cheating, but, feh.
- //Firebug.chrome.onPanelSelect(object, this);
- //if (uiListeners.length > 0)
- // dispatch(uiListeners, "onPanelSelect", [object, this]); // TODO: make Firebug.chrome a uiListener
- }
- },
- updateSelection: function(object)
- {
- },
- markChange: function(skipSelf)
- {
- if (this.dependents)
- {
- if (skipSelf)
- {
- for (var i = 0; i < this.dependents.length; ++i)
- {
- var panelName = this.dependents[i];
- if (panelName != this.name)
- this.context.invalidatePanels(panelName);
- }
- }
- else
- this.context.invalidatePanels.apply(this.context, this.dependents);
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- startInspecting: function()
- {
- },
- stopInspecting: function(object, cancelled)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- search: function(text, reverse)
- {
- },
- /**
- * Retrieves the search options that this modules supports.
- * This is used by the search UI to present the proper options.
- */
- getSearchOptionsMenuItems: function()
- {
- return [
- Firebug.Search.searchOptionMenu("search.Case Sensitive", "searchCaseSensitive")
- ];
- },
- /**
- * Navigates to the next document whose match parameter returns true.
- */
- navigateToNextDocument: function(match, reverse)
- {
- // This is an approximation of the UI that is displayed by the location
- // selector. This should be close enough, although it may be better
- // to simply generate the sorted list within the module, rather than
- // sorting within the UI.
- var self = this;
- function compare(a, b) {
- var locA = self.getObjectDescription(a);
- var locB = self.getObjectDescription(b);
- if(locA.path > locB.path)
- return 1;
- if(locA.path < locB.path)
- return -1;
- if(locA.name > locB.name)
- return 1;
- if(locA.name < locB.name)
- return -1;
- return 0;
- }
- var allLocs = this.getLocationList().sort(compare);
- for (var curPos = 0; curPos < allLocs.length && allLocs[curPos] != this.location; curPos++);
- function transformIndex(index) {
- if (reverse) {
- // For the reverse case we need to implement wrap around.
- var intermediate = curPos - index - 1;
- return (intermediate < 0 ? allLocs.length : 0) + intermediate;
- } else {
- return (curPos + index + 1) % allLocs.length;
- }
- };
- for (var next = 0; next < allLocs.length - 1; next++)
- {
- var object = allLocs[transformIndex(next)];
- if (match(object))
- {
- this.navigate(object);
- return object;
- }
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Called when "Options" clicked. Return array of
- // {label: 'name', nol10n: true, type: "checkbox", checked: <value>, command:function to set <value>}
- getOptionsMenuItems: function()
- {
- return null;
- },
- /*
- * Called by chrome.onContextMenu to build the context menu when this panel has focus.
- * See also FirebugRep for a similar function also called by onContextMenu
- * Extensions may monkey patch and chain off this call
- * @param object: the 'realObject', a model value, eg a DOM property
- * @param target: the HTML element clicked on.
- * @return an array of menu items.
- */
- getContextMenuItems: function(object, target)
- {
- return [];
- },
- getBreakOnMenuItems: function()
- {
- return [];
- },
- getEditor: function(target, value)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getDefaultSelection: function()
- {
- return null;
- },
- browseObject: function(object)
- {
- },
- getPopupObject: function(target)
- {
- return Firebug.getRepObject(target);
- },
- getTooltipObject: function(target)
- {
- return Firebug.getRepObject(target);
- },
- showInfoTip: function(infoTip, x, y)
- {
- },
- getObjectPath: function(object)
- {
- return null;
- },
- // An array of objects that can be passed to getObjectLocation.
- // The list of things a panel can show, eg sourceFiles.
- // Only shown if panel.location defined and supportsObject true
- getLocationList: function()
- {
- return null;
- },
- getDefaultLocation: function()
- {
- return null;
- },
- getObjectLocation: function(object)
- {
- return "";
- },
- // Text for the location list menu eg script panel source file list
- // return.path: group/category label, return.name: item label
- getObjectDescription: function(object)
- {
- var url = this.getObjectLocation(object);
- return FBL.splitURLBase(url);
- },
- /*
- * UI signal that a tab needs attention, eg Script panel is currently stopped on a breakpoint
- * @param: show boolean, true turns on.
- */
- highlight: function(show)
- {
- var tab = this.getTab();
- if (!tab)
- return;
- if (show)
- tab.setAttribute("highlight", "true");
- else
- tab.removeAttribute("highlight");
- },
- getTab: function()
- {
- var chrome = Firebug.chrome;
- var tab = chrome.$("fbPanelBar2").getTab(this.name);
- if (!tab)
- tab = chrome.$("fbPanelBar1").getTab(this.name);
- return tab;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Support for Break On Next
- /**
- * Called by the framework when the user clicks on the Break On Next button.
- * @param {Boolean} armed Set to true if the Break On Next feature is
- * to be armed for action and set to false if the Break On Next should be disarmed.
- * If 'armed' is true, then the next call to shouldBreakOnNext should be |true|.
- */
- breakOnNext: function(armed)
- {
- },
- /**
- * Called when a panel is selected/displayed. The method should return true
- * if the Break On Next feature is currently armed for this panel.
- */
- shouldBreakOnNext: function()
- {
- return false;
- },
- /**
- * Returns labels for Break On Next tooltip (one for enabled and one for disabled state).
- * @param {Boolean} enabled Set to true if the Break On Next feature is
- * currently activated for this panel.
- */
- getBreakOnNextTooltip: function(enabled)
- {
- return null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // xxxpedro contextMenu
- onContextMenu: function(event)
- {
- if (!this.getContextMenuItems)
- return;
- cancelEvent(event, true);
- var target = event.target || event.srcElement;
- var menu = this.getContextMenuItems(this.selection, target);
- if (!menu)
- return;
- var contextMenu = new Menu(
- {
- id: "fbPanelContextMenu",
- items: menu
- });
- contextMenu.show(event.clientX, event.clientY);
- return true;
- /*
- // TODO: xxxpedro move code to somewhere. code to get cross-browser
- // window to screen coordinates
- var box = Firebug.browser.getElementPosition(Firebug.chrome.node);
- var screenY = 0;
- // Firefox
- if (typeof window.mozInnerScreenY != "undefined")
- {
- screenY = window.mozInnerScreenY;
- }
- // Chrome
- else if (typeof window.innerHeight != "undefined")
- {
- screenY = window.outerHeight - window.innerHeight;
- }
- // IE
- else if (typeof window.screenTop != "undefined")
- {
- screenY = window.screenTop;
- }
- contextMenu.show(event.screenX-box.left, event.screenY-screenY-box.top);
- /**/
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**
- * MeasureBox
- * To get pixels size.width and size.height:
- * <ul><li> this.startMeasuring(view); </li>
- * <li> var size = this.measureText(lineNoCharsSpacer); </li>
- * <li> this.stopMeasuring(); </li>
- * </ul>
- *
- * @namespace
- */
- Firebug.MeasureBox =
- {
- startMeasuring: function(target)
- {
- if (!this.measureBox)
- {
- this.measureBox = target.ownerDocument.createElement("span");
- this.measureBox.className = "measureBox";
- }
- copyTextStyles(target, this.measureBox);
- target.ownerDocument.body.appendChild(this.measureBox);
- },
- getMeasuringElement: function()
- {
- return this.measureBox;
- },
- measureText: function(value)
- {
- this.measureBox.innerHTML = value ? escapeForSourceLine(value) : "m";
- return {width: this.measureBox.offsetWidth, height: this.measureBox.offsetHeight-1};
- },
- measureInputText: function(value)
- {
- value = value ? escapeForTextNode(value) : "m";
- if (!Firebug.showTextNodesWithWhitespace)
- value = value.replace(/\t/g,'mmmmmm').replace(/\ /g,'m');
- this.measureBox.innerHTML = value;
- return {width: this.measureBox.offsetWidth, height: this.measureBox.offsetHeight-1};
- },
- getBox: function(target)
- {
- var style = this.measureBox.ownerDocument.defaultView.getComputedStyle(this.measureBox, "");
- var box = getBoxFromStyles(style, this.measureBox);
- return box;
- },
- stopMeasuring: function()
- {
- this.measureBox.parentNode.removeChild(this.measureBox);
- }
- };
- // ************************************************************************************************
- if (FBL.domplate) Firebug.Rep = domplate(
- {
- className: "",
- inspectable: true,
- supportsObject: function(object, type)
- {
- return false;
- },
- inspectObject: function(object, context)
- {
- Firebug.chrome.select(object);
- },
- browseObject: function(object, context)
- {
- },
- persistObject: function(object, context)
- {
- },
- getRealObject: function(object, context)
- {
- return object;
- },
- getTitle: function(object)
- {
- var label = safeToString(object);
- var re = /\[object (.*?)\]/;
- var m = re.exec(label);
- ///return m ? m[1] : label;
- // if the label is in the "[object TYPE]" format return its type
- if (m)
- {
- return m[1];
- }
- // if it is IE we need to handle some special cases
- else if (
- // safeToString() fails to recognize some objects in IE
- isIE &&
- // safeToString() returns "[object]" for some objects like window.Image
- (label == "[object]" ||
- // safeToString() returns undefined for some objects like window.clientInformation
- typeof object == "object" && typeof label == "undefined")
- )
- {
- return "Object";
- }
- else
- {
- return label;
- }
- },
- getTooltip: function(object)
- {
- return null;
- },
- getContextMenuItems: function(object, target, context)
- {
- return [];
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Convenience for domplates
- STR: function(name)
- {
- return $STR(name);
- },
- cropString: function(text)
- {
- return cropString(text);
- },
- cropMultipleLines: function(text, limit)
- {
- return cropMultipleLines(text, limit);
- },
- toLowerCase: function(text)
- {
- return text ? text.toLowerCase() : text;
- },
- plural: function(n)
- {
- return n == 1 ? "" : "s";
- }
- });
- // ************************************************************************************************
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns( /** @scope ns-gui */ function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Controller
- /**@namespace*/
- FBL.Controller = {
- controllers: null,
- controllerContext: null,
- initialize: function(context)
- {
- this.controllers = [];
- this.controllerContext = context || Firebug.chrome;
- },
- shutdown: function()
- {
- this.removeControllers();
- //this.controllers = null;
- //this.controllerContext = null;
- },
- addController: function()
- {
- for (var i=0, arg; arg=arguments[i]; i++)
- {
- // If the first argument is a string, make a selector query
- // within the controller node context
- if (typeof arg[0] == "string")
- {
- arg[0] = $$(arg[0], this.controllerContext);
- }
- // bind the handler to the proper context
- var handler = arg[2];
- arg[2] = bind(handler, this);
- // save the original handler as an extra-argument, so we can
- // look for it later, when removing a particular controller
- arg[3] = handler;
- this.controllers.push(arg);
- addEvent.apply(this, arg);
- }
- },
- removeController: function()
- {
- for (var i=0, arg; arg=arguments[i]; i++)
- {
- for (var j=0, c; c=this.controllers[j]; j++)
- {
- if (arg[0] == c[0] && arg[1] == c[1] && arg[2] == c[3])
- removeEvent.apply(this, c);
- }
- }
- },
- removeControllers: function()
- {
- for (var i=0, c; c=this.controllers[i]; i++)
- {
- removeEvent.apply(this, c);
- }
- }
- };
- // ************************************************************************************************
- // PanelBar
- /**@namespace*/
- FBL.PanelBar =
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- panelMap: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- selectedPanel: null,
- parentPanelName: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- create: function(ownerPanel)
- {
- this.panelMap = {};
- this.ownerPanel = ownerPanel;
- if (ownerPanel)
- {
- ownerPanel.sidePanelBarNode = createElement("span");
- ownerPanel.sidePanelBarNode.style.display = "none";
- ownerPanel.sidePanelBarBoxNode.appendChild(ownerPanel.sidePanelBarNode);
- }
- var panels = Firebug.panelTypes;
- for (var i=0, p; p=panels[i]; i++)
- {
- if ( // normal Panel of the Chrome's PanelBar
- !ownerPanel && !p.prototype.parentPanel ||
- // Child Panel of the current Panel's SidePanelBar
- ownerPanel && p.prototype.parentPanel &&
- ownerPanel.name == p.prototype.parentPanel)
- {
- this.addPanel(p.prototype.name);
- }
- }
- },
- destroy: function()
- {
- PanelBar.shutdown.call(this);
- for (var name in this.panelMap)
- {
- this.removePanel(name);
- var panel = this.panelMap[name];
- panel.destroy();
- this.panelMap[name] = null;
- delete this.panelMap[name];
- }
- this.panelMap = null;
- this.ownerPanel = null;
- },
- initialize: function()
- {
- if (this.ownerPanel)
- this.ownerPanel.sidePanelBarNode.style.display = "inline";
- for(var name in this.panelMap)
- {
- (function(self, name){
- // tab click handler
- var onTabClick = function onTabClick()
- {
- self.selectPanel(name);
- return false;
- };
- Firebug.chrome.addController([self.panelMap[name].tabNode, "mousedown", onTabClick]);
- })(this, name);
- }
- },
- shutdown: function()
- {
- var selectedPanel = this.selectedPanel;
- if (selectedPanel)
- {
- removeClass(selectedPanel.tabNode, "fbSelectedTab");
- selectedPanel.hide();
- selectedPanel.shutdown();
- }
- if (this.ownerPanel)
- this.ownerPanel.sidePanelBarNode.style.display = "none";
- this.selectedPanel = null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- addPanel: function(panelName, parentPanel)
- {
- var PanelType = Firebug.panelTypeMap[panelName];
- var panel = this.panelMap[panelName] = new PanelType();
- panel.create();
- },
- removePanel: function(panelName)
- {
- var panel = this.panelMap[panelName];
- if (panel.hasOwnProperty(panelName))
- panel.destroy();
- },
- selectPanel: function(panelName)
- {
- var selectedPanel = this.selectedPanel;
- var panel = this.panelMap[panelName];
- if (panel && selectedPanel != panel)
- {
- if (selectedPanel)
- {
- removeClass(selectedPanel.tabNode, "fbSelectedTab");
- selectedPanel.shutdown();
- selectedPanel.hide();
- }
- if (!panel.parentPanel)
- FirebugChrome.selectedPanelName = panelName;
- this.selectedPanel = panel;
- setClass(panel.tabNode, "fbSelectedTab");
- panel.show();
- panel.initialize();
- }
- },
- getPanel: function(panelName)
- {
- var panel = this.panelMap[panelName];
- return panel;
- }
- };
- //************************************************************************************************
- // Button
- /**
- * options.element
- * options.caption
- * options.title
- *
- * options.owner
- * options.className
- * options.pressedClassName
- *
- * options.onPress
- * options.onUnpress
- * options.onClick
- *
- * @class
- * @extends FBL.Controller
- *
- */
- FBL.Button = function(options)
- {
- options = options || {};
- append(this, options);
- this.state = "unpressed";
- this.display = "unpressed";
- if (this.element)
- {
- this.container = this.element.parentNode;
- }
- else
- {
- this.shouldDestroy = true;
- this.container = this.owner.getPanel().toolButtonsNode;
- this.element = createElement("a", {
- className: this.baseClassName + " " + this.className + " fbHover",
- innerHTML: this.caption
- });
- if (this.title)
- this.element.title = this.title;
- this.container.appendChild(this.element);
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- Button.prototype = extend(Controller,
- /**@extend FBL.Button.prototype*/
- {
- type: "normal",
- caption: "caption",
- title: null,
- className: "", // custom class
- baseClassName: "fbButton", // control class
- pressedClassName: "fbBtnPressed", // control pressed class
- element: null,
- container: null,
- owner: null,
- state: null,
- display: null,
- destroy: function()
- {
- this.shutdown();
- // only remove if it is a dynamically generated button (not pre-rendered)
- if (this.shouldDestroy)
- this.container.removeChild(this.element);
- this.element = null;
- this.container = null;
- this.owner = null;
- },
- initialize: function()
- {
- Controller.initialize.apply(this);
- var element = this.element;
- this.addController([element, "mousedown", this.handlePress]);
- if (this.type == "normal")
- this.addController(
- [element, "mouseup", this.handleUnpress],
- [element, "mouseout", this.handleUnpress],
- [element, "click", this.handleClick]
- );
- },
- shutdown: function()
- {
- Controller.shutdown.apply(this);
- },
- restore: function()
- {
- this.changeState("unpressed");
- },
- changeState: function(state)
- {
- this.state = state;
- this.changeDisplay(state);
- },
- changeDisplay: function(display)
- {
- if (display != this.display)
- {
- if (display == "pressed")
- {
- setClass(this.element, this.pressedClassName);
- }
- else if (display == "unpressed")
- {
- removeClass(this.element, this.pressedClassName);
- }
- this.display = display;
- }
- },
- handlePress: function(event)
- {
- cancelEvent(event, true);
- if (this.type == "normal")
- {
- this.changeDisplay("pressed");
- this.beforeClick = true;
- }
- else if (this.type == "toggle")
- {
- if (this.state == "pressed")
- {
- this.changeState("unpressed");
- if (this.onUnpress)
- this.onUnpress.apply(this.owner, arguments);
- }
- else
- {
- this.changeState("pressed");
- if (this.onPress)
- this.onPress.apply(this.owner, arguments);
- }
- if (this.onClick)
- this.onClick.apply(this.owner, arguments);
- }
- return false;
- },
- handleUnpress: function(event)
- {
- cancelEvent(event, true);
- if (this.beforeClick)
- this.changeDisplay("unpressed");
- return false;
- },
- handleClick: function(event)
- {
- cancelEvent(event, true);
- if (this.type == "normal")
- {
- if (this.onClick)
- this.onClick.apply(this.owner);
- this.changeState("unpressed");
- }
- this.beforeClick = false;
- return false;
- }
- });
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**
- * @class
- * @extends FBL.Button
- */
- FBL.IconButton = function()
- {
- Button.apply(this, arguments);
- };
- IconButton.prototype = extend(Button.prototype,
- /**@extend FBL.IconButton.prototype*/
- {
- baseClassName: "fbIconButton",
- pressedClassName: "fbIconPressed"
- });
- //************************************************************************************************
- // Menu
- var menuItemProps = {"class": "$item.className", type: "$item.type", value: "$item.value",
- _command: "$item.command"};
- if (isIE6)
- menuItemProps.href = "javascript:void(0)";
- // Allow GUI to be loaded even when Domplate module is not installed.
- if (FBL.domplate)
- var MenuPlate = domplate(Firebug.Rep,
- {
- tag:
- DIV({"class": "fbMenu fbShadow"},
- DIV({"class": "fbMenuContent fbShadowContent"},
- FOR("item", "$object.items|memberIterator",
- TAG("$item.tag", {item: "$item"})
- )
- )
- ),
- itemTag:
- A(menuItemProps,
- "$item.label"
- ),
- checkBoxTag:
- A(extend(menuItemProps, {checked : "$item.checked"}),
- "$item.label"
- ),
- radioButtonTag:
- A(extend(menuItemProps, {selected : "$item.selected"}),
- "$item.label"
- ),
- groupTag:
- A(extend(menuItemProps, {child: "$item.child"}),
- "$item.label"
- ),
- shortcutTag:
- A(menuItemProps,
- "$item.label",
- SPAN({"class": "fbMenuShortcutKey"},
- "$item.key"
- )
- ),
- separatorTag:
- SPAN({"class": "fbMenuSeparator"}),
- memberIterator: function(items)
- {
- var result = [];
- for (var i=0, length=items.length; i<length; i++)
- {
- var item = items[i];
- // separator representation
- if (typeof item == "string" && item.indexOf("-") == 0)
- {
- result.push({tag: this.separatorTag});
- continue;
- }
- item = extend(item, {});
- item.type = item.type || "";
- item.value = item.value || "";
- var type = item.type;
- // default item representation
- item.tag = this.itemTag;
- var className = item.className || "";
- className += "fbMenuOption fbHover ";
- // specific representations
- if (type == "checkbox")
- {
- className += "fbMenuCheckBox ";
- item.tag = this.checkBoxTag;
- }
- else if (type == "radiobutton")
- {
- className += "fbMenuRadioButton ";
- item.tag = this.radioButtonTag;
- }
- else if (type == "group")
- {
- className += "fbMenuGroup ";
- item.tag = this.groupTag;
- }
- else if (type == "shortcut")
- {
- className += "fbMenuShortcut ";
- item.tag = this.shortcutTag;
- }
- if (item.checked)
- className += "fbMenuChecked ";
- else if (item.selected)
- className += "fbMenuRadioSelected ";
- if (item.disabled)
- className += "fbMenuDisabled ";
- item.className = className;
- item.label = $STR(item.label);
- result.push(item);
- }
- return result;
- }
- });
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**
- * options
- * options.element
- * options.id
- * options.items
- *
- * item.label
- * item.className
- * item.type
- * item.value
- * item.disabled
- * item.checked
- * item.selected
- * item.command
- * item.child
- *
- *
- * @class
- * @extends FBL.Controller
- *
- */
- FBL.Menu = function(options)
- {
- // if element is not pre-rendered, we must render it now
- if (!options.element)
- {
- if (options.getItems)
- options.items = options.getItems();
- options.element = MenuPlate.tag.append(
- {object: options},
- getElementByClass(Firebug.chrome.document, "fbBody"),
- MenuPlate
- );
- }
- // extend itself with the provided options
- append(this, options);
- if (typeof this.element == "string")
- {
- this.id = this.element;
- this.element = $(this.id);
- }
- else if (this.id)
- {
- this.element.id = this.id;
- }
- this.element.firebugIgnore = true;
- this.elementStyle = this.element.style;
- this.isVisible = false;
- this.handleMouseDown = bind(this.handleMouseDown, this);
- this.handleMouseOver = bind(this.handleMouseOver, this);
- this.handleMouseOut = bind(this.handleMouseOut, this);
- this.handleWindowMouseDown = bind(this.handleWindowMouseDown, this);
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var menuMap = {};
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- Menu.prototype = extend(Controller,
- /**@extend FBL.Menu.prototype*/
- {
- destroy: function()
- {
- //if (this.element) console.log("destroy", this.element.id);
- this.hide();
- // if it is a childMenu, remove its reference from the parentMenu
- if (this.parentMenu)
- this.parentMenu.childMenu = null;
- // remove the element from the document
- this.element.parentNode.removeChild(this.element);
- // clear references
- this.element = null;
- this.elementStyle = null;
- this.parentMenu = null;
- this.parentTarget = null;
- },
- initialize: function()
- {
- Controller.initialize.call(this);
- this.addController(
- [this.element, "mousedown", this.handleMouseDown],
- [this.element, "mouseover", this.handleMouseOver]
- );
- },
- shutdown: function()
- {
- Controller.shutdown.call(this);
- },
- show: function(x, y)
- {
- this.initialize();
- if (this.isVisible) return;
- //console.log("show", this.element.id);
- x = x || 0;
- y = y || 0;
- if (this.parentMenu)
- {
- var oldChildMenu = this.parentMenu.childMenu;
- if (oldChildMenu && oldChildMenu != this)
- {
- oldChildMenu.destroy();
- }
- this.parentMenu.childMenu = this;
- }
- else
- addEvent(Firebug.chrome.document, "mousedown", this.handleWindowMouseDown);
- this.elementStyle.display = "block";
- this.elementStyle.visibility = "hidden";
- var size = Firebug.chrome.getSize();
- x = Math.min(x, size.width - this.element.clientWidth - 10);
- x = Math.max(x, 0);
- y = Math.min(y, size.height - this.element.clientHeight - 10);
- y = Math.max(y, 0);
- this.elementStyle.left = x + "px";
- this.elementStyle.top = y + "px";
- this.elementStyle.visibility = "visible";
- this.isVisible = true;
- if (isFunction(this.onShow))
- this.onShow.apply(this, arguments);
- },
- hide: function()
- {
- this.clearHideTimeout();
- this.clearShowChildTimeout();
- if (!this.isVisible) return;
- //console.log("hide", this.element.id);
- this.elementStyle.display = "none";
- if(this.childMenu)
- {
- this.childMenu.destroy();
- this.childMenu = null;
- }
- if(this.parentTarget)
- removeClass(this.parentTarget, "fbMenuGroupSelected");
- this.isVisible = false;
- this.shutdown();
- if (isFunction(this.onHide))
- this.onHide.apply(this, arguments);
- },
- showChildMenu: function(target)
- {
- var id = target.getAttribute("child");
- var parent = this;
- var target = target;
- this.showChildTimeout = Firebug.chrome.window.setTimeout(function(){
- //if (!parent.isVisible) return;
- var box = Firebug.chrome.getElementBox(target);
- var childMenuObject = menuMap.hasOwnProperty(id) ?
- menuMap[id] : {element: $(id)};
- var childMenu = new Menu(extend(childMenuObject,
- {
- parentMenu: parent,
- parentTarget: target
- }));
- var offsetLeft = isIE6 ? -1 : -6; // IE6 problem with fixed position
- childMenu.show(box.left + box.width + offsetLeft, box.top -6);
- setClass(target, "fbMenuGroupSelected");
- },350);
- },
- clearHideTimeout: function()
- {
- if (this.hideTimeout)
- {
- Firebug.chrome.window.clearTimeout(this.hideTimeout);
- delete this.hideTimeout;
- }
- },
- clearShowChildTimeout: function()
- {
- if(this.showChildTimeout)
- {
- Firebug.chrome.window.clearTimeout(this.showChildTimeout);
- this.showChildTimeout = null;
- }
- },
- handleMouseDown: function(event)
- {
- cancelEvent(event, true);
- var topParent = this;
- while (topParent.parentMenu)
- topParent = topParent.parentMenu;
- var target = event.target || event.srcElement;
- target = getAncestorByClass(target, "fbMenuOption");
- if(!target || hasClass(target, "fbMenuGroup"))
- return false;
- if (target && !hasClass(target, "fbMenuDisabled"))
- {
- var type = target.getAttribute("type");
- if (type == "checkbox")
- {
- var checked = target.getAttribute("checked");
- var value = target.getAttribute("value");
- var wasChecked = hasClass(target, "fbMenuChecked");
- if (wasChecked)
- {
- removeClass(target, "fbMenuChecked");
- target.setAttribute("checked", "");
- }
- else
- {
- setClass(target, "fbMenuChecked");
- target.setAttribute("checked", "true");
- }
- if (isFunction(this.onCheck))
- this.onCheck.call(this, target, value, !wasChecked)
- }
- if (type == "radiobutton")
- {
- var selectedRadios = getElementsByClass(target.parentNode, "fbMenuRadioSelected");
- var group = target.getAttribute("group");
- for (var i = 0, length = selectedRadios.length; i < length; i++)
- {
- radio = selectedRadios[i];
- if (radio.getAttribute("group") == group)
- {
- removeClass(radio, "fbMenuRadioSelected");
- radio.setAttribute("selected", "");
- }
- }
- setClass(target, "fbMenuRadioSelected");
- target.setAttribute("selected", "true");
- }
- var handler = null;
- // target.command can be a function or a string.
- var cmd = target.command;
- // If it is a function it will be used as the handler
- if (isFunction(cmd))
- handler = cmd;
- // If it is a string it the property of the current menu object
- // will be used as the handler
- else if (typeof cmd == "string")
- handler = this[cmd];
- var closeMenu = true;
- if (handler)
- closeMenu = handler.call(this, target) !== false;
- if (closeMenu)
- topParent.hide();
- }
- return false;
- },
- handleWindowMouseDown: function(event)
- {
- //console.log("handleWindowMouseDown");
- var target = event.target || event.srcElement;
- target = getAncestorByClass(target, "fbMenu");
- if (!target)
- {
- removeEvent(Firebug.chrome.document, "mousedown", this.handleWindowMouseDown);
- this.hide();
- }
- },
- handleMouseOver: function(event)
- {
- //console.log("handleMouseOver", this.element.id);
- this.clearHideTimeout();
- this.clearShowChildTimeout();
- var target = event.target || event.srcElement;
- target = getAncestorByClass(target, "fbMenuOption");
- if(!target)
- return;
- var childMenu = this.childMenu;
- if(childMenu)
- {
- removeClass(childMenu.parentTarget, "fbMenuGroupSelected");
- if (childMenu.parentTarget != target && childMenu.isVisible)
- {
- childMenu.clearHideTimeout();
- childMenu.hideTimeout = Firebug.chrome.window.setTimeout(function(){
- childMenu.destroy();
- },300);
- }
- }
- if(hasClass(target, "fbMenuGroup"))
- {
- this.showChildMenu(target);
- }
- }
- });
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- append(Menu,
- /**@extend FBL.Menu*/
- {
- register: function(object)
- {
- menuMap[object.id] = object;
- },
- check: function(element)
- {
- setClass(element, "fbMenuChecked");
- element.setAttribute("checked", "true");
- },
- uncheck: function(element)
- {
- removeClass(element, "fbMenuChecked");
- element.setAttribute("checked", "");
- },
- disable: function(element)
- {
- setClass(element, "fbMenuDisabled");
- },
- enable: function(element)
- {
- removeClass(element, "fbMenuDisabled");
- }
- });
- //************************************************************************************************
- // Status Bar
- /**@class*/
- function StatusBar(){};
- StatusBar.prototype = extend(Controller, {
- });
- // ************************************************************************************************
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns( /**@scope ns-context*/ function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Globals
- var refreshDelay = 300;
- // Opera and some versions of webkit returns the wrong value of document.elementFromPoint()
- // function, without taking into account the scroll position. Safari 4 (webkit/531.21.8)
- // still have this issue. Google Chrome 4 (webkit/532.5) does not. So, we're assuming this
- // issue was fixed in the 532 version
- var shouldFixElementFromPoint = isOpera || isSafari && browserVersion < "532";
- var evalError = "___firebug_evaluation_error___";
- var pixelsPerInch;
- var resetStyle = "margin:0; padding:0; border:0; position:absolute; overflow:hidden; display:block;";
- var offscreenStyle = resetStyle + "top:-1234px; left:-1234px;";
- // ************************************************************************************************
- // Context
- /** @class */
- FBL.Context = function(win)
- {
- this.window = win.window;
- this.document = win.document;
- this.browser = Env.browser;
- // Some windows in IE, like iframe, doesn't have the eval() method
- if (isIE && !this.window.eval)
- {
- // But after executing the following line the method magically appears!
- this.window.execScript("null");
- // Just to make sure the "magic" really happened
- if (!this.window.eval)
- throw new Error("Firebug Error: eval() method not found in this window");
- }
- // Create a new "black-box" eval() method that runs in the global namespace
- // of the context window, without exposing the local variables declared
- // by the function that calls it
- this.eval = this.window.eval("new Function('" +
- "try{ return window.eval.apply(window,arguments) }catch(E){ E."+evalError+"=true; return E }" +
- "')");
- };
- FBL.Context.prototype =
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // partial-port of Firebug tabContext.js
- browser: null,
- loaded: true,
- setTimeout: function(fn, delay)
- {
- var win = this.window;
- if (win.setTimeout == this.setTimeout)
- throw new Error("setTimeout recursion");
- var timeout = win.setTimeout.apply ? // IE doesn't have apply method on setTimeout
- win.setTimeout.apply(win, arguments) :
- win.setTimeout(fn, delay);
- if (!this.timeouts)
- this.timeouts = {};
- this.timeouts[timeout] = 1;
- return timeout;
- },
- clearTimeout: function(timeout)
- {
- clearTimeout(timeout);
- if (this.timeouts)
- delete this.timeouts[timeout];
- },
- setInterval: function(fn, delay)
- {
- var win = this.window;
- var timeout = win.setInterval.apply ? // IE doesn't have apply method on setTimeout
- win.setInterval.apply(win, arguments) :
- win.setInterval(fn, delay);
- if (!this.intervals)
- this.intervals = {};
- this.intervals[timeout] = 1;
- return timeout;
- },
- clearInterval: function(timeout)
- {
- clearInterval(timeout);
- if (this.intervals)
- delete this.intervals[timeout];
- },
- invalidatePanels: function()
- {
- if (!this.invalidPanels)
- this.invalidPanels = {};
- for (var i = 0; i < arguments.length; ++i)
- {
- var panelName = arguments[i];
- // avoid error. need to create a better getPanel() function as explained below
- if (!Firebug.chrome || !Firebug.chrome.selectedPanel)
- return;
- //var panel = this.getPanel(panelName, true);
- //TODO: xxxpedro context how to get all panels using a single function?
- // the current workaround to make the invalidation works is invalidating
- // only sidePanels. There's also a problem with panel name (LowerCase in Firebug Lite)
- var panel = Firebug.chrome.selectedPanel.sidePanelBar ?
- Firebug.chrome.selectedPanel.sidePanelBar.getPanel(panelName, true) :
- null;
- if (panel && !panel.noRefresh)
- this.invalidPanels[panelName] = 1;
- }
- if (this.refreshTimeout)
- {
- this.clearTimeout(this.refreshTimeout);
- delete this.refreshTimeout;
- }
- this.refreshTimeout = this.setTimeout(bindFixed(function()
- {
- var invalids = [];
- for (var panelName in this.invalidPanels)
- {
- //var panel = this.getPanel(panelName, true);
- //TODO: xxxpedro context how to get all panels using a single function?
- // the current workaround to make the invalidation works is invalidating
- // only sidePanels. There's also a problem with panel name (LowerCase in Firebug Lite)
- var panel = Firebug.chrome.selectedPanel.sidePanelBar ?
- Firebug.chrome.selectedPanel.sidePanelBar.getPanel(panelName, true) :
- null;
- if (panel)
- {
- if (panel.visible && !panel.editing)
- panel.refresh();
- else
- panel.needsRefresh = true;
- // If the panel is being edited, we'll keep trying to
- // refresh it until editing is done
- if (panel.editing)
- invalids.push(panelName);
- }
- }
- delete this.invalidPanels;
- delete this.refreshTimeout;
- // Keep looping until every tab is valid
- if (invalids.length)
- this.invalidatePanels.apply(this, invalids);
- }, this), refreshDelay);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Evalutation Method
- /**
- * Evaluates an expression in the current context window.
- *
- * @param {String} expr expression to be evaluated
- *
- * @param {String} context string indicating the global location
- * of the object that will be used as the
- * context. The context is referred in
- * the expression as the "this" keyword.
- * If no context is informed, the "window"
- * context is used.
- *
- * @param {String} api string indicating the global location
- * of the object that will be used as the
- * api of the evaluation.
- *
- * @param {Function} errorHandler(message) error handler to be called
- * if the evaluation fails.
- */
- evaluate: function(expr, context, api, errorHandler)
- {
- // Need to remove line breaks otherwise only the first line will be executed
- expr = stripNewLines(expr);
- // the default context is the "window" object. It can be any string that represents
- // a global accessible element as: "my.namespaced.object"
- context = context || "window";
- var cmd,
- result;
- // if the context is the "window" object, we don't need a closure
- if (context == "window")
- {
- // try first the expression wrapped in parenthesis (so we can capture
- // object literal expressions like "{}" and "{some:1,props:2}")
- cmd = api ?
- "with("+api+"){ ("+expr+") }" :
- "(" + expr + ")";
- result = this.eval(cmd);
- // if it results in error, then try it without parenthesis
- if (result && result[evalError])
- {
- cmd = api ?
- "with("+api+"){ "+expr+" }" :
- expr;
- result = this.eval(cmd);
- }
- }
- else
- {
- // try to execute the command using a "return" statement in the evaluation closure.
- cmd = api ?
- // with API and context, trying to get the return value
- "(function(arguments){ with(" + api + "){ return (" +
- expr +
- ") } }).call(" + context + ",undefined)"
- :
- // with context only, trying to get the return value
- "(function(arguments){ return (" +
- expr +
- ") }).call(" +context + ",undefined)";
- result = this.eval(cmd);
- // if it results in error, then try it without the "return" statement
- if (result && result[evalError])
- {
- cmd = api ?
- // with API and context, no return value
- "(function(arguments){ with(" + api + "){ " +
- expr +
- " } }).call(" + context + ",undefined)"
- :
- // with context only, no return value
- "(function(arguments){ " +
- expr +
- " }).call(" + context + ",undefined)";
- result = this.eval(cmd);
- }
- }
- if (result && result[evalError])
- {
- var msg = result.name ? (result.name + ": ") : "";
- msg += result.message || result;
- if (errorHandler)
- result = errorHandler(msg)
- else
- result = msg;
- }
- return result;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Window Methods
- getWindowSize: function()
- {
- var width=0, height=0, el;
- if (typeof this.window.innerWidth == "number")
- {
- width = this.window.innerWidth;
- height = this.window.innerHeight;
- }
- else if ((el=this.document.documentElement) && (el.clientHeight || el.clientWidth))
- {
- width = el.clientWidth;
- height = el.clientHeight;
- }
- else if ((el=this.document.body) && (el.clientHeight || el.clientWidth))
- {
- width = el.clientWidth;
- height = el.clientHeight;
- }
- return {width: width, height: height};
- },
- getWindowScrollSize: function()
- {
- var width=0, height=0, el;
- // first try the document.documentElement scroll size
- if (!isIEQuiksMode && (el=this.document.documentElement) &&
- (el.scrollHeight || el.scrollWidth))
- {
- width = el.scrollWidth;
- height = el.scrollHeight;
- }
- // then we need to check if document.body has a bigger scroll size value
- // because sometimes depending on the browser and the page, the document.body
- // scroll size returns a smaller (and wrong) measure
- if ((el=this.document.body) && (el.scrollHeight || el.scrollWidth) &&
- (el.scrollWidth > width || el.scrollHeight > height))
- {
- width = el.scrollWidth;
- height = el.scrollHeight;
- }
- return {width: width, height: height};
- },
- getWindowScrollPosition: function()
- {
- var top=0, left=0, el;
- if(typeof this.window.pageYOffset == "number")
- {
- top = this.window.pageYOffset;
- left = this.window.pageXOffset;
- }
- else if((el=this.document.body) && (el.scrollTop || el.scrollLeft))
- {
- top = el.scrollTop;
- left = el.scrollLeft;
- }
- else if((el=this.document.documentElement) && (el.scrollTop || el.scrollLeft))
- {
- top = el.scrollTop;
- left = el.scrollLeft;
- }
- return {top:top, left:left};
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Element Methods
- getElementFromPoint: function(x, y)
- {
- if (shouldFixElementFromPoint)
- {
- var scroll = this.getWindowScrollPosition();
- return this.document.elementFromPoint(x + scroll.left, y + scroll.top);
- }
- else
- return this.document.elementFromPoint(x, y);
- },
- getElementPosition: function(el)
- {
- var left = 0
- var top = 0;
- do
- {
- left += el.offsetLeft;
- top += el.offsetTop;
- }
- while (el = el.offsetParent);
- return {left:left, top:top};
- },
- getElementBox: function(el)
- {
- var result = {};
- if (el.getBoundingClientRect)
- {
- var rect = el.getBoundingClientRect();
- // fix IE problem with offset when not in fullscreen mode
- var offset = isIE ? this.document.body.clientTop || this.document.documentElement.clientTop: 0;
- var scroll = this.getWindowScrollPosition();
- result.top = Math.round(rect.top - offset + scroll.top);
- result.left = Math.round(rect.left - offset + scroll.left);
- result.height = Math.round(rect.bottom - rect.top);
- result.width = Math.round(rect.right - rect.left);
- }
- else
- {
- var position = this.getElementPosition(el);
- result.top = position.top;
- result.left = position.left;
- result.height = el.offsetHeight;
- result.width = el.offsetWidth;
- }
- return result;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Measurement Methods
- getMeasurement: function(el, name)
- {
- var result = {value: 0, unit: "px"};
- var cssValue = this.getStyle(el, name);
- if (!cssValue) return result;
- if (cssValue.toLowerCase() == "auto") return result;
- var reMeasure = /(\d+\.?\d*)(.*)/;
- var m = cssValue.match(reMeasure);
- if (m)
- {
- result.value = m[1]-0;
- result.unit = m[2].toLowerCase();
- }
- return result;
- },
- getMeasurementInPixels: function(el, name)
- {
- if (!el) return null;
- var m = this.getMeasurement(el, name);
- var value = m.value;
- var unit = m.unit;
- if (unit == "px")
- return value;
- else if (unit == "pt")
- return this.pointsToPixels(name, value);
- if (unit == "em")
- return this.emToPixels(el, value);
- else if (unit == "%")
- return this.percentToPixels(el, value);
- },
- getMeasurementBox1: function(el, name)
- {
- var sufixes = ["Top", "Left", "Bottom", "Right"];
- var result = [];
- for(var i=0, sufix; sufix=sufixes[i]; i++)
- result[i] = Math.round(this.getMeasurementInPixels(el, name + sufix));
- return {top:result[0], left:result[1], bottom:result[2], right:result[3]};
- },
- getMeasurementBox: function(el, name)
- {
- var result = [];
- var sufixes = name == "border" ?
- ["TopWidth", "LeftWidth", "BottomWidth", "RightWidth"] :
- ["Top", "Left", "Bottom", "Right"];
- if (isIE)
- {
- var propName, cssValue;
- var autoMargin = null;
- for(var i=0, sufix; sufix=sufixes[i]; i++)
- {
- propName = name + sufix;
- cssValue = el.currentStyle[propName] || el.style[propName];
- if (cssValue == "auto")
- {
- if (!autoMargin)
- autoMargin = this.getCSSAutoMarginBox(el);
- result[i] = autoMargin[sufix.toLowerCase()];
- }
- else
- result[i] = this.getMeasurementInPixels(el, propName);
- }
- }
- else
- {
- for(var i=0, sufix; sufix=sufixes[i]; i++)
- result[i] = this.getMeasurementInPixels(el, name + sufix);
- }
- return {top:result[0], left:result[1], bottom:result[2], right:result[3]};
- },
- getCSSAutoMarginBox: function(el)
- {
- if (isIE && " meta title input script link a ".indexOf(" "+el.nodeName.toLowerCase()+" ") != -1)
- return {top:0, left:0, bottom:0, right:0};
- /**/
- if (isIE && " h1 h2 h3 h4 h5 h6 h7 ul p ".indexOf(" "+el.nodeName.toLowerCase()+" ") == -1)
- return {top:0, left:0, bottom:0, right:0};
- /**/
- var offsetTop = 0;
- if (false && isIEStantandMode)
- {
- var scrollSize = Firebug.browser.getWindowScrollSize();
- offsetTop = scrollSize.height;
- }
- var box = this.document.createElement("div");
- //box.style.cssText = "margin:0; padding:1px; border: 0; position:static; overflow:hidden; visibility: hidden;";
- box.style.cssText = "margin:0; padding:1px; border: 0; visibility: hidden;";
- var clone = el.cloneNode(false);
- var text = this.document.createTextNode(" ");
- clone.appendChild(text);
- box.appendChild(clone);
- this.document.body.appendChild(box);
- var marginTop = clone.offsetTop - box.offsetTop - 1;
- var marginBottom = box.offsetHeight - clone.offsetHeight - 2 - marginTop;
- var marginLeft = clone.offsetLeft - box.offsetLeft - 1;
- var marginRight = box.offsetWidth - clone.offsetWidth - 2 - marginLeft;
- this.document.body.removeChild(box);
- return {top:marginTop+offsetTop, left:marginLeft, bottom:marginBottom-offsetTop, right:marginRight};
- },
- getFontSizeInPixels: function(el)
- {
- var size = this.getMeasurement(el, "fontSize");
- if (size.unit == "px") return size.value;
- // get font size, the dirty way
- var computeDirtyFontSize = function(el, calibration)
- {
- var div = this.document.createElement("div");
- var divStyle = offscreenStyle;
- if (calibration)
- divStyle += " font-size:"+calibration+"px;";
- div.style.cssText = divStyle;
- div.innerHTML = "A";
- el.appendChild(div);
- var value = div.offsetHeight;
- el.removeChild(div);
- return value;
- }
- /*
- var calibrationBase = 200;
- var calibrationValue = computeDirtyFontSize(el, calibrationBase);
- var rate = calibrationBase / calibrationValue;
- /**/
- // the "dirty technique" fails in some environments, so we're using a static value
- // based in some tests.
- var rate = 200 / 225;
- var value = computeDirtyFontSize(el);
- return value * rate;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Unit Funtions
- pointsToPixels: function(name, value, returnFloat)
- {
- var axis = /Top$|Bottom$/.test(name) ? "y" : "x";
- var result = value * pixelsPerInch[axis] / 72;
- return returnFloat ? result : Math.round(result);
- },
- emToPixels: function(el, value)
- {
- if (!el) return null;
- var fontSize = this.getFontSizeInPixels(el);
- return Math.round(value * fontSize);
- },
- exToPixels: function(el, value)
- {
- if (!el) return null;
- // get ex value, the dirty way
- var div = this.document.createElement("div");
- div.style.cssText = offscreenStyle + "width:"+value + "ex;";
- el.appendChild(div);
- var value = div.offsetWidth;
- el.removeChild(div);
- return value;
- },
- percentToPixels: function(el, value)
- {
- if (!el) return null;
- // get % value, the dirty way
- var div = this.document.createElement("div");
- div.style.cssText = offscreenStyle + "width:"+value + "%;";
- el.appendChild(div);
- var value = div.offsetWidth;
- el.removeChild(div);
- return value;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getStyle: isIE ? function(el, name)
- {
- return el.currentStyle[name] || el.style[name] || undefined;
- }
- : function(el, name)
- {
- return this.document.defaultView.getComputedStyle(el,null)[name]
- || el.style[name] || undefined;
- }
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns( /**@scope ns-chrome*/ function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Globals
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Window Options
- var WindowDefaultOptions =
- {
- type: "frame",
- id: "FirebugUI",
- height: 250
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Instantiated objects
- commandLine,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Interface Elements Cache
- fbTop,
- fbContent,
- fbContentStyle,
- fbBottom,
- fbBtnInspect,
- fbToolbar,
- fbPanelBox1,
- fbPanelBox1Style,
- fbPanelBox2,
- fbPanelBox2Style,
- fbPanelBar2Box,
- fbPanelBar2BoxStyle,
- fbHSplitter,
- fbVSplitter,
- fbVSplitterStyle,
- fbPanel1,
- fbPanel1Style,
- fbPanel2,
- fbPanel2Style,
- fbConsole,
- fbConsoleStyle,
- fbHTML,
- fbCommandLine,
- fbLargeCommandLine,
- fbLargeCommandButtons,
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Cached size values
- topHeight,
- topPartialHeight,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- chromeRedrawSkipRate = isIE ? 75 : isOpera ? 80 : 75,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- lastSelectedPanelName,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- focusCommandLineState = 0,
- lastFocusedPanelName,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- lastHSplitterMouseMove = 0,
- onHSplitterMouseMoveBuffer = null,
- onHSplitterMouseMoveTimer = null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- lastVSplitterMouseMove = 0;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // ************************************************************************************************
- // FirebugChrome
- /**@namespace*/
- FBL.FirebugChrome =
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- isOpen: false,
- height: 250,
- sidePanelWidth: 350,
- selectedPanelName: "Console",
- selectedHTMLElementId: null,
- chromeMap: {},
- htmlSelectionStack: [],
- consoleMessageQueue: [],
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- create: function()
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FirebugChrome.create", "creating chrome window");
- createChromeWindow();
- },
- initialize: function()
- {
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FirebugChrome.initialize", "initializing chrome window");
- if (Env.chrome.type == "frame" || Env.chrome.type == "div")
- ChromeMini.create(Env.chrome);
- var chrome = Firebug.chrome = new Chrome(Env.chrome);
- FirebugChrome.chromeMap[chrome.type] = chrome;
- addGlobalEvent("keydown", onGlobalKeyDown);
- if (Env.Options.enablePersistent && chrome.type == "popup")
- {
- // TODO: xxxpedro persist - revise chrome synchronization when in persistent mode
- var frame = FirebugChrome.chromeMap.frame;
- if (frame)
- frame.close();
- //chrome.reattach(frame, chrome);
- //TODO: xxxpedro persist synchronize?
- chrome.initialize();
- }
- },
- clone: function(FBChrome)
- {
- for (var name in FBChrome)
- {
- var prop = FBChrome[name];
- if (FBChrome.hasOwnProperty(name) && !isFunction(prop))
- {
- this[name] = prop;
- }
- }
- }
- };
- // ************************************************************************************************
- // Chrome Window Creation
- var createChromeWindow = function(options)
- {
- options = extend(WindowDefaultOptions, options || {});
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Locals
- var chrome = {},
- context = options.context || Env.browser,
- type = chrome.type = Env.Options.enablePersistent ?
- "popup" :
- options.type,
- isChromeFrame = type == "frame",
- useLocalSkin = Env.useLocalSkin,
- url = useLocalSkin ?
- Env.Location.skin :
- "about:blank",
- // document.body not available in XML+XSL documents in Firefox
- body = context.document.getElementsByTagName("body")[0],
- formatNode = function(node)
- {
- if (!Env.isDebugMode)
- {
- node.firebugIgnore = true;
- }
- node.style.border = "0";
- node.style.visibility = "hidden";
- node.style.zIndex = "2147483647"; // MAX z-index = 2147483647
- node.style.position = noFixedPosition ? "absolute" : "fixed";
- node.style.width = "100%"; // "102%"; IE auto margin bug
- node.style.left = "0";
- node.style.bottom = noFixedPosition ? "-1px" : "0";
- node.style.height = options.height + "px";
- // avoid flickering during chrome rendering
- if (isFirefox)
- node.style.display = "none";
- },
- createChromeDiv = function()
- {
- //Firebug.Console.warn("Firebug Lite GUI is working in 'windowless mode'. It may behave slower and receive interferences from the page in which it is installed.");
- var node = chrome.node = createGlobalElement("div"),
- style = createGlobalElement("style"),
- css = FirebugChrome.Skin.CSS
- /*
- .replace(/;/g, " !important;")
- .replace(/!important\s!important/g, "!important")
- .replace(/display\s*:\s*(\w+)\s*!important;/g, "display:$1;")*/,
- // reset some styles to minimize interference from the main page's style
- rules = ".fbBody *{margin:0;padding:0;font-size:11px;line-height:13px;color:inherit;}" +
- // load the chrome styles
- css +
- // adjust some remaining styles
- ".fbBody #fbHSplitter{position:absolute !important;} .fbBody #fbHTML span{line-height:14px;} .fbBody .lineNo div{line-height:inherit !important;}";
- /*
- if (isIE)
- {
- // IE7 CSS bug (FbChrome table bigger than its parent div)
- rules += ".fbBody table.fbChrome{position: static !important;}";
- }/**/
- style.type = "text/css";
- if (style.styleSheet)
- style.styleSheet.cssText = rules;
- else
- style.appendChild(context.document.createTextNode(rules));
- document.getElementsByTagName("head")[0].appendChild(style);
- node.className = "fbBody";
- node.style.overflow = "hidden";
- node.innerHTML = getChromeDivTemplate();
- if (isIE)
- {
- // IE7 CSS bug (FbChrome table bigger than its parent div)
- setTimeout(function(){
- node.firstChild.style.height = "1px";
- node.firstChild.style.position = "static";
- },0);
- /**/
- }
- formatNode(node);
- body.appendChild(node);
- chrome.window = window;
- chrome.document = document;
- onChromeLoad(chrome);
- };
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- try
- {
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // create the Chrome as a "div" (windowless mode)
- if (type == "div")
- {
- createChromeDiv();
- return;
- }
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // cretate the Chrome as an "iframe"
- else if (isChromeFrame)
- {
- // Create the Chrome Frame
- var node = chrome.node = createGlobalElement("iframe");
- node.setAttribute("src", url);
- node.setAttribute("frameBorder", "0");
- formatNode(node);
- body.appendChild(node);
- // must set the id after appending to the document, otherwise will cause an
- // strange error in IE, making the iframe load the page in which the bookmarklet
- // was created (like getfirebug.com), before loading the injected UI HTML,
- // generating an "Access Denied" error.
- node.id = options.id;
- }
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // create the Chrome as a "popup"
- else
- {
- var height = FirebugChrome.height || options.height,
- options = [
- "true,top=",
- Math.max(screen.availHeight - height - 61 /* Google Chrome bug */, 0),
- ",left=0,height=",
- height,
- ",width=",
- screen.availWidth-10, // Opera opens popup in a new tab if it's too big!
- ",resizable"
- ].join(""),
- node = chrome.node = context.window.open(
- url,
- "popup",
- options
- );
- if (node)
- {
- try
- {
- node.focus();
- }
- catch(E)
- {
- alert("Firebug Error: Firebug popup was blocked.");
- return;
- }
- }
- else
- {
- alert("Firebug Error: Firebug popup was blocked.");
- return;
- }
- }
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Inject the interface HTML if it is not using the local skin
- if (!useLocalSkin)
- {
- var tpl = getChromeTemplate(!isChromeFrame),
- doc = isChromeFrame ? node.contentWindow.document : node.document;
- doc.write(tpl);
- doc.close();
- }
- //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Wait the Window to be loaded
- var win,
- waitDelay = useLocalSkin ? isChromeFrame ? 200 : 300 : 100,
- waitForWindow = function()
- {
- if ( // Frame loaded... OR
- isChromeFrame && (win=node.contentWindow) &&
- node.contentWindow.document.getElementById("fbCommandLine") ||
- // Popup loaded
- !isChromeFrame && (win=node.window) && node.document &&
- node.document.getElementById("fbCommandLine") )
- {
- chrome.window = win.window;
- chrome.document = win.document;
- // Prevent getting the wrong chrome height in FF when opening a popup
- setTimeout(function(){
- onChromeLoad(chrome);
- },0);
- }
- else
- setTimeout(waitForWindow, waitDelay);
- };
- waitForWindow();
- }
- catch(e)
- {
- var msg = e.message || e;
- if (/access/i.test(msg))
- {
- // Firebug Lite could not create a window for its Graphical User Interface due to
- // a access restriction. This happens in some pages, when loading via bookmarklet.
- // In such cases, the only way is to load the GUI in a "windowless mode".
- if (isChromeFrame)
- body.removeChild(node);
- else if(type == "popup")
- node.close();
- // Load the GUI in a "windowless mode"
- createChromeDiv();
- }
- else
- {
- alert("Firebug Error: Firebug GUI could not be created.");
- }
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var onChromeLoad = function onChromeLoad(chrome)
- {
- Env.chrome = chrome;
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Chrome onChromeLoad", "chrome window loaded");
- if (Env.Options.enablePersistent)
- {
- // TODO: xxxpedro persist - make better chrome synchronization when in persistent mode
- Env.FirebugChrome = FirebugChrome;
- chrome.window.Firebug = chrome.window.Firebug || {};
- chrome.window.Firebug.SharedEnv = Env;
- if (Env.isDevelopmentMode)
- {
- Env.browser.window.FBDev.loadChromeApplication(chrome);
- }
- else
- {
- var doc = chrome.document;
- var script = doc.createElement("script");
- script.src = Env.Location.app + "#remote,persist";
- doc.getElementsByTagName("head")[0].appendChild(script);
- }
- }
- else
- {
- if (chrome.type == "frame" || chrome.type == "div")
- {
- // initialize the chrome application
- setTimeout(function(){
- FBL.Firebug.initialize();
- },0);
- }
- else if (chrome.type == "popup")
- {
- var oldChrome = FirebugChrome.chromeMap.frame;
- var newChrome = new Chrome(chrome);
- // TODO: xxxpedro sync detach reattach attach
- dispatch(newChrome.panelMap, "detach", [oldChrome, newChrome]);
- if (oldChrome)
- oldChrome.close();
- newChrome.reattach(oldChrome, newChrome);
- }
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var getChromeDivTemplate = function()
- {
- return FirebugChrome.Skin.HTML;
- };
- var getChromeTemplate = function(isPopup)
- {
- var tpl = FirebugChrome.Skin;
- var r = [], i = -1;
- r[++i] = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">';
- r[++i] = '<html><head><title>';
- r[++i] = Firebug.version;
- /*
- r[++i] = '</title><link href="';
- r[++i] = Env.Location.skinDir + 'firebug.css';
- r[++i] = '" rel="stylesheet" type="text/css" />';
- /**/
- r[++i] = '</title><style>html,body{margin:0;padding:0;overflow:hidden;}';
- r[++i] = tpl.CSS;
- r[++i] = '</style>';
- /**/
- r[++i] = '</head><body class="fbBody' + (isPopup ? ' FirebugPopup' : '') + '">';
- r[++i] = tpl.HTML;
- r[++i] = '</body></html>';
- return r.join("");
- };
- // ************************************************************************************************
- // Chrome Class
- /**@class*/
- var Chrome = function Chrome(chrome)
- {
- var type = chrome.type;
- var Base = type == "frame" || type == "div" ? ChromeFrameBase : ChromePopupBase;
- append(this, Base); // inherit from base class (ChromeFrameBase or ChromePopupBase)
- append(this, chrome); // inherit chrome window properties
- append(this, new Context(chrome.window)); // inherit from Context class
- FirebugChrome.chromeMap[type] = this;
- Firebug.chrome = this;
- Env.chrome = chrome.window;
- this.commandLineVisible = false;
- this.sidePanelVisible = false;
- this.create();
- return this;
- };
- // ************************************************************************************************
- // ChromeBase
- /**
- * @namespace
- * @extends FBL.Controller
- * @extends FBL.PanelBar
- **/
- var ChromeBase = {};
- append(ChromeBase, Controller);
- append(ChromeBase, PanelBar);
- append(ChromeBase,
- /**@extend ns-chrome-ChromeBase*/
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // inherited properties
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // inherited from createChrome function
- node: null,
- type: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // inherited from Context.prototype
- document: null,
- window: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // value properties
- sidePanelVisible: false,
- commandLineVisible: false,
- largeCommandLineVisible: false,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // object properties
- inspectButton: null,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- create: function()
- {
- PanelBar.create.call(this);
- if (Firebug.Inspector)
- this.inspectButton = new Button({
- type: "toggle",
- element: $("fbChrome_btInspect"),
- owner: Firebug.Inspector,
- onPress: Firebug.Inspector.startInspecting,
- onUnpress: Firebug.Inspector.stopInspecting
- });
- },
- destroy: function()
- {
- if(Firebug.Inspector)
- this.inspectButton.destroy();
- PanelBar.destroy.call(this);
- this.shutdown();
- },
- testMenu: function()
- {
- var firebugMenu = new Menu(
- {
- id: "fbFirebugMenu",
- items:
- [
- {
- label: "Open Firebug",
- type: "shortcut",
- key: isFirefox ? "Shift+F12" : "F12",
- checked: true,
- command: "toggleChrome"
- },
- {
- label: "Open Firebug in New Window",
- type: "shortcut",
- key: isFirefox ? "Ctrl+Shift+F12" : "Ctrl+F12",
- command: "openPopup"
- },
- {
- label: "Inspect Element",
- type: "shortcut",
- key: "Ctrl+Shift+C",
- command: "toggleInspect"
- },
- {
- label: "Command Line",
- type: "shortcut",
- key: "Ctrl+Shift+L",
- command: "focusCommandLine"
- },
- "-",
- {
- label: "Options",
- type: "group",
- child: "fbFirebugOptionsMenu"
- },
- "-",
- {
- label: "Firebug Lite Website...",
- command: "visitWebsite"
- },
- {
- label: "Discussion Group...",
- command: "visitDiscussionGroup"
- },
- {
- label: "Issue Tracker...",
- command: "visitIssueTracker"
- }
- ],
- onHide: function()
- {
- iconButton.restore();
- },
- toggleChrome: function()
- {
- Firebug.chrome.toggle();
- },
- openPopup: function()
- {
- Firebug.chrome.toggle(true, true);
- },
- toggleInspect: function()
- {
- Firebug.Inspector.toggleInspect();
- },
- focusCommandLine: function()
- {
- Firebug.chrome.focusCommandLine();
- },
- visitWebsite: function()
- {
- this.visit("http://getfirebug.com/lite.html");
- },
- visitDiscussionGroup: function()
- {
- this.visit("http://groups.google.com/group/firebug");
- },
- visitIssueTracker: function()
- {
- this.visit("http://code.google.com/p/fbug/issues/list");
- },
- visit: function(url)
- {
- window.open(url);
- }
- });
- /**@private*/
- var firebugOptionsMenu =
- {
- id: "fbFirebugOptionsMenu",
- getItems: function()
- {
- var cookiesDisabled = !Firebug.saveCookies;
- return [
- {
- label: "Save Options in Cookies",
- type: "checkbox",
- value: "saveCookies",
- checked: Firebug.saveCookies,
- command: "saveOptions"
- },
- "-",
- {
- label: "Start Opened",
- type: "checkbox",
- value: "startOpened",
- checked: Firebug.startOpened,
- disabled: cookiesDisabled
- },
- {
- label: "Start in New Window",
- type: "checkbox",
- value: "startInNewWindow",
- checked: Firebug.startInNewWindow,
- disabled: cookiesDisabled
- },
- {
- label: "Show Icon When Hidden",
- type: "checkbox",
- value: "showIconWhenHidden",
- checked: Firebug.showIconWhenHidden,
- disabled: cookiesDisabled
- },
- {
- label: "Override Console Object",
- type: "checkbox",
- value: "overrideConsole",
- checked: Firebug.overrideConsole,
- disabled: cookiesDisabled
- },
- {
- label: "Ignore Firebug Elements",
- type: "checkbox",
- value: "ignoreFirebugElements",
- checked: Firebug.ignoreFirebugElements,
- disabled: cookiesDisabled
- },
- {
- label: "Disable When Firebug Active",
- type: "checkbox",
- value: "disableWhenFirebugActive",
- checked: Firebug.disableWhenFirebugActive,
- disabled: cookiesDisabled
- },
- {
- label: "Disable XHR Listener",
- type: "checkbox",
- value: "disableXHRListener",
- checked: Firebug.disableXHRListener,
- disabled: cookiesDisabled
- },
- {
- label: "Enable Trace Mode",
- type: "checkbox",
- value: "enableTrace",
- checked: Firebug.enableTrace,
- disabled: cookiesDisabled
- },
- {
- label: "Enable Persistent Mode (experimental)",
- type: "checkbox",
- value: "enablePersistent",
- checked: Firebug.enablePersistent,
- disabled: cookiesDisabled
- },
- "-",
- {
- label: "Reset All Firebug Options",
- command: "restorePrefs",
- disabled: cookiesDisabled
- }
- ];
- },
- onCheck: function(target, value, checked)
- {
- Firebug.setPref(value, checked);
- },
- saveOptions: function(target)
- {
- var saveEnabled = target.getAttribute("checked");
- if (!saveEnabled) this.restorePrefs();
- this.updateMenu(target);
- return false;
- },
- restorePrefs: function(target)
- {
- Firebug.restorePrefs();
- if(Firebug.saveCookies)
- Firebug.savePrefs();
- else
- Firebug.erasePrefs();
- if (target)
- this.updateMenu(target);
- return false;
- },
- updateMenu: function(target)
- {
- var options = getElementsByClass(target.parentNode, "fbMenuOption");
- var firstOption = options[0];
- var enabled = Firebug.saveCookies;
- if (enabled)
- Menu.check(firstOption);
- else
- Menu.uncheck(firstOption);
- if (enabled)
- Menu.check(options[0]);
- else
- Menu.uncheck(options[0]);
- for (var i = 1, length = options.length; i < length; i++)
- {
- var option = options[i];
- var value = option.getAttribute("value");
- var pref = Firebug[value];
- if (pref)
- Menu.check(option);
- else
- Menu.uncheck(option);
- if (enabled)
- Menu.enable(option);
- else
- Menu.disable(option);
- }
- }
- };
- Menu.register(firebugOptionsMenu);
- var menu = firebugMenu;
- var testMenuClick = function(event)
- {
- //console.log("testMenuClick");
- cancelEvent(event, true);
- var target = event.target || event.srcElement;
- if (menu.isVisible)
- menu.hide();
- else
- {
- var offsetLeft = isIE6 ? 1 : -4, // IE6 problem with fixed position
- chrome = Firebug.chrome,
- box = chrome.getElementBox(target),
- offset = chrome.type == "div" ?
- chrome.getElementPosition(chrome.node) :
- {top: 0, left: 0};
- menu.show(
- box.left + offsetLeft - offset.left,
- box.top + box.height -5 - offset.top
- );
- }
- return false;
- };
- var iconButton = new IconButton({
- type: "toggle",
- element: $("fbFirebugButton"),
- onClick: testMenuClick
- });
- iconButton.initialize();
- //addEvent($("fbToolbarIcon"), "click", testMenuClick);
- },
- initialize: function()
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- if (Env.bookmarkletOutdated)
- Firebug.Console.logFormatted([
- "A new bookmarklet version is available. " +
- "Please visit http://getfirebug.com/firebuglite#Install and update it."
- ], Firebug.context, "warn");
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- if (Firebug.Console)
- Firebug.Console.flush();
- if (Firebug.Trace)
- FBTrace.flush(Firebug.Trace);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.chrome.initialize", "initializing chrome application");
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // initialize inherited classes
- Controller.initialize.call(this);
- PanelBar.initialize.call(this);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // create the interface elements cache
- fbTop = $("fbTop");
- fbContent = $("fbContent");
- fbContentStyle = fbContent.style;
- fbBottom = $("fbBottom");
- fbBtnInspect = $("fbBtnInspect");
- fbToolbar = $("fbToolbar");
- fbPanelBox1 = $("fbPanelBox1");
- fbPanelBox1Style = fbPanelBox1.style;
- fbPanelBox2 = $("fbPanelBox2");
- fbPanelBox2Style = fbPanelBox2.style;
- fbPanelBar2Box = $("fbPanelBar2Box");
- fbPanelBar2BoxStyle = fbPanelBar2Box.style;
- fbHSplitter = $("fbHSplitter");
- fbVSplitter = $("fbVSplitter");
- fbVSplitterStyle = fbVSplitter.style;
- fbPanel1 = $("fbPanel1");
- fbPanel1Style = fbPanel1.style;
- fbPanel2 = $("fbPanel2");
- fbPanel2Style = fbPanel2.style;
- fbConsole = $("fbConsole");
- fbConsoleStyle = fbConsole.style;
- fbHTML = $("fbHTML");
- fbCommandLine = $("fbCommandLine");
- fbLargeCommandLine = $("fbLargeCommandLine");
- fbLargeCommandButtons = $("fbLargeCommandButtons");
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // static values cache
- topHeight = fbTop.offsetHeight;
- topPartialHeight = fbToolbar.offsetHeight;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- disableTextSelection($("fbToolbar"));
- disableTextSelection($("fbPanelBarBox"));
- disableTextSelection($("fbPanelBar1"));
- disableTextSelection($("fbPanelBar2"));
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Add the "javascript:void(0)" href attributes used to make the hover effect in IE6
- if (isIE6 && Firebug.Selector)
- {
- // TODO: xxxpedro change to getElementsByClass
- var as = $$(".fbHover");
- for (var i=0, a; a=as[i]; i++)
- {
- a.setAttribute("href", "javascript:void(0)");
- }
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // initialize all panels
- /*
- var panelMap = Firebug.panelTypes;
- for (var i=0, p; p=panelMap[i]; i++)
- {
- if (!p.parentPanel)
- {
- this.addPanel(p.prototype.name);
- }
- }
- /**/
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- if(Firebug.Inspector)
- this.inspectButton.initialize();
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- this.addController(
- [$("fbLargeCommandLineIcon"), "click", this.showLargeCommandLine]
- );
- // ************************************************************************************************
- // Select the first registered panel
- // TODO: BUG IE7
- var self = this;
- setTimeout(function(){
- self.selectPanel(FirebugChrome.selectedPanelName);
- if (FirebugChrome.selectedPanelName == "Console" && Firebug.CommandLine)
- Firebug.chrome.focusCommandLine();
- },0);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- //this.draw();
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var onPanelMouseDown = function onPanelMouseDown(event)
- {
- //console.log("onPanelMouseDown", event.target || event.srcElement, event);
- var target = event.target || event.srcElement;
- if (FBL.isLeftClick(event))
- {
- var editable = FBL.getAncestorByClass(target, "editable");
- // if an editable element has been clicked then start editing
- if (editable)
- {
- Firebug.Editor.startEditing(editable);
- FBL.cancelEvent(event);
- }
- // if any other element has been clicked then stop editing
- else
- {
- if (!hasClass(target, "textEditorInner"))
- Firebug.Editor.stopEditing();
- }
- }
- else if (FBL.isMiddleClick(event) && Firebug.getRepNode(target))
- {
- // Prevent auto-scroll when middle-clicking a rep object
- FBL.cancelEvent(event);
- }
- };
- Firebug.getElementPanel = function(element)
- {
- var panelNode = getAncestorByClass(element, "fbPanel");
- var id = panelNode.id.substr(2);
- var panel = Firebug.chrome.panelMap[id];
- if (!panel)
- {
- if (Firebug.chrome.selectedPanel.sidePanelBar)
- panel = Firebug.chrome.selectedPanel.sidePanelBar.panelMap[id];
- }
- return panel;
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // TODO: xxxpedro port to Firebug
- // Improved window key code event listener. Only one "keydown" event will be attached
- // to the window, and the onKeyCodeListen() function will delegate which listeners
- // should be called according to the event.keyCode fired.
- var onKeyCodeListenersMap = [];
- var onKeyCodeListen = function(event)
- {
- for (var keyCode in onKeyCodeListenersMap)
- {
- var listeners = onKeyCodeListenersMap[keyCode];
- for (var i = 0, listener; listener = listeners[i]; i++)
- {
- var filter = listener.filter || FBL.noKeyModifiers;
- if (event.keyCode == keyCode && (!filter || filter(event)))
- {
- listener.listener();
- FBL.cancelEvent(event, true);
- return false;
- }
- }
- }
- };
- addEvent(Firebug.chrome.document, "keydown", onKeyCodeListen);
- /**
- * @name keyCodeListen
- * @memberOf FBL.FirebugChrome
- */
- Firebug.chrome.keyCodeListen = function(key, filter, listener, capture)
- {
- var keyCode = KeyEvent["DOM_VK_"+key];
- if (!onKeyCodeListenersMap[keyCode])
- onKeyCodeListenersMap[keyCode] = [];
- onKeyCodeListenersMap[keyCode].push({
- filter: filter,
- listener: listener
- });
- return keyCode;
- };
- /**
- * @name keyIgnore
- * @memberOf FBL.FirebugChrome
- */
- Firebug.chrome.keyIgnore = function(keyCode)
- {
- onKeyCodeListenersMap[keyCode] = null;
- delete onKeyCodeListenersMap[keyCode];
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /**/
- // move to shutdown
- //removeEvent(Firebug.chrome.document, "keydown", listener[0]);
- /*
- Firebug.chrome.keyCodeListen = function(key, filter, listener, capture)
- {
- if (!filter)
- filter = FBL.noKeyModifiers;
- var keyCode = KeyEvent["DOM_VK_"+key];
- var fn = function fn(event)
- {
- if (event.keyCode == keyCode && (!filter || filter(event)))
- {
- listener();
- FBL.cancelEvent(event, true);
- return false;
- }
- }
- addEvent(Firebug.chrome.document, "keydown", fn);
- return [fn, capture];
- };
- Firebug.chrome.keyIgnore = function(listener)
- {
- removeEvent(Firebug.chrome.document, "keydown", listener[0]);
- };
- /**/
- this.addController(
- [fbPanel1, "mousedown", onPanelMouseDown],
- [fbPanel2, "mousedown", onPanelMouseDown]
- );
- /**/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // menus can be used without domplate
- if (FBL.domplate)
- this.testMenu();
- /**/
- //test XHR
- /*
- setTimeout(function(){
- FBL.Ajax.request({url: "../content/firebug/boot.js"});
- FBL.Ajax.request({url: "../content/firebug/boot.js.invalid"});
- },1000);
- /**/
- },
- shutdown: function()
- {
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- if(Firebug.Inspector)
- this.inspectButton.shutdown();
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // remove disableTextSelection event handlers
- restoreTextSelection($("fbToolbar"));
- restoreTextSelection($("fbPanelBarBox"));
- restoreTextSelection($("fbPanelBar1"));
- restoreTextSelection($("fbPanelBar2"));
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // shutdown inherited classes
- Controller.shutdown.call(this);
- PanelBar.shutdown.call(this);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Remove the interface elements cache (this must happen after calling
- // the shutdown method of all dependent components to avoid errors)
- fbTop = null;
- fbContent = null;
- fbContentStyle = null;
- fbBottom = null;
- fbBtnInspect = null;
- fbToolbar = null;
- fbPanelBox1 = null;
- fbPanelBox1Style = null;
- fbPanelBox2 = null;
- fbPanelBox2Style = null;
- fbPanelBar2Box = null;
- fbPanelBar2BoxStyle = null;
- fbHSplitter = null;
- fbVSplitter = null;
- fbVSplitterStyle = null;
- fbPanel1 = null;
- fbPanel1Style = null;
- fbPanel2 = null;
- fbConsole = null;
- fbConsoleStyle = null;
- fbHTML = null;
- fbCommandLine = null;
- fbLargeCommandLine = null;
- fbLargeCommandButtons = null;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // static values cache
- topHeight = null;
- topPartialHeight = null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- toggle: function(forceOpen, popup)
- {
- if(popup)
- {
- this.detach();
- }
- else
- {
- if (isOpera && Firebug.chrome.type == "popup" && Firebug.chrome.node.closed)
- {
- var frame = FirebugChrome.chromeMap.frame;
- frame.reattach();
- FirebugChrome.chromeMap.popup = null;
- frame.open();
- return;
- }
- // If the context is a popup, ignores the toggle process
- if (Firebug.chrome.type == "popup") return;
- var shouldOpen = forceOpen || !FirebugChrome.isOpen;
- if(shouldOpen)
- this.open();
- else
- this.close();
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- detach: function()
- {
- if(!FirebugChrome.chromeMap.popup)
- {
- createChromeWindow({type: "popup"});
- }
- },
- reattach: function(oldChrome, newChrome)
- {
- Firebug.browser.window.Firebug = Firebug;
- // chrome synchronization
- var newPanelMap = newChrome.panelMap;
- var oldPanelMap = oldChrome.panelMap;
- var panel;
- for(var name in newPanelMap)
- {
- // TODO: xxxpedro innerHTML
- panel = newPanelMap[name];
- if (panel.options.innerHTMLSync)
- panel.panelNode.innerHTML = oldPanelMap[name].panelNode.innerHTML;
- }
- Firebug.chrome = newChrome;
- // TODO: xxxpedro sync detach reattach attach
- //dispatch(Firebug.chrome.panelMap, "detach", [oldChrome, newChrome]);
- if (newChrome.type == "popup")
- {
- newChrome.initialize();
- //dispatch(Firebug.modules, "initialize", []);
- }
- else
- {
- // TODO: xxxpedro only needed in persistent
- // should use FirebugChrome.clone, but popup FBChrome
- // isn't acessible
- FirebugChrome.selectedPanelName = oldChrome.selectedPanel.name;
- }
- dispatch(newPanelMap, "reattach", [oldChrome, newChrome]);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- draw: function()
- {
- var size = this.getSize();
- // Height related values
- var commandLineHeight = Firebug.chrome.commandLineVisible ? fbCommandLine.offsetHeight : 0,
- y = Math.max(size.height /* chrome height */, topHeight),
- heightValue = Math.max(y - topHeight - commandLineHeight /* fixed height */, 0),
- height = heightValue + "px",
- // Width related values
- sideWidthValue = Firebug.chrome.sidePanelVisible ? FirebugChrome.sidePanelWidth : 0,
- width = Math.max(size.width /* chrome width */ - sideWidthValue, 0) + "px";
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Height related rendering
- fbPanelBox1Style.height = height;
- fbPanel1Style.height = height;
- if (isIE || isOpera)
- {
- // Fix IE and Opera problems with auto resizing the verticall splitter
- fbVSplitterStyle.height = Math.max(y - topPartialHeight - commandLineHeight, 0) + "px";
- }
- //xxxpedro FF2 only?
- /*
- else if (isFirefox)
- {
- // Fix Firefox problem with table rows with 100% height (fit height)
- fbContentStyle.maxHeight = Math.max(y - fixedHeight, 0)+ "px";
- }/**/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Width related rendering
- fbPanelBox1Style.width = width;
- fbPanel1Style.width = width;
- // SidePanel rendering
- if (Firebug.chrome.sidePanelVisible)
- {
- sideWidthValue = Math.max(sideWidthValue - 6, 0);
- var sideWidth = sideWidthValue + "px";
- fbPanelBox2Style.width = sideWidth;
- fbVSplitterStyle.right = sideWidth;
- if (Firebug.chrome.largeCommandLineVisible)
- {
- fbLargeCommandLine = $("fbLargeCommandLine");
- fbLargeCommandLine.style.height = heightValue - 4 + "px";
- fbLargeCommandLine.style.width = sideWidthValue - 2 + "px";
- fbLargeCommandButtons = $("fbLargeCommandButtons");
- fbLargeCommandButtons.style.width = sideWidth;
- }
- else
- {
- fbPanel2Style.height = height;
- fbPanel2Style.width = sideWidth;
- fbPanelBar2BoxStyle.width = sideWidth;
- }
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getSize: function()
- {
- return this.type == "div" ?
- {
- height: this.node.offsetHeight,
- width: this.node.offsetWidth
- }
- :
- this.getWindowSize();
- },
- resize: function()
- {
- var self = this;
- // avoid partial resize when maximizing window
- setTimeout(function(){
- self.draw();
- if (noFixedPosition && (self.type == "frame" || self.type == "div"))
- self.fixIEPosition();
- }, 0);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- layout: function(panel)
- {
- if (FBTrace.DBG_CHROME) FBTrace.sysout("Chrome.layout", "");
- var options = panel.options;
- changeCommandLineVisibility(options.hasCommandLine);
- changeSidePanelVisibility(panel.hasSidePanel);
- Firebug.chrome.draw();
- },
- showLargeCommandLine: function(hideToggleIcon)
- {
- var chrome = Firebug.chrome;
- if (!chrome.largeCommandLineVisible)
- {
- chrome.largeCommandLineVisible = true;
- if (chrome.selectedPanel.options.hasCommandLine)
- {
- if (Firebug.CommandLine)
- Firebug.CommandLine.blur();
- changeCommandLineVisibility(false);
- }
- changeSidePanelVisibility(true);
- fbLargeCommandLine.style.display = "block";
- fbLargeCommandButtons.style.display = "block";
- fbPanel2Style.display = "none";
- fbPanelBar2BoxStyle.display = "none";
- chrome.draw();
- fbLargeCommandLine.focus();
- if (Firebug.CommandLine)
- Firebug.CommandLine.setMultiLine(true);
- }
- },
- hideLargeCommandLine: function()
- {
- if (Firebug.chrome.largeCommandLineVisible)
- {
- Firebug.chrome.largeCommandLineVisible = false;
- if (Firebug.CommandLine)
- Firebug.CommandLine.setMultiLine(false);
- fbLargeCommandLine.blur();
- fbPanel2Style.display = "block";
- fbPanelBar2BoxStyle.display = "block";
- fbLargeCommandLine.style.display = "none";
- fbLargeCommandButtons.style.display = "none";
- changeSidePanelVisibility(false);
- if (Firebug.chrome.selectedPanel.options.hasCommandLine)
- changeCommandLineVisibility(true);
- Firebug.chrome.draw();
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- focusCommandLine: function()
- {
- var selectedPanelName = this.selectedPanel.name, panelToSelect;
- if (focusCommandLineState == 0 || selectedPanelName != "Console")
- {
- focusCommandLineState = 0;
- lastFocusedPanelName = selectedPanelName;
- panelToSelect = "Console";
- }
- if (focusCommandLineState == 1)
- {
- panelToSelect = lastFocusedPanelName;
- }
- this.selectPanel(panelToSelect);
- try
- {
- if (Firebug.CommandLine)
- {
- if (panelToSelect == "Console")
- Firebug.CommandLine.focus();
- else
- Firebug.CommandLine.blur();
- }
- }
- catch(e)
- {
- //TODO: xxxpedro trace error
- }
- focusCommandLineState = ++focusCommandLineState % 2;
- }
- });
- // ************************************************************************************************
- // ChromeFrameBase
- /**
- * @namespace
- * @extends ns-chrome-ChromeBase
- */
- var ChromeFrameBase = extend(ChromeBase,
- /**@extend ns-chrome-ChromeFrameBase*/
- {
- create: function()
- {
- ChromeBase.create.call(this);
- // restore display for the anti-flicker trick
- if (isFirefox)
- this.node.style.display = "block";
- if (Env.Options.startInNewWindow)
- {
- this.close();
- this.toggle(true, true);
- return;
- }
- if (Env.Options.startOpened)
- this.open();
- else
- this.close();
- },
- destroy: function()
- {
- removeGlobalEvent("keydown", onGlobalKeyDown);
- ChromeBase.destroy.call(this);
- this.document = null;
- delete this.document;
- this.window = null;
- delete this.window;
- this.node.parentNode.removeChild(this.node);
- this.node = null;
- delete this.node;
- },
- initialize: function()
- {
- //FBTrace.sysout("Frame", "initialize();")
- ChromeBase.initialize.call(this);
- this.addController(
- [Firebug.browser.window, "resize", this.resize],
- [$("fbWindow_btClose"), "click", this.close],
- [$("fbWindow_btDetach"), "click", this.detach],
- [$("fbWindow_btDeactivate"), "click", this.deactivate]
- );
- if (!Env.Options.enablePersistent)
- this.addController([Firebug.browser.window, "unload", Firebug.shutdown]);
- if (noFixedPosition)
- {
- this.addController(
- [Firebug.browser.window, "scroll", this.fixIEPosition]
- );
- }
- fbVSplitter.onmousedown = onVSplitterMouseDown;
- fbHSplitter.onmousedown = onHSplitterMouseDown;
- this.isInitialized = true;
- },
- shutdown: function()
- {
- fbVSplitter.onmousedown = null;
- fbHSplitter.onmousedown = null;
- ChromeBase.shutdown.apply(this);
- this.isInitialized = false;
- },
- reattach: function()
- {
- var frame = FirebugChrome.chromeMap.frame;
- ChromeBase.reattach(FirebugChrome.chromeMap.popup, this);
- },
- open: function()
- {
- if (!FirebugChrome.isOpen)
- {
- FirebugChrome.isOpen = true;
- if (Env.isChromeExtension)
- localStorage.setItem("Firebug", "1,1");
- var node = this.node;
- node.style.visibility = "hidden"; // Avoid flickering
- if (Firebug.showIconWhenHidden)
- {
- if (ChromeMini.isInitialized)
- {
- ChromeMini.shutdown();
- }
- }
- else
- node.style.display = "block";
- var main = $("fbChrome");
- // IE6 throws an error when setting this property! why?
- //main.style.display = "table";
- main.style.display = "";
- var self = this;
- setTimeout(function(){
- node.style.visibility = "visible";
- //dispatch(Firebug.modules, "initialize", []);
- self.initialize();
- if (noFixedPosition)
- self.fixIEPosition();
- self.draw();
- }, 10);
- }
- },
- close: function()
- {
- if (FirebugChrome.isOpen || !this.isInitialized)
- {
- if (this.isInitialized)
- {
- //dispatch(Firebug.modules, "shutdown", []);
- this.shutdown();
- }
- FirebugChrome.isOpen = false;
- if (Env.isChromeExtension)
- localStorage.setItem("Firebug", "1,0");
- var node = this.node;
- if (Firebug.showIconWhenHidden)
- {
- node.style.visibility = "hidden"; // Avoid flickering
- // TODO: xxxpedro - persist IE fixed?
- var main = $("fbChrome", FirebugChrome.chromeMap.frame.document);
- main.style.display = "none";
- ChromeMini.initialize();
- node.style.visibility = "visible";
- }
- else
- node.style.display = "none";
- }
- },
- deactivate: function()
- {
- // if it is running as a Chrome extension, dispatch a message to the extension signaling
- // that Firebug should be deactivated for the current tab
- if (Env.isChromeExtension)
- {
- localStorage.removeItem("Firebug");
- Firebug.GoogleChrome.dispatch("FB_deactivate");
- // xxxpedro problem here regarding Chrome extension. We can't deactivate the whole
- // app, otherwise it won't be able to be reactivated without reloading the page.
- // but we need to stop listening global keys, otherwise the key activation won't work.
- Firebug.chrome.close();
- }
- else
- {
- Firebug.shutdown();
- }
- },
- fixIEPosition: function()
- {
- // fix IE problem with offset when not in fullscreen mode
- var doc = this.document;
- var offset = isIE ? doc.body.clientTop || doc.documentElement.clientTop: 0;
- var size = Firebug.browser.getWindowSize();
- var scroll = Firebug.browser.getWindowScrollPosition();
- var maxHeight = size.height;
- var height = this.node.offsetHeight;
- var bodyStyle = doc.body.currentStyle;
- this.node.style.top = maxHeight - height + scroll.top + "px";
- if ((this.type == "frame" || this.type == "div") &&
- (bodyStyle.marginLeft || bodyStyle.marginRight))
- {
- this.node.style.width = size.width + "px";
- }
- if (fbVSplitterStyle)
- fbVSplitterStyle.right = FirebugChrome.sidePanelWidth + "px";
- this.draw();
- }
- });
- // ************************************************************************************************
- // ChromeMini
- /**
- * @namespace
- * @extends FBL.Controller
- */
- var ChromeMini = extend(Controller,
- /**@extend ns-chrome-ChromeMini*/
- {
- create: function(chrome)
- {
- append(this, chrome);
- this.type = "mini";
- },
- initialize: function()
- {
- Controller.initialize.apply(this);
- var doc = FirebugChrome.chromeMap.frame.document;
- var mini = $("fbMiniChrome", doc);
- mini.style.display = "block";
- var miniIcon = $("fbMiniIcon", doc);
- var width = miniIcon.offsetWidth + 10;
- miniIcon.title = "Open " + Firebug.version;
- var errors = $("fbMiniErrors", doc);
- if (errors.offsetWidth)
- width += errors.offsetWidth + 10;
- var node = this.node;
- node.style.height = "27px";
- node.style.width = width + "px";
- node.style.left = "";
- node.style.right = 0;
- if (this.node.nodeName.toLowerCase() == "iframe")
- {
- node.setAttribute("allowTransparency", "true");
- this.document.body.style.backgroundColor = "transparent";
- }
- else
- node.style.background = "transparent";
- if (noFixedPosition)
- this.fixIEPosition();
- this.addController(
- [$("fbMiniIcon", doc), "click", onMiniIconClick]
- );
- if (noFixedPosition)
- {
- this.addController(
- [Firebug.browser.window, "scroll", this.fixIEPosition]
- );
- }
- this.isInitialized = true;
- },
- shutdown: function()
- {
- var node = this.node;
- node.style.height = FirebugChrome.height + "px";
- node.style.width = "100%";
- node.style.left = 0;
- node.style.right = "";
- if (this.node.nodeName.toLowerCase() == "iframe")
- {
- node.setAttribute("allowTransparency", "false");
- this.document.body.style.backgroundColor = "#fff";
- }
- else
- node.style.background = "#fff";
- if (noFixedPosition)
- this.fixIEPosition();
- var doc = FirebugChrome.chromeMap.frame.document;
- var mini = $("fbMiniChrome", doc);
- mini.style.display = "none";
- Controller.shutdown.apply(this);
- this.isInitialized = false;
- },
- draw: function()
- {
- },
- fixIEPosition: ChromeFrameBase.fixIEPosition
- });
- // ************************************************************************************************
- // ChromePopupBase
- /**
- * @namespace
- * @extends ns-chrome-ChromeBase
- */
- var ChromePopupBase = extend(ChromeBase,
- /**@extend ns-chrome-ChromePopupBase*/
- {
- initialize: function()
- {
- setClass(this.document.body, "FirebugPopup");
- ChromeBase.initialize.call(this);
- this.addController(
- [Firebug.chrome.window, "resize", this.resize],
- [Firebug.chrome.window, "unload", this.destroy]
- );
- if (Env.Options.enablePersistent)
- {
- this.persist = bind(this.persist, this);
- addEvent(Firebug.browser.window, "unload", this.persist);
- }
- else
- this.addController(
- [Firebug.browser.window, "unload", this.close]
- );
- fbVSplitter.onmousedown = onVSplitterMouseDown;
- },
- destroy: function()
- {
- // TODO: xxxpedro sync detach reattach attach
- var frame = FirebugChrome.chromeMap.frame;
- if(frame)
- {
- dispatch(frame.panelMap, "detach", [this, frame]);
- frame.reattach(this, frame);
- }
- if (Env.Options.enablePersistent)
- {
- removeEvent(Firebug.browser.window, "unload", this.persist);
- }
- ChromeBase.destroy.apply(this);
- FirebugChrome.chromeMap.popup = null;
- this.node.close();
- },
- persist: function()
- {
- persistTimeStart = new Date().getTime();
- removeEvent(Firebug.browser.window, "unload", this.persist);
- Firebug.Inspector.destroy();
- Firebug.browser.window.FirebugOldBrowser = true;
- var persistTimeStart = new Date().getTime();
- var waitMainWindow = function()
- {
- var doc, head;
- try
- {
- if (window.opener && !window.opener.FirebugOldBrowser && (doc = window.opener.document)/* &&
- doc.documentElement && (head = doc.documentElement.firstChild)*/)
- {
- try
- {
- // exposes the FBL to the global namespace when in debug mode
- if (Env.isDebugMode)
- {
- window.FBL = FBL;
- }
- window.Firebug = Firebug;
- window.opener.Firebug = Firebug;
- Env.browser = window.opener;
- Firebug.browser = Firebug.context = new Context(Env.browser);
- registerConsole();
- // the delay time should be calculated right after registering the
- // console, once right after the console registration, call log messages
- // will be properly handled
- var persistDelay = new Date().getTime() - persistTimeStart;
- var chrome = Firebug.chrome;
- addEvent(Firebug.browser.window, "unload", chrome.persist);
- FBL.cacheDocument();
- Firebug.Inspector.create();
- var htmlPanel = chrome.getPanel("HTML");
- htmlPanel.createUI();
- Firebug.Console.logFormatted(
- ["Firebug could not capture console calls during " +
- persistDelay + "ms"],
- Firebug.context,
- "info"
- );
- }
- catch(pE)
- {
- alert("persist error: " + (pE.message || pE));
- }
- }
- else
- {
- window.setTimeout(waitMainWindow, 0);
- }
- } catch (E) {
- window.close();
- }
- };
- waitMainWindow();
- },
- close: function()
- {
- this.destroy();
- }
- });
- //************************************************************************************************
- // UI helpers
- var changeCommandLineVisibility = function changeCommandLineVisibility(visibility)
- {
- var last = Firebug.chrome.commandLineVisible;
- var visible = Firebug.chrome.commandLineVisible =
- typeof visibility == "boolean" ? visibility : !Firebug.chrome.commandLineVisible;
- if (visible != last)
- {
- if (visible)
- {
- fbBottom.className = "";
- if (Firebug.CommandLine)
- Firebug.CommandLine.activate();
- }
- else
- {
- if (Firebug.CommandLine)
- Firebug.CommandLine.deactivate();
- fbBottom.className = "hide";
- }
- }
- };
- var changeSidePanelVisibility = function changeSidePanelVisibility(visibility)
- {
- var last = Firebug.chrome.sidePanelVisible;
- Firebug.chrome.sidePanelVisible =
- typeof visibility == "boolean" ? visibility : !Firebug.chrome.sidePanelVisible;
- if (Firebug.chrome.sidePanelVisible != last)
- {
- fbPanelBox2.className = Firebug.chrome.sidePanelVisible ? "" : "hide";
- fbPanelBar2Box.className = Firebug.chrome.sidePanelVisible ? "" : "hide";
- }
- };
- // ************************************************************************************************
- // F12 Handler
- var onGlobalKeyDown = function onGlobalKeyDown(event)
- {
- var keyCode = event.keyCode;
- var shiftKey = event.shiftKey;
- var ctrlKey = event.ctrlKey;
- if (keyCode == 123 /* F12 */ && (!isFirefox && !shiftKey || shiftKey && isFirefox))
- {
- Firebug.chrome.toggle(false, ctrlKey);
- cancelEvent(event, true);
- // TODO: xxxpedro replace with a better solution. we're doing this
- // to allow reactivating with the F12 key after being deactivated
- if (Env.isChromeExtension)
- {
- Firebug.GoogleChrome.dispatch("FB_enableIcon");
- }
- }
- else if (keyCode == 67 /* C */ && ctrlKey && shiftKey)
- {
- Firebug.Inspector.toggleInspect();
- cancelEvent(event, true);
- }
- else if (keyCode == 76 /* L */ && ctrlKey && shiftKey)
- {
- Firebug.chrome.focusCommandLine();
- cancelEvent(event, true);
- }
- };
- var onMiniIconClick = function onMiniIconClick(event)
- {
- Firebug.chrome.toggle(false, event.ctrlKey);
- cancelEvent(event, true);
- };
- // ************************************************************************************************
- // Horizontal Splitter Handling
- var onHSplitterMouseDown = function onHSplitterMouseDown(event)
- {
- addGlobalEvent("mousemove", onHSplitterMouseMove);
- addGlobalEvent("mouseup", onHSplitterMouseUp);
- if (isIE)
- addEvent(Firebug.browser.document.documentElement, "mouseleave", onHSplitterMouseUp);
- fbHSplitter.className = "fbOnMovingHSplitter";
- return false;
- };
- var onHSplitterMouseMove = function onHSplitterMouseMove(event)
- {
- cancelEvent(event, true);
- var clientY = event.clientY;
- var win = isIE
- ? event.srcElement.ownerDocument.parentWindow
- : event.target.ownerDocument && event.target.ownerDocument.defaultView;
- if (!win)
- return;
- if (win != win.parent)
- {
- var frameElement = win.frameElement;
- if (frameElement)
- {
- var framePos = Firebug.browser.getElementPosition(frameElement).top;
- clientY += framePos;
- if (frameElement.style.position != "fixed")
- clientY -= Firebug.browser.getWindowScrollPosition().top;
- }
- }
- if (isOpera && isQuiksMode && win.frameElement.id == "FirebugUI")
- {
- clientY = Firebug.browser.getWindowSize().height - win.frameElement.offsetHeight + clientY;
- }
- /*
- console.log(
- typeof win.FBL != "undefined" ? "no-Chrome" : "Chrome",
- //win.frameElement.id,
- event.target,
- clientY
- );/**/
- onHSplitterMouseMoveBuffer = clientY; // buffer
- if (new Date().getTime() - lastHSplitterMouseMove > chromeRedrawSkipRate) // frame skipping
- {
- lastHSplitterMouseMove = new Date().getTime();
- handleHSplitterMouseMove();
- }
- else
- if (!onHSplitterMouseMoveTimer)
- onHSplitterMouseMoveTimer = setTimeout(handleHSplitterMouseMove, chromeRedrawSkipRate);
- // improving the resizing performance by canceling the mouse event.
- // canceling events will prevent the page to receive such events, which would imply
- // in more processing being expended.
- cancelEvent(event, true);
- return false;
- };
- var handleHSplitterMouseMove = function()
- {
- if (onHSplitterMouseMoveTimer)
- {
- clearTimeout(onHSplitterMouseMoveTimer);
- onHSplitterMouseMoveTimer = null;
- }
- var clientY = onHSplitterMouseMoveBuffer;
- var windowSize = Firebug.browser.getWindowSize();
- var scrollSize = Firebug.browser.getWindowScrollSize();
- // compute chrome fixed size (top bar and command line)
- var commandLineHeight = Firebug.chrome.commandLineVisible ? fbCommandLine.offsetHeight : 0;
- var fixedHeight = topHeight + commandLineHeight;
- var chromeNode = Firebug.chrome.node;
- var scrollbarSize = !isIE && (scrollSize.width > windowSize.width) ? 17 : 0;
- //var height = !isOpera ? chromeNode.offsetTop + chromeNode.clientHeight : windowSize.height;
- var height = windowSize.height;
- // compute the min and max size of the chrome
- var chromeHeight = Math.max(height - clientY + 5 - scrollbarSize, fixedHeight);
- chromeHeight = Math.min(chromeHeight, windowSize.height - scrollbarSize);
- FirebugChrome.height = chromeHeight;
- chromeNode.style.height = chromeHeight + "px";
- if (noFixedPosition)
- Firebug.chrome.fixIEPosition();
- Firebug.chrome.draw();
- };
- var onHSplitterMouseUp = function onHSplitterMouseUp(event)
- {
- removeGlobalEvent("mousemove", onHSplitterMouseMove);
- removeGlobalEvent("mouseup", onHSplitterMouseUp);
- if (isIE)
- removeEvent(Firebug.browser.document.documentElement, "mouseleave", onHSplitterMouseUp);
- fbHSplitter.className = "";
- Firebug.chrome.draw();
- // avoid text selection in IE when returning to the document
- // after the mouse leaves the document during the resizing
- return false;
- };
- // ************************************************************************************************
- // Vertical Splitter Handling
- var onVSplitterMouseDown = function onVSplitterMouseDown(event)
- {
- addGlobalEvent("mousemove", onVSplitterMouseMove);
- addGlobalEvent("mouseup", onVSplitterMouseUp);
- return false;
- };
- var onVSplitterMouseMove = function onVSplitterMouseMove(event)
- {
- if (new Date().getTime() - lastVSplitterMouseMove > chromeRedrawSkipRate) // frame skipping
- {
- var target = event.target || event.srcElement;
- if (target && target.ownerDocument) // avoid error when cursor reaches out of the chrome
- {
- var clientX = event.clientX;
- var win = document.all
- ? event.srcElement.ownerDocument.parentWindow
- : event.target.ownerDocument.defaultView;
- if (win != win.parent)
- clientX += win.frameElement ? win.frameElement.offsetLeft : 0;
- var size = Firebug.chrome.getSize();
- var x = Math.max(size.width - clientX + 3, 6);
- FirebugChrome.sidePanelWidth = x;
- Firebug.chrome.draw();
- }
- lastVSplitterMouseMove = new Date().getTime();
- }
- cancelEvent(event, true);
- return false;
- };
- var onVSplitterMouseUp = function onVSplitterMouseUp(event)
- {
- removeGlobalEvent("mousemove", onVSplitterMouseMove);
- removeGlobalEvent("mouseup", onVSplitterMouseUp);
- Firebug.chrome.draw();
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- Firebug.Lite =
- {
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- Firebug.Lite.Browser = function(window)
- {
- this.contentWindow = window;
- this.contentDocument = window.document;
- this.currentURI =
- {
- spec: window.location.href
- };
- };
- Firebug.Lite.Browser.prototype =
- {
- toString: function()
- {
- return "Firebug.Lite.Browser";
- }
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- Firebug.Lite.Cache =
- {
- ID: "firebug" + new Date().getTime()
- };
- // ************************************************************************************************
- /**
- * TODO: if a cached element is cloned, the expando property will be cloned too in IE
- * which will result in a bug. Firebug Lite will think the new cloned node is the old
- * one.
- *
- * TODO: Investigate a possibility of cache validation, to be customized by each
- * kind of cache. For ElementCache it should validate if the element still is
- * inserted at the DOM.
- */
- var cacheUID = 0;
- var createCache = function()
- {
- var map = {};
- var CID = Firebug.Lite.Cache.ID;
- // better detection
- var supportsDeleteExpando = !document.all;
- var cacheFunction = function(element)
- {
- return cacheAPI.set(element);
- };
- var cacheAPI =
- {
- get: function(key)
- {
- return map.hasOwnProperty(key) ?
- map[key] :
- null;
- },
- set: function(element)
- {
- var id = element[CID];
- if (!id)
- {
- id = ++cacheUID;
- element[CID] = id;
- }
- if (!map.hasOwnProperty(id))
- {
- map[id] = element;
- }
- return id;
- },
- unset: function(element)
- {
- var id = element[CID];
- if (supportsDeleteExpando)
- {
- delete element[CID];
- }
- else if (element.removeAttribute)
- {
- element.removeAttribute(CID);
- }
- delete map[id];
- },
- key: function(element)
- {
- return element[CID];
- },
- has: function(element)
- {
- return map.hasOwnProperty(element[CID]);
- },
- clear: function()
- {
- for (var id in map)
- {
- var element = map[id];
- cacheAPI.unset(element);
- }
- }
- };
- FBL.append(cacheFunction, cacheAPI);
- return cacheFunction;
- };
- // ************************************************************************************************
- // TODO: xxxpedro : check if we need really this on FBL scope
- Firebug.Lite.Cache.StyleSheet = createCache();
- Firebug.Lite.Cache.Element = createCache();
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- Firebug.Lite.Proxy =
- {
- // jsonp callbacks
- _callbacks: {},
- /**
- * Load a resource, either locally (directly) or externally (via proxy) using
- * synchronous XHR calls. Loading external resources requires the proxy plugin to
- * be installed and configured (see /plugin/proxy/proxy.php).
- */
- load: function(url)
- {
- var resourceDomain = getDomain(url);
- var isLocalResource =
- // empty domain means local URL
- !resourceDomain ||
- // same domain means local too
- resourceDomain == Firebug.context.window.location.host; // TODO: xxxpedro context
- return isLocalResource ? fetchResource(url) : fetchProxyResource(url);
- },
- /**
- * Load a resource using JSONP technique.
- */
- loadJSONP: function(url, callback)
- {
- var script = createGlobalElement("script"),
- doc = Firebug.context.document,
- uid = "" + new Date().getTime(),
- callbackName = "callback=Firebug.Lite.Proxy._callbacks." + uid,
- jsonpURL = url.indexOf("?") != -1 ?
- url + "&" + callbackName :
- url + "?" + callbackName;
- Firebug.Lite.Proxy._callbacks[uid] = function(data)
- {
- if (callback)
- callback(data);
- script.parentNode.removeChild(script);
- delete Firebug.Lite.Proxy._callbacks[uid];
- };
- script.src = jsonpURL;
- if (doc.documentElement)
- doc.documentElement.appendChild(script);
- },
- /**
- * Load a resource using YQL (not reliable).
- */
- YQL: function(url, callback)
- {
- var yql = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" +
- encodeURIComponent(url) + "%22&format=xml";
- this.loadJSONP(yql, function(data)
- {
- var source = data.results[0];
- // clean up YQL bogus elements
- var match = /<body>\s+<p>([\s\S]+)<\/p>\s+<\/body>$/.exec(source);
- if (match)
- source = match[1];
- console.log(source);
- });
- }
- };
- // ************************************************************************************************
- var fetchResource = function(url)
- {
- var xhr = FBL.Ajax.getXHRObject();
- xhr.open("get", url, false);
- xhr.send();
- return xhr.responseText;
- };
- var fetchProxyResource = function(url)
- {
- var proxyURL = Env.Location.baseDir + "plugin/proxy/proxy.php?url=" + encodeURIComponent(url);
- var response = fetchResource(proxyURL);
- try
- {
- var data = eval("(" + response + ")");
- }
- catch(E)
- {
- return "ERROR: Firebug Lite Proxy plugin returned an invalid response.";
- }
- return data ? data.contents : "";
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- Firebug.Lite.Script = function(window)
- {
- this.fileName = null;
- this.isValid = null;
- this.baseLineNumber = null;
- this.lineExtent = null;
- this.tag = null;
- this.functionName = null;
- this.functionSource = null;
- };
- Firebug.Lite.Script.prototype =
- {
- isLineExecutable: function(){},
- pcToLine: function(){},
- lineToPc: function(){},
- toString: function()
- {
- return "Firebug.Lite.Script";
- }
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- Firebug.Lite.Style =
- {
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns( /**@scope ns-selector*/ function() { with (FBL) {
- // ************************************************************************************************
- /*
- * Sizzle CSS Selector Engine - v1.0
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
- var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
- done = 0,
- toString = Object.prototype.toString,
- hasDuplicate = false,
- baseHasDuplicate = true;
- // Here we check if the JavaScript engine is using some sort of
- // optimization where it does not always call our comparision
- // function. If that is the case, discard the hasDuplicate value.
- // Thus far that includes Google Chrome.
- [0, 0].sort(function(){
- baseHasDuplicate = false;
- return 0;
- });
- /**
- * @name Firebug.Selector
- * @namespace
- */
- /**
- * @exports Sizzle as Firebug.Selector
- */
- var Sizzle = function(selector, context, results, seed) {
- results = results || [];
- var origContext = context = context || document;
- if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
- return [];
- }
- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
- var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
- soFar = selector;
- // Reset the position of the chunker regexp (start from head)
- while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
- soFar = m[3];
- parts.push( m[1] );
- if ( m[2] ) {
- extra = m[3];
- break;
- }
- }
- if ( parts.length > 1 && origPOS.exec( selector ) ) {
- if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
- set = posProcess( parts[0] + parts[1], context );
- } else {
- set = Expr.relative[ parts[0] ] ?
- [ context ] :
- Sizzle( parts.shift(), context );
- while ( parts.length ) {
- selector = parts.shift();
- if ( Expr.relative[ selector ] )
- selector += parts.shift();
- set = posProcess( selector, set );
- }
- }
- } else {
- // Take a shortcut and set the context if the root selector is an ID
- // (but not if it'll be faster if the inner selector is an ID)
- if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
- Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
- var ret = Sizzle.find( parts.shift(), context, contextXML );
- context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
- }
- if ( context ) {
- var ret = seed ?
- { expr: parts.pop(), set: makeArray(seed) } :
- Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
- set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
- if ( parts.length > 0 ) {
- checkSet = makeArray(set);
- } else {
- prune = false;
- }
- while ( parts.length ) {
- var cur = parts.pop(), pop = cur;
- if ( !Expr.relative[ cur ] ) {
- cur = "";
- } else {
- pop = parts.pop();
- }
- if ( pop == null ) {
- pop = context;
- }
- Expr.relative[ cur ]( checkSet, pop, contextXML );
- }
- } else {
- checkSet = parts = [];
- }
- }
- if ( !checkSet ) {
- checkSet = set;
- }
- if ( !checkSet ) {
- throw "Syntax error, unrecognized expression: " + (cur || selector);
- }
- if ( toString.call(checkSet) === "[object Array]" ) {
- if ( !prune ) {
- results.push.apply( results, checkSet );
- } else if ( context && context.nodeType === 1 ) {
- for ( var i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
- results.push( set[i] );
- }
- }
- } else {
- for ( var i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
- results.push( set[i] );
- }
- }
- }
- } else {
- makeArray( checkSet, results );
- }
- if ( extra ) {
- Sizzle( extra, origContext, results, seed );
- Sizzle.uniqueSort( results );
- }
- return results;
- };
- Sizzle.uniqueSort = function(results){
- if ( sortOrder ) {
- hasDuplicate = baseHasDuplicate;
- results.sort(sortOrder);
- if ( hasDuplicate ) {
- for ( var i = 1; i < results.length; i++ ) {
- if ( results[i] === results[i-1] ) {
- results.splice(i--, 1);
- }
- }
- }
- }
- return results;
- };
- Sizzle.matches = function(expr, set){
- return Sizzle(expr, null, null, set);
- };
- Sizzle.find = function(expr, context, isXML){
- var set, match;
- if ( !expr ) {
- return [];
- }
- for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
- var type = Expr.order[i], match;
- if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
- var left = match[1];
- match.splice(1,1);
- if ( left.substr( left.length - 1 ) !== "\\" ) {
- match[1] = (match[1] || "").replace(/\\/g, "");
- set = Expr.find[ type ]( match, context, isXML );
- if ( set != null ) {
- expr = expr.replace( Expr.match[ type ], "" );
- break;
- }
- }
- }
- }
- if ( !set ) {
- set = context.getElementsByTagName("*");
- }
- return {set: set, expr: expr};
- };
- Sizzle.filter = function(expr, set, inplace, not){
- var old = expr, result = [], curLoop = set, match, anyFound,
- isXMLFilter = set && set[0] && isXML(set[0]);
- while ( expr && set.length ) {
- for ( var type in Expr.filter ) {
- if ( (match = Expr.match[ type ].exec( expr )) != null ) {
- var filter = Expr.filter[ type ], found, item;
- anyFound = false;
- if ( curLoop == result ) {
- result = [];
- }
- if ( Expr.preFilter[ type ] ) {
- match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
- if ( !match ) {
- anyFound = found = true;
- } else if ( match === true ) {
- continue;
- }
- }
- if ( match ) {
- for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
- if ( item ) {
- found = filter( item, match, i, curLoop );
- var pass = not ^ !!found;
- if ( inplace && found != null ) {
- if ( pass ) {
- anyFound = true;
- } else {
- curLoop[i] = false;
- }
- } else if ( pass ) {
- result.push( item );
- anyFound = true;
- }
- }
- }
- }
- if ( found !== undefined ) {
- if ( !inplace ) {
- curLoop = result;
- }
- expr = expr.replace( Expr.match[ type ], "" );
- if ( !anyFound ) {
- return [];
- }
- break;
- }
- }
- }
- // Improper expression
- if ( expr == old ) {
- if ( anyFound == null ) {
- throw "Syntax error, unrecognized expression: " + expr;
- } else {
- break;
- }
- }
- old = expr;
- }
- return curLoop;
- };
- /**#@+ @ignore */
- var Expr = Sizzle.selectors = {
- order: [ "ID", "NAME", "TAG" ],
- match: {
- ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
- CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
- NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
- ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
- TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
- CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
- POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
- PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
- },
- leftMatch: {},
- attrMap: {
- "class": "className",
- "for": "htmlFor"
- },
- attrHandle: {
- href: function(elem){
- return elem.getAttribute("href");
- }
- },
- relative: {
- "+": function(checkSet, part, isXML){
- var isPartStr = typeof part === "string",
- isTag = isPartStr && !/\W/.test(part),
- isPartStrNotTag = isPartStr && !isTag;
- if ( isTag && !isXML ) {
- part = part.toUpperCase();
- }
- for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
- if ( (elem = checkSet[i]) ) {
- while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
- checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
- elem || false :
- elem === part;
- }
- }
- if ( isPartStrNotTag ) {
- Sizzle.filter( part, checkSet, true );
- }
- },
- ">": function(checkSet, part, isXML){
- var isPartStr = typeof part === "string";
- if ( isPartStr && !/\W/.test(part) ) {
- part = isXML ? part : part.toUpperCase();
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- var parent = elem.parentNode;
- checkSet[i] = parent.nodeName === part ? parent : false;
- }
- }
- } else {
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- checkSet[i] = isPartStr ?
- elem.parentNode :
- elem.parentNode === part;
- }
- }
- if ( isPartStr ) {
- Sizzle.filter( part, checkSet, true );
- }
- }
- },
- "": function(checkSet, part, isXML){
- var doneName = done++, checkFn = dirCheck;
- if ( !/\W/.test(part) ) {
- var nodeCheck = part = isXML ? part : part.toUpperCase();
- checkFn = dirNodeCheck;
- }
- checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
- },
- "~": function(checkSet, part, isXML){
- var doneName = done++, checkFn = dirCheck;
- if ( typeof part === "string" && !/\W/.test(part) ) {
- var nodeCheck = part = isXML ? part : part.toUpperCase();
- checkFn = dirNodeCheck;
- }
- checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
- }
- },
- find: {
- ID: function(match, context, isXML){
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
- return m ? [m] : [];
- }
- },
- NAME: function(match, context, isXML){
- if ( typeof context.getElementsByName !== "undefined" ) {
- var ret = [], results = context.getElementsByName(match[1]);
- for ( var i = 0, l = results.length; i < l; i++ ) {
- if ( results[i].getAttribute("name") === match[1] ) {
- ret.push( results[i] );
- }
- }
- return ret.length === 0 ? null : ret;
- }
- },
- TAG: function(match, context){
- return context.getElementsByTagName(match[1]);
- }
- },
- preFilter: {
- CLASS: function(match, curLoop, inplace, result, not, isXML){
- match = " " + match[1].replace(/\\/g, "") + " ";
- if ( isXML ) {
- return match;
- }
- for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
- if ( elem ) {
- if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
- if ( !inplace )
- result.push( elem );
- } else if ( inplace ) {
- curLoop[i] = false;
- }
- }
- }
- return false;
- },
- ID: function(match){
- return match[1].replace(/\\/g, "");
- },
- TAG: function(match, curLoop){
- for ( var i = 0; curLoop[i] === false; i++ ){}
- return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
- },
- CHILD: function(match){
- if ( match[1] == "nth" ) {
- // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
- var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
- match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
- !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
- // calculate the numbers (first)n+(last) including if they are negative
- match[2] = (test[1] + (test[2] || 1)) - 0;
- match[3] = test[3] - 0;
- }
- // TODO: Move to normal caching system
- match[0] = done++;
- return match;
- },
- ATTR: function(match, curLoop, inplace, result, not, isXML){
- var name = match[1].replace(/\\/g, "");
- if ( !isXML && Expr.attrMap[name] ) {
- match[1] = Expr.attrMap[name];
- }
- if ( match[2] === "~=" ) {
- match[4] = " " + match[4] + " ";
- }
- return match;
- },
- PSEUDO: function(match, curLoop, inplace, result, not){
- if ( match[1] === "not" ) {
- // If we're dealing with a complex expression, or a simple one
- if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
- match[3] = Sizzle(match[3], null, null, curLoop);
- } else {
- var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
- if ( !inplace ) {
- result.push.apply( result, ret );
- }
- return false;
- }
- } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
- return true;
- }
- return match;
- },
- POS: function(match){
- match.unshift( true );
- return match;
- }
- },
- filters: {
- enabled: function(elem){
- return elem.disabled === false && elem.type !== "hidden";
- },
- disabled: function(elem){
- return elem.disabled === true;
- },
- checked: function(elem){
- return elem.checked === true;
- },
- selected: function(elem){
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- elem.parentNode.selectedIndex;
- return elem.selected === true;
- },
- parent: function(elem){
- return !!elem.firstChild;
- },
- empty: function(elem){
- return !elem.firstChild;
- },
- has: function(elem, i, match){
- return !!Sizzle( match[3], elem ).length;
- },
- header: function(elem){
- return /h\d/i.test( elem.nodeName );
- },
- text: function(elem){
- return "text" === elem.type;
- },
- radio: function(elem){
- return "radio" === elem.type;
- },
- checkbox: function(elem){
- return "checkbox" === elem.type;
- },
- file: function(elem){
- return "file" === elem.type;
- },
- password: function(elem){
- return "password" === elem.type;
- },
- submit: function(elem){
- return "submit" === elem.type;
- },
- image: function(elem){
- return "image" === elem.type;
- },
- reset: function(elem){
- return "reset" === elem.type;
- },
- button: function(elem){
- return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
- },
- input: function(elem){
- return /input|select|textarea|button/i.test(elem.nodeName);
- }
- },
- setFilters: {
- first: function(elem, i){
- return i === 0;
- },
- last: function(elem, i, match, array){
- return i === array.length - 1;
- },
- even: function(elem, i){
- return i % 2 === 0;
- },
- odd: function(elem, i){
- return i % 2 === 1;
- },
- lt: function(elem, i, match){
- return i < match[3] - 0;
- },
- gt: function(elem, i, match){
- return i > match[3] - 0;
- },
- nth: function(elem, i, match){
- return match[3] - 0 == i;
- },
- eq: function(elem, i, match){
- return match[3] - 0 == i;
- }
- },
- filter: {
- PSEUDO: function(elem, match, i, array){
- var name = match[1], filter = Expr.filters[ name ];
- if ( filter ) {
- return filter( elem, i, match, array );
- } else if ( name === "contains" ) {
- return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
- } else if ( name === "not" ) {
- var not = match[3];
- for ( var i = 0, l = not.length; i < l; i++ ) {
- if ( not[i] === elem ) {
- return false;
- }
- }
- return true;
- }
- },
- CHILD: function(elem, match){
- var type = match[1], node = elem;
- switch (type) {
- case 'only':
- case 'first':
- while ( (node = node.previousSibling) ) {
- if ( node.nodeType === 1 ) return false;
- }
- if ( type == 'first') return true;
- node = elem;
- case 'last':
- while ( (node = node.nextSibling) ) {
- if ( node.nodeType === 1 ) return false;
- }
- return true;
- case 'nth':
- var first = match[2], last = match[3];
- if ( first == 1 && last == 0 ) {
- return true;
- }
- var doneName = match[0],
- parent = elem.parentNode;
- if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
- var count = 0;
- for ( node = parent.firstChild; node; node = node.nextSibling ) {
- if ( node.nodeType === 1 ) {
- node.nodeIndex = ++count;
- }
- }
- parent.sizcache = doneName;
- }
- var diff = elem.nodeIndex - last;
- if ( first == 0 ) {
- return diff == 0;
- } else {
- return ( diff % first == 0 && diff / first >= 0 );
- }
- }
- },
- ID: function(elem, match){
- return elem.nodeType === 1 && elem.getAttribute("id") === match;
- },
- TAG: function(elem, match){
- return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
- },
- CLASS: function(elem, match){
- return (" " + (elem.className || elem.getAttribute("class")) + " ")
- .indexOf( match ) > -1;
- },
- ATTR: function(elem, match){
- var name = match[1],
- result = Expr.attrHandle[ name ] ?
- Expr.attrHandle[ name ]( elem ) :
- elem[ name ] != null ?
- elem[ name ] :
- elem.getAttribute( name ),
- value = result + "",
- type = match[2],
- check = match[4];
- return result == null ?
- type === "!=" :
- type === "=" ?
- value === check :
- type === "*=" ?
- value.indexOf(check) >= 0 :
- type === "~=" ?
- (" " + value + " ").indexOf(check) >= 0 :
- !check ?
- value && result !== false :
- type === "!=" ?
- value != check :
- type === "^=" ?
- value.indexOf(check) === 0 :
- type === "$=" ?
- value.substr(value.length - check.length) === check :
- type === "|=" ?
- value === check || value.substr(0, check.length + 1) === check + "-" :
- false;
- },
- POS: function(elem, match, i, array){
- var name = match[2], filter = Expr.setFilters[ name ];
- if ( filter ) {
- return filter( elem, i, match, array );
- }
- }
- }
- };
- var origPOS = Expr.match.POS;
- for ( var type in Expr.match ) {
- Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
- Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
- }
- var makeArray = function(array, results) {
- array = Array.prototype.slice.call( array, 0 );
- if ( results ) {
- results.push.apply( results, array );
- return results;
- }
- return array;
- };
- // Perform a simple check to determine if the browser is capable of
- // converting a NodeList to an array using builtin methods.
- try {
- Array.prototype.slice.call( document.documentElement.childNodes, 0 );
- // Provide a fallback method if it does not work
- } catch(e){
- makeArray = function(array, results) {
- var ret = results || [];
- if ( toString.call(array) === "[object Array]" ) {
- Array.prototype.push.apply( ret, array );
- } else {
- if ( typeof array.length === "number" ) {
- for ( var i = 0, l = array.length; i < l; i++ ) {
- ret.push( array[i] );
- }
- } else {
- for ( var i = 0; array[i]; i++ ) {
- ret.push( array[i] );
- }
- }
- }
- return ret;
- };
- }
- var sortOrder;
- if ( document.documentElement.compareDocumentPosition ) {
- sortOrder = function( a, b ) {
- if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
- if ( a == b ) {
- hasDuplicate = true;
- }
- return 0;
- }
- var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
- if ( ret === 0 ) {
- hasDuplicate = true;
- }
- return ret;
- };
- } else if ( "sourceIndex" in document.documentElement ) {
- sortOrder = function( a, b ) {
- if ( !a.sourceIndex || !b.sourceIndex ) {
- if ( a == b ) {
- hasDuplicate = true;
- }
- return 0;
- }
- var ret = a.sourceIndex - b.sourceIndex;
- if ( ret === 0 ) {
- hasDuplicate = true;
- }
- return ret;
- };
- } else if ( document.createRange ) {
- sortOrder = function( a, b ) {
- if ( !a.ownerDocument || !b.ownerDocument ) {
- if ( a == b ) {
- hasDuplicate = true;
- }
- return 0;
- }
- var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
- aRange.setStart(a, 0);
- aRange.setEnd(a, 0);
- bRange.setStart(b, 0);
- bRange.setEnd(b, 0);
- var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
- if ( ret === 0 ) {
- hasDuplicate = true;
- }
- return ret;
- };
- }
- // Check to see if the browser returns elements by name when
- // querying by getElementById (and provide a workaround)
- (function(){
- // We're going to inject a fake input element with a specified name
- var form = document.createElement("div"),
- id = "script" + (new Date).getTime();
- form.innerHTML = "<a name='" + id + "'/>";
- // Inject it into the root element, check its status, and remove it quickly
- var root = document.documentElement;
- root.insertBefore( form, root.firstChild );
- // The workaround has to do additional checks after a getElementById
- // Which slows things down for other browsers (hence the branching)
- if ( !!document.getElementById( id ) ) {
- Expr.find.ID = function(match, context, isXML){
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
- return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
- }
- };
- Expr.filter.ID = function(elem, match){
- var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
- return elem.nodeType === 1 && node && node.nodeValue === match;
- };
- }
- root.removeChild( form );
- root = form = null; // release memory in IE
- })();
- (function(){
- // Check to see if the browser returns only elements
- // when doing getElementsByTagName("*")
- // Create a fake element
- var div = document.createElement("div");
- div.appendChild( document.createComment("") );
- // Make sure no comments are found
- if ( div.getElementsByTagName("*").length > 0 ) {
- Expr.find.TAG = function(match, context){
- var results = context.getElementsByTagName(match[1]);
- // Filter out possible comments
- if ( match[1] === "*" ) {
- var tmp = [];
- for ( var i = 0; results[i]; i++ ) {
- if ( results[i].nodeType === 1 ) {
- tmp.push( results[i] );
- }
- }
- results = tmp;
- }
- return results;
- };
- }
- // Check to see if an attribute returns normalized href attributes
- div.innerHTML = "<a href='#'></a>";
- if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
- div.firstChild.getAttribute("href") !== "#" ) {
- Expr.attrHandle.href = function(elem){
- return elem.getAttribute("href", 2);
- };
- }
- div = null; // release memory in IE
- })();
- if ( document.querySelectorAll ) (function(){
- var oldSizzle = Sizzle, div = document.createElement("div");
- div.innerHTML = "<p class='TEST'></p>";
- // Safari can't handle uppercase or unicode characters when
- // in quirks mode.
- if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
- return;
- }
- Sizzle = function(query, context, extra, seed){
- context = context || document;
- // Only use querySelectorAll on non-XML documents
- // (ID selectors don't work in non-HTML documents)
- if ( !seed && context.nodeType === 9 && !isXML(context) ) {
- try {
- return makeArray( context.querySelectorAll(query), extra );
- } catch(e){}
- }
- return oldSizzle(query, context, extra, seed);
- };
- for ( var prop in oldSizzle ) {
- Sizzle[ prop ] = oldSizzle[ prop ];
- }
- div = null; // release memory in IE
- })();
- if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
- var div = document.createElement("div");
- div.innerHTML = "<div class='test e'></div><div class='test'></div>";
- // Opera can't find a second classname (in 9.6)
- if ( div.getElementsByClassName("e").length === 0 )
- return;
- // Safari caches class attributes, doesn't catch changes (in 3.2)
- div.lastChild.className = "e";
- if ( div.getElementsByClassName("e").length === 1 )
- return;
- Expr.order.splice(1, 0, "CLASS");
- Expr.find.CLASS = function(match, context, isXML) {
- if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
- return context.getElementsByClassName(match[1]);
- }
- };
- div = null; // release memory in IE
- })();
- function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- var sibDir = dir == "previousSibling" && !isXML;
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- if ( sibDir && elem.nodeType === 1 ){
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- elem = elem[dir];
- var match = false;
- while ( elem ) {
- if ( elem.sizcache === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
- if ( elem.nodeType === 1 && !isXML ){
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- if ( elem.nodeName === cur ) {
- match = elem;
- break;
- }
- elem = elem[dir];
- }
- checkSet[i] = match;
- }
- }
- }
- function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- var sibDir = dir == "previousSibling" && !isXML;
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
- if ( elem ) {
- if ( sibDir && elem.nodeType === 1 ) {
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- elem = elem[dir];
- var match = false;
- while ( elem ) {
- if ( elem.sizcache === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
- if ( elem.nodeType === 1 ) {
- if ( !isXML ) {
- elem.sizcache = doneName;
- elem.sizset = i;
- }
- if ( typeof cur !== "string" ) {
- if ( elem === cur ) {
- match = true;
- break;
- }
- } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
- match = elem;
- break;
- }
- }
- elem = elem[dir];
- }
- checkSet[i] = match;
- }
- }
- }
- var contains = document.compareDocumentPosition ? function(a, b){
- return a.compareDocumentPosition(b) & 16;
- } : function(a, b){
- return a !== b && (a.contains ? a.contains(b) : true);
- };
- var isXML = function(elem){
- return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
- !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
- };
- var posProcess = function(selector, context){
- var tmpSet = [], later = "", match,
- root = context.nodeType ? [context] : context;
- // Position selectors must be done after the filter
- // And so must :not(positional) so we move all PSEUDOs to the end
- while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
- later += match[0];
- selector = selector.replace( Expr.match.PSEUDO, "" );
- }
- selector = Expr.relative[selector] ? selector + "*" : selector;
- for ( var i = 0, l = root.length; i < l; i++ ) {
- Sizzle( selector, root[i], tmpSet );
- }
- return Sizzle.filter( later, tmpSet );
- };
- // EXPOSE
- Firebug.Selector = Sizzle;
- /**#@-*/
- // ************************************************************************************************
- }});
- // Problems in IE
- // FIXED - eval return
- // FIXED - addEventListener problem in IE
- // FIXED doc.createRange?
- //
- // class reserved word
- // test all honza examples in IE6 and IE7
- /* See license.txt for terms of usage */
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function DomplateTag(tagName)
- {
- this.tagName = tagName;
- }
- function DomplateEmbed()
- {
- }
- function DomplateLoop()
- {
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ( /** @scope ns-domplate */ function() {
- var womb = null;
- var domplate = FBL.domplate = function()
- {
- var lastSubject;
- for (var i = 0; i < arguments.length; ++i)
- lastSubject = lastSubject ? copyObject(lastSubject, arguments[i]) : arguments[i];
- for (var name in lastSubject)
- {
- var val = lastSubject[name];
- if (isTag(val))
- val.tag.subject = lastSubject;
- }
- return lastSubject;
- };
- domplate.context = function(context, fn)
- {
- var lastContext = domplate.lastContext;
- domplate.topContext = context;
- fn.apply(context);
- domplate.topContext = lastContext;
- };
- FBL.TAG = function()
- {
- var embed = new DomplateEmbed();
- return embed.merge(arguments);
- };
- FBL.FOR = function()
- {
- var loop = new DomplateLoop();
- return loop.merge(arguments);
- };
- DomplateTag.prototype =
- {
- merge: function(args, oldTag)
- {
- if (oldTag)
- this.tagName = oldTag.tagName;
- this.context = oldTag ? oldTag.context : null;
- this.subject = oldTag ? oldTag.subject : null;
- this.attrs = oldTag ? copyObject(oldTag.attrs) : {};
- this.classes = oldTag ? copyObject(oldTag.classes) : {};
- this.props = oldTag ? copyObject(oldTag.props) : null;
- this.listeners = oldTag ? copyArray(oldTag.listeners) : null;
- this.children = oldTag ? copyArray(oldTag.children) : [];
- this.vars = oldTag ? copyArray(oldTag.vars) : [];
- var attrs = args.length ? args[0] : null;
- var hasAttrs = typeof(attrs) == "object" && !isTag(attrs);
- this.children = [];
- if (domplate.topContext)
- this.context = domplate.topContext;
- if (args.length)
- parseChildren(args, hasAttrs ? 1 : 0, this.vars, this.children);
- if (hasAttrs)
- this.parseAttrs(attrs);
- return creator(this, DomplateTag);
- },
- parseAttrs: function(args)
- {
- for (var name in args)
- {
- var val = parseValue(args[name]);
- readPartNames(val, this.vars);
- if (name.indexOf("on") == 0)
- {
- var eventName = name.substr(2);
- if (!this.listeners)
- this.listeners = [];
- this.listeners.push(eventName, val);
- }
- else if (name.indexOf("_") == 0)
- {
- var propName = name.substr(1);
- if (!this.props)
- this.props = {};
- this.props[propName] = val;
- }
- else if (name.indexOf("$") == 0)
- {
- var className = name.substr(1);
- if (!this.classes)
- this.classes = {};
- this.classes[className] = val;
- }
- else
- {
- if (name == "class" && this.attrs.hasOwnProperty(name) )
- this.attrs[name] += " " + val;
- else
- this.attrs[name] = val;
- }
- }
- },
- compile: function()
- {
- if (this.renderMarkup)
- return;
- this.compileMarkup();
- this.compileDOM();
- //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate renderMarkup: ", this.renderMarkup);
- //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate renderDOM:", this.renderDOM);
- //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate domArgs:", this.domArgs);
- },
- compileMarkup: function()
- {
- this.markupArgs = [];
- var topBlock = [], topOuts = [], blocks = [], info = {args: this.markupArgs, argIndex: 0};
- this.generateMarkup(topBlock, topOuts, blocks, info);
- this.addCode(topBlock, topOuts, blocks);
- var fnBlock = ['r=(function (__code__, __context__, __in__, __out__'];
- for (var i = 0; i < info.argIndex; ++i)
- fnBlock.push(', s', i);
- fnBlock.push(') {');
- if (this.subject)
- fnBlock.push('with (this) {');
- if (this.context)
- fnBlock.push('with (__context__) {');
- fnBlock.push('with (__in__) {');
- fnBlock.push.apply(fnBlock, blocks);
- if (this.subject)
- fnBlock.push('}');
- if (this.context)
- fnBlock.push('}');
- fnBlock.push('}})');
- function __link__(tag, code, outputs, args)
- {
- if (!tag || !tag.tag)
- return;
- tag.tag.compile();
- var tagOutputs = [];
- var markupArgs = [code, tag.tag.context, args, tagOutputs];
- markupArgs.push.apply(markupArgs, tag.tag.markupArgs);
- tag.tag.renderMarkup.apply(tag.tag.subject, markupArgs);
- outputs.push(tag);
- outputs.push(tagOutputs);
- }
- function __escape__(value)
- {
- function replaceChars(ch)
- {
- switch (ch)
- {
- case "<":
- return "<";
- case ">":
- return ">";
- case "&":
- return "&";
- case "'":
- return "'";
- case '"':
- return """;
- }
- return "?";
- };
- return String(value).replace(/[<>&"']/g, replaceChars);
- }
- function __loop__(iter, outputs, fn)
- {
- var iterOuts = [];
- outputs.push(iterOuts);
- if (iter instanceof Array)
- iter = new ArrayIterator(iter);
- try
- {
- while (1)
- {
- var value = iter.next();
- var itemOuts = [0,0];
- iterOuts.push(itemOuts);
- fn.apply(this, [value, itemOuts]);
- }
- }
- catch (exc)
- {
- if (exc != StopIteration)
- throw exc;
- }
- }
- var js = fnBlock.join("");
- var r = null;
- eval(js);
- this.renderMarkup = r;
- },
- getVarNames: function(args)
- {
- if (this.vars)
- args.push.apply(args, this.vars);
- for (var i = 0; i < this.children.length; ++i)
- {
- var child = this.children[i];
- if (isTag(child))
- child.tag.getVarNames(args);
- else if (child instanceof Parts)
- {
- for (var i = 0; i < child.parts.length; ++i)
- {
- if (child.parts[i] instanceof Variable)
- {
- var name = child.parts[i].name;
- var names = name.split(".");
- args.push(names[0]);
- }
- }
- }
- }
- },
- generateMarkup: function(topBlock, topOuts, blocks, info)
- {
- topBlock.push(',"<', this.tagName, '"');
- for (var name in this.attrs)
- {
- if (name != "class")
- {
- var val = this.attrs[name];
- topBlock.push(', " ', name, '=\\""');
- addParts(val, ',', topBlock, info, true);
- topBlock.push(', "\\""');
- }
- }
- if (this.listeners)
- {
- for (var i = 0; i < this.listeners.length; i += 2)
- readPartNames(this.listeners[i+1], topOuts);
- }
- if (this.props)
- {
- for (var name in this.props)
- readPartNames(this.props[name], topOuts);
- }
- if ( this.attrs.hasOwnProperty("class") || this.classes)
- {
- topBlock.push(', " class=\\""');
- if (this.attrs.hasOwnProperty("class"))
- addParts(this.attrs["class"], ',', topBlock, info, true);
- topBlock.push(', " "');
- for (var name in this.classes)
- {
- topBlock.push(', (');
- addParts(this.classes[name], '', topBlock, info);
- topBlock.push(' ? "', name, '" + " " : "")');
- }
- topBlock.push(', "\\""');
- }
- topBlock.push(',">"');
- this.generateChildMarkup(topBlock, topOuts, blocks, info);
- topBlock.push(',"</', this.tagName, '>"');
- },
- generateChildMarkup: function(topBlock, topOuts, blocks, info)
- {
- for (var i = 0; i < this.children.length; ++i)
- {
- var child = this.children[i];
- if (isTag(child))
- child.tag.generateMarkup(topBlock, topOuts, blocks, info);
- else
- addParts(child, ',', topBlock, info, true);
- }
- },
- addCode: function(topBlock, topOuts, blocks)
- {
- if (topBlock.length)
- blocks.push('__code__.push(""', topBlock.join(""), ');');
- if (topOuts.length)
- blocks.push('__out__.push(', topOuts.join(","), ');');
- topBlock.splice(0, topBlock.length);
- topOuts.splice(0, topOuts.length);
- },
- addLocals: function(blocks)
- {
- var varNames = [];
- this.getVarNames(varNames);
- var map = {};
- for (var i = 0; i < varNames.length; ++i)
- {
- var name = varNames[i];
- if ( map.hasOwnProperty(name) )
- continue;
- map[name] = 1;
- var names = name.split(".");
- blocks.push('var ', names[0] + ' = ' + '__in__.' + names[0] + ';');
- }
- },
- compileDOM: function()
- {
- var path = [];
- var blocks = [];
- this.domArgs = [];
- path.embedIndex = 0;
- path.loopIndex = 0;
- path.staticIndex = 0;
- path.renderIndex = 0;
- var nodeCount = this.generateDOM(path, blocks, this.domArgs);
- var fnBlock = ['r=(function (root, context, o'];
- for (var i = 0; i < path.staticIndex; ++i)
- fnBlock.push(', ', 's'+i);
- for (var i = 0; i < path.renderIndex; ++i)
- fnBlock.push(', ', 'd'+i);
- fnBlock.push(') {');
- for (var i = 0; i < path.loopIndex; ++i)
- fnBlock.push('var l', i, ' = 0;');
- for (var i = 0; i < path.embedIndex; ++i)
- fnBlock.push('var e', i, ' = 0;');
- if (this.subject)
- fnBlock.push('with (this) {');
- if (this.context)
- fnBlock.push('with (context) {');
- fnBlock.push(blocks.join(""));
- if (this.subject)
- fnBlock.push('}');
- if (this.context)
- fnBlock.push('}');
- fnBlock.push('return ', nodeCount, ';');
- fnBlock.push('})');
- function __bind__(object, fn)
- {
- return function(event) { return fn.apply(object, [event]); };
- }
- function __link__(node, tag, args)
- {
- if (!tag || !tag.tag)
- return;
- tag.tag.compile();
- var domArgs = [node, tag.tag.context, 0];
- domArgs.push.apply(domArgs, tag.tag.domArgs);
- domArgs.push.apply(domArgs, args);
- //if (FBTrace.DBG_DOM) FBTrace.dumpProperties("domplate__link__ domArgs:", domArgs);
- return tag.tag.renderDOM.apply(tag.tag.subject, domArgs);
- }
- var self = this;
- function __loop__(iter, fn)
- {
- var nodeCount = 0;
- for (var i = 0; i < iter.length; ++i)
- {
- iter[i][0] = i;
- iter[i][1] = nodeCount;
- nodeCount += fn.apply(this, iter[i]);
- //if (FBTrace.DBG_DOM) FBTrace.sysout("nodeCount", nodeCount);
- }
- return nodeCount;
- }
- function __path__(parent, offset)
- {
- //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate __path__ offset: "+ offset+"\n");
- var root = parent;
- for (var i = 2; i < arguments.length; ++i)
- {
- var index = arguments[i];
- if (i == 3)
- index += offset;
- if (index == -1)
- parent = parent.parentNode;
- else
- parent = parent.childNodes[index];
- }
- //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate: "+arguments[2]+", root: "+ root+", parent: "+ parent+"\n");
- return parent;
- }
- var js = fnBlock.join("");
- //if (FBTrace.DBG_DOM) FBTrace.sysout(js.replace(/(\;|\{)/g, "$1\n"));
- var r = null;
- eval(js);
- this.renderDOM = r;
- },
- generateDOM: function(path, blocks, args)
- {
- if (this.listeners || this.props)
- this.generateNodePath(path, blocks);
- if (this.listeners)
- {
- for (var i = 0; i < this.listeners.length; i += 2)
- {
- var val = this.listeners[i+1];
- var arg = generateArg(val, path, args);
- //blocks.push('node.addEventListener("', this.listeners[i], '", __bind__(this, ', arg, '), false);');
- blocks.push('addEvent(node, "', this.listeners[i], '", __bind__(this, ', arg, '), false);');
- }
- }
- if (this.props)
- {
- for (var name in this.props)
- {
- var val = this.props[name];
- var arg = generateArg(val, path, args);
- blocks.push('node.', name, ' = ', arg, ';');
- }
- }
- this.generateChildDOM(path, blocks, args);
- return 1;
- },
- generateNodePath: function(path, blocks)
- {
- blocks.push("var node = __path__(root, o");
- for (var i = 0; i < path.length; ++i)
- blocks.push(",", path[i]);
- blocks.push(");");
- },
- generateChildDOM: function(path, blocks, args)
- {
- path.push(0);
- for (var i = 0; i < this.children.length; ++i)
- {
- var child = this.children[i];
- if (isTag(child))
- path[path.length-1] += '+' + child.tag.generateDOM(path, blocks, args);
- else
- path[path.length-1] += '+1';
- }
- path.pop();
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- DomplateEmbed.prototype = copyObject(DomplateTag.prototype,
- {
- merge: function(args, oldTag)
- {
- this.value = oldTag ? oldTag.value : parseValue(args[0]);
- this.attrs = oldTag ? oldTag.attrs : {};
- this.vars = oldTag ? copyArray(oldTag.vars) : [];
- var attrs = args[1];
- for (var name in attrs)
- {
- var val = parseValue(attrs[name]);
- this.attrs[name] = val;
- readPartNames(val, this.vars);
- }
- return creator(this, DomplateEmbed);
- },
- getVarNames: function(names)
- {
- if (this.value instanceof Parts)
- names.push(this.value.parts[0].name);
- if (this.vars)
- names.push.apply(names, this.vars);
- },
- generateMarkup: function(topBlock, topOuts, blocks, info)
- {
- this.addCode(topBlock, topOuts, blocks);
- blocks.push('__link__(');
- addParts(this.value, '', blocks, info);
- blocks.push(', __code__, __out__, {');
- var lastName = null;
- for (var name in this.attrs)
- {
- if (lastName)
- blocks.push(',');
- lastName = name;
- var val = this.attrs[name];
- blocks.push('"', name, '":');
- addParts(val, '', blocks, info);
- }
- blocks.push('});');
- //this.generateChildMarkup(topBlock, topOuts, blocks, info);
- },
- generateDOM: function(path, blocks, args)
- {
- var embedName = 'e'+path.embedIndex++;
- this.generateNodePath(path, blocks);
- var valueName = 'd' + path.renderIndex++;
- var argsName = 'd' + path.renderIndex++;
- blocks.push(embedName + ' = __link__(node, ', valueName, ', ', argsName, ');');
- return embedName;
- }
- });
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- DomplateLoop.prototype = copyObject(DomplateTag.prototype,
- {
- merge: function(args, oldTag)
- {
- this.varName = oldTag ? oldTag.varName : args[0];
- this.iter = oldTag ? oldTag.iter : parseValue(args[1]);
- this.vars = [];
- this.children = oldTag ? copyArray(oldTag.children) : [];
- var offset = Math.min(args.length, 2);
- parseChildren(args, offset, this.vars, this.children);
- return creator(this, DomplateLoop);
- },
- getVarNames: function(names)
- {
- if (this.iter instanceof Parts)
- names.push(this.iter.parts[0].name);
- DomplateTag.prototype.getVarNames.apply(this, [names]);
- },
- generateMarkup: function(topBlock, topOuts, blocks, info)
- {
- this.addCode(topBlock, topOuts, blocks);
- var iterName;
- if (this.iter instanceof Parts)
- {
- var part = this.iter.parts[0];
- iterName = part.name;
- if (part.format)
- {
- for (var i = 0; i < part.format.length; ++i)
- iterName = part.format[i] + "(" + iterName + ")";
- }
- }
- else
- iterName = this.iter;
- blocks.push('__loop__.apply(this, [', iterName, ', __out__, function(', this.varName, ', __out__) {');
- this.generateChildMarkup(topBlock, topOuts, blocks, info);
- this.addCode(topBlock, topOuts, blocks);
- blocks.push('}]);');
- },
- generateDOM: function(path, blocks, args)
- {
- var iterName = 'd'+path.renderIndex++;
- var counterName = 'i'+path.loopIndex;
- var loopName = 'l'+path.loopIndex++;
- if (!path.length)
- path.push(-1, 0);
- var preIndex = path.renderIndex;
- path.renderIndex = 0;
- var nodeCount = 0;
- var subBlocks = [];
- var basePath = path[path.length-1];
- for (var i = 0; i < this.children.length; ++i)
- {
- path[path.length-1] = basePath+'+'+loopName+'+'+nodeCount;
- var child = this.children[i];
- if (isTag(child))
- nodeCount += '+' + child.tag.generateDOM(path, subBlocks, args);
- else
- nodeCount += '+1';
- }
- path[path.length-1] = basePath+'+'+loopName;
- blocks.push(loopName,' = __loop__.apply(this, [', iterName, ', function(', counterName,',',loopName);
- for (var i = 0; i < path.renderIndex; ++i)
- blocks.push(',d'+i);
- blocks.push(') {');
- blocks.push(subBlocks.join(""));
- blocks.push('return ', nodeCount, ';');
- blocks.push('}]);');
- path.renderIndex = preIndex;
- return loopName;
- }
- });
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function Variable(name, format)
- {
- this.name = name;
- this.format = format;
- }
- function Parts(parts)
- {
- this.parts = parts;
- }
- // ************************************************************************************************
- function parseParts(str)
- {
- var re = /\$([_A-Za-z][_A-Za-z0-9.|]*)/g;
- var index = 0;
- var parts = [];
- var m;
- while (m = re.exec(str))
- {
- var pre = str.substr(index, (re.lastIndex-m[0].length)-index);
- if (pre)
- parts.push(pre);
- var expr = m[1].split("|");
- parts.push(new Variable(expr[0], expr.slice(1)));
- index = re.lastIndex;
- }
- if (!index)
- return str;
- var post = str.substr(index);
- if (post)
- parts.push(post);
- return new Parts(parts);
- }
- function parseValue(val)
- {
- return typeof(val) == 'string' ? parseParts(val) : val;
- }
- function parseChildren(args, offset, vars, children)
- {
- for (var i = offset; i < args.length; ++i)
- {
- var val = parseValue(args[i]);
- children.push(val);
- readPartNames(val, vars);
- }
- }
- function readPartNames(val, vars)
- {
- if (val instanceof Parts)
- {
- for (var i = 0; i < val.parts.length; ++i)
- {
- var part = val.parts[i];
- if (part instanceof Variable)
- vars.push(part.name);
- }
- }
- }
- function generateArg(val, path, args)
- {
- if (val instanceof Parts)
- {
- var vals = [];
- for (var i = 0; i < val.parts.length; ++i)
- {
- var part = val.parts[i];
- if (part instanceof Variable)
- {
- var varName = 'd'+path.renderIndex++;
- if (part.format)
- {
- for (var j = 0; j < part.format.length; ++j)
- varName = part.format[j] + '(' + varName + ')';
- }
- vals.push(varName);
- }
- else
- vals.push('"'+part.replace(/"/g, '\\"')+'"');
- }
- return vals.join('+');
- }
- else
- {
- args.push(val);
- return 's' + path.staticIndex++;
- }
- }
- function addParts(val, delim, block, info, escapeIt)
- {
- var vals = [];
- if (val instanceof Parts)
- {
- for (var i = 0; i < val.parts.length; ++i)
- {
- var part = val.parts[i];
- if (part instanceof Variable)
- {
- var partName = part.name;
- if (part.format)
- {
- for (var j = 0; j < part.format.length; ++j)
- partName = part.format[j] + "(" + partName + ")";
- }
- if (escapeIt)
- vals.push("__escape__(" + partName + ")");
- else
- vals.push(partName);
- }
- else
- vals.push('"'+ part + '"');
- }
- }
- else if (isTag(val))
- {
- info.args.push(val);
- vals.push('s'+info.argIndex++);
- }
- else
- vals.push('"'+ val + '"');
- var parts = vals.join(delim);
- if (parts)
- block.push(delim, parts);
- }
- function isTag(obj)
- {
- return (typeof(obj) == "function" || obj instanceof Function) && !!obj.tag;
- }
- function creator(tag, cons)
- {
- var fn = new Function(
- "var tag = arguments.callee.tag;" +
- "var cons = arguments.callee.cons;" +
- "var newTag = new cons();" +
- "return newTag.merge(arguments, tag);");
- fn.tag = tag;
- fn.cons = cons;
- extend(fn, Renderer);
- return fn;
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function copyArray(oldArray)
- {
- var ary = [];
- if (oldArray)
- for (var i = 0; i < oldArray.length; ++i)
- ary.push(oldArray[i]);
- return ary;
- }
- function copyObject(l, r)
- {
- var m = {};
- extend(m, l);
- extend(m, r);
- return m;
- }
- function extend(l, r)
- {
- for (var n in r)
- l[n] = r[n];
- }
- function addEvent(object, name, handler)
- {
- if (document.all)
- object.attachEvent("on"+name, handler);
- else
- object.addEventListener(name, handler, false);
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function ArrayIterator(array)
- {
- var index = -1;
- this.next = function()
- {
- if (++index >= array.length)
- throw StopIteration;
- return array[index];
- };
- }
- function StopIteration() {}
- FBL.$break = function()
- {
- throw StopIteration;
- };
- // ************************************************************************************************
- var Renderer =
- {
- renderHTML: function(args, outputs, self)
- {
- var code = [];
- var markupArgs = [code, this.tag.context, args, outputs];
- markupArgs.push.apply(markupArgs, this.tag.markupArgs);
- this.tag.renderMarkup.apply(self ? self : this.tag.subject, markupArgs);
- return code.join("");
- },
- insertRows: function(args, before, self)
- {
- this.tag.compile();
- var outputs = [];
- var html = this.renderHTML(args, outputs, self);
- var doc = before.ownerDocument;
- var div = doc.createElement("div");
- div.innerHTML = "<table><tbody>"+html+"</tbody></table>";
- var tbody = div.firstChild.firstChild;
- var parent = before.tagName == "TR" ? before.parentNode : before;
- var after = before.tagName == "TR" ? before.nextSibling : null;
- var firstRow = tbody.firstChild, lastRow;
- while (tbody.firstChild)
- {
- lastRow = tbody.firstChild;
- if (after)
- parent.insertBefore(lastRow, after);
- else
- parent.appendChild(lastRow);
- }
- var offset = 0;
- if (before.tagName == "TR")
- {
- var node = firstRow.parentNode.firstChild;
- for (; node && node != firstRow; node = node.nextSibling)
- ++offset;
- }
- var domArgs = [firstRow, this.tag.context, offset];
- domArgs.push.apply(domArgs, this.tag.domArgs);
- domArgs.push.apply(domArgs, outputs);
- this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs);
- return [firstRow, lastRow];
- },
- insertBefore: function(args, before, self)
- {
- return this.insertNode(args, before.ownerDocument, before, false, self);
- },
- insertAfter: function(args, after, self)
- {
- return this.insertNode(args, after.ownerDocument, after, true, self);
- },
- insertNode: function(args, doc, element, isAfter, self)
- {
- if (!args)
- args = {};
- this.tag.compile();
- var outputs = [];
- var html = this.renderHTML(args, outputs, self);
- //if (FBTrace.DBG_DOM)
- // FBTrace.sysout("domplate.insertNode html: "+html+"\n");
- var doc = element.ownerDocument;
- if (!womb || womb.ownerDocument != doc)
- womb = doc.createElement("div");
- womb.innerHTML = html;
- var root = womb.firstChild;
- if (isAfter)
- {
- while (womb.firstChild)
- if (element.nextSibling)
- element.parentNode.insertBefore(womb.firstChild, element.nextSibling);
- else
- element.parentNode.appendChild(womb.firstChild);
- }
- else
- {
- while (womb.lastChild)
- element.parentNode.insertBefore(womb.lastChild, element);
- }
- var domArgs = [root, this.tag.context, 0];
- domArgs.push.apply(domArgs, this.tag.domArgs);
- domArgs.push.apply(domArgs, outputs);
- //if (FBTrace.DBG_DOM)
- // FBTrace.sysout("domplate.insertNode domArgs:", domArgs);
- this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs);
- return root;
- },
- /**/
- /*
- insertAfter: function(args, before, self)
- {
- this.tag.compile();
- var outputs = [];
- var html = this.renderHTML(args, outputs, self);
- var doc = before.ownerDocument;
- if (!womb || womb.ownerDocument != doc)
- womb = doc.createElement("div");
- womb.innerHTML = html;
- var root = womb.firstChild;
- while (womb.firstChild)
- if (before.nextSibling)
- before.parentNode.insertBefore(womb.firstChild, before.nextSibling);
- else
- before.parentNode.appendChild(womb.firstChild);
- var domArgs = [root, this.tag.context, 0];
- domArgs.push.apply(domArgs, this.tag.domArgs);
- domArgs.push.apply(domArgs, outputs);
- this.tag.renderDOM.apply(self ? self : (this.tag.subject ? this.tag.subject : null),
- domArgs);
- return root;
- },
- /**/
- replace: function(args, parent, self)
- {
- this.tag.compile();
- var outputs = [];
- var html = this.renderHTML(args, outputs, self);
- var root;
- if (parent.nodeType == 1)
- {
- parent.innerHTML = html;
- root = parent.firstChild;
- }
- else
- {
- if (!parent || parent.nodeType != 9)
- parent = document;
- if (!womb || womb.ownerDocument != parent)
- womb = parent.createElement("div");
- womb.innerHTML = html;
- root = womb.firstChild;
- //womb.removeChild(root);
- }
- var domArgs = [root, this.tag.context, 0];
- domArgs.push.apply(domArgs, this.tag.domArgs);
- domArgs.push.apply(domArgs, outputs);
- this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs);
- return root;
- },
- append: function(args, parent, self)
- {
- this.tag.compile();
- var outputs = [];
- var html = this.renderHTML(args, outputs, self);
- //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate.append html: "+html+"\n");
- if (!womb || womb.ownerDocument != parent.ownerDocument)
- womb = parent.ownerDocument.createElement("div");
- womb.innerHTML = html;
- // TODO: xxxpedro domplate port to Firebug
- var root = womb.firstChild;
- while (womb.firstChild)
- parent.appendChild(womb.firstChild);
- // clearing element reference to avoid reference error in IE8 when switching contexts
- womb = null;
- var domArgs = [root, this.tag.context, 0];
- domArgs.push.apply(domArgs, this.tag.domArgs);
- domArgs.push.apply(domArgs, outputs);
- //if (FBTrace.DBG_DOM) FBTrace.dumpProperties("domplate append domArgs:", domArgs);
- this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs);
- return root;
- }
- };
- // ************************************************************************************************
- function defineTags()
- {
- for (var i = 0; i < arguments.length; ++i)
- {
- var tagName = arguments[i];
- var fn = new Function("var newTag = new arguments.callee.DomplateTag('"+tagName+"'); return newTag.merge(arguments);");
- fn.DomplateTag = DomplateTag;
- var fnName = tagName.toUpperCase();
- FBL[fnName] = fn;
- }
- }
- defineTags(
- "a", "button", "br", "canvas", "code", "col", "colgroup", "div", "fieldset", "form", "h1", "h2", "h3", "hr",
- "img", "input", "label", "legend", "li", "ol", "optgroup", "option", "p", "pre", "select",
- "span", "strong", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "tr", "tt", "ul", "iframe"
- );
- })();
- /* See license.txt for terms of usage */
- var FirebugReps = FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // Common Tags
- var OBJECTBOX = this.OBJECTBOX =
- SPAN({"class": "objectBox objectBox-$className"});
- var OBJECTBLOCK = this.OBJECTBLOCK =
- DIV({"class": "objectBox objectBox-$className"});
- var OBJECTLINK = this.OBJECTLINK = isIE6 ? // IE6 object link representation
- A({
- "class": "objectLink objectLink-$className a11yFocus",
- href: "javascript:void(0)",
- _repObject: "$object"
- })
- : // Other browsers
- A({
- "class": "objectLink objectLink-$className a11yFocus",
- _repObject: "$object"
- });
- // ************************************************************************************************
- this.Undefined = domplate(Firebug.Rep,
- {
- tag: OBJECTBOX("undefined"),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "undefined",
- supportsObject: function(object, type)
- {
- return type == "undefined";
- }
- });
- // ************************************************************************************************
- this.Null = domplate(Firebug.Rep,
- {
- tag: OBJECTBOX("null"),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "null",
- supportsObject: function(object, type)
- {
- return object == null;
- }
- });
- // ************************************************************************************************
- this.Nada = domplate(Firebug.Rep,
- {
- tag: SPAN(""),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "nada"
- });
- // ************************************************************************************************
- this.Number = domplate(Firebug.Rep,
- {
- tag: OBJECTBOX("$object"),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "number",
- supportsObject: function(object, type)
- {
- return type == "boolean" || type == "number";
- }
- });
- // ************************************************************************************************
- this.String = domplate(Firebug.Rep,
- {
- tag: OBJECTBOX(""$object""),
- shortTag: OBJECTBOX(""$object|cropString""),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "string",
- supportsObject: function(object, type)
- {
- return type == "string";
- }
- });
- // ************************************************************************************************
- this.Text = domplate(Firebug.Rep,
- {
- tag: OBJECTBOX("$object"),
- shortTag: OBJECTBOX("$object|cropString"),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "text"
- });
- // ************************************************************************************************
- this.Caption = domplate(Firebug.Rep,
- {
- tag: SPAN({"class": "caption"}, "$object")
- });
- // ************************************************************************************************
- this.Warning = domplate(Firebug.Rep,
- {
- tag: DIV({"class": "warning focusRow", role : 'listitem'}, "$object|STR")
- });
- // ************************************************************************************************
- this.Func = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK("$object|summarizeFunction"),
- summarizeFunction: function(fn)
- {
- var fnRegex = /function ([^(]+\([^)]*\)) \{/;
- var fnText = safeToString(fn);
- var m = fnRegex.exec(fnText);
- return m ? m[1] : "function()";
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- copySource: function(fn)
- {
- copyToClipboard(safeToString(fn));
- },
- monitor: function(fn, script, monitored)
- {
- if (monitored)
- Firebug.Debugger.unmonitorScript(fn, script, "monitor");
- else
- Firebug.Debugger.monitorScript(fn, script, "monitor");
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "function",
- supportsObject: function(object, type)
- {
- return isFunction(object);
- },
- inspectObject: function(fn, context)
- {
- var sourceLink = findSourceForFunction(fn, context);
- if (sourceLink)
- Firebug.chrome.select(sourceLink);
- if (FBTrace.DBG_FUNCTION_NAME)
- FBTrace.sysout("reps.function.inspectObject selected sourceLink is ", sourceLink);
- },
- getTooltip: function(fn, context)
- {
- var script = findScriptForFunctionInContext(context, fn);
- if (script)
- return $STRF("Line", [normalizeURL(script.fileName), script.baseLineNumber]);
- else
- if (fn.toString)
- return fn.toString();
- },
- getTitle: function(fn, context)
- {
- var name = fn.name ? fn.name : "function";
- return name + "()";
- },
- getContextMenuItems: function(fn, target, context, script)
- {
- if (!script)
- script = findScriptForFunctionInContext(context, fn);
- if (!script)
- return;
- var scriptInfo = getSourceFileAndLineByScript(context, script);
- var monitored = scriptInfo ? fbs.isMonitored(scriptInfo.sourceFile.href, scriptInfo.lineNo) : false;
- var name = script ? getFunctionName(script, context) : fn.name;
- return [
- {label: "CopySource", command: bindFixed(this.copySource, this, fn) },
- "-",
- {label: $STRF("ShowCallsInConsole", [name]), nol10n: true,
- type: "checkbox", checked: monitored,
- command: bindFixed(this.monitor, this, fn, script, monitored) }
- ];
- }
- });
- // ************************************************************************************************
- /*
- this.jsdScript = domplate(Firebug.Rep,
- {
- copySource: function(script)
- {
- var fn = script.functionObject.getWrappedValue();
- return FirebugReps.Func.copySource(fn);
- },
- monitor: function(fn, script, monitored)
- {
- fn = script.functionObject.getWrappedValue();
- return FirebugReps.Func.monitor(fn, script, monitored);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "jsdScript",
- inspectable: false,
- supportsObject: function(object, type)
- {
- return object instanceof jsdIScript;
- },
- inspectObject: function(script, context)
- {
- var sourceLink = getSourceLinkForScript(script, context);
- if (sourceLink)
- Firebug.chrome.select(sourceLink);
- },
- getRealObject: function(script, context)
- {
- return script;
- },
- getTooltip: function(script)
- {
- return $STRF("jsdIScript", [script.tag]);
- },
- getTitle: function(script, context)
- {
- var fn = script.functionObject.getWrappedValue();
- return FirebugReps.Func.getTitle(fn, context);
- },
- getContextMenuItems: function(script, target, context)
- {
- var fn = script.functionObject.getWrappedValue();
- var scriptInfo = getSourceFileAndLineByScript(context, script);
- var monitored = scriptInfo ? fbs.isMonitored(scriptInfo.sourceFile.href, scriptInfo.lineNo) : false;
- var name = getFunctionName(script, context);
- return [
- {label: "CopySource", command: bindFixed(this.copySource, this, script) },
- "-",
- {label: $STRF("ShowCallsInConsole", [name]), nol10n: true,
- type: "checkbox", checked: monitored,
- command: bindFixed(this.monitor, this, fn, script, monitored) }
- ];
- }
- });
- /**/
- //************************************************************************************************
- this.Obj = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK(
- SPAN({"class": "objectTitle"}, "$object|getTitle "),
- SPAN({"class": "objectProps"},
- SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"),
- FOR("prop", "$object|propIterator",
- SPAN({"class": "objectPropName", role: "presentation"}, "$prop.name"),
- SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"),
- TAG("$prop.tag", {object: "$prop.object"}),
- SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim")
- ),
- SPAN({"class": "objectRightBrace"}, "}")
- )
- ),
- propNumberTag:
- SPAN({"class": "objectProp-number"}, "$object"),
- propStringTag:
- SPAN({"class": "objectProp-string"}, ""$object""),
- propObjectTag:
- SPAN({"class": "objectProp-object"}, "$object"),
- propIterator: function (object)
- {
- ///Firebug.ObjectShortIteratorMax;
- var maxLength = 55; // default max length for long representation
- if (!object)
- return [];
- var props = [];
- var length = 0;
- var numProperties = 0;
- var numPropertiesShown = 0;
- var maxLengthReached = false;
- var lib = this;
- var propRepsMap =
- {
- "boolean": this.propNumberTag,
- "number": this.propNumberTag,
- "string": this.propStringTag,
- "object": this.propObjectTag
- };
- try
- {
- var title = Firebug.Rep.getTitle(object);
- length += title.length;
- for (var name in object)
- {
- var value;
- try
- {
- value = object[name];
- }
- catch (exc)
- {
- continue;
- }
- var type = typeof(value);
- if (type == "boolean" ||
- type == "number" ||
- (type == "string" && value) ||
- (type == "object" && value && value.toString))
- {
- var tag = propRepsMap[type];
- var value = (type == "object") ?
- Firebug.getRep(value).getTitle(value) :
- value + "";
- length += name.length + value.length + 4;
- if (length <= maxLength)
- {
- props.push({
- tag: tag,
- name: name,
- object: value,
- equal: "=",
- delim: ", "
- });
- numPropertiesShown++;
- }
- else
- maxLengthReached = true;
- }
- numProperties++;
- if (maxLengthReached && numProperties > numPropertiesShown)
- break;
- }
- if (numProperties > numPropertiesShown)
- {
- props.push({
- object: "...", //xxxHonza localization
- tag: FirebugReps.Caption.tag,
- name: "",
- equal:"",
- delim:""
- });
- }
- else if (props.length > 0)
- {
- props[props.length-1].delim = '';
- }
- }
- catch (exc)
- {
- // Sometimes we get exceptions when trying to read from certain objects, like
- // StorageList, but don't let that gum up the works
- // XXXjjb also History.previous fails because object is a web-page object which does not have
- // permission to read the history
- }
- return props;
- },
- fb_1_6_propIterator: function (object, max)
- {
- max = max || 3;
- if (!object)
- return [];
- var props = [];
- var len = 0, count = 0;
- try
- {
- for (var name in object)
- {
- var value;
- try
- {
- value = object[name];
- }
- catch (exc)
- {
- continue;
- }
- var t = typeof(value);
- if (t == "boolean" || t == "number" || (t == "string" && value)
- || (t == "object" && value && value.toString))
- {
- var rep = Firebug.getRep(value);
- var tag = rep.shortTag || rep.tag;
- if (t == "object")
- {
- value = rep.getTitle(value);
- tag = rep.titleTag;
- }
- count++;
- if (count <= max)
- props.push({tag: tag, name: name, object: value, equal: "=", delim: ", "});
- else
- break;
- }
- }
- if (count > max)
- {
- props[Math.max(1,max-1)] = {
- object: "more...", //xxxHonza localization
- tag: FirebugReps.Caption.tag,
- name: "",
- equal:"",
- delim:""
- };
- }
- else if (props.length > 0)
- {
- props[props.length-1].delim = '';
- }
- }
- catch (exc)
- {
- // Sometimes we get exceptions when trying to read from certain objects, like
- // StorageList, but don't let that gum up the works
- // XXXjjb also History.previous fails because object is a web-page object which does not have
- // permission to read the history
- }
- return props;
- },
- /*
- propIterator: function (object)
- {
- if (!object)
- return [];
- var props = [];
- var len = 0;
- try
- {
- for (var name in object)
- {
- var val;
- try
- {
- val = object[name];
- }
- catch (exc)
- {
- continue;
- }
- var t = typeof val;
- if (t == "boolean" || t == "number" || (t == "string" && val)
- || (t == "object" && !isFunction(val) && val && val.toString))
- {
- var title = (t == "object")
- ? Firebug.getRep(val).getTitle(val)
- : val+"";
- len += name.length + title.length + 1;
- if (len < 50)
- props.push({name: name, value: title});
- else
- break;
- }
- }
- }
- catch (exc)
- {
- // Sometimes we get exceptions when trying to read from certain objects, like
- // StorageList, but don't let that gum up the works
- // XXXjjb also History.previous fails because object is a web-page object which does not have
- // permission to read the history
- }
- return props;
- },
- /**/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "object",
- supportsObject: function(object, type)
- {
- return true;
- }
- });
- // ************************************************************************************************
- this.Arr = domplate(Firebug.Rep,
- {
- tag:
- OBJECTBOX({_repObject: "$object"},
- SPAN({"class": "arrayLeftBracket", role : "presentation"}, "["),
- FOR("item", "$object|arrayIterator",
- TAG("$item.tag", {object: "$item.object"}),
- SPAN({"class": "arrayComma", role : "presentation"}, "$item.delim")
- ),
- SPAN({"class": "arrayRightBracket", role : "presentation"}, "]")
- ),
- shortTag:
- OBJECTBOX({_repObject: "$object"},
- SPAN({"class": "arrayLeftBracket", role : "presentation"}, "["),
- FOR("item", "$object|shortArrayIterator",
- TAG("$item.tag", {object: "$item.object"}),
- SPAN({"class": "arrayComma", role : "presentation"}, "$item.delim")
- ),
- // TODO: xxxpedro - confirm this on Firebug
- //FOR("prop", "$object|shortPropIterator",
- // " $prop.name=",
- // SPAN({"class": "objectPropValue"}, "$prop.value|cropString")
- //),
- SPAN({"class": "arrayRightBracket"}, "]")
- ),
- arrayIterator: function(array)
- {
- var items = [];
- for (var i = 0; i < array.length; ++i)
- {
- var value = array[i];
- var rep = Firebug.getRep(value);
- var tag = rep.shortTag ? rep.shortTag : rep.tag;
- var delim = (i == array.length-1 ? "" : ", ");
- items.push({object: value, tag: tag, delim: delim});
- }
- return items;
- },
- shortArrayIterator: function(array)
- {
- var items = [];
- for (var i = 0; i < array.length && i < 3; ++i)
- {
- var value = array[i];
- var rep = Firebug.getRep(value);
- var tag = rep.shortTag ? rep.shortTag : rep.tag;
- var delim = (i == array.length-1 ? "" : ", ");
- items.push({object: value, tag: tag, delim: delim});
- }
- if (array.length > 3)
- items.push({object: (array.length-3) + " more...", tag: FirebugReps.Caption.tag, delim: ""});
- return items;
- },
- shortPropIterator: this.Obj.propIterator,
- getItemIndex: function(child)
- {
- var arrayIndex = 0;
- for (child = child.previousSibling; child; child = child.previousSibling)
- {
- if (child.repObject)
- ++arrayIndex;
- }
- return arrayIndex;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "array",
- supportsObject: function(object)
- {
- return this.isArray(object);
- },
- // http://code.google.com/p/fbug/issues/detail?id=874
- // BEGIN Yahoo BSD Source (modified here) YAHOO.lang.isArray, YUI 2.2.2 June 2007
- isArray: function(obj) {
- try {
- if (!obj)
- return false;
- else if (isIE && !isFunction(obj) && typeof obj == "object" && isFinite(obj.length) && obj.nodeType != 8)
- return true;
- else if (isFinite(obj.length) && isFunction(obj.splice))
- return true;
- else if (isFinite(obj.length) && isFunction(obj.callee)) // arguments
- return true;
- else if (instanceOf(obj, "HTMLCollection"))
- return true;
- else if (instanceOf(obj, "NodeList"))
- return true;
- else
- return false;
- }
- catch(exc)
- {
- if (FBTrace.DBG_ERRORS)
- {
- FBTrace.sysout("isArray FAILS:", exc); /* Something weird: without the try/catch, OOM, with no exception?? */
- FBTrace.sysout("isArray Fails on obj", obj);
- }
- }
- return false;
- },
- // END Yahoo BSD SOURCE See license below.
- getTitle: function(object, context)
- {
- return "[" + object.length + "]";
- }
- });
- // ************************************************************************************************
- this.Property = domplate(Firebug.Rep,
- {
- supportsObject: function(object)
- {
- return object instanceof Property;
- },
- getRealObject: function(prop, context)
- {
- return prop.object[prop.name];
- },
- getTitle: function(prop, context)
- {
- return prop.name;
- }
- });
- // ************************************************************************************************
- this.NetFile = domplate(this.Obj,
- {
- supportsObject: function(object)
- {
- return object instanceof Firebug.NetFile;
- },
- browseObject: function(file, context)
- {
- openNewTab(file.href);
- return true;
- },
- getRealObject: function(file, context)
- {
- return null;
- }
- });
- // ************************************************************************************************
- this.Except = domplate(Firebug.Rep,
- {
- tag:
- OBJECTBOX({_repObject: "$object"}, "$object.message"),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "exception",
- supportsObject: function(object)
- {
- return object instanceof ErrorCopy;
- }
- });
- // ************************************************************************************************
- this.Element = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK(
- "<",
- SPAN({"class": "nodeTag"}, "$object.nodeName|toLowerCase"),
- FOR("attr", "$object|attrIterator",
- " $attr.nodeName="", SPAN({"class": "nodeValue"}, "$attr.nodeValue"), """
- ),
- ">"
- ),
- shortTag:
- OBJECTLINK(
- SPAN({"class": "$object|getVisible"},
- SPAN({"class": "selectorTag"}, "$object|getSelectorTag"),
- SPAN({"class": "selectorId"}, "$object|getSelectorId"),
- SPAN({"class": "selectorClass"}, "$object|getSelectorClass"),
- SPAN({"class": "selectorValue"}, "$object|getValue")
- )
- ),
- getVisible: function(elt)
- {
- return isVisible(elt) ? "" : "selectorHidden";
- },
- getSelectorTag: function(elt)
- {
- return elt.nodeName.toLowerCase();
- },
- getSelectorId: function(elt)
- {
- return elt.id ? "#" + elt.id : "";
- },
- getSelectorClass: function(elt)
- {
- return elt.className ? "." + elt.className.split(" ")[0] : "";
- },
- getValue: function(elt)
- {
- // TODO: xxxpedro
- return "";
- var value;
- if (elt instanceof HTMLImageElement)
- value = getFileName(elt.src);
- else if (elt instanceof HTMLAnchorElement)
- value = getFileName(elt.href);
- else if (elt instanceof HTMLInputElement)
- value = elt.value;
- else if (elt instanceof HTMLFormElement)
- value = getFileName(elt.action);
- else if (elt instanceof HTMLScriptElement)
- value = getFileName(elt.src);
- return value ? " " + cropString(value, 20) : "";
- },
- attrIterator: function(elt)
- {
- var attrs = [];
- var idAttr, classAttr;
- if (elt.attributes)
- {
- for (var i = 0; i < elt.attributes.length; ++i)
- {
- var attr = elt.attributes[i];
- if (attr.nodeName && attr.nodeName.indexOf("firebug-") != -1)
- continue;
- else if (attr.nodeName == "id")
- idAttr = attr;
- else if (attr.nodeName == "class")
- classAttr = attr;
- else
- attrs.push(attr);
- }
- }
- if (classAttr)
- attrs.splice(0, 0, classAttr);
- if (idAttr)
- attrs.splice(0, 0, idAttr);
- return attrs;
- },
- shortAttrIterator: function(elt)
- {
- var attrs = [];
- if (elt.attributes)
- {
- for (var i = 0; i < elt.attributes.length; ++i)
- {
- var attr = elt.attributes[i];
- if (attr.nodeName == "id" || attr.nodeName == "class")
- attrs.push(attr);
- }
- }
- return attrs;
- },
- getHidden: function(elt)
- {
- return isVisible(elt) ? "" : "nodeHidden";
- },
- getXPath: function(elt)
- {
- return getElementTreeXPath(elt);
- },
- // TODO: xxxpedro remove this?
- getNodeText: function(element)
- {
- var text = element.textContent;
- if (Firebug.showFullTextNodes)
- return text;
- else
- return cropString(text, 50);
- },
- /**/
- getNodeTextGroups: function(element)
- {
- var text = element.textContent;
- if (!Firebug.showFullTextNodes)
- {
- text=cropString(text,50);
- }
- var escapeGroups=[];
- if (Firebug.showTextNodesWithWhitespace)
- escapeGroups.push({
- 'group': 'whitespace',
- 'class': 'nodeWhiteSpace',
- 'extra': {
- '\t': '_Tab',
- '\n': '_Para',
- ' ' : '_Space'
- }
- });
- if (Firebug.showTextNodesWithEntities)
- escapeGroups.push({
- 'group':'text',
- 'class':'nodeTextEntity',
- 'extra':{}
- });
- if (escapeGroups.length)
- return escapeGroupsForEntities(text, escapeGroups);
- else
- return [{str:text,'class':'',extra:''}];
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- copyHTML: function(elt)
- {
- var html = getElementXML(elt);
- copyToClipboard(html);
- },
- copyInnerHTML: function(elt)
- {
- copyToClipboard(elt.innerHTML);
- },
- copyXPath: function(elt)
- {
- var xpath = getElementXPath(elt);
- copyToClipboard(xpath);
- },
- persistor: function(context, xpath)
- {
- var elts = xpath
- ? getElementsByXPath(context.window.document, xpath)
- : null;
- return elts && elts.length ? elts[0] : null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "element",
- supportsObject: function(object)
- {
- //return object instanceof Element || object.nodeType == 1 && typeof object.nodeName == "string";
- return instanceOf(object, "Element");
- },
- browseObject: function(elt, context)
- {
- var tag = elt.nodeName.toLowerCase();
- if (tag == "script")
- openNewTab(elt.src);
- else if (tag == "link")
- openNewTab(elt.href);
- else if (tag == "a")
- openNewTab(elt.href);
- else if (tag == "img")
- openNewTab(elt.src);
- return true;
- },
- persistObject: function(elt, context)
- {
- var xpath = getElementXPath(elt);
- return bind(this.persistor, top, xpath);
- },
- getTitle: function(element, context)
- {
- return getElementCSSSelector(element);
- },
- getTooltip: function(elt)
- {
- return this.getXPath(elt);
- },
- getContextMenuItems: function(elt, target, context)
- {
- var monitored = areEventsMonitored(elt, null, context);
- return [
- {label: "CopyHTML", command: bindFixed(this.copyHTML, this, elt) },
- {label: "CopyInnerHTML", command: bindFixed(this.copyInnerHTML, this, elt) },
- {label: "CopyXPath", command: bindFixed(this.copyXPath, this, elt) },
- "-",
- {label: "ShowEventsInConsole", type: "checkbox", checked: monitored,
- command: bindFixed(toggleMonitorEvents, FBL, elt, null, monitored, context) },
- "-",
- {label: "ScrollIntoView", command: bindFixed(elt.scrollIntoView, elt) }
- ];
- }
- });
- // ************************************************************************************************
- this.TextNode = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK(
- "<",
- SPAN({"class": "nodeTag"}, "TextNode"),
- " textContent="", SPAN({"class": "nodeValue"}, "$object.textContent|cropString"), """,
- ">"
- ),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "textNode",
- supportsObject: function(object)
- {
- return object instanceof Text;
- }
- });
- // ************************************************************************************************
- this.Document = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK("Document ", SPAN({"class": "objectPropValue"}, "$object|getLocation")),
- getLocation: function(doc)
- {
- return doc.location ? getFileName(doc.location.href) : "";
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "object",
- supportsObject: function(object)
- {
- //return object instanceof Document || object instanceof XMLDocument;
- return instanceOf(object, "Document");
- },
- browseObject: function(doc, context)
- {
- openNewTab(doc.location.href);
- return true;
- },
- persistObject: function(doc, context)
- {
- return this.persistor;
- },
- persistor: function(context)
- {
- return context.window.document;
- },
- getTitle: function(win, context)
- {
- return "document";
- },
- getTooltip: function(doc)
- {
- return doc.location.href;
- }
- });
- // ************************************************************************************************
- this.StyleSheet = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK("StyleSheet ", SPAN({"class": "objectPropValue"}, "$object|getLocation")),
- getLocation: function(styleSheet)
- {
- return getFileName(styleSheet.href);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- copyURL: function(styleSheet)
- {
- copyToClipboard(styleSheet.href);
- },
- openInTab: function(styleSheet)
- {
- openNewTab(styleSheet.href);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "object",
- supportsObject: function(object)
- {
- //return object instanceof CSSStyleSheet;
- return instanceOf(object, "CSSStyleSheet");
- },
- browseObject: function(styleSheet, context)
- {
- openNewTab(styleSheet.href);
- return true;
- },
- persistObject: function(styleSheet, context)
- {
- return bind(this.persistor, top, styleSheet.href);
- },
- getTooltip: function(styleSheet)
- {
- return styleSheet.href;
- },
- getContextMenuItems: function(styleSheet, target, context)
- {
- return [
- {label: "CopyLocation", command: bindFixed(this.copyURL, this, styleSheet) },
- "-",
- {label: "OpenInTab", command: bindFixed(this.openInTab, this, styleSheet) }
- ];
- },
- persistor: function(context, href)
- {
- return getStyleSheetByHref(href, context);
- }
- });
- // ************************************************************************************************
- this.Window = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK("Window ", SPAN({"class": "objectPropValue"}, "$object|getLocation")),
- getLocation: function(win)
- {
- try
- {
- return (win && win.location && !win.closed) ? getFileName(win.location.href) : "";
- }
- catch (exc)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("reps.Window window closed?");
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "object",
- supportsObject: function(object)
- {
- return instanceOf(object, "Window");
- },
- browseObject: function(win, context)
- {
- openNewTab(win.location.href);
- return true;
- },
- persistObject: function(win, context)
- {
- return this.persistor;
- },
- persistor: function(context)
- {
- return context.window;
- },
- getTitle: function(win, context)
- {
- return "window";
- },
- getTooltip: function(win)
- {
- if (win && !win.closed)
- return win.location.href;
- }
- });
- // ************************************************************************************************
- this.Event = domplate(Firebug.Rep,
- {
- tag: TAG("$copyEventTag", {object: "$object|copyEvent"}),
- copyEventTag:
- OBJECTLINK("$object|summarizeEvent"),
- summarizeEvent: function(event)
- {
- var info = [event.type, ' '];
- var eventFamily = getEventFamily(event.type);
- if (eventFamily == "mouse")
- info.push("clientX=", event.clientX, ", clientY=", event.clientY);
- else if (eventFamily == "key")
- info.push("charCode=", event.charCode, ", keyCode=", event.keyCode);
- return info.join("");
- },
- copyEvent: function(event)
- {
- return new EventCopy(event);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "object",
- supportsObject: function(object)
- {
- //return object instanceof Event || object instanceof EventCopy;
- return instanceOf(object, "Event") || instanceOf(object, "EventCopy");
- },
- getTitle: function(event, context)
- {
- return "Event " + event.type;
- }
- });
- // ************************************************************************************************
- this.SourceLink = domplate(Firebug.Rep,
- {
- tag:
- OBJECTLINK({$collapsed: "$object|hideSourceLink"}, "$object|getSourceLinkTitle"),
- hideSourceLink: function(sourceLink)
- {
- return sourceLink ? sourceLink.href.indexOf("XPCSafeJSObjectWrapper") != -1 : true;
- },
- getSourceLinkTitle: function(sourceLink)
- {
- if (!sourceLink)
- return "";
- try
- {
- var fileName = getFileName(sourceLink.href);
- fileName = decodeURIComponent(fileName);
- fileName = cropString(fileName, 17);
- }
- catch(exc)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("reps.getSourceLinkTitle decodeURIComponent fails for \'"+fileName+"\': "+exc, exc);
- }
- return typeof sourceLink.line == "number" ?
- fileName + " (line " + sourceLink.line + ")" :
- fileName;
- // TODO: xxxpedro
- //return $STRF("Line", [fileName, sourceLink.line]);
- },
- copyLink: function(sourceLink)
- {
- copyToClipboard(sourceLink.href);
- },
- openInTab: function(sourceLink)
- {
- openNewTab(sourceLink.href);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "sourceLink",
- supportsObject: function(object)
- {
- return object instanceof SourceLink;
- },
- getTooltip: function(sourceLink)
- {
- return decodeURI(sourceLink.href);
- },
- inspectObject: function(sourceLink, context)
- {
- if (sourceLink.type == "js")
- {
- var scriptFile = getSourceFileByHref(sourceLink.href, context);
- if (scriptFile)
- return Firebug.chrome.select(sourceLink);
- }
- else if (sourceLink.type == "css")
- {
- // If an object is defined, treat it as the highest priority for
- // inspect actions
- if (sourceLink.object) {
- Firebug.chrome.select(sourceLink.object);
- return;
- }
- var stylesheet = getStyleSheetByHref(sourceLink.href, context);
- if (stylesheet)
- {
- var ownerNode = stylesheet.ownerNode;
- if (ownerNode)
- {
- Firebug.chrome.select(sourceLink, "html");
- return;
- }
- var panel = context.getPanel("stylesheet");
- if (panel && panel.getRuleByLine(stylesheet, sourceLink.line))
- return Firebug.chrome.select(sourceLink);
- }
- }
- // Fallback is to just open the view-source window on the file
- viewSource(sourceLink.href, sourceLink.line);
- },
- browseObject: function(sourceLink, context)
- {
- openNewTab(sourceLink.href);
- return true;
- },
- getContextMenuItems: function(sourceLink, target, context)
- {
- return [
- {label: "CopyLocation", command: bindFixed(this.copyLink, this, sourceLink) },
- "-",
- {label: "OpenInTab", command: bindFixed(this.openInTab, this, sourceLink) }
- ];
- }
- });
- // ************************************************************************************************
- this.SourceFile = domplate(this.SourceLink,
- {
- tag:
- OBJECTLINK({$collapsed: "$object|hideSourceLink"}, "$object|getSourceLinkTitle"),
- persistor: function(context, href)
- {
- return getSourceFileByHref(href, context);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "sourceFile",
- supportsObject: function(object)
- {
- return object instanceof SourceFile;
- },
- persistObject: function(sourceFile)
- {
- return bind(this.persistor, top, sourceFile.href);
- },
- browseObject: function(sourceLink, context)
- {
- },
- getTooltip: function(sourceFile)
- {
- return sourceFile.href;
- }
- });
- // ************************************************************************************************
- this.StackFrame = domplate(Firebug.Rep, // XXXjjb Since the repObject is fn the stack does not have correct line numbers
- {
- tag:
- OBJECTBLOCK(
- A({"class": "objectLink objectLink-function focusRow a11yFocus", _repObject: "$object.fn"}, "$object|getCallName"),
- " ( ",
- FOR("arg", "$object|argIterator",
- TAG("$arg.tag", {object: "$arg.value"}),
- SPAN({"class": "arrayComma"}, "$arg.delim")
- ),
- " )",
- SPAN({"class": "objectLink-sourceLink objectLink"}, "$object|getSourceLinkTitle")
- ),
- getCallName: function(frame)
- {
- //TODO: xxxpedro reps StackFrame
- return frame.name || "anonymous";
- //return getFunctionName(frame.script, frame.context);
- },
- getSourceLinkTitle: function(frame)
- {
- //TODO: xxxpedro reps StackFrame
- var fileName = cropString(getFileName(frame.href), 20);
- return fileName + (frame.lineNo ? " (line " + frame.lineNo + ")" : "");
- var fileName = cropString(getFileName(frame.href), 17);
- return $STRF("Line", [fileName, frame.lineNo]);
- },
- argIterator: function(frame)
- {
- if (!frame.args)
- return [];
- var items = [];
- for (var i = 0; i < frame.args.length; ++i)
- {
- var arg = frame.args[i];
- if (!arg)
- break;
- var rep = Firebug.getRep(arg.value);
- var tag = rep.shortTag ? rep.shortTag : rep.tag;
- var delim = (i == frame.args.length-1 ? "" : ", ");
- items.push({name: arg.name, value: arg.value, tag: tag, delim: delim});
- }
- return items;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "stackFrame",
- supportsObject: function(object)
- {
- return object instanceof StackFrame;
- },
- inspectObject: function(stackFrame, context)
- {
- var sourceLink = new SourceLink(stackFrame.href, stackFrame.lineNo, "js");
- Firebug.chrome.select(sourceLink);
- },
- getTooltip: function(stackFrame, context)
- {
- return $STRF("Line", [stackFrame.href, stackFrame.lineNo]);
- }
- });
- // ************************************************************************************************
- this.StackTrace = domplate(Firebug.Rep,
- {
- tag:
- FOR("frame", "$object.frames focusRow",
- TAG(this.StackFrame.tag, {object: "$frame"})
- ),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "stackTrace",
- supportsObject: function(object)
- {
- return object instanceof StackTrace;
- }
- });
- // ************************************************************************************************
- this.jsdStackFrame = domplate(Firebug.Rep,
- {
- inspectable: false,
- supportsObject: function(object)
- {
- return (object instanceof jsdIStackFrame) && (object.isValid);
- },
- getTitle: function(frame, context)
- {
- if (!frame.isValid) return "(invalid frame)"; // XXXjjb avoid frame.script == null
- return getFunctionName(frame.script, context);
- },
- getTooltip: function(frame, context)
- {
- if (!frame.isValid) return "(invalid frame)"; // XXXjjb avoid frame.script == null
- var sourceInfo = FBL.getSourceFileAndLineByScript(context, frame.script, frame);
- if (sourceInfo)
- return $STRF("Line", [sourceInfo.sourceFile.href, sourceInfo.lineNo]);
- else
- return $STRF("Line", [frame.script.fileName, frame.line]);
- },
- getContextMenuItems: function(frame, target, context)
- {
- var fn = frame.script.functionObject.getWrappedValue();
- return FirebugReps.Func.getContextMenuItems(fn, target, context, frame.script);
- }
- });
- // ************************************************************************************************
- this.ErrorMessage = domplate(Firebug.Rep,
- {
- tag:
- OBJECTBOX({
- $hasTwisty: "$object|hasStackTrace",
- $hasBreakSwitch: "$object|hasBreakSwitch",
- $breakForError: "$object|hasErrorBreak",
- _repObject: "$object",
- _stackTrace: "$object|getLastErrorStackTrace",
- onclick: "$onToggleError"},
- DIV({"class": "errorTitle a11yFocus", role : 'checkbox', 'aria-checked' : 'false'},
- "$object.message|getMessage"
- ),
- DIV({"class": "errorTrace"}),
- DIV({"class": "errorSourceBox errorSource-$object|getSourceType"},
- IMG({"class": "errorBreak a11yFocus", src:"blank.gif", role : 'checkbox', 'aria-checked':'false', title: "Break on this error"}),
- A({"class": "errorSource a11yFocus"}, "$object|getLine")
- ),
- TAG(this.SourceLink.tag, {object: "$object|getSourceLink"})
- ),
- getLastErrorStackTrace: function(error)
- {
- return error.trace;
- },
- hasStackTrace: function(error)
- {
- var url = error.href.toString();
- var fromCommandLine = (url.indexOf("XPCSafeJSObjectWrapper") != -1);
- return !fromCommandLine && error.trace;
- },
- hasBreakSwitch: function(error)
- {
- return error.href && error.lineNo > 0;
- },
- hasErrorBreak: function(error)
- {
- return fbs.hasErrorBreakpoint(error.href, error.lineNo);
- },
- getMessage: function(message)
- {
- var re = /\[Exception... "(.*?)" nsresult:/;
- var m = re.exec(message);
- return m ? m[1] : message;
- },
- getLine: function(error)
- {
- if (error.category == "js")
- {
- if (error.source)
- return cropString(error.source, 80);
- else if (error.href && error.href.indexOf("XPCSafeJSObjectWrapper") == -1)
- return cropString(error.getSourceLine(), 80);
- }
- },
- getSourceLink: function(error)
- {
- var ext = error.category == "css" ? "css" : "js";
- return error.lineNo ? new SourceLink(error.href, error.lineNo, ext) : null;
- },
- getSourceType: function(error)
- {
- // Errors occurring inside of HTML event handlers look like "foo.html (line 1)"
- // so let's try to skip those
- if (error.source)
- return "syntax";
- else if (error.lineNo == 1 && getFileExtension(error.href) != "js")
- return "none";
- else if (error.category == "css")
- return "none";
- else if (!error.href || !error.lineNo)
- return "none";
- else
- return "exec";
- },
- onToggleError: function(event)
- {
- var target = event.currentTarget;
- if (hasClass(event.target, "errorBreak"))
- {
- this.breakOnThisError(target.repObject);
- }
- else if (hasClass(event.target, "errorSource"))
- {
- var panel = Firebug.getElementPanel(event.target);
- this.inspectObject(target.repObject, panel.context);
- }
- else if (hasClass(event.target, "errorTitle"))
- {
- var traceBox = target.childNodes[1];
- toggleClass(target, "opened");
- event.target.setAttribute('aria-checked', hasClass(target, "opened"));
- if (hasClass(target, "opened"))
- {
- if (target.stackTrace)
- var node = FirebugReps.StackTrace.tag.append({object: target.stackTrace}, traceBox);
- if (Firebug.A11yModel.enabled)
- {
- var panel = Firebug.getElementPanel(event.target);
- dispatch([Firebug.A11yModel], "onLogRowContentCreated", [panel , traceBox]);
- }
- }
- else
- clearNode(traceBox);
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- copyError: function(error)
- {
- var message = [
- this.getMessage(error.message),
- error.href,
- "Line " + error.lineNo
- ];
- copyToClipboard(message.join("\n"));
- },
- breakOnThisError: function(error)
- {
- if (this.hasErrorBreak(error))
- Firebug.Debugger.clearErrorBreakpoint(error.href, error.lineNo);
- else
- Firebug.Debugger.setErrorBreakpoint(error.href, error.lineNo);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "errorMessage",
- inspectable: false,
- supportsObject: function(object)
- {
- return object instanceof ErrorMessage;
- },
- inspectObject: function(error, context)
- {
- var sourceLink = this.getSourceLink(error);
- FirebugReps.SourceLink.inspectObject(sourceLink, context);
- },
- getContextMenuItems: function(error, target, context)
- {
- var breakOnThisError = this.hasErrorBreak(error);
- var items = [
- {label: "CopyError", command: bindFixed(this.copyError, this, error) }
- ];
- if (error.category == "css")
- {
- items.push(
- "-",
- {label: "BreakOnThisError", type: "checkbox", checked: breakOnThisError,
- command: bindFixed(this.breakOnThisError, this, error) },
- optionMenu("BreakOnAllErrors", "breakOnErrors")
- );
- }
- return items;
- }
- });
- // ************************************************************************************************
- this.Assert = domplate(Firebug.Rep,
- {
- tag:
- DIV(
- DIV({"class": "errorTitle"}),
- DIV({"class": "assertDescription"})
- ),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "assert",
- inspectObject: function(error, context)
- {
- var sourceLink = this.getSourceLink(error);
- Firebug.chrome.select(sourceLink);
- },
- getContextMenuItems: function(error, target, context)
- {
- var breakOnThisError = this.hasErrorBreak(error);
- return [
- {label: "CopyError", command: bindFixed(this.copyError, this, error) },
- "-",
- {label: "BreakOnThisError", type: "checkbox", checked: breakOnThisError,
- command: bindFixed(this.breakOnThisError, this, error) },
- {label: "BreakOnAllErrors", type: "checkbox", checked: Firebug.breakOnErrors,
- command: bindFixed(this.breakOnAllErrors, this, error) }
- ];
- }
- });
- // ************************************************************************************************
- this.SourceText = domplate(Firebug.Rep,
- {
- tag:
- DIV(
- FOR("line", "$object|lineIterator",
- DIV({"class": "sourceRow", role : "presentation"},
- SPAN({"class": "sourceLine", role : "presentation"}, "$line.lineNo"),
- SPAN({"class": "sourceRowText", role : "presentation"}, "$line.text")
- )
- )
- ),
- lineIterator: function(sourceText)
- {
- var maxLineNoChars = (sourceText.lines.length + "").length;
- var list = [];
- for (var i = 0; i < sourceText.lines.length; ++i)
- {
- // Make sure all line numbers are the same width (with a fixed-width font)
- var lineNo = (i+1) + "";
- while (lineNo.length < maxLineNoChars)
- lineNo = " " + lineNo;
- list.push({lineNo: lineNo, text: sourceText.lines[i]});
- }
- return list;
- },
- getHTML: function(sourceText)
- {
- return getSourceLineRange(sourceText, 1, sourceText.lines.length);
- }
- });
- //************************************************************************************************
- this.nsIDOMHistory = domplate(Firebug.Rep,
- {
- tag:OBJECTBOX({onclick: "$showHistory"},
- OBJECTLINK("$object|summarizeHistory")
- ),
- className: "nsIDOMHistory",
- summarizeHistory: function(history)
- {
- try
- {
- var items = history.length;
- return items + " history entries";
- }
- catch(exc)
- {
- return "object does not support history (nsIDOMHistory)";
- }
- },
- showHistory: function(history)
- {
- try
- {
- var items = history.length; // if this throws, then unsupported
- Firebug.chrome.select(history);
- }
- catch (exc)
- {
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- supportsObject: function(object, type)
- {
- return (object instanceof Ci.nsIDOMHistory);
- }
- });
- // ************************************************************************************************
- this.ApplicationCache = domplate(Firebug.Rep,
- {
- tag:OBJECTBOX({onclick: "$showApplicationCache"},
- OBJECTLINK("$object|summarizeCache")
- ),
- summarizeCache: function(applicationCache)
- {
- try
- {
- return applicationCache.length + " items in offline cache";
- }
- catch(exc)
- {
- return "https://bugzilla.mozilla.org/show_bug.cgi?id=422264";
- }
- },
- showApplicationCache: function(event)
- {
- openNewTab("https://bugzilla.mozilla.org/show_bug.cgi?id=422264");
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "applicationCache",
- supportsObject: function(object, type)
- {
- if (Ci.nsIDOMOfflineResourceList)
- return (object instanceof Ci.nsIDOMOfflineResourceList);
- }
- });
- this.Storage = domplate(Firebug.Rep,
- {
- tag: OBJECTBOX({onclick: "$show"}, OBJECTLINK("$object|summarize")),
- summarize: function(storage)
- {
- return storage.length +" items in Storage";
- },
- show: function(storage)
- {
- openNewTab("http://dev.w3.org/html5/webstorage/#storage-0");
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- className: "Storage",
- supportsObject: function(object, type)
- {
- return (object instanceof Storage);
- }
- });
- // ************************************************************************************************
- Firebug.registerRep(
- //this.nsIDOMHistory, // make this early to avoid exceptions
- this.Undefined,
- this.Null,
- this.Number,
- this.String,
- this.Window,
- //this.ApplicationCache, // must come before Arr (array) else exceptions.
- //this.ErrorMessage,
- this.Element,
- //this.TextNode,
- this.Document,
- this.StyleSheet,
- this.Event,
- //this.SourceLink,
- //this.SourceFile,
- //this.StackTrace,
- //this.StackFrame,
- //this.jsdStackFrame,
- //this.jsdScript,
- //this.NetFile,
- this.Property,
- this.Except,
- this.Arr
- );
- Firebug.setDefaultReps(this.Func, this.Obj);
- }});
- // ************************************************************************************************
- /*
- * The following is http://developer.yahoo.com/yui/license.txt and applies to only code labeled "Yahoo BSD Source"
- * in only this file reps.js. John J. Barton June 2007.
- *
- Software License Agreement (BSD License)
- Copyright (c) 2006, Yahoo! Inc.
- All rights reserved.
- Redistribution and use of this software in source and binary forms, with or without modification, are
- permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of Yahoo! Inc. nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of Yahoo! Inc.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * /
- */
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // Constants
- var saveTimeout = 400;
- var pageAmount = 10;
- // ************************************************************************************************
- // Globals
- var currentTarget = null;
- var currentGroup = null;
- var currentPanel = null;
- var currentEditor = null;
- var defaultEditor = null;
- var originalClassName = null;
- var originalValue = null;
- var defaultValue = null;
- var previousValue = null;
- var invalidEditor = false;
- var ignoreNextInput = false;
- // ************************************************************************************************
- Firebug.Editor = extend(Firebug.Module,
- {
- supportsStopEvent: true,
- dispatchName: "editor",
- tabCharacter: " ",
- startEditing: function(target, value, editor)
- {
- this.stopEditing();
- if (hasClass(target, "insertBefore") || hasClass(target, "insertAfter"))
- return;
- var panel = Firebug.getElementPanel(target);
- if (!panel.editable)
- return;
- if (FBTrace.DBG_EDITOR)
- FBTrace.sysout("editor.startEditing " + value, target);
- defaultValue = target.getAttribute("defaultValue");
- if (value == undefined)
- {
- var textContent = isIE ? "innerText" : "textContent";
- value = target[textContent];
- if (value == defaultValue)
- value = "";
- }
- originalValue = previousValue = value;
- invalidEditor = false;
- currentTarget = target;
- currentPanel = panel;
- currentGroup = getAncestorByClass(target, "editGroup");
- currentPanel.editing = true;
- var panelEditor = currentPanel.getEditor(target, value);
- currentEditor = editor ? editor : panelEditor;
- if (!currentEditor)
- currentEditor = getDefaultEditor(currentPanel);
- var inlineParent = getInlineParent(target);
- var targetSize = getOffsetSize(inlineParent);
- setClass(panel.panelNode, "editing");
- setClass(target, "editing");
- if (currentGroup)
- setClass(currentGroup, "editing");
- currentEditor.show(target, currentPanel, value, targetSize);
- //dispatch(this.fbListeners, "onBeginEditing", [currentPanel, currentEditor, target, value]);
- currentEditor.beginEditing(target, value);
- if (FBTrace.DBG_EDITOR)
- FBTrace.sysout("Editor start panel "+currentPanel.name);
- this.attachListeners(currentEditor, panel.context);
- },
- stopEditing: function(cancel)
- {
- if (!currentTarget)
- return;
- if (FBTrace.DBG_EDITOR)
- FBTrace.sysout("editor.stopEditing cancel:" + cancel+" saveTimeout: "+this.saveTimeout);
- clearTimeout(this.saveTimeout);
- delete this.saveTimeout;
- this.detachListeners(currentEditor, currentPanel.context);
- removeClass(currentPanel.panelNode, "editing");
- removeClass(currentTarget, "editing");
- if (currentGroup)
- removeClass(currentGroup, "editing");
- var value = currentEditor.getValue();
- if (value == defaultValue)
- value = "";
- var removeGroup = currentEditor.endEditing(currentTarget, value, cancel);
- try
- {
- if (cancel)
- {
- //dispatch([Firebug.A11yModel], 'onInlineEditorClose', [currentPanel, currentTarget, removeGroup && !originalValue]);
- if (value != originalValue)
- this.saveEditAndNotifyListeners(currentTarget, originalValue, previousValue);
- if (removeGroup && !originalValue && currentGroup)
- currentGroup.parentNode.removeChild(currentGroup);
- }
- else if (!value)
- {
- this.saveEditAndNotifyListeners(currentTarget, null, previousValue);
- if (removeGroup && currentGroup)
- currentGroup.parentNode.removeChild(currentGroup);
- }
- else
- this.save(value);
- }
- catch (exc)
- {
- //throw exc.message;
- //ERROR(exc);
- }
- currentEditor.hide();
- currentPanel.editing = false;
- //dispatch(this.fbListeners, "onStopEdit", [currentPanel, currentEditor, currentTarget]);
- //if (FBTrace.DBG_EDITOR)
- // FBTrace.sysout("Editor stop panel "+currentPanel.name);
- currentTarget = null;
- currentGroup = null;
- currentPanel = null;
- currentEditor = null;
- originalValue = null;
- invalidEditor = false;
- return value;
- },
- cancelEditing: function()
- {
- return this.stopEditing(true);
- },
- update: function(saveNow)
- {
- if (this.saveTimeout)
- clearTimeout(this.saveTimeout);
- invalidEditor = true;
- currentEditor.layout();
- if (saveNow)
- this.save();
- else
- {
- var context = currentPanel.context;
- this.saveTimeout = context.setTimeout(bindFixed(this.save, this), saveTimeout);
- if (FBTrace.DBG_EDITOR)
- FBTrace.sysout("editor.update saveTimeout: "+this.saveTimeout);
- }
- },
- save: function(value)
- {
- if (!invalidEditor)
- return;
- if (value == undefined)
- value = currentEditor.getValue();
- if (FBTrace.DBG_EDITOR)
- FBTrace.sysout("editor.save saveTimeout: "+this.saveTimeout+" currentPanel: "+(currentPanel?currentPanel.name:"null"));
- try
- {
- this.saveEditAndNotifyListeners(currentTarget, value, previousValue);
- previousValue = value;
- invalidEditor = false;
- }
- catch (exc)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("editor.save FAILS "+exc, exc);
- }
- },
- saveEditAndNotifyListeners: function(currentTarget, value, previousValue)
- {
- currentEditor.saveEdit(currentTarget, value, previousValue);
- //dispatch(this.fbListeners, "onSaveEdit", [currentPanel, currentEditor, currentTarget, value, previousValue]);
- },
- setEditTarget: function(element)
- {
- if (!element)
- {
- dispatch([Firebug.A11yModel], 'onInlineEditorClose', [currentPanel, currentTarget, true]);
- this.stopEditing();
- }
- else if (hasClass(element, "insertBefore"))
- this.insertRow(element, "before");
- else if (hasClass(element, "insertAfter"))
- this.insertRow(element, "after");
- else
- this.startEditing(element);
- },
- tabNextEditor: function()
- {
- if (!currentTarget)
- return;
- var value = currentEditor.getValue();
- var nextEditable = currentTarget;
- do
- {
- nextEditable = !value && currentGroup
- ? getNextOutsider(nextEditable, currentGroup)
- : getNextByClass(nextEditable, "editable");
- }
- while (nextEditable && !nextEditable.offsetHeight);
- this.setEditTarget(nextEditable);
- },
- tabPreviousEditor: function()
- {
- if (!currentTarget)
- return;
- var value = currentEditor.getValue();
- var prevEditable = currentTarget;
- do
- {
- prevEditable = !value && currentGroup
- ? getPreviousOutsider(prevEditable, currentGroup)
- : getPreviousByClass(prevEditable, "editable");
- }
- while (prevEditable && !prevEditable.offsetHeight);
- this.setEditTarget(prevEditable);
- },
- insertRow: function(relative, insertWhere)
- {
- var group =
- relative || getAncestorByClass(currentTarget, "editGroup") || currentTarget;
- var value = this.stopEditing();
- currentPanel = Firebug.getElementPanel(group);
- currentEditor = currentPanel.getEditor(group, value);
- if (!currentEditor)
- currentEditor = getDefaultEditor(currentPanel);
- currentGroup = currentEditor.insertNewRow(group, insertWhere);
- if (!currentGroup)
- return;
- var editable = hasClass(currentGroup, "editable")
- ? currentGroup
- : getNextByClass(currentGroup, "editable");
- if (editable)
- this.setEditTarget(editable);
- },
- insertRowForObject: function(relative)
- {
- var container = getAncestorByClass(relative, "insertInto");
- if (container)
- {
- relative = getChildByClass(container, "insertBefore");
- if (relative)
- this.insertRow(relative, "before");
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- attachListeners: function(editor, context)
- {
- var win = isIE ?
- currentTarget.ownerDocument.parentWindow :
- currentTarget.ownerDocument.defaultView;
- addEvent(win, "resize", this.onResize);
- addEvent(win, "blur", this.onBlur);
- var chrome = Firebug.chrome;
- this.listeners = [
- chrome.keyCodeListen("ESCAPE", null, bind(this.cancelEditing, this))
- ];
- if (editor.arrowCompletion)
- {
- this.listeners.push(
- chrome.keyCodeListen("UP", null, bindFixed(editor.completeValue, editor, -1)),
- chrome.keyCodeListen("DOWN", null, bindFixed(editor.completeValue, editor, 1)),
- chrome.keyCodeListen("PAGE_UP", null, bindFixed(editor.completeValue, editor, -pageAmount)),
- chrome.keyCodeListen("PAGE_DOWN", null, bindFixed(editor.completeValue, editor, pageAmount))
- );
- }
- if (currentEditor.tabNavigation)
- {
- this.listeners.push(
- chrome.keyCodeListen("RETURN", null, bind(this.tabNextEditor, this)),
- chrome.keyCodeListen("RETURN", isControl, bind(this.insertRow, this, null, "after")),
- chrome.keyCodeListen("TAB", null, bind(this.tabNextEditor, this)),
- chrome.keyCodeListen("TAB", isShift, bind(this.tabPreviousEditor, this))
- );
- }
- else if (currentEditor.multiLine)
- {
- this.listeners.push(
- chrome.keyCodeListen("TAB", null, insertTab)
- );
- }
- else
- {
- this.listeners.push(
- chrome.keyCodeListen("RETURN", null, bindFixed(this.stopEditing, this))
- );
- if (currentEditor.tabCompletion)
- {
- this.listeners.push(
- chrome.keyCodeListen("TAB", null, bind(editor.completeValue, editor, 1)),
- chrome.keyCodeListen("TAB", isShift, bind(editor.completeValue, editor, -1))
- );
- }
- }
- },
- detachListeners: function(editor, context)
- {
- if (!this.listeners)
- return;
- var win = isIE ?
- currentTarget.ownerDocument.parentWindow :
- currentTarget.ownerDocument.defaultView;
- removeEvent(win, "resize", this.onResize);
- removeEvent(win, "blur", this.onBlur);
- var chrome = Firebug.chrome;
- if (chrome)
- {
- for (var i = 0; i < this.listeners.length; ++i)
- chrome.keyIgnore(this.listeners[i]);
- }
- delete this.listeners;
- },
- onResize: function(event)
- {
- currentEditor.layout(true);
- },
- onBlur: function(event)
- {
- if (currentEditor.enterOnBlur && isAncestor(event.target, currentEditor.box))
- this.stopEditing();
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Module
- initialize: function()
- {
- Firebug.Module.initialize.apply(this, arguments);
- this.onResize = bindFixed(this.onResize, this);
- this.onBlur = bind(this.onBlur, this);
- },
- disable: function()
- {
- this.stopEditing();
- },
- showContext: function(browser, context)
- {
- this.stopEditing();
- },
- showPanel: function(browser, panel)
- {
- this.stopEditing();
- }
- });
- // ************************************************************************************************
- // BaseEditor
- Firebug.BaseEditor = extend(Firebug.MeasureBox,
- {
- getValue: function()
- {
- },
- setValue: function(value)
- {
- },
- show: function(target, panel, value, textSize, targetSize)
- {
- },
- hide: function()
- {
- },
- layout: function(forceAll)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Support for context menus within inline editors.
- getContextMenuItems: function(target)
- {
- var items = [];
- items.push({label: "Cut", commandID: "cmd_cut"});
- items.push({label: "Copy", commandID: "cmd_copy"});
- items.push({label: "Paste", commandID: "cmd_paste"});
- return items;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Editor Module listeners will get "onBeginEditing" just before this call
- beginEditing: function(target, value)
- {
- },
- // Editor Module listeners will get "onSaveEdit" just after this call
- saveEdit: function(target, value, previousValue)
- {
- },
- endEditing: function(target, value, cancel)
- {
- // Remove empty groups by default
- return true;
- },
- insertNewRow: function(target, insertWhere)
- {
- }
- });
- // ************************************************************************************************
- // InlineEditor
- // basic inline editor attributes
- var inlineEditorAttributes = {
- "class": "textEditorInner",
- type: "text",
- spellcheck: "false",
- onkeypress: "$onKeyPress",
- onoverflow: "$onOverflow",
- oncontextmenu: "$onContextMenu"
- };
- // IE does not support the oninput event, so we're using the onkeydown to signalize
- // the relevant keyboard events, and the onpropertychange to actually handle the
- // input event, which should happen after the onkeydown event is fired and after the
- // value of the input is updated, but before the onkeyup and before the input (with the
- // new value) is rendered
- if (isIE)
- {
- inlineEditorAttributes.onpropertychange = "$onInput";
- inlineEditorAttributes.onkeydown = "$onKeyDown";
- }
- // for other browsers we use the oninput event
- else
- {
- inlineEditorAttributes.oninput = "$onInput";
- }
- Firebug.InlineEditor = function(doc)
- {
- this.initializeInline(doc);
- };
- Firebug.InlineEditor.prototype = domplate(Firebug.BaseEditor,
- {
- enterOnBlur: true,
- outerMargin: 8,
- shadowExpand: 7,
- tag:
- DIV({"class": "inlineEditor"},
- DIV({"class": "textEditorTop1"},
- DIV({"class": "textEditorTop2"})
- ),
- DIV({"class": "textEditorInner1"},
- DIV({"class": "textEditorInner2"},
- INPUT(
- inlineEditorAttributes
- )
- )
- ),
- DIV({"class": "textEditorBottom1"},
- DIV({"class": "textEditorBottom2"})
- )
- ),
- inputTag :
- INPUT({"class": "textEditorInner", type: "text",
- /*oninput: "$onInput",*/ onkeypress: "$onKeyPress", onoverflow: "$onOverflow"}
- ),
- expanderTag:
- IMG({"class": "inlineExpander", src: "blank.gif"}),
- initialize: function()
- {
- this.fixedWidth = false;
- this.completeAsYouType = true;
- this.tabNavigation = true;
- this.multiLine = false;
- this.tabCompletion = false;
- this.arrowCompletion = true;
- this.noWrap = true;
- this.numeric = false;
- },
- destroy: function()
- {
- this.destroyInput();
- },
- initializeInline: function(doc)
- {
- if (FBTrace.DBG_EDITOR)
- FBTrace.sysout("Firebug.InlineEditor initializeInline()");
- //this.box = this.tag.replace({}, doc, this);
- this.box = this.tag.append({}, doc.body, this);
- //this.input = this.box.childNodes[1].firstChild.firstChild; // XXXjjb childNode[1] required
- this.input = this.box.getElementsByTagName("input")[0];
- if (isIElt8)
- {
- this.input.style.top = "-8px";
- }
- this.expander = this.expanderTag.replace({}, doc, this);
- this.initialize();
- },
- destroyInput: function()
- {
- // XXXjoe Need to remove input/keypress handlers to avoid leaks
- },
- getValue: function()
- {
- return this.input.value;
- },
- setValue: function(value)
- {
- // It's only a one-line editor, so new lines shouldn't be allowed
- return this.input.value = stripNewLines(value);
- },
- show: function(target, panel, value, targetSize)
- {
- //dispatch([Firebug.A11yModel], "onInlineEditorShow", [panel, this]);
- this.target = target;
- this.panel = panel;
- this.targetSize = targetSize;
- // TODO: xxxpedro editor
- //this.targetOffset = getClientOffset(target);
- // Some browsers (IE, Google Chrome and Safari) will have problem trying to get the
- // offset values of invisible elements, or empty elements. So, in order to get the
- // correct values, we temporary inject a character in the innerHTML of the empty element,
- // then we get the offset values, and next, we restore the original innerHTML value.
- var innerHTML = target.innerHTML;
- var isEmptyElement = !innerHTML;
- if (isEmptyElement)
- target.innerHTML = ".";
- // Get the position of the target element (that is about to be edited)
- this.targetOffset =
- {
- x: target.offsetLeft,
- y: target.offsetTop
- };
- // Restore the original innerHTML value of the empty element
- if (isEmptyElement)
- target.innerHTML = innerHTML;
- this.originalClassName = this.box.className;
- var classNames = target.className.split(" ");
- for (var i = 0; i < classNames.length; ++i)
- setClass(this.box, "editor-" + classNames[i]);
- // Make the editor match the target's font style
- copyTextStyles(target, this.box);
- this.setValue(value);
- if (this.fixedWidth)
- this.updateLayout(true);
- else
- {
- this.startMeasuring(target);
- this.textSize = this.measureInputText(value);
- // Correct the height of the box to make the funky CSS drop-shadow line up
- var parent = this.input.parentNode;
- if (hasClass(parent, "textEditorInner2"))
- {
- var yDiff = this.textSize.height - this.shadowExpand;
- // IE6 height offset
- if (isIE6)
- yDiff -= 2;
- parent.style.height = yDiff + "px";
- parent.parentNode.style.height = yDiff + "px";
- }
- this.updateLayout(true);
- }
- this.getAutoCompleter().reset();
- if (isIElt8)
- panel.panelNode.appendChild(this.box);
- else
- target.offsetParent.appendChild(this.box);
- //console.log(target);
- //this.input.select(); // it's called bellow, with setTimeout
- if (isIE)
- {
- // reset input style
- this.input.style.fontFamily = "Monospace";
- this.input.style.fontSize = "11px";
- }
- // Insert the "expander" to cover the target element with white space
- if (!this.fixedWidth)
- {
- copyBoxStyles(target, this.expander);
- target.parentNode.replaceChild(this.expander, target);
- collapse(target, true);
- this.expander.parentNode.insertBefore(target, this.expander);
- }
- //TODO: xxxpedro
- //scrollIntoCenterView(this.box, null, true);
- // Display the editor after change its size and position to avoid flickering
- this.box.style.display = "block";
- // we need to call input.focus() and input.select() with a timeout,
- // otherwise it won't work on all browsers due to timing issues
- var self = this;
- setTimeout(function(){
- self.input.focus();
- self.input.select();
- },0);
- },
- hide: function()
- {
- this.box.className = this.originalClassName;
- if (!this.fixedWidth)
- {
- this.stopMeasuring();
- collapse(this.target, false);
- if (this.expander.parentNode)
- this.expander.parentNode.removeChild(this.expander);
- }
- if (this.box.parentNode)
- {
- ///setSelectionRange(this.input, 0, 0);
- this.input.blur();
- this.box.parentNode.removeChild(this.box);
- }
- delete this.target;
- delete this.panel;
- },
- layout: function(forceAll)
- {
- if (!this.fixedWidth)
- this.textSize = this.measureInputText(this.input.value);
- if (forceAll)
- this.targetOffset = getClientOffset(this.expander);
- this.updateLayout(false, forceAll);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- beginEditing: function(target, value)
- {
- },
- saveEdit: function(target, value, previousValue)
- {
- },
- endEditing: function(target, value, cancel)
- {
- // Remove empty groups by default
- return true;
- },
- insertNewRow: function(target, insertWhere)
- {
- },
- advanceToNext: function(target, charCode)
- {
- return false;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getAutoCompleteRange: function(value, offset)
- {
- },
- getAutoCompleteList: function(preExpr, expr, postExpr)
- {
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getAutoCompleter: function()
- {
- if (!this.autoCompleter)
- {
- this.autoCompleter = new Firebug.AutoCompleter(null,
- bind(this.getAutoCompleteRange, this), bind(this.getAutoCompleteList, this),
- true, false);
- }
- return this.autoCompleter;
- },
- completeValue: function(amt)
- {
- //console.log("completeValue");
- var selectRangeCallback = this.getAutoCompleter().complete(currentPanel.context, this.input, true, amt < 0);
- if (selectRangeCallback)
- {
- Firebug.Editor.update(true);
- // We need to select the editor text after calling update in Safari/Chrome,
- // otherwise the text won't be selected
- if (isSafari)
- setTimeout(selectRangeCallback,0);
- else
- selectRangeCallback();
- }
- else
- this.incrementValue(amt);
- },
- incrementValue: function(amt)
- {
- var value = this.input.value;
- // TODO: xxxpedro editor
- if (isIE)
- var start = getInputSelectionStart(this.input), end = start;
- else
- var start = this.input.selectionStart, end = this.input.selectionEnd;
- //debugger;
- var range = this.getAutoCompleteRange(value, start);
- if (!range || range.type != "int")
- range = {start: 0, end: value.length-1};
- var expr = value.substr(range.start, range.end-range.start+1);
- preExpr = value.substr(0, range.start);
- postExpr = value.substr(range.end+1);
- // See if the value is an integer, and if so increment it
- var intValue = parseInt(expr);
- if (!!intValue || intValue == 0)
- {
- var m = /\d+/.exec(expr);
- var digitPost = expr.substr(m.index+m[0].length);
- var completion = intValue-amt;
- this.input.value = preExpr + completion + digitPost + postExpr;
- setSelectionRange(this.input, start, end);
- Firebug.Editor.update(true);
- return true;
- }
- else
- return false;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onKeyPress: function(event)
- {
- //console.log("onKeyPress", event);
- if (event.keyCode == 27 && !this.completeAsYouType)
- {
- var reverted = this.getAutoCompleter().revert(this.input);
- if (reverted)
- cancelEvent(event);
- }
- else if (event.charCode && this.advanceToNext(this.target, event.charCode))
- {
- Firebug.Editor.tabNextEditor();
- cancelEvent(event);
- }
- else
- {
- if (this.numeric && event.charCode && (event.charCode < 48 || event.charCode > 57)
- && event.charCode != 45 && event.charCode != 46)
- FBL.cancelEvent(event);
- else
- {
- // If the user backspaces, don't autocomplete after the upcoming input event
- this.ignoreNextInput = event.keyCode == 8;
- }
- }
- },
- onOverflow: function()
- {
- this.updateLayout(false, false, 3);
- },
- onKeyDown: function(event)
- {
- //console.log("onKeyDown", event.keyCode);
- if (event.keyCode > 46 || event.keyCode == 32 || event.keyCode == 8)
- {
- this.keyDownPressed = true;
- }
- },
- onInput: function(event)
- {
- //debugger;
- // skip not relevant onpropertychange calls on IE
- if (isIE)
- {
- if (event.propertyName != "value" || !isVisible(this.input) || !this.keyDownPressed)
- return;
- this.keyDownPressed = false;
- }
- //console.log("onInput", event);
- //console.trace();
- var selectRangeCallback;
- if (this.ignoreNextInput)
- {
- this.ignoreNextInput = false;
- this.getAutoCompleter().reset();
- }
- else if (this.completeAsYouType)
- selectRangeCallback = this.getAutoCompleter().complete(currentPanel.context, this.input, false);
- else
- this.getAutoCompleter().reset();
- Firebug.Editor.update();
- if (selectRangeCallback)
- {
- // We need to select the editor text after calling update in Safari/Chrome,
- // otherwise the text won't be selected
- if (isSafari)
- setTimeout(selectRangeCallback,0);
- else
- selectRangeCallback();
- }
- },
- onContextMenu: function(event)
- {
- cancelEvent(event);
- var popup = $("fbInlineEditorPopup");
- FBL.eraseNode(popup);
- var target = event.target || event.srcElement;
- var menu = this.getContextMenuItems(target);
- if (menu)
- {
- for (var i = 0; i < menu.length; ++i)
- FBL.createMenuItem(popup, menu[i]);
- }
- if (!popup.firstChild)
- return false;
- popup.openPopupAtScreen(event.screenX, event.screenY, true);
- return true;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- updateLayout: function(initial, forceAll, extraWidth)
- {
- if (this.fixedWidth)
- {
- this.box.style.left = (this.targetOffset.x) + "px";
- this.box.style.top = (this.targetOffset.y) + "px";
- var w = this.target.offsetWidth;
- var h = this.target.offsetHeight;
- this.input.style.width = w + "px";
- this.input.style.height = (h-3) + "px";
- }
- else
- {
- if (initial || forceAll)
- {
- this.box.style.left = this.targetOffset.x + "px";
- this.box.style.top = this.targetOffset.y + "px";
- }
- var approxTextWidth = this.textSize.width;
- var maxWidth = (currentPanel.panelNode.scrollWidth - this.targetOffset.x)
- - this.outerMargin;
- var wrapped = initial
- ? this.noWrap && this.targetSize.height > this.textSize.height+3
- : this.noWrap && approxTextWidth > maxWidth;
- if (wrapped)
- {
- var style = isIE ?
- this.target.currentStyle :
- this.target.ownerDocument.defaultView.getComputedStyle(this.target, "");
- targetMargin = parseInt(style.marginLeft) + parseInt(style.marginRight);
- // Make the width fit the remaining x-space from the offset to the far right
- approxTextWidth = maxWidth - targetMargin;
- this.input.style.width = "100%";
- this.box.style.width = approxTextWidth + "px";
- }
- else
- {
- // Make the input one character wider than the text value so that
- // typing does not ever cause the textbox to scroll
- var charWidth = this.measureInputText('m').width;
- // Sometimes we need to make the editor a little wider, specifically when
- // an overflow happens, otherwise it will scroll off some text on the left
- if (extraWidth)
- charWidth *= extraWidth;
- var inputWidth = approxTextWidth + charWidth;
- if (initial)
- {
- if (isIE)
- {
- // TODO: xxxpedro
- var xDiff = 13;
- this.box.style.width = (inputWidth + xDiff) + "px";
- }
- else
- this.box.style.width = "auto";
- }
- else
- {
- // TODO: xxxpedro
- var xDiff = isIE ? 13: this.box.scrollWidth - this.input.offsetWidth;
- this.box.style.width = (inputWidth + xDiff) + "px";
- }
- this.input.style.width = inputWidth + "px";
- }
- this.expander.style.width = approxTextWidth + "px";
- this.expander.style.height = Math.max(this.textSize.height-3,0) + "px";
- }
- if (forceAll)
- scrollIntoCenterView(this.box, null, true);
- }
- });
- // ************************************************************************************************
- // Autocompletion
- Firebug.AutoCompleter = function(getExprOffset, getRange, evaluator, selectMode, caseSensitive)
- {
- var candidates = null;
- var originalValue = null;
- var originalOffset = -1;
- var lastExpr = null;
- var lastOffset = -1;
- var exprOffset = 0;
- var lastIndex = 0;
- var preParsed = null;
- var preExpr = null;
- var postExpr = null;
- this.revert = function(textBox)
- {
- if (originalOffset != -1)
- {
- textBox.value = originalValue;
- setSelectionRange(textBox, originalOffset, originalOffset);
- this.reset();
- return true;
- }
- else
- {
- this.reset();
- return false;
- }
- };
- this.reset = function()
- {
- candidates = null;
- originalValue = null;
- originalOffset = -1;
- lastExpr = null;
- lastOffset = 0;
- exprOffset = 0;
- };
- this.complete = function(context, textBox, cycle, reverse)
- {
- //console.log("complete", context, textBox, cycle, reverse);
- // TODO: xxxpedro important port to firebug (variable leak)
- //var value = lastValue = textBox.value;
- var value = textBox.value;
- //var offset = textBox.selectionStart;
- var offset = getInputSelectionStart(textBox);
- // The result of selectionStart() in Safari/Chrome is 1 unit less than the result
- // in Firefox. Therefore, we need to manually adjust the value here.
- if (isSafari && !cycle && offset >= 0) offset++;
- if (!selectMode && originalOffset != -1)
- offset = originalOffset;
- if (!candidates || !cycle || offset != lastOffset)
- {
- originalOffset = offset;
- originalValue = value;
- // Find the part of the string that will be parsed
- var parseStart = getExprOffset ? getExprOffset(value, offset, context) : 0;
- preParsed = value.substr(0, parseStart);
- var parsed = value.substr(parseStart);
- // Find the part of the string that is being completed
- var range = getRange ? getRange(parsed, offset-parseStart, context) : null;
- if (!range)
- range = {start: 0, end: parsed.length-1 };
- var expr = parsed.substr(range.start, range.end-range.start+1);
- preExpr = parsed.substr(0, range.start);
- postExpr = parsed.substr(range.end+1);
- exprOffset = parseStart + range.start;
- if (!cycle)
- {
- if (!expr)
- return;
- else if (lastExpr && lastExpr.indexOf(expr) != 0)
- {
- candidates = null;
- }
- else if (lastExpr && lastExpr.length >= expr.length)
- {
- candidates = null;
- lastExpr = expr;
- return;
- }
- }
- lastExpr = expr;
- lastOffset = offset;
- var searchExpr;
- // Check if the cursor is at the very right edge of the expression, or
- // somewhere in the middle of it
- if (expr && offset != parseStart+range.end+1)
- {
- if (cycle)
- {
- // We are in the middle of the expression, but we can
- // complete by cycling to the next item in the values
- // list after the expression
- offset = range.start;
- searchExpr = expr;
- expr = "";
- }
- else
- {
- // We can't complete unless we are at the ridge edge
- return;
- }
- }
- var values = evaluator(preExpr, expr, postExpr, context);
- if (!values)
- return;
- if (expr)
- {
- // Filter the list of values to those which begin with expr. We
- // will then go on to complete the first value in the resulting list
- candidates = [];
- if (caseSensitive)
- {
- for (var i = 0; i < values.length; ++i)
- {
- var name = values[i];
- if (name.indexOf && name.indexOf(expr) == 0)
- candidates.push(name);
- }
- }
- else
- {
- var lowerExpr = caseSensitive ? expr : expr.toLowerCase();
- for (var i = 0; i < values.length; ++i)
- {
- var name = values[i];
- if (name.indexOf && name.toLowerCase().indexOf(lowerExpr) == 0)
- candidates.push(name);
- }
- }
- lastIndex = reverse ? candidates.length-1 : 0;
- }
- else if (searchExpr)
- {
- var searchIndex = -1;
- // Find the first instance of searchExpr in the values list. We
- // will then complete the string that is found
- if (caseSensitive)
- {
- searchIndex = values.indexOf(expr);
- }
- else
- {
- var lowerExpr = searchExpr.toLowerCase();
- for (var i = 0; i < values.length; ++i)
- {
- var name = values[i];
- if (name && name.toLowerCase().indexOf(lowerExpr) == 0)
- {
- searchIndex = i;
- break;
- }
- }
- }
- // Nothing found, so there's nothing to complete to
- if (searchIndex == -1)
- return this.reset();
- expr = searchExpr;
- candidates = cloneArray(values);
- lastIndex = searchIndex;
- }
- else
- {
- expr = "";
- candidates = [];
- for (var i = 0; i < values.length; ++i)
- {
- if (values[i].substr)
- candidates.push(values[i]);
- }
- lastIndex = -1;
- }
- }
- if (cycle)
- {
- expr = lastExpr;
- lastIndex += reverse ? -1 : 1;
- }
- if (!candidates.length)
- return;
- if (lastIndex >= candidates.length)
- lastIndex = 0;
- else if (lastIndex < 0)
- lastIndex = candidates.length-1;
- var completion = candidates[lastIndex];
- var preCompletion = expr.substr(0, offset-exprOffset);
- var postCompletion = completion.substr(offset-exprOffset);
- textBox.value = preParsed + preExpr + preCompletion + postCompletion + postExpr;
- var offsetEnd = preParsed.length + preExpr.length + completion.length;
- // TODO: xxxpedro remove the following commented code, if the lib.setSelectionRange()
- // is working well.
- /*
- if (textBox.setSelectionRange)
- {
- // we must select the range with a timeout, otherwise the text won't
- // be properly selected (because after this function executes, the editor's
- // input will be resized to fit the whole text)
- setTimeout(function(){
- if (selectMode)
- textBox.setSelectionRange(offset, offsetEnd);
- else
- textBox.setSelectionRange(offsetEnd, offsetEnd);
- },0);
- }
- /**/
- // we must select the range with a timeout, otherwise the text won't
- // be properly selected (because after this function executes, the editor's
- // input will be resized to fit the whole text)
- /*
- setTimeout(function(){
- if (selectMode)
- setSelectionRange(textBox, offset, offsetEnd);
- else
- setSelectionRange(textBox, offsetEnd, offsetEnd);
- },0);
- return true;
- /**/
- // The editor text should be selected only after calling the editor.update()
- // in Safari/Chrome, otherwise the text won't be selected. So, we're returning
- // a function to be called later (in the proper time for all browsers).
- //
- // TODO: xxxpedro see if we can move the editor.update() calls to here, and avoid
- // returning a closure. the complete() function seems to be called only twice in
- // editor.js. See if this function is called anywhere else (like css.js for example).
- return function(){
- //console.log("autocomplete ", textBox, offset, offsetEnd);
- if (selectMode)
- setSelectionRange(textBox, offset, offsetEnd);
- else
- setSelectionRange(textBox, offsetEnd, offsetEnd);
- };
- /**/
- };
- };
- // ************************************************************************************************
- // Local Helpers
- var getDefaultEditor = function getDefaultEditor(panel)
- {
- if (!defaultEditor)
- {
- var doc = panel.document;
- defaultEditor = new Firebug.InlineEditor(doc);
- }
- return defaultEditor;
- }
- /**
- * An outsider is the first element matching the stepper element that
- * is not an child of group. Elements tagged with insertBefore or insertAfter
- * classes are also excluded from these results unless they are the sibling
- * of group, relative to group's parent editGroup. This allows for the proper insertion
- * rows when groups are nested.
- */
- var getOutsider = function getOutsider(element, group, stepper)
- {
- var parentGroup = getAncestorByClass(group.parentNode, "editGroup");
- var next;
- do
- {
- next = stepper(next || element);
- }
- while (isAncestor(next, group) || isGroupInsert(next, parentGroup));
- return next;
- }
- var isGroupInsert = function isGroupInsert(next, group)
- {
- return (!group || isAncestor(next, group))
- && (hasClass(next, "insertBefore") || hasClass(next, "insertAfter"));
- }
- var getNextOutsider = function getNextOutsider(element, group)
- {
- return getOutsider(element, group, bind(getNextByClass, FBL, "editable"));
- }
- var getPreviousOutsider = function getPreviousOutsider(element, group)
- {
- return getOutsider(element, group, bind(getPreviousByClass, FBL, "editable"));
- }
- var getInlineParent = function getInlineParent(element)
- {
- var lastInline = element;
- for (; element; element = element.parentNode)
- {
- //var s = element.ownerDocument.defaultView.getComputedStyle(element, "");
- var s = isIE ?
- element.currentStyle :
- element.ownerDocument.defaultView.getComputedStyle(element, "");
- if (s.display != "inline")
- return lastInline;
- else
- lastInline = element;
- }
- return null;
- }
- var insertTab = function insertTab()
- {
- insertTextIntoElement(currentEditor.input, Firebug.Editor.tabCharacter);
- }
- // ************************************************************************************************
- Firebug.registerModule(Firebug.Editor);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Inspector Module
- var ElementCache = Firebug.Lite.Cache.Element;
- var inspectorTS, inspectorTimer, isInspecting;
- Firebug.Inspector =
- {
- create: function()
- {
- offlineFragment = Env.browser.document.createDocumentFragment();
- createBoxModelInspector();
- createOutlineInspector();
- },
- destroy: function()
- {
- destroyBoxModelInspector();
- destroyOutlineInspector();
- offlineFragment = null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Inspect functions
- toggleInspect: function()
- {
- if (isInspecting)
- {
- this.stopInspecting();
- }
- else
- {
- Firebug.chrome.inspectButton.changeState("pressed");
- this.startInspecting();
- }
- },
- startInspecting: function()
- {
- isInspecting = true;
- Firebug.chrome.selectPanel("HTML");
- createInspectorFrame();
- var size = Firebug.browser.getWindowScrollSize();
- fbInspectFrame.style.width = size.width + "px";
- fbInspectFrame.style.height = size.height + "px";
- //addEvent(Firebug.browser.document.documentElement, "mousemove", Firebug.Inspector.onInspectingBody);
- addEvent(fbInspectFrame, "mousemove", Firebug.Inspector.onInspecting);
- addEvent(fbInspectFrame, "mousedown", Firebug.Inspector.onInspectingClick);
- },
- stopInspecting: function()
- {
- isInspecting = false;
- if (outlineVisible) this.hideOutline();
- removeEvent(fbInspectFrame, "mousemove", Firebug.Inspector.onInspecting);
- removeEvent(fbInspectFrame, "mousedown", Firebug.Inspector.onInspectingClick);
- destroyInspectorFrame();
- Firebug.chrome.inspectButton.restore();
- if (Firebug.chrome.type == "popup")
- Firebug.chrome.node.focus();
- },
- onInspectingClick: function(e)
- {
- fbInspectFrame.style.display = "none";
- var targ = Firebug.browser.getElementFromPoint(e.clientX, e.clientY);
- fbInspectFrame.style.display = "block";
- // Avoid inspecting the outline, and the FirebugUI
- var id = targ.id;
- if (id && /^fbOutline\w$/.test(id)) return;
- if (id == "FirebugUI") return;
- // Avoid looking at text nodes in Opera
- while (targ.nodeType != 1) targ = targ.parentNode;
- //Firebug.Console.log(targ);
- Firebug.Inspector.stopInspecting();
- },
- onInspecting: function(e)
- {
- if (new Date().getTime() - lastInspecting > 30)
- {
- fbInspectFrame.style.display = "none";
- var targ = Firebug.browser.getElementFromPoint(e.clientX, e.clientY);
- fbInspectFrame.style.display = "block";
- // Avoid inspecting the outline, and the FirebugUI
- var id = targ.id;
- if (id && /^fbOutline\w$/.test(id)) return;
- if (id == "FirebugUI") return;
- // Avoid looking at text nodes in Opera
- while (targ.nodeType != 1) targ = targ.parentNode;
- if (targ.nodeName.toLowerCase() == "body") return;
- //Firebug.Console.log(e.clientX, e.clientY, targ);
- Firebug.Inspector.drawOutline(targ);
- if (ElementCache(targ))
- {
- var target = ""+ElementCache.key(targ);
- var lazySelect = function()
- {
- inspectorTS = new Date().getTime();
- Firebug.HTML.selectTreeNode(""+ElementCache.key(targ))
- };
- if (inspectorTimer)
- {
- clearTimeout(inspectorTimer);
- inspectorTimer = null;
- }
- if (new Date().getTime() - inspectorTS > 200)
- setTimeout(lazySelect, 0)
- else
- inspectorTimer = setTimeout(lazySelect, 300);
- }
- lastInspecting = new Date().getTime();
- }
- },
- // TODO: xxxpedro remove this?
- onInspectingBody: function(e)
- {
- if (new Date().getTime() - lastInspecting > 30)
- {
- var targ = e.target;
- // Avoid inspecting the outline, and the FirebugUI
- var id = targ.id;
- if (id && /^fbOutline\w$/.test(id)) return;
- if (id == "FirebugUI") return;
- // Avoid looking at text nodes in Opera
- while (targ.nodeType != 1) targ = targ.parentNode;
- if (targ.nodeName.toLowerCase() == "body") return;
- //Firebug.Console.log(e.clientX, e.clientY, targ);
- Firebug.Inspector.drawOutline(targ);
- if (ElementCache.has(targ))
- FBL.Firebug.HTML.selectTreeNode(""+ElementCache.key(targ));
- lastInspecting = new Date().getTime();
- }
- },
- /**
- *
- * llttttttrr
- * llttttttrr
- * ll rr
- * ll rr
- * llbbbbbbrr
- * llbbbbbbrr
- */
- drawOutline: function(el)
- {
- var border = 2;
- var scrollbarSize = 17;
- var windowSize = Firebug.browser.getWindowSize();
- var scrollSize = Firebug.browser.getWindowScrollSize();
- var scrollPosition = Firebug.browser.getWindowScrollPosition();
- var box = Firebug.browser.getElementBox(el);
- var top = box.top;
- var left = box.left;
- var height = box.height;
- var width = box.width;
- var freeHorizontalSpace = scrollPosition.left + windowSize.width - left - width -
- (!isIE && scrollSize.height > windowSize.height ? // is *vertical* scrollbar visible
- scrollbarSize : 0);
- var freeVerticalSpace = scrollPosition.top + windowSize.height - top - height -
- (!isIE && scrollSize.width > windowSize.width ? // is *horizontal* scrollbar visible
- scrollbarSize : 0);
- var numVerticalBorders = freeVerticalSpace > 0 ? 2 : 1;
- var o = outlineElements;
- var style;
- style = o.fbOutlineT.style;
- style.top = top-border + "px";
- style.left = left + "px";
- style.height = border + "px"; // TODO: on initialize()
- style.width = width + "px";
- style = o.fbOutlineL.style;
- style.top = top-border + "px";
- style.left = left-border + "px";
- style.height = height+ numVerticalBorders*border + "px";
- style.width = border + "px"; // TODO: on initialize()
- style = o.fbOutlineB.style;
- if (freeVerticalSpace > 0)
- {
- style.top = top+height + "px";
- style.left = left + "px";
- style.width = width + "px";
- //style.height = border + "px"; // TODO: on initialize() or worst case?
- }
- else
- {
- style.top = -2*border + "px";
- style.left = -2*border + "px";
- style.width = border + "px";
- //style.height = border + "px";
- }
- style = o.fbOutlineR.style;
- if (freeHorizontalSpace > 0)
- {
- style.top = top-border + "px";
- style.left = left+width + "px";
- style.height = height + numVerticalBorders*border + "px";
- style.width = (freeHorizontalSpace < border ? freeHorizontalSpace : border) + "px";
- }
- else
- {
- style.top = -2*border + "px";
- style.left = -2*border + "px";
- style.height = border + "px";
- style.width = border + "px";
- }
- if (!outlineVisible) this.showOutline();
- },
- hideOutline: function()
- {
- if (!outlineVisible) return;
- for (var name in outline)
- offlineFragment.appendChild(outlineElements[name]);
- outlineVisible = false;
- },
- showOutline: function()
- {
- if (outlineVisible) return;
- if (boxModelVisible) this.hideBoxModel();
- for (var name in outline)
- Firebug.browser.document.getElementsByTagName("body")[0].appendChild(outlineElements[name]);
- outlineVisible = true;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Box Model
- drawBoxModel: function(el)
- {
- // avoid error when the element is not attached a document
- if (!el || !el.parentNode)
- return;
- var box = Firebug.browser.getElementBox(el);
- var windowSize = Firebug.browser.getWindowSize();
- var scrollPosition = Firebug.browser.getWindowScrollPosition();
- // element may be occluded by the chrome, when in frame mode
- var offsetHeight = Firebug.chrome.type == "frame" ? FirebugChrome.height : 0;
- // if element box is not inside the viewport, don't draw the box model
- if (box.top > scrollPosition.top + windowSize.height - offsetHeight ||
- box.left > scrollPosition.left + windowSize.width ||
- scrollPosition.top > box.top + box.height ||
- scrollPosition.left > box.left + box.width )
- return;
- var top = box.top;
- var left = box.left;
- var height = box.height;
- var width = box.width;
- var margin = Firebug.browser.getMeasurementBox(el, "margin");
- var padding = Firebug.browser.getMeasurementBox(el, "padding");
- var border = Firebug.browser.getMeasurementBox(el, "border");
- boxModelStyle.top = top - margin.top + "px";
- boxModelStyle.left = left - margin.left + "px";
- boxModelStyle.height = height + margin.top + margin.bottom + "px";
- boxModelStyle.width = width + margin.left + margin.right + "px";
- boxBorderStyle.top = margin.top + "px";
- boxBorderStyle.left = margin.left + "px";
- boxBorderStyle.height = height + "px";
- boxBorderStyle.width = width + "px";
- boxPaddingStyle.top = margin.top + border.top + "px";
- boxPaddingStyle.left = margin.left + border.left + "px";
- boxPaddingStyle.height = height - border.top - border.bottom + "px";
- boxPaddingStyle.width = width - border.left - border.right + "px";
- boxContentStyle.top = margin.top + border.top + padding.top + "px";
- boxContentStyle.left = margin.left + border.left + padding.left + "px";
- boxContentStyle.height = height - border.top - padding.top - padding.bottom - border.bottom + "px";
- boxContentStyle.width = width - border.left - padding.left - padding.right - border.right + "px";
- if (!boxModelVisible) this.showBoxModel();
- },
- hideBoxModel: function()
- {
- if (!boxModelVisible) return;
- offlineFragment.appendChild(boxModel);
- boxModelVisible = false;
- },
- showBoxModel: function()
- {
- if (boxModelVisible) return;
- if (outlineVisible) this.hideOutline();
- Firebug.browser.document.getElementsByTagName("body")[0].appendChild(boxModel);
- boxModelVisible = true;
- }
- };
- // ************************************************************************************************
- // Inspector Internals
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Shared variables
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Internal variables
- var offlineFragment = null;
- var boxModelVisible = false;
- var boxModel, boxModelStyle,
- boxMargin, boxMarginStyle,
- boxBorder, boxBorderStyle,
- boxPadding, boxPaddingStyle,
- boxContent, boxContentStyle;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var resetStyle = "margin:0; padding:0; border:0; position:absolute; overflow:hidden; display:block;";
- var offscreenStyle = resetStyle + "top:-1234px; left:-1234px;";
- var inspectStyle = resetStyle + "z-index: 2147483500;";
- var inspectFrameStyle = resetStyle + "z-index: 2147483550; top:0; left:0; background:url(" +
- Env.Location.skinDir + "pixel_transparent.gif);";
- //if (Env.Options.enableTrace) inspectFrameStyle = resetStyle + "z-index: 2147483550; top: 0; left: 0; background: #ff0; opacity: 0.05; _filter: alpha(opacity=5);";
- var inspectModelOpacity = isIE ? "filter:alpha(opacity=80);" : "opacity:0.8;";
- var inspectModelStyle = inspectStyle + inspectModelOpacity;
- var inspectMarginStyle = inspectStyle + "background: #EDFF64; height:100%; width:100%;";
- var inspectBorderStyle = inspectStyle + "background: #666;";
- var inspectPaddingStyle = inspectStyle + "background: SlateBlue;";
- var inspectContentStyle = inspectStyle + "background: SkyBlue;";
- var outlineStyle = {
- fbHorizontalLine: "background: #3875D7;height: 2px;",
- fbVerticalLine: "background: #3875D7;width: 2px;"
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var lastInspecting = 0;
- var fbInspectFrame = null;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var outlineVisible = false;
- var outlineElements = {};
- var outline = {
- "fbOutlineT": "fbHorizontalLine",
- "fbOutlineL": "fbVerticalLine",
- "fbOutlineB": "fbHorizontalLine",
- "fbOutlineR": "fbVerticalLine"
- };
- var getInspectingTarget = function()
- {
- };
- // ************************************************************************************************
- // Section
- var createInspectorFrame = function createInspectorFrame()
- {
- fbInspectFrame = createGlobalElement("div");
- fbInspectFrame.id = "fbInspectFrame";
- fbInspectFrame.firebugIgnore = true;
- fbInspectFrame.style.cssText = inspectFrameStyle;
- Firebug.browser.document.getElementsByTagName("body")[0].appendChild(fbInspectFrame);
- };
- var destroyInspectorFrame = function destroyInspectorFrame()
- {
- if (fbInspectFrame)
- {
- Firebug.browser.document.getElementsByTagName("body")[0].removeChild(fbInspectFrame);
- fbInspectFrame = null;
- }
- };
- var createOutlineInspector = function createOutlineInspector()
- {
- for (var name in outline)
- {
- var el = outlineElements[name] = createGlobalElement("div");
- el.id = name;
- el.firebugIgnore = true;
- el.style.cssText = inspectStyle + outlineStyle[outline[name]];
- offlineFragment.appendChild(el);
- }
- };
- var destroyOutlineInspector = function destroyOutlineInspector()
- {
- for (var name in outline)
- {
- var el = outlineElements[name];
- el.parentNode.removeChild(el);
- }
- };
- var createBoxModelInspector = function createBoxModelInspector()
- {
- boxModel = createGlobalElement("div");
- boxModel.id = "fbBoxModel";
- boxModel.firebugIgnore = true;
- boxModelStyle = boxModel.style;
- boxModelStyle.cssText = inspectModelStyle;
- boxMargin = createGlobalElement("div");
- boxMargin.id = "fbBoxMargin";
- boxMarginStyle = boxMargin.style;
- boxMarginStyle.cssText = inspectMarginStyle;
- boxModel.appendChild(boxMargin);
- boxBorder = createGlobalElement("div");
- boxBorder.id = "fbBoxBorder";
- boxBorderStyle = boxBorder.style;
- boxBorderStyle.cssText = inspectBorderStyle;
- boxModel.appendChild(boxBorder);
- boxPadding = createGlobalElement("div");
- boxPadding.id = "fbBoxPadding";
- boxPaddingStyle = boxPadding.style;
- boxPaddingStyle.cssText = inspectPaddingStyle;
- boxModel.appendChild(boxPadding);
- boxContent = createGlobalElement("div");
- boxContent.id = "fbBoxContent";
- boxContentStyle = boxContent.style;
- boxContentStyle.cssText = inspectContentStyle;
- boxModel.appendChild(boxContent);
- offlineFragment.appendChild(boxModel);
- };
- var destroyBoxModelInspector = function destroyBoxModelInspector()
- {
- boxModel.parentNode.removeChild(boxModel);
- };
- // ************************************************************************************************
- // Section
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- // next-generation Console Panel (will override consoje.js)
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Constants
- /*
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const nsIPrefBranch2 = Ci.nsIPrefBranch2;
- const PrefService = Cc["@mozilla.org/preferences-service;1"];
- const prefs = PrefService.getService(nsIPrefBranch2);
- /**/
- /*
- // new offline message handler
- o = {x:1,y:2};
- r = Firebug.getRep(o);
- r.tag.tag.compile();
- outputs = [];
- html = r.tag.renderHTML({object:o}, outputs);
- // finish rendering the template (the DOM part)
- target = $("build");
- target.innerHTML = html;
- root = target.firstChild;
- domArgs = [root, r.tag.context, 0];
- domArgs.push.apply(domArgs, r.tag.domArgs);
- domArgs.push.apply(domArgs, outputs);
- r.tag.tag.renderDOM.apply(self ? self : r.tag.subject, domArgs);
- */
- var consoleQueue = [];
- var lastHighlightedObject;
- var FirebugContext = Env.browser;
- // ************************************************************************************************
- var maxQueueRequests = 500;
- // ************************************************************************************************
- Firebug.ConsoleBase =
- {
- log: function(object, context, className, rep, noThrottle, sourceLink)
- {
- //dispatch(this.fbListeners,"log",[context, object, className, sourceLink]);
- return this.logRow(appendObject, object, context, className, rep, sourceLink, noThrottle);
- },
- logFormatted: function(objects, context, className, noThrottle, sourceLink)
- {
- //dispatch(this.fbListeners,"logFormatted",[context, objects, className, sourceLink]);
- return this.logRow(appendFormatted, objects, context, className, null, sourceLink, noThrottle);
- },
- openGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush)
- {
- return this.logRow(appendOpenGroup, objects, context, className, rep, sourceLink, noThrottle);
- },
- closeGroup: function(context, noThrottle)
- {
- return this.logRow(appendCloseGroup, null, context, null, null, null, noThrottle, true);
- },
- logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow)
- {
- // TODO: xxxpedro console console2
- noThrottle = true; // xxxpedro forced because there is no TabContext yet
- if (!context)
- context = FirebugContext;
- if (FBTrace.DBG_ERRORS && !context)
- FBTrace.sysout("Console.logRow has no context, skipping objects", objects);
- if (!context)
- return;
- if (noThrottle || !context)
- {
- var panel = this.getPanel(context);
- if (panel)
- {
- var row = panel.append(appender, objects, className, rep, sourceLink, noRow);
- var container = panel.panelNode;
- // TODO: xxxpedro what is this? console console2
- /*
- var template = Firebug.NetMonitor.NetLimit;
- while (container.childNodes.length > maxQueueRequests + 1)
- {
- clearDomplate(container.firstChild.nextSibling);
- container.removeChild(container.firstChild.nextSibling);
- panel.limit.limitInfo.totalCount++;
- template.updateCounter(panel.limit);
- }
- dispatch([Firebug.A11yModel], "onLogRowCreated", [panel , row]);
- /**/
- return row;
- }
- else
- {
- consoleQueue.push([appender, objects, context, className, rep, sourceLink, noThrottle, noRow]);
- }
- }
- else
- {
- if (!context.throttle)
- {
- //FBTrace.sysout("console.logRow has not context.throttle! ");
- return;
- }
- var args = [appender, objects, context, className, rep, sourceLink, true, noRow];
- context.throttle(this.logRow, this, args);
- }
- },
- appendFormatted: function(args, row, context)
- {
- if (!context)
- context = FirebugContext;
- var panel = this.getPanel(context);
- panel.appendFormatted(args, row);
- },
- clear: function(context)
- {
- if (!context)
- //context = FirebugContext;
- context = Firebug.context;
- /*
- if (context)
- Firebug.Errors.clear(context);
- /**/
- var panel = this.getPanel(context, true);
- if (panel)
- {
- panel.clear();
- }
- },
- // Override to direct output to your panel
- getPanel: function(context, noCreate)
- {
- //return context.getPanel("console", noCreate);
- // TODO: xxxpedro console console2
- return Firebug.chrome ? Firebug.chrome.getPanel("Console") : null;
- }
- };
- // ************************************************************************************************
- //TODO: xxxpedro
- //var ActivableConsole = extend(Firebug.ActivableModule, Firebug.ConsoleBase);
- var ActivableConsole = extend(Firebug.ConsoleBase,
- {
- isAlwaysEnabled: function()
- {
- return true;
- }
- });
- Firebug.Console = Firebug.Console = extend(ActivableConsole,
- //Firebug.Console = extend(ActivableConsole,
- {
- dispatchName: "console",
- error: function()
- {
- Firebug.Console.logFormatted(arguments, Firebug.browser, "error");
- },
- flush: function()
- {
- dispatch(this.fbListeners,"flush",[]);
- for (var i=0, length=consoleQueue.length; i<length; i++)
- {
- var args = consoleQueue[i];
- this.logRow.apply(this, args);
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Module
- showPanel: function(browser, panel)
- {
- },
- getFirebugConsoleElement: function(context, win)
- {
- var element = win.document.getElementById("_firebugConsole");
- if (!element)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("getFirebugConsoleElement forcing element");
- var elementForcer = "(function(){var r=null; try { r = window._getFirebugConsoleElement();}catch(exc){r=exc;} return r;})();"; // we could just add the elements here
- if (context.stopped)
- Firebug.Console.injector.evaluateConsoleScript(context); // todo evaluate consoleForcer on stack
- else
- var r = Firebug.CommandLine.evaluateInWebPage(elementForcer, context, win);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("getFirebugConsoleElement forcing element result "+r, r);
- var element = win.document.getElementById("_firebugConsole");
- if (!element) // elementForce fails
- {
- if (FBTrace.DBG_ERRORS) FBTrace.sysout("console.getFirebugConsoleElement: no _firebugConsole in win:", win);
- Firebug.Console.logFormatted(["Firebug cannot find _firebugConsole element", r, win], context, "error", true);
- }
- }
- return element;
- },
- isReadyElsePreparing: function(context, win) // this is the only code that should call injector.attachIfNeeded
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.isReadyElsePreparing, win is " +
- (win?"an argument: ":"null, context.window: ") +
- (win?win.location:context.window.location), (win?win:context.window));
- if (win)
- return this.injector.attachIfNeeded(context, win);
- else
- {
- var attached = true;
- for (var i = 0; i < context.windows.length; i++)
- attached = attached && this.injector.attachIfNeeded(context, context.windows[i]);
- // already in the list above attached = attached && this.injector.attachIfNeeded(context, context.window);
- if (context.windows.indexOf(context.window) == -1)
- FBTrace.sysout("isReadyElsePreparing ***************** context.window not in context.windows");
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.isReadyElsePreparing attached to "+context.windows.length+" and returns "+attached);
- return attached;
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends ActivableModule
- initialize: function()
- {
- this.panelName = "console";
- //TODO: xxxpedro
- //Firebug.ActivableModule.initialize.apply(this, arguments);
- //Firebug.Debugger.addListener(this);
- },
- enable: function()
- {
- if (Firebug.Console.isAlwaysEnabled())
- this.watchForErrors();
- },
- disable: function()
- {
- if (Firebug.Console.isAlwaysEnabled())
- this.unwatchForErrors();
- },
- initContext: function(context, persistedState)
- {
- Firebug.ActivableModule.initContext.apply(this, arguments);
- context.consoleReloadWarning = true; // mark as need to warn.
- },
- loadedContext: function(context)
- {
- for (var url in context.sourceFileMap)
- return; // if there are any sourceFiles, then do nothing
- // else we saw no JS, so the reload warning it not needed.
- this.clearReloadWarning(context);
- },
- clearReloadWarning: function(context) // remove the warning about reloading.
- {
- if (context.consoleReloadWarning)
- {
- var panel = context.getPanel(this.panelName);
- panel.clearReloadWarning();
- delete context.consoleReloadWarning;
- }
- },
- togglePersist: function(context)
- {
- var panel = context.getPanel(this.panelName);
- panel.persistContent = panel.persistContent ? false : true;
- Firebug.chrome.setGlobalAttribute("cmd_togglePersistConsole", "checked", panel.persistContent);
- },
- showContext: function(browser, context)
- {
- Firebug.chrome.setGlobalAttribute("cmd_clearConsole", "disabled", !context);
- Firebug.ActivableModule.showContext.apply(this, arguments);
- },
- destroyContext: function(context, persistedState)
- {
- Firebug.Console.injector.detachConsole(context, context.window); // TODO iterate windows?
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onPanelEnable: function(panelName)
- {
- if (panelName != this.panelName) // we don't care about other panels
- return;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.onPanelEnable**************");
- this.watchForErrors();
- Firebug.Debugger.addDependentModule(this); // we inject the console during JS compiles so we need jsd
- },
- onPanelDisable: function(panelName)
- {
- if (panelName != this.panelName) // we don't care about other panels
- return;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.onPanelDisable**************");
- Firebug.Debugger.removeDependentModule(this); // we inject the console during JS compiles so we need jsd
- this.unwatchForErrors();
- // Make sure possible errors coming from the page and displayed in the Firefox
- // status bar are removed.
- this.clear();
- },
- onSuspendFirebug: function()
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.onSuspendFirebug\n");
- if (Firebug.Console.isAlwaysEnabled())
- this.unwatchForErrors();
- },
- onResumeFirebug: function()
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.onResumeFirebug\n");
- if (Firebug.Console.isAlwaysEnabled())
- this.watchForErrors();
- },
- watchForErrors: function()
- {
- Firebug.Errors.checkEnabled();
- $('fbStatusIcon').setAttribute("console", "on");
- },
- unwatchForErrors: function()
- {
- Firebug.Errors.checkEnabled();
- $('fbStatusIcon').removeAttribute("console");
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Firebug.Debugger listener
- onMonitorScript: function(context, frame)
- {
- Firebug.Console.log(frame, context);
- },
- onFunctionCall: function(context, frame, depth, calling)
- {
- if (calling)
- Firebug.Console.openGroup([frame, "depth:"+depth], context);
- else
- Firebug.Console.closeGroup(context);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow)
- {
- if (!context)
- context = FirebugContext;
- if (FBTrace.DBG_WINDOWS && !context) FBTrace.sysout("Console.logRow: no context \n");
- if (this.isAlwaysEnabled())
- return Firebug.ConsoleBase.logRow.apply(this, arguments);
- }
- });
- Firebug.ConsoleListener =
- {
- log: function(context, object, className, sourceLink)
- {
- },
- logFormatted: function(context, objects, className, sourceLink)
- {
- }
- };
- // ************************************************************************************************
- Firebug.ConsolePanel = function () {} // XXjjb attach Firebug so this panel can be extended.
- //TODO: xxxpedro
- //Firebug.ConsolePanel.prototype = extend(Firebug.ActivablePanel,
- Firebug.ConsolePanel.prototype = extend(Firebug.Panel,
- {
- wasScrolledToBottom: false,
- messageCount: 0,
- lastLogTime: 0,
- groups: null,
- limit: null,
- append: function(appender, objects, className, rep, sourceLink, noRow)
- {
- var container = this.getTopContainer();
- if (noRow)
- {
- appender.apply(this, [objects]);
- }
- else
- {
- // xxxHonza: Don't update the this.wasScrolledToBottom flag now.
- // At the beginning (when the first log is created) the isScrolledToBottom
- // always returns true.
- //if (this.panelNode.offsetHeight)
- // this.wasScrolledToBottom = isScrolledToBottom(this.panelNode);
- var row = this.createRow("logRow", className);
- appender.apply(this, [objects, row, rep]);
- if (sourceLink)
- FirebugReps.SourceLink.tag.append({object: sourceLink}, row);
- container.appendChild(row);
- this.filterLogRow(row, this.wasScrolledToBottom);
- if (this.wasScrolledToBottom)
- scrollToBottom(this.panelNode);
- return row;
- }
- },
- clear: function()
- {
- if (this.panelNode)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("ConsolePanel.clear");
- clearNode(this.panelNode);
- this.insertLogLimit(this.context);
- }
- },
- insertLogLimit: function()
- {
- // Create limit row. This row is the first in the list of entries
- // and initially hidden. It's displayed as soon as the number of
- // entries reaches the limit.
- var row = this.createRow("limitRow");
- var limitInfo = {
- totalCount: 0,
- limitPrefsTitle: $STRF("LimitPrefsTitle", [Firebug.prefDomain+".console.logLimit"])
- };
- //TODO: xxxpedro console net limit!?
- return;
- var netLimitRep = Firebug.NetMonitor.NetLimit;
- var nodes = netLimitRep.createTable(row, limitInfo);
- this.limit = nodes[1];
- var container = this.panelNode;
- container.insertBefore(nodes[0], container.firstChild);
- },
- insertReloadWarning: function()
- {
- // put the message in, we will clear if the window console is injected.
- this.warningRow = this.append(appendObject, $STR("message.Reload to activate window console"), "info");
- },
- clearReloadWarning: function()
- {
- if (this.warningRow)
- {
- this.warningRow.parentNode.removeChild(this.warningRow);
- delete this.warningRow;
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- appendObject: function(object, row, rep)
- {
- if (!rep)
- rep = Firebug.getRep(object);
- return rep.tag.append({object: object}, row);
- },
- appendFormatted: function(objects, row, rep)
- {
- if (!objects || !objects.length)
- return;
- function logText(text, row)
- {
- var node = row.ownerDocument.createTextNode(text);
- row.appendChild(node);
- }
- var format = objects[0];
- var objIndex = 0;
- if (typeof(format) != "string")
- {
- format = "";
- objIndex = -1;
- }
- else // a string
- {
- if (objects.length === 1) // then we have only a string...
- {
- if (format.length < 1) { // ...and it has no characters.
- logText("(an empty string)", row);
- return;
- }
- }
- }
- var parts = parseFormat(format);
- var trialIndex = objIndex;
- for (var i= 0; i < parts.length; i++)
- {
- var part = parts[i];
- if (part && typeof(part) == "object")
- {
- if (++trialIndex > objects.length) // then too few parameters for format, assume unformatted.
- {
- format = "";
- objIndex = -1;
- parts.length = 0;
- break;
- }
- }
- }
- for (var i = 0; i < parts.length; ++i)
- {
- var part = parts[i];
- if (part && typeof(part) == "object")
- {
- var object = objects[++objIndex];
- if (typeof(object) != "undefined")
- this.appendObject(object, row, part.rep);
- else
- this.appendObject(part.type, row, FirebugReps.Text);
- }
- else
- FirebugReps.Text.tag.append({object: part}, row);
- }
- for (var i = objIndex+1; i < objects.length; ++i)
- {
- logText(" ", row);
- var object = objects[i];
- if (typeof(object) == "string")
- FirebugReps.Text.tag.append({object: object}, row);
- else
- this.appendObject(object, row);
- }
- },
- appendOpenGroup: function(objects, row, rep)
- {
- if (!this.groups)
- this.groups = [];
- setClass(row, "logGroup");
- setClass(row, "opened");
- var innerRow = this.createRow("logRow");
- setClass(innerRow, "logGroupLabel");
- if (rep)
- rep.tag.replace({"objects": objects}, innerRow);
- else
- this.appendFormatted(objects, innerRow, rep);
- row.appendChild(innerRow);
- //dispatch([Firebug.A11yModel], 'onLogRowCreated', [this, innerRow]);
- var groupBody = this.createRow("logGroupBody");
- row.appendChild(groupBody);
- groupBody.setAttribute('role', 'group');
- this.groups.push(groupBody);
- addEvent(innerRow, "mousedown", function(event)
- {
- if (isLeftClick(event))
- {
- //console.log(event.currentTarget == event.target);
- var target = event.target || event.srcElement;
- target = getAncestorByClass(target, "logGroupLabel");
- var groupRow = target.parentNode;
- if (hasClass(groupRow, "opened"))
- {
- removeClass(groupRow, "opened");
- target.setAttribute('aria-expanded', 'false');
- }
- else
- {
- setClass(groupRow, "opened");
- target.setAttribute('aria-expanded', 'true');
- }
- }
- });
- },
- appendCloseGroup: function(object, row, rep)
- {
- if (this.groups)
- this.groups.pop();
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // TODO: xxxpedro console2
- onMouseMove: function(event)
- {
- var target = event.srcElement || event.target;
- var object = getAncestorByClass(target, "objectLink-element");
- object = object ? object.repObject : null;
- if(object && instanceOf(object, "Element") && object.nodeType == 1)
- {
- if(object != lastHighlightedObject)
- {
- Firebug.Inspector.drawBoxModel(object);
- object = lastHighlightedObject;
- }
- }
- else
- Firebug.Inspector.hideBoxModel();
- },
- onMouseDown: function(event)
- {
- var target = event.srcElement || event.target;
- var object = getAncestorByClass(target, "objectLink");
- var repObject = object ? object.repObject : null;
- if (!repObject)
- {
- return;
- }
- if (hasClass(object, "objectLink-object"))
- {
- Firebug.chrome.selectPanel("DOM");
- Firebug.chrome.getPanel("DOM").select(repObject, true);
- }
- else if (hasClass(object, "objectLink-element"))
- {
- Firebug.chrome.selectPanel("HTML");
- Firebug.chrome.getPanel("HTML").select(repObject, true);
- }
- /*
- if(object && instanceOf(object, "Element") && object.nodeType == 1)
- {
- if(object != lastHighlightedObject)
- {
- Firebug.Inspector.drawBoxModel(object);
- object = lastHighlightedObject;
- }
- }
- else
- Firebug.Inspector.hideBoxModel();
- /**/
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- name: "Console",
- title: "Console",
- //searchable: true,
- //breakable: true,
- //editable: false,
- options:
- {
- hasCommandLine: true,
- hasToolButtons: true,
- isPreRendered: true
- },
- create: function()
- {
- Firebug.Panel.create.apply(this, arguments);
- this.context = Firebug.browser.window;
- this.document = Firebug.chrome.document;
- this.onMouseMove = bind(this.onMouseMove, this);
- this.onMouseDown = bind(this.onMouseDown, this);
- this.clearButton = new Button({
- element: $("fbConsole_btClear"),
- owner: Firebug.Console,
- onClick: Firebug.Console.clear
- });
- },
- initialize: function()
- {
- Firebug.Panel.initialize.apply(this, arguments); // loads persisted content
- //Firebug.ActivablePanel.initialize.apply(this, arguments); // loads persisted content
- if (!this.persistedContent && Firebug.Console.isAlwaysEnabled())
- {
- this.insertLogLimit(this.context);
- // Initialize log limit and listen for changes.
- this.updateMaxLimit();
- if (this.context.consoleReloadWarning) // we have not yet injected the console
- this.insertReloadWarning();
- }
- //Firebug.Console.injector.install(Firebug.browser.window);
- addEvent(this.panelNode, "mouseover", this.onMouseMove);
- addEvent(this.panelNode, "mousedown", this.onMouseDown);
- this.clearButton.initialize();
- //consolex.trace();
- //TODO: xxxpedro remove this
- /*
- Firebug.Console.openGroup(["asd"], null, "group", null, false);
- Firebug.Console.log("asd");
- Firebug.Console.log("asd");
- Firebug.Console.log("asd");
- /**/
- //TODO: xxxpedro preferences prefs
- //prefs.addObserver(Firebug.prefDomain, this, false);
- },
- initializeNode : function()
- {
- //dispatch([Firebug.A11yModel], 'onInitializeNode', [this]);
- if (FBTrace.DBG_CONSOLE)
- {
- this.onScroller = bind(this.onScroll, this);
- addEvent(this.panelNode, "scroll", this.onScroller);
- }
- this.onResizer = bind(this.onResize, this);
- this.resizeEventTarget = Firebug.chrome.$('fbContentBox');
- addEvent(this.resizeEventTarget, "resize", this.onResizer);
- },
- destroyNode : function()
- {
- //dispatch([Firebug.A11yModel], 'onDestroyNode', [this]);
- if (this.onScroller)
- removeEvent(this.panelNode, "scroll", this.onScroller);
- //removeEvent(this.resizeEventTarget, "resize", this.onResizer);
- },
- shutdown: function()
- {
- //TODO: xxxpedro console console2
- this.clearButton.shutdown();
- removeEvent(this.panelNode, "mousemove", this.onMouseMove);
- removeEvent(this.panelNode, "mousedown", this.onMouseDown);
- this.destroyNode();
- Firebug.Panel.shutdown.apply(this, arguments);
- //TODO: xxxpedro preferences prefs
- //prefs.removeObserver(Firebug.prefDomain, this, false);
- },
- ishow: function(state)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("Console.panel show; " + this.context.getName(), state);
- var enabled = Firebug.Console.isAlwaysEnabled();
- if (enabled)
- {
- Firebug.Console.disabledPanelPage.hide(this);
- this.showCommandLine(true);
- this.showToolbarButtons("fbConsoleButtons", true);
- Firebug.chrome.setGlobalAttribute("cmd_togglePersistConsole", "checked", this.persistContent);
- if (state && state.wasScrolledToBottom)
- {
- this.wasScrolledToBottom = state.wasScrolledToBottom;
- delete state.wasScrolledToBottom;
- }
- if (this.wasScrolledToBottom)
- scrollToBottom(this.panelNode);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.show ------------------ wasScrolledToBottom: " +
- this.wasScrolledToBottom + ", " + this.context.getName());
- }
- else
- {
- this.hide(state);
- Firebug.Console.disabledPanelPage.show(this);
- }
- },
- ihide: function(state)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("Console.panel hide; " + this.context.getName(), state);
- this.showToolbarButtons("fbConsoleButtons", false);
- this.showCommandLine(false);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.hide ------------------ wasScrolledToBottom: " +
- this.wasScrolledToBottom + ", " + this.context.getName());
- },
- destroy: function(state)
- {
- if (this.panelNode.offsetHeight)
- this.wasScrolledToBottom = isScrolledToBottom(this.panelNode);
- if (state)
- state.wasScrolledToBottom = this.wasScrolledToBottom;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.destroy ------------------ wasScrolledToBottom: " +
- this.wasScrolledToBottom + ", " + this.context.getName());
- },
- shouldBreakOnNext: function()
- {
- // xxxHonza: shouldn't the breakOnErrors be context related?
- // xxxJJB, yes, but we can't support it because we can't yet tell
- // which window the error is on.
- return Firebug.getPref(Firebug.servicePrefDomain, "breakOnErrors");
- },
- getBreakOnNextTooltip: function(enabled)
- {
- return (enabled ? $STR("console.Disable Break On All Errors") :
- $STR("console.Break On All Errors"));
- },
- enablePanel: function(module)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.ConsolePanel.enablePanel; " + this.context.getName());
- Firebug.ActivablePanel.enablePanel.apply(this, arguments);
- this.showCommandLine(true);
- if (this.wasScrolledToBottom)
- scrollToBottom(this.panelNode);
- },
- disablePanel: function(module)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.ConsolePanel.disablePanel; " + this.context.getName());
- Firebug.ActivablePanel.disablePanel.apply(this, arguments);
- this.showCommandLine(false);
- },
- getOptionsMenuItems: function()
- {
- return [
- optionMenu("ShowJavaScriptErrors", "showJSErrors"),
- optionMenu("ShowJavaScriptWarnings", "showJSWarnings"),
- optionMenu("ShowCSSErrors", "showCSSErrors"),
- optionMenu("ShowXMLErrors", "showXMLErrors"),
- optionMenu("ShowXMLHttpRequests", "showXMLHttpRequests"),
- optionMenu("ShowChromeErrors", "showChromeErrors"),
- optionMenu("ShowChromeMessages", "showChromeMessages"),
- optionMenu("ShowExternalErrors", "showExternalErrors"),
- optionMenu("ShowNetworkErrors", "showNetworkErrors"),
- this.getShowStackTraceMenuItem(),
- this.getStrictOptionMenuItem(),
- "-",
- optionMenu("LargeCommandLine", "largeCommandLine")
- ];
- },
- getShowStackTraceMenuItem: function()
- {
- var menuItem = serviceOptionMenu("ShowStackTrace", "showStackTrace");
- if (FirebugContext && !Firebug.Debugger.isAlwaysEnabled())
- menuItem.disabled = true;
- return menuItem;
- },
- getStrictOptionMenuItem: function()
- {
- var strictDomain = "javascript.options";
- var strictName = "strict";
- var strictValue = prefs.getBoolPref(strictDomain+"."+strictName);
- return {label: "JavascriptOptionsStrict", type: "checkbox", checked: strictValue,
- command: bindFixed(Firebug.setPref, Firebug, strictDomain, strictName, !strictValue) };
- },
- getBreakOnMenuItems: function()
- {
- //xxxHonza: no BON options for now.
- /*return [
- optionMenu("console.option.Persist Break On Error", "persistBreakOnError")
- ];*/
- return [];
- },
- search: function(text)
- {
- if (!text)
- return;
- // Make previously visible nodes invisible again
- if (this.matchSet)
- {
- for (var i in this.matchSet)
- removeClass(this.matchSet[i], "matched");
- }
- this.matchSet = [];
- function findRow(node) { return getAncestorByClass(node, "logRow"); }
- var search = new TextSearch(this.panelNode, findRow);
- var logRow = search.find(text);
- if (!logRow)
- {
- dispatch([Firebug.A11yModel], 'onConsoleSearchMatchFound', [this, text, []]);
- return false;
- }
- for (; logRow; logRow = search.findNext())
- {
- setClass(logRow, "matched");
- this.matchSet.push(logRow);
- }
- dispatch([Firebug.A11yModel], 'onConsoleSearchMatchFound', [this, text, this.matchSet]);
- return true;
- },
- breakOnNext: function(breaking)
- {
- Firebug.setPref(Firebug.servicePrefDomain, "breakOnErrors", breaking);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // private
- createRow: function(rowName, className)
- {
- var elt = this.document.createElement("div");
- elt.className = rowName + (className ? " " + rowName + "-" + className : "");
- return elt;
- },
- getTopContainer: function()
- {
- if (this.groups && this.groups.length)
- return this.groups[this.groups.length-1];
- else
- return this.panelNode;
- },
- filterLogRow: function(logRow, scrolledToBottom)
- {
- if (this.searchText)
- {
- setClass(logRow, "matching");
- setClass(logRow, "matched");
- // Search after a delay because we must wait for a frame to be created for
- // the new logRow so that the finder will be able to locate it
- setTimeout(bindFixed(function()
- {
- if (this.searchFilter(this.searchText, logRow))
- this.matchSet.push(logRow);
- else
- removeClass(logRow, "matched");
- removeClass(logRow, "matching");
- if (scrolledToBottom)
- scrollToBottom(this.panelNode);
- }, this), 100);
- }
- },
- searchFilter: function(text, logRow)
- {
- var count = this.panelNode.childNodes.length;
- var searchRange = this.document.createRange();
- searchRange.setStart(this.panelNode, 0);
- searchRange.setEnd(this.panelNode, count);
- var startPt = this.document.createRange();
- startPt.setStartBefore(logRow);
- var endPt = this.document.createRange();
- endPt.setStartAfter(logRow);
- return finder.Find(text, searchRange, startPt, endPt) != null;
- },
- // nsIPrefObserver
- observe: function(subject, topic, data)
- {
- // We're observing preferences only.
- if (topic != "nsPref:changed")
- return;
- // xxxHonza check this out.
- var prefDomain = "Firebug.extension.";
- var prefName = data.substr(prefDomain.length);
- if (prefName == "console.logLimit")
- this.updateMaxLimit();
- },
- updateMaxLimit: function()
- {
- var value = 1000;
- //TODO: xxxpedro preferences log limit?
- //var value = Firebug.getPref(Firebug.prefDomain, "console.logLimit");
- maxQueueRequests = value ? value : maxQueueRequests;
- },
- showCommandLine: function(shouldShow)
- {
- //TODO: xxxpedro show command line important
- return;
- if (shouldShow)
- {
- collapse(Firebug.chrome.$("fbCommandBox"), false);
- Firebug.CommandLine.setMultiLine(Firebug.largeCommandLine, Firebug.chrome);
- }
- else
- {
- // Make sure that entire content of the Console panel is hidden when
- // the panel is disabled.
- Firebug.CommandLine.setMultiLine(false, Firebug.chrome, Firebug.largeCommandLine);
- collapse(Firebug.chrome.$("fbCommandBox"), true);
- }
- },
- onScroll: function(event)
- {
- // Update the scroll position flag if the position changes.
- this.wasScrolledToBottom = FBL.isScrolledToBottom(this.panelNode);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.onScroll ------------------ wasScrolledToBottom: " +
- this.wasScrolledToBottom + ", wasScrolledToBottom: " +
- this.context.getName(), event);
- },
- onResize: function(event)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("console.onResize ------------------ wasScrolledToBottom: " +
- this.wasScrolledToBottom + ", offsetHeight: " + this.panelNode.offsetHeight +
- ", scrollTop: " + this.panelNode.scrollTop + ", scrollHeight: " +
- this.panelNode.scrollHeight + ", " + this.context.getName(), event);
- if (this.wasScrolledToBottom)
- scrollToBottom(this.panelNode);
- }
- });
- // ************************************************************************************************
- function parseFormat(format)
- {
- var parts = [];
- if (format.length <= 0)
- return parts;
- var reg = /((^%|.%)(\d+)?(\.)([a-zA-Z]))|((^%|.%)([a-zA-Z]))/;
- for (var m = reg.exec(format); m; m = reg.exec(format))
- {
- if (m[0].substr(0, 2) == "%%")
- {
- parts.push(format.substr(0, m.index));
- parts.push(m[0].substr(1));
- }
- else
- {
- var type = m[8] ? m[8] : m[5];
- var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
- var rep = null;
- switch (type)
- {
- case "s":
- rep = FirebugReps.Text;
- break;
- case "f":
- case "i":
- case "d":
- rep = FirebugReps.Number;
- break;
- case "o":
- rep = null;
- break;
- }
- parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
- parts.push({rep: rep, precision: precision, type: ("%" + type)});
- }
- format = format.substr(m.index+m[0].length);
- }
- parts.push(format);
- return parts;
- }
- // ************************************************************************************************
- var appendObject = Firebug.ConsolePanel.prototype.appendObject;
- var appendFormatted = Firebug.ConsolePanel.prototype.appendFormatted;
- var appendOpenGroup = Firebug.ConsolePanel.prototype.appendOpenGroup;
- var appendCloseGroup = Firebug.ConsolePanel.prototype.appendCloseGroup;
- // ************************************************************************************************
- //Firebug.registerActivableModule(Firebug.Console);
- Firebug.registerModule(Firebug.Console);
- Firebug.registerPanel(Firebug.ConsolePanel);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // Constants
- //const Cc = Components.classes;
- //const Ci = Components.interfaces;
- var frameCounters = {};
- var traceRecursion = 0;
- Firebug.Console.injector =
- {
- install: function(context)
- {
- var win = context.window;
- var consoleHandler = new FirebugConsoleHandler(context, win);
- var properties =
- [
- "log",
- "debug",
- "info",
- "warn",
- "error",
- "assert",
- "dir",
- "dirxml",
- "group",
- "groupCollapsed",
- "groupEnd",
- "time",
- "timeEnd",
- "count",
- "trace",
- "profile",
- "profileEnd",
- "clear",
- "open",
- "close"
- ];
- var Handler = function(name)
- {
- var c = consoleHandler;
- var f = consoleHandler[name];
- return function(){return f.apply(c,arguments)};
- };
- var installer = function(c)
- {
- for (var i=0, l=properties.length; i<l; i++)
- {
- var name = properties[i];
- c[name] = new Handler(name);
- c.firebuglite = Firebug.version;
- }
- };
- var consoleNS = (!isFirefox || isFirefox && !("console" in win)) ? "console" : "firebug";
- var sandbox = new win.Function("arguments.callee.install(window." + consoleNS + "={})");
- sandbox.install = installer;
- sandbox();
- },
- isAttached: function(context, win)
- {
- if (win.wrappedJSObject)
- {
- var attached = (win.wrappedJSObject._getFirebugConsoleElement ? true : false);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("Console.isAttached:"+attached+" to win.wrappedJSObject "+safeGetWindowLocation(win.wrappedJSObject));
- return attached;
- }
- else
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("Console.isAttached? to win "+win.location+" fnc:"+win._getFirebugConsoleElement);
- return (win._getFirebugConsoleElement ? true : false);
- }
- },
- attachIfNeeded: function(context, win)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("Console.attachIfNeeded has win "+(win? ((win.wrappedJSObject?"YES":"NO")+" wrappedJSObject"):"null") );
- if (this.isAttached(context, win))
- return true;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("Console.attachIfNeeded found isAttached false ");
- this.attachConsoleInjector(context, win);
- this.addConsoleListener(context, win);
- Firebug.Console.clearReloadWarning(context);
- var attached = this.isAttached(context, win);
- if (attached)
- dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]);
- return attached;
- },
- attachConsoleInjector: function(context, win)
- {
- var consoleInjection = this.getConsoleInjectionScript(); // Do it all here.
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("attachConsoleInjector evaluating in "+win.location, consoleInjection);
- Firebug.CommandLine.evaluateInWebPage(consoleInjection, context, win);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("attachConsoleInjector evaluation completed for "+win.location);
- },
- getConsoleInjectionScript: function() {
- if (!this.consoleInjectionScript)
- {
- var script = "";
- script += "window.__defineGetter__('console', function() {\n";
- script += " return (window._firebug ? window._firebug : window.loadFirebugConsole()); })\n\n";
- script += "window.loadFirebugConsole = function() {\n";
- script += "window._firebug = new _FirebugConsole();";
- if (FBTrace.DBG_CONSOLE)
- script += " window.dump('loadFirebugConsole '+window.location+'\\n');\n";
- script += " return window._firebug };\n";
- var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js");
- script += theFirebugConsoleScript;
- this.consoleInjectionScript = script;
- }
- return this.consoleInjectionScript;
- },
- forceConsoleCompilationInPage: function(context, win)
- {
- if (!win)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("no win in forceConsoleCompilationInPage!");
- return;
- }
- var consoleForcer = "window.loadFirebugConsole();";
- if (context.stopped)
- Firebug.Console.injector.evaluateConsoleScript(context); // todo evaluate consoleForcer on stack
- else
- Firebug.CommandLine.evaluateInWebPage(consoleForcer, context, win);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("forceConsoleCompilationInPage "+win.location, consoleForcer);
- },
- evaluateConsoleScript: function(context)
- {
- var scriptSource = this.getConsoleInjectionScript(); // TODO XXXjjb this should be getConsoleInjectionScript
- Firebug.Debugger.evaluate(scriptSource, context);
- },
- addConsoleListener: function(context, win)
- {
- if (!context.activeConsoleHandlers) // then we have not been this way before
- context.activeConsoleHandlers = [];
- else
- { // we've been this way before...
- for (var i=0; i<context.activeConsoleHandlers.length; i++)
- {
- if (context.activeConsoleHandlers[i].window == win)
- {
- context.activeConsoleHandlers[i].detach();
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("consoleInjector addConsoleListener removed handler("+context.activeConsoleHandlers[i].handler_name+") from _firebugConsole in : "+win.location+"\n");
- context.activeConsoleHandlers.splice(i,1);
- }
- }
- }
- // We need the element to attach our event listener.
- var element = Firebug.Console.getFirebugConsoleElement(context, win);
- if (element)
- element.setAttribute("FirebugVersion", Firebug.version); // Initialize Firebug version.
- else
- return false;
- var handler = new FirebugConsoleHandler(context, win);
- handler.attachTo(element);
- context.activeConsoleHandlers.push(handler);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("consoleInjector addConsoleListener attached handler("+handler.handler_name+") to _firebugConsole in : "+win.location+"\n");
- return true;
- },
- detachConsole: function(context, win)
- {
- if (win && win.document)
- {
- var element = win.document.getElementById("_firebugConsole");
- if (element)
- element.parentNode.removeChild(element);
- }
- }
- }
- var total_handlers = 0;
- var FirebugConsoleHandler = function FirebugConsoleHandler(context, win)
- {
- this.window = win;
- this.attachTo = function(element)
- {
- this.element = element;
- // When raised on our injected element, callback to Firebug and append to console
- this.boundHandler = bind(this.handleEvent, this);
- this.element.addEventListener('firebugAppendConsole', this.boundHandler, true); // capturing
- };
- this.detach = function()
- {
- this.element.removeEventListener('firebugAppendConsole', this.boundHandler, true);
- };
- this.handler_name = ++total_handlers;
- this.handleEvent = function(event)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("FirebugConsoleHandler("+this.handler_name+") "+event.target.getAttribute("methodName")+", event", event);
- if (!Firebug.CommandLine.CommandHandler.handle(event, this, win))
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("FirebugConsoleHandler", this);
- var methodName = event.target.getAttribute("methodName");
- Firebug.Console.log($STRF("console.MethodNotSupported", [methodName]));
- }
- };
- this.firebuglite = Firebug.version;
- this.init = function()
- {
- var consoleElement = win.document.getElementById('_firebugConsole');
- consoleElement.setAttribute("FirebugVersion", Firebug.version);
- };
- this.log = function()
- {
- logFormatted(arguments, "log");
- };
- this.debug = function()
- {
- logFormatted(arguments, "debug", true);
- };
- this.info = function()
- {
- logFormatted(arguments, "info", true);
- };
- this.warn = function()
- {
- logFormatted(arguments, "warn", true);
- };
- this.error = function()
- {
- //TODO: xxxpedro console error
- //if (arguments.length == 1)
- //{
- // logAssert("error", arguments); // add more info based on stack trace
- //}
- //else
- //{
- //Firebug.Errors.increaseCount(context);
- logFormatted(arguments, "error", true); // user already added info
- //}
- };
- this.exception = function()
- {
- logAssert("error", arguments);
- };
- this.assert = function(x)
- {
- if (!x)
- {
- var rest = [];
- for (var i = 1; i < arguments.length; i++)
- rest.push(arguments[i]);
- logAssert("assert", rest);
- }
- };
- this.dir = function(o)
- {
- Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
- };
- this.dirxml = function(o)
- {
- ///if (o instanceof Window)
- if (instanceOf(o, "Window"))
- o = o.document.documentElement;
- ///else if (o instanceof Document)
- else if (instanceOf(o, "Document"))
- o = o.documentElement;
- // TODO: xxxpedro html3
- ///Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement);
- var div = Firebug.Console.log(o, context, "dirxml");
- var html = [];
- Firebug.Reps.appendNode(o, html);
- div.innerHTML = html.join("");
- };
- this.group = function()
- {
- //TODO: xxxpedro;
- //var sourceLink = getStackLink();
- var sourceLink = null;
- Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink);
- };
- this.groupEnd = function()
- {
- Firebug.Console.closeGroup(context);
- };
- this.groupCollapsed = function()
- {
- var sourceLink = getStackLink();
- // noThrottle true is probably ok, openGroups will likely be short strings.
- var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink);
- removeClass(row, "opened");
- };
- this.profile = function(title)
- {
- logFormatted(["console.profile() not supported."], "warn", true);
- //Firebug.Profiler.startProfiling(context, title);
- };
- this.profileEnd = function()
- {
- logFormatted(["console.profile() not supported."], "warn", true);
- //Firebug.Profiler.stopProfiling(context);
- };
- this.count = function(key)
- {
- // TODO: xxxpedro console2: is there a better way to find a unique ID for the coun() call?
- var frameId = "0";
- //var frameId = FBL.getStackFrameId();
- if (frameId)
- {
- if (!frameCounters)
- frameCounters = {};
- if (key != undefined)
- frameId += key;
- var frameCounter = frameCounters[frameId];
- if (!frameCounter)
- {
- var logRow = logFormatted(["0"], null, true, true);
- frameCounter = {logRow: logRow, count: 1};
- frameCounters[frameId] = frameCounter;
- }
- else
- ++frameCounter.count;
- var label = key == undefined
- ? frameCounter.count
- : key + " " + frameCounter.count;
- frameCounter.logRow.firstChild.firstChild.nodeValue = label;
- }
- };
- this.trace = function()
- {
- var getFuncName = function getFuncName (f)
- {
- if (f.getName instanceof Function)
- {
- return f.getName();
- }
- if (f.name) // in FireFox, Function objects have a name property...
- {
- return f.name;
- }
- var name = f.toString().match(/function\s*([_$\w\d]*)/)[1];
- return name || "anonymous";
- };
- var wasVisited = function(fn)
- {
- for (var i=0, l=frames.length; i<l; i++)
- {
- if (frames[i].fn == fn)
- {
- return true;
- }
- }
- return false;
- };
- traceRecursion++;
- if (traceRecursion > 1)
- {
- traceRecursion--;
- return;
- }
- var frames = [];
- for (var fn = arguments.callee.caller.caller; fn; fn = fn.caller)
- {
- if (wasVisited(fn)) break;
- var args = [];
- for (var i = 0, l = fn.arguments.length; i < l; ++i)
- {
- args.push({value: fn.arguments[i]});
- }
- frames.push({fn: fn, name: getFuncName(fn), args: args});
- }
- // ****************************************************************************************
- try
- {
- (0)();
- }
- catch(e)
- {
- var result = e;
- var stack =
- result.stack || // Firefox / Google Chrome
- result.stacktrace || // Opera
- "";
- stack = stack.replace(/\n\r|\r\n/g, "\n"); // normalize line breaks
- var items = stack.split(/[\n\r]/);
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Google Chrome
- if (FBL.isSafari)
- {
- //var reChromeStackItem = /^\s+at\s+([^\(]+)\s\((.*)\)$/;
- //var reChromeStackItem = /^\s+at\s+(.*)((?:http|https|ftp|file):\/\/.*)$/;
- var reChromeStackItem = /^\s+at\s+(.*)((?:http|https|ftp|file):\/\/.*)$/;
- var reChromeStackItemName = /\s*\($/;
- var reChromeStackItemValue = /^(.+)\:(\d+\:\d+)\)?$/;
- var framePos = 0;
- for (var i=4, length=items.length; i<length; i++, framePos++)
- {
- var frame = frames[framePos];
- var item = items[i];
- var match = item.match(reChromeStackItem);
- //Firebug.Console.log("["+ framePos +"]--------------------------");
- //Firebug.Console.log(item);
- //Firebug.Console.log("................");
- if (match)
- {
- var name = match[1];
- if (name)
- {
- name = name.replace(reChromeStackItemName, "");
- frame.name = name;
- }
- //Firebug.Console.log("name: "+name);
- var value = match[2].match(reChromeStackItemValue);
- if (value)
- {
- frame.href = value[1];
- frame.lineNo = value[2];
- //Firebug.Console.log("url: "+value[1]);
- //Firebug.Console.log("line: "+value[2]);
- }
- //else
- // Firebug.Console.log(match[2]);
- }
- }
- }
- /**/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- else if (FBL.isFirefox)
- {
- // Firefox
- var reFirefoxStackItem = /^(.*)@(.*)$/;
- var reFirefoxStackItemValue = /^(.+)\:(\d+)$/;
- var framePos = 0;
- for (var i=2, length=items.length; i<length; i++, framePos++)
- {
- var frame = frames[framePos] || {};
- var item = items[i];
- var match = item.match(reFirefoxStackItem);
- if (match)
- {
- var name = match[1];
- //Firebug.Console.logFormatted("name: "+name);
- var value = match[2].match(reFirefoxStackItemValue);
- if (value)
- {
- frame.href = value[1];
- frame.lineNo = value[2];
- //Firebug.Console.log("href: "+ value[1]);
- //Firebug.Console.log("line: " + value[2]);
- }
- //else
- // Firebug.Console.logFormatted([match[2]]);
- }
- }
- }
- /**/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- /*
- else if (FBL.isOpera)
- {
- // Opera
- var reOperaStackItem = /^\s\s(?:\.\.\.\s\s)?Line\s(\d+)\sof\s(.+)$/;
- var reOperaStackItemValue = /^linked\sscript\s(.+)$/;
- for (var i=0, length=items.length; i<length; i+=2)
- {
- var item = items[i];
- var match = item.match(reOperaStackItem);
- if (match)
- {
- //Firebug.Console.log(match[1]);
- var value = match[2].match(reOperaStackItemValue);
- if (value)
- {
- //Firebug.Console.log(value[1]);
- }
- //else
- // Firebug.Console.log(match[2]);
- //Firebug.Console.log("--------------------------");
- }
- }
- }
- /**/
- }
- //console.log(stack);
- //console.dir(frames);
- Firebug.Console.log({frames: frames}, context, "stackTrace", FirebugReps.StackTrace);
- traceRecursion--;
- };
- this.trace_ok = function()
- {
- var getFuncName = function getFuncName (f)
- {
- if (f.getName instanceof Function)
- return f.getName();
- if (f.name) // in FireFox, Function objects have a name property...
- return f.name;
- var name = f.toString().match(/function\s*([_$\w\d]*)/)[1];
- return name || "anonymous";
- };
- var wasVisited = function(fn)
- {
- for (var i=0, l=frames.length; i<l; i++)
- {
- if (frames[i].fn == fn)
- return true;
- }
- return false;
- };
- var frames = [];
- for (var fn = arguments.callee.caller; fn; fn = fn.caller)
- {
- if (wasVisited(fn)) break;
- var args = [];
- for (var i = 0, l = fn.arguments.length; i < l; ++i)
- {
- args.push({value: fn.arguments[i]});
- }
- frames.push({fn: fn, name: getFuncName(fn), args: args});
- }
- Firebug.Console.log({frames: frames}, context, "stackTrace", FirebugReps.StackTrace);
- };
- this.clear = function()
- {
- Firebug.Console.clear(context);
- };
- this.time = function(name, reset)
- {
- if (!name)
- return;
- var time = new Date().getTime();
- if (!this.timeCounters)
- this.timeCounters = {};
- var key = "KEY"+name.toString();
- if (!reset && this.timeCounters[key])
- return;
- this.timeCounters[key] = time;
- };
- this.timeEnd = function(name)
- {
- var time = new Date().getTime();
- if (!this.timeCounters)
- return;
- var key = "KEY"+name.toString();
- var timeCounter = this.timeCounters[key];
- if (timeCounter)
- {
- var diff = time - timeCounter;
- var label = name + ": " + diff + "ms";
- this.info(label);
- delete this.timeCounters[key];
- }
- return diff;
- };
- // These functions are over-ridden by commandLine
- this.evaluated = function(result, context)
- {
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("consoleInjector.FirebugConsoleHandler evalutated default called", result);
- Firebug.Console.log(result, context);
- };
- this.evaluateError = function(result, context)
- {
- Firebug.Console.log(result, context, "errorMessage");
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function logFormatted(args, className, linkToSource, noThrottle)
- {
- var sourceLink = linkToSource ? getStackLink() : null;
- return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
- }
- function logAssert(category, args)
- {
- Firebug.Errors.increaseCount(context);
- if (!args || !args.length || args.length == 0)
- var msg = [FBL.$STR("Assertion")];
- else
- var msg = args[0];
- if (Firebug.errorStackTrace)
- {
- var trace = Firebug.errorStackTrace;
- delete Firebug.errorStackTrace;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("logAssert trace from errorStackTrace", trace);
- }
- else if (msg.stack)
- {
- var trace = parseToStackTrace(msg.stack);
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("logAssert trace from msg.stack", trace);
- }
- else
- {
- var trace = getJSDUserStack();
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("logAssert trace from getJSDUserStack", trace);
- }
- var errorObject = new FBL.ErrorMessage(msg, (msg.fileName?msg.fileName:win.location), (msg.lineNumber?msg.lineNumber:0), "", category, context, trace);
- if (trace && trace.frames && trace.frames[0])
- errorObject.correctWithStackTrace(trace);
- errorObject.resetSource();
- var objects = errorObject;
- if (args.length > 1)
- {
- objects = [errorObject];
- for (var i = 1; i < args.length; i++)
- objects.push(args[i]);
- }
- var row = Firebug.Console.log(objects, context, "errorMessage", null, true); // noThrottle
- row.scrollIntoView();
- }
- function getComponentsStackDump()
- {
- // Starting with our stack, walk back to the user-level code
- var frame = Components.stack;
- var userURL = win.location.href.toString();
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("consoleInjector.getComponentsStackDump initial stack for userURL "+userURL, frame);
- // Drop frames until we get into user code.
- while (frame && FBL.isSystemURL(frame.filename) )
- frame = frame.caller;
- // Drop two more frames, the injected console function and firebugAppendConsole()
- if (frame)
- frame = frame.caller;
- if (frame)
- frame = frame.caller;
- if (FBTrace.DBG_CONSOLE)
- FBTrace.sysout("consoleInjector.getComponentsStackDump final stack for userURL "+userURL, frame);
- return frame;
- }
- function getStackLink()
- {
- // TODO: xxxpedro console2
- return;
- //return FBL.getFrameSourceLink(getComponentsStackDump());
- }
- function getJSDUserStack()
- {
- var trace = FBL.getCurrentStackTrace(context);
- var frames = trace ? trace.frames : null;
- if (frames && (frames.length > 0) )
- {
- var oldest = frames.length - 1; // 6 - 1 = 5
- for (var i = 0; i < frames.length; i++)
- {
- if (frames[oldest - i].href.indexOf("chrome:") == 0) break;
- var fn = frames[oldest - i].fn + "";
- if (fn && (fn.indexOf("_firebugEvalEvent") != -1) ) break; // command line
- }
- FBTrace.sysout("consoleInjector getJSDUserStack: "+frames.length+" oldest: "+oldest+" i: "+i+" i - oldest + 2: "+(i - oldest + 2), trace);
- trace.frames = trace.frames.slice(2 - i); // take the oldest frames, leave 2 behind they are injection code
- return trace;
- }
- else
- return "Firebug failed to get stack trace with any frames";
- }
- }
- // ************************************************************************************************
- // Register console namespace
- FBL.registerConsole = function()
- {
- //TODO: xxxpedro console options override
- //if (Env.Options.overrideConsole)
- var win = Env.browser.window;
- Firebug.Console.injector.install(win);
- };
- registerConsole();
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Globals
- var commandPrefix = ">>>";
- var reOpenBracket = /[\[\(\{]/;
- var reCloseBracket = /[\]\)\}]/;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var commandHistory = [];
- var commandPointer = -1;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var isAutoCompleting = null;
- var autoCompletePrefix = null;
- var autoCompleteExpr = null;
- var autoCompleteBuffer = null;
- var autoCompletePosition = null;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var fbCommandLine = null;
- var fbLargeCommandLine = null;
- var fbLargeCommandButtons = null;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var _completion =
- {
- window:
- [
- "console"
- ],
- document:
- [
- "getElementById",
- "getElementsByTagName"
- ]
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var _stack = function(command)
- {
- commandHistory.push(command);
- commandPointer = commandHistory.length;
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // ************************************************************************************************
- // CommandLine
- Firebug.CommandLine = extend(Firebug.Module,
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- element: null,
- isMultiLine: false,
- isActive: false,
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- initialize: function(doc)
- {
- this.clear = bind(this.clear, this);
- this.enter = bind(this.enter, this);
- this.onError = bind(this.onError, this);
- this.onKeyDown = bind(this.onKeyDown, this);
- this.onMultiLineKeyDown = bind(this.onMultiLineKeyDown, this);
- addEvent(Firebug.browser.window, "error", this.onError);
- addEvent(Firebug.chrome.window, "error", this.onError);
- },
- shutdown: function(doc)
- {
- this.deactivate();
- removeEvent(Firebug.browser.window, "error", this.onError);
- removeEvent(Firebug.chrome.window, "error", this.onError);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- activate: function(multiLine, hideToggleIcon, onRun)
- {
- defineCommandLineAPI();
- if (this.isActive)
- {
- if (this.isMultiLine == multiLine) return;
- this.deactivate();
- }
- fbCommandLine = $("fbCommandLine");
- fbLargeCommandLine = $("fbLargeCommandLine");
- fbLargeCommandButtons = $("fbLargeCommandButtons");
- if (multiLine)
- {
- onRun = onRun || this.enter;
- this.isMultiLine = true;
- this.element = fbLargeCommandLine;
- addEvent(this.element, "keydown", this.onMultiLineKeyDown);
- addEvent($("fbSmallCommandLineIcon"), "click", Firebug.chrome.hideLargeCommandLine);
- this.runButton = new Button({
- element: $("fbCommand_btRun"),
- owner: Firebug.CommandLine,
- onClick: onRun
- });
- this.runButton.initialize();
- this.clearButton = new Button({
- element: $("fbCommand_btClear"),
- owner: Firebug.CommandLine,
- onClick: this.clear
- });
- this.clearButton.initialize();
- }
- else
- {
- this.isMultiLine = false;
- this.element = fbCommandLine;
- if (!fbCommandLine)
- return;
- addEvent(this.element, "keydown", this.onKeyDown);
- }
- //Firebug.Console.log("activate", this.element);
- if (isOpera)
- fixOperaTabKey(this.element);
- if(this.lastValue)
- this.element.value = this.lastValue;
- this.isActive = true;
- },
- deactivate: function()
- {
- if (!this.isActive) return;
- //Firebug.Console.log("deactivate", this.element);
- this.isActive = false;
- this.lastValue = this.element.value;
- if (this.isMultiLine)
- {
- removeEvent(this.element, "keydown", this.onMultiLineKeyDown);
- removeEvent($("fbSmallCommandLineIcon"), "click", Firebug.chrome.hideLargeCommandLine);
- this.runButton.destroy();
- this.clearButton.destroy();
- }
- else
- {
- removeEvent(this.element, "keydown", this.onKeyDown);
- }
- this.element = null
- delete this.element;
- fbCommandLine = null;
- fbLargeCommandLine = null;
- fbLargeCommandButtons = null;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- focus: function()
- {
- this.element.focus();
- },
- blur: function()
- {
- this.element.blur();
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- clear: function()
- {
- this.element.value = "";
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- evaluate: function(expr)
- {
- // TODO: need to register the API in console.firebug.commandLineAPI
- var api = "Firebug.CommandLine.API"
- var result = Firebug.context.evaluate(expr, "window", api, Firebug.Console.error);
- return result;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- enter: function()
- {
- var command = this.element.value;
- if (!command) return;
- _stack(command);
- Firebug.Console.log(commandPrefix + " " + stripNewLines(command), Firebug.browser, "command", FirebugReps.Text);
- var result = this.evaluate(command);
- Firebug.Console.log(result);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- prevCommand: function()
- {
- if (commandPointer > 0 && commandHistory.length > 0)
- this.element.value = commandHistory[--commandPointer];
- },
- nextCommand: function()
- {
- var element = this.element;
- var limit = commandHistory.length -1;
- var i = commandPointer;
- if (i < limit)
- element.value = commandHistory[++commandPointer];
- else if (i == limit)
- {
- ++commandPointer;
- element.value = "";
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- autocomplete: function(reverse)
- {
- var element = this.element;
- var command = element.value;
- var offset = getExpressionOffset(command);
- var valBegin = offset ? command.substr(0, offset) : "";
- var val = command.substr(offset);
- var buffer, obj, objName, commandBegin, result, prefix;
- // if it is the beginning of the completion
- if(!isAutoCompleting)
- {
- // group1 - command begin
- // group2 - base object
- // group3 - property prefix
- var reObj = /(.*[^_$\w\d\.])?((?:[_$\w][_$\w\d]*\.)*)([_$\w][_$\w\d]*)?$/;
- var r = reObj.exec(val);
- // parse command
- if (r[1] || r[2] || r[3])
- {
- commandBegin = r[1] || "";
- objName = r[2] || "";
- prefix = r[3] || "";
- }
- else if (val == "")
- {
- commandBegin = objName = prefix = "";
- } else
- return;
- isAutoCompleting = true;
- // find base object
- if(objName == "")
- obj = window;
- else
- {
- objName = objName.replace(/\.$/, "");
- var n = objName.split(".");
- var target = window, o;
- for (var i=0, ni; ni = n[i]; i++)
- {
- if (o = target[ni])
- target = o;
- else
- {
- target = null;
- break;
- }
- }
- obj = target;
- }
- // map base object
- if(obj)
- {
- autoCompletePrefix = prefix;
- autoCompleteExpr = valBegin + commandBegin + (objName ? objName + "." : "");
- autoCompletePosition = -1;
- buffer = autoCompleteBuffer = isIE ?
- _completion[objName || "window"] || [] : [];
- for(var p in obj)
- buffer.push(p);
- }
- // if it is the continuation of the last completion
- } else
- buffer = autoCompleteBuffer;
- if (buffer)
- {
- prefix = autoCompletePrefix;
- var diff = reverse ? -1 : 1;
- for(var i=autoCompletePosition+diff, l=buffer.length, bi; i>=0 && i<l; i+=diff)
- {
- bi = buffer[i];
- if (bi.indexOf(prefix) == 0)
- {
- autoCompletePosition = i;
- result = bi;
- break;
- }
- }
- }
- if (result)
- element.value = autoCompleteExpr + result;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- setMultiLine: function(multiLine)
- {
- if (multiLine == this.isMultiLine) return;
- this.activate(multiLine);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onError: function(msg, href, lineNo)
- {
- href = href || "";
- var lastSlash = href.lastIndexOf("/");
- var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
- var html = [
- '<span class="errorMessage">', msg, '</span>',
- '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
- ];
- // TODO: xxxpedro ajust to Console2
- //Firebug.Console.writeRow(html, "error");
- },
- onKeyDown: function(e)
- {
- e = e || event;
- var code = e.keyCode;
- /*tab, shift, control, alt*/
- if (code != 9 && code != 16 && code != 17 && code != 18)
- {
- isAutoCompleting = false;
- }
- if (code == 13 /* enter */)
- {
- this.enter();
- this.clear();
- }
- else if (code == 27 /* ESC */)
- {
- setTimeout(this.clear, 0);
- }
- else if (code == 38 /* up */)
- {
- this.prevCommand();
- }
- else if (code == 40 /* down */)
- {
- this.nextCommand();
- }
- else if (code == 9 /* tab */)
- {
- this.autocomplete(e.shiftKey);
- }
- else
- return;
- cancelEvent(e, true);
- return false;
- },
- onMultiLineKeyDown: function(e)
- {
- e = e || event;
- var code = e.keyCode;
- if (code == 13 /* enter */ && e.ctrlKey)
- {
- this.enter();
- }
- }
- });
- Firebug.registerModule(Firebug.CommandLine);
- // ************************************************************************************************
- //
- function getExpressionOffset(command)
- {
- // XXXjoe This is kind of a poor-man's JavaScript parser - trying
- // to find the start of the expression that the cursor is inside.
- // Not 100% fool proof, but hey...
- var bracketCount = 0;
- var start = command.length-1;
- for (; start >= 0; --start)
- {
- var c = command[start];
- if ((c == "," || c == ";" || c == " ") && !bracketCount)
- break;
- if (reOpenBracket.test(c))
- {
- if (bracketCount)
- --bracketCount;
- else
- break;
- }
- else if (reCloseBracket.test(c))
- ++bracketCount;
- }
- return start + 1;
- }
- // ************************************************************************************************
- // CommandLine API
- var CommandLineAPI =
- {
- $: function(id)
- {
- return Firebug.browser.document.getElementById(id)
- },
- $$: function(selector, context)
- {
- context = context || Firebug.browser.document;
- return Firebug.Selector ?
- Firebug.Selector(selector, context) :
- Firebug.Console.error("Firebug.Selector module not loaded.");
- },
- $0: null,
- $1: null,
- dir: function(o)
- {
- Firebug.Console.log(o, Firebug.context, "dir", Firebug.DOMPanel.DirTable);
- },
- dirxml: function(o)
- {
- ///if (o instanceof Window)
- if (instanceOf(o, "Window"))
- o = o.document.documentElement;
- ///else if (o instanceof Document)
- else if (instanceOf(o, "Document"))
- o = o.documentElement;
- // TODO: xxxpedro html3
- ///Firebug.Console.log(o, Firebug.context, "dirxml", Firebug.HTMLPanel.SoloElement);
- var div = Firebug.Console.log(o, Firebug.context, "dirxml");
- var html = [];
- Firebug.Reps.appendNode(o, html);
- div.innerHTML = html.join("");
- }
- };
- // ************************************************************************************************
- var defineCommandLineAPI = function defineCommandLineAPI()
- {
- Firebug.CommandLine.API = {};
- for (var m in CommandLineAPI)
- if (!Env.browser.window[m])
- Firebug.CommandLine.API[m] = CommandLineAPI[m];
- var stack = FirebugChrome.htmlSelectionStack;
- if (stack)
- {
- Firebug.CommandLine.API.$0 = stack[0];
- Firebug.CommandLine.API.$1 = stack[1];
- }
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- if (Env.Options.disableXHRListener)
- return;
- // ************************************************************************************************
- // XHRSpy
- var XHRSpy = function()
- {
- this.requestHeaders = [];
- this.responseHeaders = [];
- };
- XHRSpy.prototype =
- {
- method: null,
- url: null,
- async: null,
- xhrRequest: null,
- href: null,
- loaded: false,
- logRow: null,
- responseText: null,
- requestHeaders: null,
- responseHeaders: null,
- sourceLink: null, // {href:"file.html", line: 22}
- getURL: function()
- {
- return this.href;
- }
- };
- // ************************************************************************************************
- // XMLHttpRequestWrapper
- var XMLHttpRequestWrapper = function(activeXObject)
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // XMLHttpRequestWrapper internal variables
- var xhrRequest = typeof activeXObject != "undefined" ?
- activeXObject :
- new _XMLHttpRequest(),
- spy = new XHRSpy(),
- self = this,
- reqType,
- reqUrl,
- reqStartTS;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // XMLHttpRequestWrapper internal methods
- var updateSelfPropertiesIgnore = {
- abort: 1,
- channel: 1,
- getAllResponseHeaders: 1,
- getInterface: 1,
- getResponseHeader: 1,
- mozBackgroundRequest: 1,
- multipart: 1,
- onreadystatechange: 1,
- open: 1,
- send: 1,
- setRequestHeader: 1
- };
- var updateSelfProperties = function()
- {
- if (supportsXHRIterator)
- {
- for (var propName in xhrRequest)
- {
- if (propName in updateSelfPropertiesIgnore)
- continue;
- try
- {
- var propValue = xhrRequest[propName];
- if (propValue && !isFunction(propValue))
- self[propName] = propValue;
- }
- catch(E)
- {
- //console.log(propName, E.message);
- }
- }
- }
- else
- {
- // will fail to read these xhrRequest properties if the request is not completed
- if (xhrRequest.readyState == 4)
- {
- self.status = xhrRequest.status;
- self.statusText = xhrRequest.statusText;
- self.responseText = xhrRequest.responseText;
- self.responseXML = xhrRequest.responseXML;
- }
- }
- };
- var updateXHRPropertiesIgnore = {
- channel: 1,
- onreadystatechange: 1,
- readyState: 1,
- responseBody: 1,
- responseText: 1,
- responseXML: 1,
- status: 1,
- statusText: 1,
- upload: 1
- };
- var updateXHRProperties = function()
- {
- for (var propName in self)
- {
- if (propName in updateXHRPropertiesIgnore)
- continue;
- try
- {
- var propValue = self[propName];
- if (propValue && !xhrRequest[propName])
- {
- xhrRequest[propName] = propValue;
- }
- }
- catch(E)
- {
- //console.log(propName, E.message);
- }
- }
- };
- var logXHR = function()
- {
- var row = Firebug.Console.log(spy, null, "spy", Firebug.Spy.XHR);
- if (row)
- {
- setClass(row, "loading");
- spy.logRow = row;
- }
- };
- var finishXHR = function()
- {
- var duration = new Date().getTime() - reqStartTS;
- var success = xhrRequest.status == 200;
- var responseHeadersText = xhrRequest.getAllResponseHeaders();
- var responses = responseHeadersText ? responseHeadersText.split(/[\n\r]/) : [];
- var reHeader = /^(\S+):\s*(.*)/;
- for (var i=0, l=responses.length; i<l; i++)
- {
- var text = responses[i];
- var match = text.match(reHeader);
- if (match)
- {
- var name = match[1];
- var value = match[2];
- // update the spy mimeType property so we can detect when to show
- // custom response viewers (such as HTML, XML or JSON viewer)
- if (name == "Content-Type")
- spy.mimeType = value;
- /*
- if (name == "Last Modified")
- {
- if (!spy.cacheEntry)
- spy.cacheEntry = [];
- spy.cacheEntry.push({
- name: [name],
- value: [value]
- });
- }
- /**/
- spy.responseHeaders.push({
- name: [name],
- value: [value]
- });
- }
- }
- with({
- row: spy.logRow,
- status: xhrRequest.status == 0 ?
- // if xhrRequest.status == 0 then accessing xhrRequest.statusText
- // will cause an error, so we must handle this case (Issue 3504)
- "" : xhrRequest.status + " " + xhrRequest.statusText,
- time: duration,
- success: success
- })
- {
- setTimeout(function(){
- spy.responseText = xhrRequest.responseText;
- // update row information to avoid "ethernal spinning gif" bug in IE
- row = row || spy.logRow;
- // if chrome document is not loaded, there will be no row yet, so just ignore
- if (!row) return;
- // update the XHR representation data
- handleRequestStatus(success, status, time);
- },200);
- }
- spy.loaded = true;
- /*
- // commented because they are being updated by the updateSelfProperties() function
- self.status = xhrRequest.status;
- self.statusText = xhrRequest.statusText;
- self.responseText = xhrRequest.responseText;
- self.responseXML = xhrRequest.responseXML;
- /**/
- updateSelfProperties();
- };
- var handleStateChange = function()
- {
- //Firebug.Console.log(["onreadystatechange", xhrRequest.readyState, xhrRequest.readyState == 4 && xhrRequest.status]);
- self.readyState = xhrRequest.readyState;
- if (xhrRequest.readyState == 4)
- {
- finishXHR();
- xhrRequest.onreadystatechange = function(){};
- }
- //Firebug.Console.log(spy.url + ": " + xhrRequest.readyState);
- self.onreadystatechange();
- };
- // update the XHR representation data
- var handleRequestStatus = function(success, status, time)
- {
- var row = spy.logRow;
- FBL.removeClass(row, "loading");
- if (!success)
- FBL.setClass(row, "error");
- var item = FBL.$$(".spyStatus", row)[0];
- item.innerHTML = status;
- if (time)
- {
- var item = FBL.$$(".spyTime", row)[0];
- item.innerHTML = time + "ms";
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // XMLHttpRequestWrapper public properties and handlers
- this.readyState = 0;
- this.onreadystatechange = function(){};
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // XMLHttpRequestWrapper public methods
- this.open = function(method, url, async, user, password)
- {
- //Firebug.Console.log("xhrRequest open");
- updateSelfProperties();
- if (spy.loaded)
- spy = new XHRSpy();
- spy.method = method;
- spy.url = url;
- spy.async = async;
- spy.href = url;
- spy.xhrRequest = xhrRequest;
- spy.urlParams = parseURLParamsArray(url);
- try
- {
- // xhrRequest.open.apply may not be available in IE
- if (supportsApply)
- xhrRequest.open.apply(xhrRequest, arguments);
- else
- xhrRequest.open(method, url, async, user, password);
- }
- catch(e)
- {
- }
- xhrRequest.onreadystatechange = handleStateChange;
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.send = function(data)
- {
- //Firebug.Console.log("xhrRequest send");
- spy.data = data;
- reqStartTS = new Date().getTime();
- updateXHRProperties();
- try
- {
- xhrRequest.send(data);
- }
- catch(e)
- {
- // TODO: xxxpedro XHR throws or not?
- //throw e;
- }
- finally
- {
- logXHR();
- if (!spy.async)
- {
- self.readyState = xhrRequest.readyState;
- // sometimes an error happens when calling finishXHR()
- // Issue 3422: Firebug Lite breaks Google Instant Search
- try
- {
- finishXHR();
- }
- catch(E)
- {
- }
- }
- }
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.setRequestHeader = function(header, value)
- {
- spy.requestHeaders.push({name: [header], value: [value]});
- return xhrRequest.setRequestHeader(header, value);
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.abort = function()
- {
- xhrRequest.abort();
- updateSelfProperties();
- handleRequestStatus(false, "Aborted");
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.getResponseHeader = function(header)
- {
- return xhrRequest.getResponseHeader(header);
- };
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- this.getAllResponseHeaders = function()
- {
- return xhrRequest.getAllResponseHeaders();
- };
- /**/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Clone XHR object
- // xhrRequest.open.apply not available in IE and will throw an error in
- // IE6 by simply reading xhrRequest.open so we must sniff it
- var supportsApply = !isIE6 &&
- xhrRequest &&
- xhrRequest.open &&
- typeof xhrRequest.open.apply != "undefined";
- var numberOfXHRProperties = 0;
- for (var propName in xhrRequest)
- {
- numberOfXHRProperties++;
- if (propName in updateSelfPropertiesIgnore)
- continue;
- try
- {
- var propValue = xhrRequest[propName];
- if (isFunction(propValue))
- {
- if (typeof self[propName] == "undefined")
- {
- this[propName] = (function(name, xhr){
- return supportsApply ?
- // if the browser supports apply
- function()
- {
- return xhr[name].apply(xhr, arguments);
- }
- :
- function(a,b,c,d,e)
- {
- return xhr[name](a,b,c,d,e);
- };
- })(propName, xhrRequest);
- }
- }
- else
- this[propName] = propValue;
- }
- catch(E)
- {
- //console.log(propName, E.message);
- }
- }
- // IE6 does not support for (var prop in XHR)
- var supportsXHRIterator = numberOfXHRProperties > 0;
- /**/
- return this;
- };
- // ************************************************************************************************
- // ActiveXObject Wrapper (IE6 only)
- var _ActiveXObject;
- var isIE6 = /msie 6/i.test(navigator.appVersion);
- if (isIE6)
- {
- _ActiveXObject = window.ActiveXObject;
- var xhrObjects = " MSXML2.XMLHTTP.5.0 MSXML2.XMLHTTP.4.0 MSXML2.XMLHTTP.3.0 MSXML2.XMLHTTP Microsoft.XMLHTTP ";
- window.ActiveXObject = function(name)
- {
- var error = null;
- try
- {
- var activeXObject = new _ActiveXObject(name);
- }
- catch(e)
- {
- error = e;
- }
- finally
- {
- if (!error)
- {
- if (xhrObjects.indexOf(" " + name + " ") != -1)
- return new XMLHttpRequestWrapper(activeXObject);
- else
- return activeXObject;
- }
- else
- throw error.message;
- }
- };
- }
- // ************************************************************************************************
- // Register the XMLHttpRequestWrapper for non-IE6 browsers
- if (!isIE6)
- {
- var _XMLHttpRequest = XMLHttpRequest;
- window.XMLHttpRequest = function()
- {
- return new XMLHttpRequestWrapper();
- };
- }
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var reIgnore = /about:|javascript:|resource:|chrome:|jar:/;
- var layoutInterval = 300;
- var indentWidth = 18;
- var cacheSession = null;
- var contexts = new Array();
- var panelName = "net";
- var maxQueueRequests = 500;
- //var panelBar1 = $("fbPanelBar1"); // chrome not available at startup
- var activeRequests = [];
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var mimeExtensionMap =
- {
- "txt": "text/plain",
- "html": "text/html",
- "htm": "text/html",
- "xhtml": "text/html",
- "xml": "text/xml",
- "css": "text/css",
- "js": "application/x-javascript",
- "jss": "application/x-javascript",
- "jpg": "image/jpg",
- "jpeg": "image/jpeg",
- "gif": "image/gif",
- "png": "image/png",
- "bmp": "image/bmp",
- "swf": "application/x-shockwave-flash",
- "flv": "video/x-flv"
- };
- var fileCategories =
- {
- "undefined": 1,
- "html": 1,
- "css": 1,
- "js": 1,
- "xhr": 1,
- "image": 1,
- "flash": 1,
- "txt": 1,
- "bin": 1
- };
- var textFileCategories =
- {
- "txt": 1,
- "html": 1,
- "xhr": 1,
- "css": 1,
- "js": 1
- };
- var binaryFileCategories =
- {
- "bin": 1,
- "flash": 1
- };
- var mimeCategoryMap =
- {
- "text/plain": "txt",
- "application/octet-stream": "bin",
- "text/html": "html",
- "text/xml": "html",
- "text/css": "css",
- "application/x-javascript": "js",
- "text/javascript": "js",
- "application/javascript" : "js",
- "image/jpeg": "image",
- "image/jpg": "image",
- "image/gif": "image",
- "image/png": "image",
- "image/bmp": "image",
- "application/x-shockwave-flash": "flash",
- "video/x-flv": "flash"
- };
- var binaryCategoryMap =
- {
- "image": 1,
- "flash" : 1
- };
- // ************************************************************************************************
- /**
- * @module Represents a module object for the Net panel. This object is derived
- * from <code>Firebug.ActivableModule</code> in order to support activation (enable/disable).
- * This allows to avoid (performance) expensive features if the functionality is not necessary
- * for the user.
- */
- Firebug.NetMonitor = extend(Firebug.ActivableModule,
- {
- dispatchName: "netMonitor",
- clear: function(context)
- {
- // The user pressed a Clear button so, remove content of the panel...
- var panel = context.getPanel(panelName, true);
- if (panel)
- panel.clear();
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Module
- initialize: function()
- {
- return;
- this.panelName = panelName;
- Firebug.ActivableModule.initialize.apply(this, arguments);
- if (Firebug.TraceModule)
- Firebug.TraceModule.addListener(this.TraceListener);
- // HTTP observer must be registered now (and not in monitorContext, since if a
- // page is opened in a new tab the top document request would be missed otherwise.
- NetHttpObserver.registerObserver();
- NetHttpActivityObserver.registerObserver();
- Firebug.Debugger.addListener(this.DebuggerListener);
- },
- shutdown: function()
- {
- return;
- prefs.removeObserver(Firebug.prefDomain, this, false);
- if (Firebug.TraceModule)
- Firebug.TraceModule.removeListener(this.TraceListener);
- NetHttpObserver.unregisterObserver();
- NetHttpActivityObserver.unregisterObserver();
- Firebug.Debugger.removeListener(this.DebuggerListener);
- }
- });
- /**
- * @domplate Represents a template that is used to reneder detailed info about a request.
- * This template is rendered when a request is expanded.
- */
- Firebug.NetMonitor.NetInfoBody = domplate(Firebug.Rep, new Firebug.Listener(),
- {
- tag:
- DIV({"class": "netInfoBody", _repObject: "$file"},
- TAG("$infoTabs", {file: "$file"}),
- TAG("$infoBodies", {file: "$file"})
- ),
- infoTabs:
- DIV({"class": "netInfoTabs focusRow subFocusRow", "role": "tablist"},
- A({"class": "netInfoParamsTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Params",
- $collapsed: "$file|hideParams"},
- $STR("URLParameters")
- ),
- A({"class": "netInfoHeadersTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Headers"},
- $STR("Headers")
- ),
- A({"class": "netInfoPostTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Post",
- $collapsed: "$file|hidePost"},
- $STR("Post")
- ),
- A({"class": "netInfoPutTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Put",
- $collapsed: "$file|hidePut"},
- $STR("Put")
- ),
- A({"class": "netInfoResponseTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Response",
- $collapsed: "$file|hideResponse"},
- $STR("Response")
- ),
- A({"class": "netInfoCacheTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Cache",
- $collapsed: "$file|hideCache"},
- $STR("Cache")
- ),
- A({"class": "netInfoHtmlTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab",
- view: "Html",
- $collapsed: "$file|hideHtml"},
- $STR("HTML")
- )
- ),
- infoBodies:
- DIV({"class": "netInfoBodies outerFocusRow"},
- TABLE({"class": "netInfoParamsText netInfoText netInfoParamsTable", "role": "tabpanel",
- cellpadding: 0, cellspacing: 0}, TBODY()),
- DIV({"class": "netInfoHeadersText netInfoText", "role": "tabpanel"}),
- DIV({"class": "netInfoPostText netInfoText", "role": "tabpanel"}),
- DIV({"class": "netInfoPutText netInfoText", "role": "tabpanel"}),
- PRE({"class": "netInfoResponseText netInfoText", "role": "tabpanel"}),
- DIV({"class": "netInfoCacheText netInfoText", "role": "tabpanel"},
- TABLE({"class": "netInfoCacheTable", cellpadding: 0, cellspacing: 0, "role": "presentation"},
- TBODY({"role": "list", "aria-label": $STR("Cache")})
- )
- ),
- DIV({"class": "netInfoHtmlText netInfoText", "role": "tabpanel"},
- IFRAME({"class": "netInfoHtmlPreview", "role": "document"})
- )
- ),
- headerDataTag:
- FOR("param", "$headers",
- TR({"role": "listitem"},
- TD({"class": "netInfoParamName", "role": "presentation"},
- TAG("$param|getNameTag", {param: "$param"})
- ),
- TD({"class": "netInfoParamValue", "role": "list", "aria-label": "$param.name"},
- FOR("line", "$param|getParamValueIterator",
- CODE({"class": "focusRow subFocusRow", "role": "listitem"}, "$line")
- )
- )
- )
- ),
- customTab:
- A({"class": "netInfo$tabId\\Tab netInfoTab", onclick: "$onClickTab", view: "$tabId", "role": "tab"},
- "$tabTitle"
- ),
- customBody:
- DIV({"class": "netInfo$tabId\\Text netInfoText", "role": "tabpanel"}),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- nameTag:
- SPAN("$param|getParamName"),
- nameWithTooltipTag:
- SPAN({title: "$param.name"}, "$param|getParamName"),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getNameTag: function(param)
- {
- return (this.getParamName(param) == param.name) ? this.nameTag : this.nameWithTooltipTag;
- },
- getParamName: function(param)
- {
- var limit = 25;
- var name = param.name;
- if (name.length > limit)
- name = name.substr(0, limit) + "...";
- return name;
- },
- getParamTitle: function(param)
- {
- var limit = 25;
- var name = param.name;
- if (name.length > limit)
- return name;
- return "";
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- hideParams: function(file)
- {
- return !file.urlParams || !file.urlParams.length;
- },
- hidePost: function(file)
- {
- return file.method.toUpperCase() != "POST";
- },
- hidePut: function(file)
- {
- return file.method.toUpperCase() != "PUT";
- },
- hideResponse: function(file)
- {
- return false;
- //return file.category in binaryFileCategories;
- },
- hideCache: function(file)
- {
- return true;
- //xxxHonza: I don't see any reason why not to display the cache also info for images.
- return !file.cacheEntry; // || file.category=="image";
- },
- hideHtml: function(file)
- {
- return (file.mimeType != "text/html") && (file.mimeType != "application/xhtml+xml");
- },
- onClickTab: function(event)
- {
- this.selectTab(event.currentTarget || event.srcElement);
- },
- getParamValueIterator: function(param)
- {
- // TODO: xxxpedro console2
- return param.value;
- // This value is inserted into CODE element and so, make sure the HTML isn't escaped (1210).
- // This is why the second parameter is true.
- // The CODE (with style white-space:pre) element preserves whitespaces so they are
- // displayed the same, as they come from the server (1194).
- // In case of a long header values of post parameters the value must be wrapped (2105).
- return wrapText(param.value, true);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- appendTab: function(netInfoBox, tabId, tabTitle)
- {
- // Create new tab and body.
- var args = {tabId: tabId, tabTitle: tabTitle};
- ///this.customTab.append(args, netInfoBox.getElementsByClassName("netInfoTabs").item(0));
- ///this.customBody.append(args, netInfoBox.getElementsByClassName("netInfoBodies").item(0));
- this.customTab.append(args, $$(".netInfoTabs", netInfoBox)[0]);
- this.customBody.append(args, $$(".netInfoBodies", netInfoBox)[0]);
- },
- selectTabByName: function(netInfoBox, tabName)
- {
- var tab = getChildByClass(netInfoBox, "netInfoTabs", "netInfo"+tabName+"Tab");
- if (tab)
- this.selectTab(tab);
- },
- selectTab: function(tab)
- {
- var view = tab.getAttribute("view");
- var netInfoBox = getAncestorByClass(tab, "netInfoBody");
- var selectedTab = netInfoBox.selectedTab;
- if (selectedTab)
- {
- //netInfoBox.selectedText.removeAttribute("selected");
- removeClass(netInfoBox.selectedText, "netInfoTextSelected");
- removeClass(selectedTab, "netInfoTabSelected");
- //selectedTab.removeAttribute("selected");
- selectedTab.setAttribute("aria-selected", "false");
- }
- var textBodyName = "netInfo" + view + "Text";
- selectedTab = netInfoBox.selectedTab = tab;
- netInfoBox.selectedText = $$("."+textBodyName, netInfoBox)[0];
- //netInfoBox.selectedText = netInfoBox.getElementsByClassName(textBodyName).item(0);
- //netInfoBox.selectedText.setAttribute("selected", "true");
- setClass(netInfoBox.selectedText, "netInfoTextSelected");
- setClass(selectedTab, "netInfoTabSelected");
- selectedTab.setAttribute("selected", "true");
- selectedTab.setAttribute("aria-selected", "true");
- var file = Firebug.getRepObject(netInfoBox);
- //var context = Firebug.getElementPanel(netInfoBox).context;
- var context = Firebug.chrome;
- this.updateInfo(netInfoBox, file, context);
- },
- updateInfo: function(netInfoBox, file, context)
- {
- if (FBTrace.DBG_NET)
- FBTrace.sysout("net.updateInfo; file", file);
- if (!netInfoBox)
- {
- if (FBTrace.DBG_NET || FBTrace.DBG_ERRORS)
- FBTrace.sysout("net.updateInfo; ERROR netInfo == null " + file.href, file);
- return;
- }
- var tab = netInfoBox.selectedTab;
- if (hasClass(tab, "netInfoParamsTab"))
- {
- if (file.urlParams && !netInfoBox.urlParamsPresented)
- {
- netInfoBox.urlParamsPresented = true;
- this.insertHeaderRows(netInfoBox, file.urlParams, "Params");
- }
- }
- else if (hasClass(tab, "netInfoHeadersTab"))
- {
- var headersText = $$(".netInfoHeadersText", netInfoBox)[0];
- //var headersText = netInfoBox.getElementsByClassName("netInfoHeadersText").item(0);
- if (file.responseHeaders && !netInfoBox.responseHeadersPresented)
- {
- netInfoBox.responseHeadersPresented = true;
- NetInfoHeaders.renderHeaders(headersText, file.responseHeaders, "ResponseHeaders");
- }
- if (file.requestHeaders && !netInfoBox.requestHeadersPresented)
- {
- netInfoBox.requestHeadersPresented = true;
- NetInfoHeaders.renderHeaders(headersText, file.requestHeaders, "RequestHeaders");
- }
- }
- else if (hasClass(tab, "netInfoPostTab"))
- {
- if (!netInfoBox.postPresented)
- {
- netInfoBox.postPresented = true;
- //var postText = netInfoBox.getElementsByClassName("netInfoPostText").item(0);
- var postText = $$(".netInfoPostText", netInfoBox)[0];
- NetInfoPostData.render(context, postText, file);
- }
- }
- else if (hasClass(tab, "netInfoPutTab"))
- {
- if (!netInfoBox.putPresented)
- {
- netInfoBox.putPresented = true;
- //var putText = netInfoBox.getElementsByClassName("netInfoPutText").item(0);
- var putText = $$(".netInfoPutText", netInfoBox)[0];
- NetInfoPostData.render(context, putText, file);
- }
- }
- else if (hasClass(tab, "netInfoResponseTab") && file.loaded && !netInfoBox.responsePresented)
- {
- ///var responseTextBox = netInfoBox.getElementsByClassName("netInfoResponseText").item(0);
- var responseTextBox = $$(".netInfoResponseText", netInfoBox)[0];
- if (file.category == "image")
- {
- netInfoBox.responsePresented = true;
- var responseImage = netInfoBox.ownerDocument.createElement("img");
- responseImage.src = file.href;
- clearNode(responseTextBox);
- responseTextBox.appendChild(responseImage, responseTextBox);
- }
- else ///if (!(binaryCategoryMap.hasOwnProperty(file.category)))
- {
- this.setResponseText(file, netInfoBox, responseTextBox, context);
- }
- }
- else if (hasClass(tab, "netInfoCacheTab") && file.loaded && !netInfoBox.cachePresented)
- {
- var responseTextBox = netInfoBox.getElementsByClassName("netInfoCacheText").item(0);
- if (file.cacheEntry) {
- netInfoBox.cachePresented = true;
- this.insertHeaderRows(netInfoBox, file.cacheEntry, "Cache");
- }
- }
- else if (hasClass(tab, "netInfoHtmlTab") && file.loaded && !netInfoBox.htmlPresented)
- {
- netInfoBox.htmlPresented = true;
- var text = Utils.getResponseText(file, context);
- ///var iframe = netInfoBox.getElementsByClassName("netInfoHtmlPreview").item(0);
- var iframe = $$(".netInfoHtmlPreview", netInfoBox)[0];
- ///iframe.contentWindow.document.body.innerHTML = text;
- // TODO: xxxpedro net - remove scripts
- var reScript = /<script(.|\s)*?\/script>/gi;
- text = text.replace(reScript, "");
- iframe.contentWindow.document.write(text);
- iframe.contentWindow.document.close();
- }
- // Notify listeners about update so, content of custom tabs can be updated.
- dispatch(NetInfoBody.fbListeners, "updateTabBody", [netInfoBox, file, context]);
- },
- setResponseText: function(file, netInfoBox, responseTextBox, context)
- {
- //**********************************************
- //**********************************************
- //**********************************************
- netInfoBox.responsePresented = true;
- // line breaks somehow are different in IE
- // make this only once in the initialization? we don't have net panels and modules yet.
- if (isIE)
- responseTextBox.style.whiteSpace = "nowrap";
- responseTextBox[
- typeof responseTextBox.textContent != "undefined" ?
- "textContent" :
- "innerText"
- ] = file.responseText;
- return;
- //**********************************************
- //**********************************************
- //**********************************************
- // Get response text and make sure it doesn't exceed the max limit.
- var text = Utils.getResponseText(file, context);
- var limit = Firebug.netDisplayedResponseLimit + 15;
- var limitReached = text ? (text.length > limit) : false;
- if (limitReached)
- text = text.substr(0, limit) + "...";
- // Insert the response into the UI.
- if (text)
- insertWrappedText(text, responseTextBox);
- else
- insertWrappedText("", responseTextBox);
- // Append a message informing the user that the response isn't fully displayed.
- if (limitReached)
- {
- var object = {
- text: $STR("net.responseSizeLimitMessage"),
- onClickLink: function() {
- var panel = context.getPanel("net", true);
- panel.openResponseInTab(file);
- }
- };
- Firebug.NetMonitor.ResponseSizeLimit.append(object, responseTextBox);
- }
- netInfoBox.responsePresented = true;
- if (FBTrace.DBG_NET)
- FBTrace.sysout("net.setResponseText; response text updated");
- },
- insertHeaderRows: function(netInfoBox, headers, tableName, rowName)
- {
- if (!headers.length)
- return;
- var headersTable = $$(".netInfo"+tableName+"Table", netInfoBox)[0];
- //var headersTable = netInfoBox.getElementsByClassName("netInfo"+tableName+"Table").item(0);
- var tbody = getChildByClass(headersTable, "netInfo" + rowName + "Body");
- if (!tbody)
- tbody = headersTable.firstChild;
- var titleRow = getChildByClass(tbody, "netInfo" + rowName + "Title");
- this.headerDataTag.insertRows({headers: headers}, titleRow ? titleRow : tbody);
- removeClass(titleRow, "collapsed");
- }
- });
- var NetInfoBody = Firebug.NetMonitor.NetInfoBody;
- // ************************************************************************************************
- /**
- * @domplate Used within the Net panel to display raw source of request and response headers
- * as well as pretty-formatted summary of these headers.
- */
- Firebug.NetMonitor.NetInfoHeaders = domplate(Firebug.Rep, //new Firebug.Listener(),
- {
- tag:
- DIV({"class": "netInfoHeadersTable", "role": "tabpanel"},
- DIV({"class": "netInfoHeadersGroup netInfoResponseHeadersTitle"},
- SPAN($STR("ResponseHeaders")),
- SPAN({"class": "netHeadersViewSource response collapsed", onclick: "$onViewSource",
- _sourceDisplayed: false, _rowName: "ResponseHeaders"},
- $STR("net.headers.view source")
- )
- ),
- TABLE({cellpadding: 0, cellspacing: 0},
- TBODY({"class": "netInfoResponseHeadersBody", "role": "list",
- "aria-label": $STR("ResponseHeaders")})
- ),
- DIV({"class": "netInfoHeadersGroup netInfoRequestHeadersTitle"},
- SPAN($STR("RequestHeaders")),
- SPAN({"class": "netHeadersViewSource request collapsed", onclick: "$onViewSource",
- _sourceDisplayed: false, _rowName: "RequestHeaders"},
- $STR("net.headers.view source")
- )
- ),
- TABLE({cellpadding: 0, cellspacing: 0},
- TBODY({"class": "netInfoRequestHeadersBody", "role": "list",
- "aria-label": $STR("RequestHeaders")})
- )
- ),
- sourceTag:
- TR({"role": "presentation"},
- TD({colspan: 2, "role": "presentation"},
- PRE({"class": "source"})
- )
- ),
- onViewSource: function(event)
- {
- var target = event.target;
- var requestHeaders = (target.rowName == "RequestHeaders");
- var netInfoBox = getAncestorByClass(target, "netInfoBody");
- var file = netInfoBox.repObject;
- if (target.sourceDisplayed)
- {
- var headers = requestHeaders ? file.requestHeaders : file.responseHeaders;
- this.insertHeaderRows(netInfoBox, headers, target.rowName);
- target.innerHTML = $STR("net.headers.view source");
- }
- else
- {
- var source = requestHeaders ? file.requestHeadersText : file.responseHeadersText;
- this.insertSource(netInfoBox, source, target.rowName);
- target.innerHTML = $STR("net.headers.pretty print");
- }
- target.sourceDisplayed = !target.sourceDisplayed;
- cancelEvent(event);
- },
- insertSource: function(netInfoBox, source, rowName)
- {
- // This breaks copy to clipboard.
- //if (source)
- // source = source.replace(/\r\n/gm, "<span style='color:lightgray'>\\r\\n</span>\r\n");
- ///var tbody = netInfoBox.getElementsByClassName("netInfo" + rowName + "Body").item(0);
- var tbody = $$(".netInfo" + rowName + "Body", netInfoBox)[0];
- var node = this.sourceTag.replace({}, tbody);
- ///var sourceNode = node.getElementsByClassName("source").item(0);
- var sourceNode = $$(".source", node)[0];
- sourceNode.innerHTML = source;
- },
- insertHeaderRows: function(netInfoBox, headers, rowName)
- {
- var headersTable = $$(".netInfoHeadersTable", netInfoBox)[0];
- var tbody = $$(".netInfo" + rowName + "Body", headersTable)[0];
- //var headersTable = netInfoBox.getElementsByClassName("netInfoHeadersTable").item(0);
- //var tbody = headersTable.getElementsByClassName("netInfo" + rowName + "Body").item(0);
- clearNode(tbody);
- if (!headers.length)
- return;
- NetInfoBody.headerDataTag.insertRows({headers: headers}, tbody);
- var titleRow = getChildByClass(headersTable, "netInfo" + rowName + "Title");
- removeClass(titleRow, "collapsed");
- },
- init: function(parent)
- {
- var rootNode = this.tag.append({}, parent);
- var netInfoBox = getAncestorByClass(parent, "netInfoBody");
- var file = netInfoBox.repObject;
- var viewSource;
- viewSource = $$(".request", rootNode)[0];
- //viewSource = rootNode.getElementsByClassName("netHeadersViewSource request").item(0);
- if (file.requestHeadersText)
- removeClass(viewSource, "collapsed");
- viewSource = $$(".response", rootNode)[0];
- //viewSource = rootNode.getElementsByClassName("netHeadersViewSource response").item(0);
- if (file.responseHeadersText)
- removeClass(viewSource, "collapsed");
- },
- renderHeaders: function(parent, headers, rowName)
- {
- if (!parent.firstChild)
- this.init(parent);
- this.insertHeaderRows(parent, headers, rowName);
- }
- });
- var NetInfoHeaders = Firebug.NetMonitor.NetInfoHeaders;
- // ************************************************************************************************
- /**
- * @domplate Represents posted data within request info (the info, which is visible when
- * a request entry is expanded. This template renders content of the Post tab.
- */
- Firebug.NetMonitor.NetInfoPostData = domplate(Firebug.Rep, /*new Firebug.Listener(),*/
- {
- // application/x-www-form-urlencoded
- paramsTable:
- TABLE({"class": "netInfoPostParamsTable", cellpadding: 0, cellspacing: 0, "role": "presentation"},
- TBODY({"role": "list", "aria-label": $STR("net.label.Parameters")},
- TR({"class": "netInfoPostParamsTitle", "role": "presentation"},
- TD({colspan: 3, "role": "presentation"},
- DIV({"class": "netInfoPostParams"},
- $STR("net.label.Parameters"),
- SPAN({"class": "netInfoPostContentType"},
- "application/x-www-form-urlencoded"
- )
- )
- )
- )
- )
- ),
- // multipart/form-data
- partsTable:
- TABLE({"class": "netInfoPostPartsTable", cellpadding: 0, cellspacing: 0, "role": "presentation"},
- TBODY({"role": "list", "aria-label": $STR("net.label.Parts")},
- TR({"class": "netInfoPostPartsTitle", "role": "presentation"},
- TD({colspan: 2, "role":"presentation" },
- DIV({"class": "netInfoPostParams"},
- $STR("net.label.Parts"),
- SPAN({"class": "netInfoPostContentType"},
- "multipart/form-data"
- )
- )
- )
- )
- )
- ),
- // application/json
- jsonTable:
- TABLE({"class": "netInfoPostJSONTable", cellpadding: 0, cellspacing: 0, "role": "presentation"},
- ///TBODY({"role": "list", "aria-label": $STR("jsonviewer.tab.JSON")},
- TBODY({"role": "list", "aria-label": $STR("JSON")},
- TR({"class": "netInfoPostJSONTitle", "role": "presentation"},
- TD({"role": "presentation" },
- DIV({"class": "netInfoPostParams"},
- ///$STR("jsonviewer.tab.JSON")
- $STR("JSON")
- )
- )
- ),
- TR(
- TD({"class": "netInfoPostJSONBody"})
- )
- )
- ),
- // application/xml
- xmlTable:
- TABLE({"class": "netInfoPostXMLTable", cellpadding: 0, cellspacing: 0, "role": "presentation"},
- TBODY({"role": "list", "aria-label": $STR("xmlviewer.tab.XML")},
- TR({"class": "netInfoPostXMLTitle", "role": "presentation"},
- TD({"role": "presentation" },
- DIV({"class": "netInfoPostParams"},
- $STR("xmlviewer.tab.XML")
- )
- )
- ),
- TR(
- TD({"class": "netInfoPostXMLBody"})
- )
- )
- ),
- sourceTable:
- TABLE({"class": "netInfoPostSourceTable", cellpadding: 0, cellspacing: 0, "role": "presentation"},
- TBODY({"role": "list", "aria-label": $STR("net.label.Source")},
- TR({"class": "netInfoPostSourceTitle", "role": "presentation"},
- TD({colspan: 2, "role": "presentation"},
- DIV({"class": "netInfoPostSource"},
- $STR("net.label.Source")
- )
- )
- )
- )
- ),
- sourceBodyTag:
- TR({"role": "presentation"},
- TD({colspan: 2, "role": "presentation"},
- FOR("line", "$param|getParamValueIterator",
- CODE({"class":"focusRow subFocusRow" , "role": "listitem"},"$line")
- )
- )
- ),
- getParamValueIterator: function(param)
- {
- return NetInfoBody.getParamValueIterator(param);
- },
- render: function(context, parentNode, file)
- {
- //debugger;
- var spy = getAncestorByClass(parentNode, "spyHead");
- var spyObject = spy.repObject;
- var data = spyObject.data;
- ///var contentType = Utils.findHeader(file.requestHeaders, "content-type");
- var contentType = file.mimeType;
- ///var text = Utils.getPostText(file, context, true);
- ///if (text == undefined)
- /// return;
- ///if (Utils.isURLEncodedRequest(file, context))
- // fake Utils.isURLEncodedRequest identification
- if (contentType && contentType == "application/x-www-form-urlencoded" ||
- data && data.indexOf("=") != -1)
- {
- ///var lines = text.split("\n");
- ///var params = parseURLEncodedText(lines[lines.length-1]);
- var params = parseURLEncodedTextArray(data);
- if (params)
- this.insertParameters(parentNode, params);
- }
- ///if (Utils.isMultiPartRequest(file, context))
- ///{
- /// var data = this.parseMultiPartText(file, context);
- /// if (data)
- /// this.insertParts(parentNode, data);
- ///}
- // moved to the top
- ///var contentType = Utils.findHeader(file.requestHeaders, "content-type");
- ///if (Firebug.JSONViewerModel.isJSON(contentType))
- var jsonData = {
- responseText: data
- };
- if (Firebug.JSONViewerModel.isJSON(contentType, data))
- ///this.insertJSON(parentNode, file, context);
- this.insertJSON(parentNode, jsonData, context);
- ///if (Firebug.XMLViewerModel.isXML(contentType))
- /// this.insertXML(parentNode, file, context);
- ///var postText = Utils.getPostText(file, context);
- ///postText = Utils.formatPostText(postText);
- var postText = data;
- if (postText)
- this.insertSource(parentNode, postText);
- },
- insertParameters: function(parentNode, params)
- {
- if (!params || !params.length)
- return;
- var paramTable = this.paramsTable.append({object:{}}, parentNode);
- var row = $$(".netInfoPostParamsTitle", paramTable)[0];
- //var paramTable = this.paramsTable.append(null, parentNode);
- //var row = paramTable.getElementsByClassName("netInfoPostParamsTitle").item(0);
- var tbody = paramTable.getElementsByTagName("tbody")[0];
- NetInfoBody.headerDataTag.insertRows({headers: params}, row);
- },
- insertParts: function(parentNode, data)
- {
- if (!data.params || !data.params.length)
- return;
- var partsTable = this.partsTable.append({object:{}}, parentNode);
- var row = $$(".netInfoPostPartsTitle", paramTable)[0];
- //var partsTable = this.partsTable.append(null, parentNode);
- //var row = partsTable.getElementsByClassName("netInfoPostPartsTitle").item(0);
- NetInfoBody.headerDataTag.insertRows({headers: data.params}, row);
- },
- insertJSON: function(parentNode, file, context)
- {
- ///var text = Utils.getPostText(file, context);
- var text = file.responseText;
- ///var data = parseJSONString(text, "http://" + file.request.originalURI.host);
- var data = parseJSONString(text);
- if (!data)
- return;
- ///var jsonTable = this.jsonTable.append(null, parentNode);
- var jsonTable = this.jsonTable.append({}, parentNode);
- ///var jsonBody = jsonTable.getElementsByClassName("netInfoPostJSONBody").item(0);
- var jsonBody = $$(".netInfoPostJSONBody", jsonTable)[0];
- if (!this.toggles)
- this.toggles = {};
- Firebug.DOMPanel.DirTable.tag.replace(
- {object: data, toggles: this.toggles}, jsonBody);
- },
- insertXML: function(parentNode, file, context)
- {
- var text = Utils.getPostText(file, context);
- var jsonTable = this.xmlTable.append(null, parentNode);
- ///var jsonBody = jsonTable.getElementsByClassName("netInfoPostXMLBody").item(0);
- var jsonBody = $$(".netInfoPostXMLBody", jsonTable)[0];
- Firebug.XMLViewerModel.insertXML(jsonBody, text);
- },
- insertSource: function(parentNode, text)
- {
- var sourceTable = this.sourceTable.append({object:{}}, parentNode);
- var row = $$(".netInfoPostSourceTitle", sourceTable)[0];
- //var sourceTable = this.sourceTable.append(null, parentNode);
- //var row = sourceTable.getElementsByClassName("netInfoPostSourceTitle").item(0);
- var param = {value: [text]};
- this.sourceBodyTag.insertRows({param: param}, row);
- },
- parseMultiPartText: function(file, context)
- {
- var text = Utils.getPostText(file, context);
- if (text == undefined)
- return null;
- FBTrace.sysout("net.parseMultiPartText; boundary: ", text);
- var boundary = text.match(/\s*boundary=\s*(.*)/)[1];
- var divider = "\r\n\r\n";
- var bodyStart = text.indexOf(divider);
- var body = text.substr(bodyStart + divider.length);
- var postData = {};
- postData.mimeType = "multipart/form-data";
- postData.params = [];
- var parts = body.split("--" + boundary);
- for (var i=0; i<parts.length; i++)
- {
- var part = parts[i].split(divider);
- if (part.length != 2)
- continue;
- var m = part[0].match(/\s*name=\"(.*)\"(;|$)/);
- postData.params.push({
- name: (m && m.length > 1) ? m[1] : "",
- value: trim(part[1])
- });
- }
- return postData;
- }
- });
- var NetInfoPostData = Firebug.NetMonitor.NetInfoPostData;
- // ************************************************************************************************
- // TODO: xxxpedro net i18n
- var $STRP = function(a){return a;};
- Firebug.NetMonitor.NetLimit = domplate(Firebug.Rep,
- {
- collapsed: true,
- tableTag:
- DIV(
- TABLE({width: "100%", cellpadding: 0, cellspacing: 0},
- TBODY()
- )
- ),
- limitTag:
- TR({"class": "netRow netLimitRow", $collapsed: "$isCollapsed"},
- TD({"class": "netCol netLimitCol", colspan: 6},
- TABLE({cellpadding: 0, cellspacing: 0},
- TBODY(
- TR(
- TD(
- SPAN({"class": "netLimitLabel"},
- $STRP("plural.Limit_Exceeded", [0])
- )
- ),
- TD({style: "width:100%"}),
- TD(
- BUTTON({"class": "netLimitButton", title: "$limitPrefsTitle",
- onclick: "$onPreferences"},
- $STR("LimitPrefs")
- )
- ),
- TD(" ")
- )
- )
- )
- )
- ),
- isCollapsed: function()
- {
- return this.collapsed;
- },
- onPreferences: function(event)
- {
- openNewTab("about:config");
- },
- updateCounter: function(row)
- {
- removeClass(row, "collapsed");
- // Update info within the limit row.
- var limitLabel = row.getElementsByClassName("netLimitLabel").item(0);
- limitLabel.firstChild.nodeValue = $STRP("plural.Limit_Exceeded", [row.limitInfo.totalCount]);
- },
- createTable: function(parent, limitInfo)
- {
- var table = this.tableTag.replace({}, parent);
- var row = this.createRow(table.firstChild.firstChild, limitInfo);
- return [table, row];
- },
- createRow: function(parent, limitInfo)
- {
- var row = this.limitTag.insertRows(limitInfo, parent, this)[0];
- row.limitInfo = limitInfo;
- return row;
- },
- // nsIPrefObserver
- observe: function(subject, topic, data)
- {
- // We're observing preferences only.
- if (topic != "nsPref:changed")
- return;
- if (data.indexOf("net.logLimit") != -1)
- this.updateMaxLimit();
- },
- updateMaxLimit: function()
- {
- var value = Firebug.getPref(Firebug.prefDomain, "net.logLimit");
- maxQueueRequests = value ? value : maxQueueRequests;
- }
- });
- var NetLimit = Firebug.NetMonitor.NetLimit;
- // ************************************************************************************************
- Firebug.NetMonitor.ResponseSizeLimit = domplate(Firebug.Rep,
- {
- tag:
- DIV({"class": "netInfoResponseSizeLimit"},
- SPAN("$object.beforeLink"),
- A({"class": "objectLink", onclick: "$onClickLink"},
- "$object.linkText"
- ),
- SPAN("$object.afterLink")
- ),
- reLink: /^(.*)<a>(.*)<\/a>(.*$)/,
- append: function(obj, parent)
- {
- var m = obj.text.match(this.reLink);
- return this.tag.append({onClickLink: obj.onClickLink,
- object: {
- beforeLink: m[1],
- linkText: m[2],
- afterLink: m[3]
- }}, parent, this);
- }
- });
- // ************************************************************************************************
- // ************************************************************************************************
- Firebug.NetMonitor.Utils =
- {
- findHeader: function(headers, name)
- {
- if (!headers)
- return null;
- name = name.toLowerCase();
- for (var i = 0; i < headers.length; ++i)
- {
- var headerName = headers[i].name.toLowerCase();
- if (headerName == name)
- return headers[i].value;
- }
- },
- formatPostText: function(text)
- {
- if (text instanceof XMLDocument)
- return getElementXML(text.documentElement);
- else
- return text;
- },
- getPostText: function(file, context, noLimit)
- {
- if (!file.postText)
- {
- file.postText = readPostTextFromRequest(file.request, context);
- if (!file.postText && context)
- file.postText = readPostTextFromPage(file.href, context);
- }
- if (!file.postText)
- return file.postText;
- var limit = Firebug.netDisplayedPostBodyLimit;
- if (file.postText.length > limit && !noLimit)
- {
- return cropString(file.postText, limit,
- "\n\n... " + $STR("net.postDataSizeLimitMessage") + " ...\n\n");
- }
- return file.postText;
- },
- getResponseText: function(file, context)
- {
- // The response can be also empty string so, check agains "undefined".
- return (typeof(file.responseText) != "undefined")? file.responseText :
- context.sourceCache.loadText(file.href, file.method, file);
- },
- isURLEncodedRequest: function(file, context)
- {
- var text = Utils.getPostText(file, context);
- if (text && text.toLowerCase().indexOf("content-type: application/x-www-form-urlencoded") == 0)
- return true;
- // The header value doesn't have to be always exactly "application/x-www-form-urlencoded",
- // there can be even charset specified. So, use indexOf rather than just "==".
- var headerValue = Utils.findHeader(file.requestHeaders, "content-type");
- if (headerValue && headerValue.indexOf("application/x-www-form-urlencoded") == 0)
- return true;
- return false;
- },
- isMultiPartRequest: function(file, context)
- {
- var text = Utils.getPostText(file, context);
- if (text && text.toLowerCase().indexOf("content-type: multipart/form-data") == 0)
- return true;
- return false;
- },
- getMimeType: function(mimeType, uri)
- {
- if (!mimeType || !(mimeCategoryMap.hasOwnProperty(mimeType)))
- {
- var ext = getFileExtension(uri);
- if (!ext)
- return mimeType;
- else
- {
- var extMimeType = mimeExtensionMap[ext.toLowerCase()];
- return extMimeType ? extMimeType : mimeType;
- }
- }
- else
- return mimeType;
- },
- getDateFromSeconds: function(s)
- {
- var d = new Date();
- d.setTime(s*1000);
- return d;
- },
- getHttpHeaders: function(request, file)
- {
- try
- {
- var http = QI(request, Ci.nsIHttpChannel);
- file.status = request.responseStatus;
- // xxxHonza: is there any problem to do this in requestedFile method?
- file.method = http.requestMethod;
- file.urlParams = parseURLParams(file.href);
- file.mimeType = Utils.getMimeType(request.contentType, request.name);
- if (!file.responseHeaders && Firebug.collectHttpHeaders)
- {
- var requestHeaders = [], responseHeaders = [];
- http.visitRequestHeaders({
- visitHeader: function(name, value)
- {
- requestHeaders.push({name: name, value: value});
- }
- });
- http.visitResponseHeaders({
- visitHeader: function(name, value)
- {
- responseHeaders.push({name: name, value: value});
- }
- });
- file.requestHeaders = requestHeaders;
- file.responseHeaders = responseHeaders;
- }
- }
- catch (exc)
- {
- // An exception can be throwed e.g. when the request is aborted and
- // request.responseStatus is accessed.
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("net.getHttpHeaders FAILS " + file.href, exc);
- }
- },
- isXHR: function(request)
- {
- try
- {
- var callbacks = request.notificationCallbacks;
- var xhrRequest = callbacks ? callbacks.getInterface(Ci.nsIXMLHttpRequest) : null;
- if (FBTrace.DBG_NET)
- FBTrace.sysout("net.isXHR; " + (xhrRequest != null) + ", " + safeGetName(request));
- return (xhrRequest != null);
- }
- catch (exc)
- {
- }
- return false;
- },
- getFileCategory: function(file)
- {
- if (file.category)
- {
- if (FBTrace.DBG_NET)
- FBTrace.sysout("net.getFileCategory; current: " + file.category + " for: " + file.href, file);
- return file.category;
- }
- if (file.isXHR)
- {
- if (FBTrace.DBG_NET)
- FBTrace.sysout("net.getFileCategory; XHR for: " + file.href, file);
- return file.category = "xhr";
- }
- if (!file.mimeType)
- {
- var ext = getFileExtension(file.href);
- if (ext)
- file.mimeType = mimeExtensionMap[ext.toLowerCase()];
- }
- /*if (FBTrace.DBG_NET)
- FBTrace.sysout("net.getFileCategory; " + mimeCategoryMap[file.mimeType] +
- ", mimeType: " + file.mimeType + " for: " + file.href, file);*/
- if (!file.mimeType)
- return "";
- // Solve cases when charset is also specified, eg "text/html; charset=UTF-8".
- var mimeType = file.mimeType;
- if (mimeType)
- mimeType = mimeType.split(";")[0];
- return (file.category = mimeCategoryMap[mimeType]);
- }
- };
- var Utils = Firebug.NetMonitor.Utils;
- // ************************************************************************************************
- //Firebug.registerRep(Firebug.NetMonitor.NetRequestTable);
- //Firebug.registerActivableModule(Firebug.NetMonitor);
- //Firebug.registerPanel(NetPanel);
- Firebug.registerModule(Firebug.NetMonitor);
- //Firebug.registerRep(Firebug.NetMonitor.BreakpointRep);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // Constants
- //const Cc = Components.classes;
- //const Ci = Components.interfaces;
- // List of contexts with XHR spy attached.
- var contexts = [];
- // ************************************************************************************************
- // Spy Module
- /**
- * @module Represents a XHR Spy module. The main purpose of the XHR Spy feature is to monitor
- * XHR activity of the current page and create appropriate log into the Console panel.
- * This feature can be controlled by an option <i>Show XMLHttpRequests</i> (from within the
- * console panel).
- *
- * The module is responsible for attaching/detaching a HTTP Observers when Firebug is
- * activated/deactivated for a site.
- */
- Firebug.Spy = extend(Firebug.Module,
- /** @lends Firebug.Spy */
- {
- dispatchName: "spy",
- initialize: function()
- {
- if (Firebug.TraceModule)
- Firebug.TraceModule.addListener(this.TraceListener);
- Firebug.Module.initialize.apply(this, arguments);
- },
- shutdown: function()
- {
- Firebug.Module.shutdown.apply(this, arguments);
- if (Firebug.TraceModule)
- Firebug.TraceModule.removeListener(this.TraceListener);
- },
- initContext: function(context)
- {
- context.spies = [];
- if (Firebug.showXMLHttpRequests && Firebug.Console.isAlwaysEnabled())
- this.attachObserver(context, context.window);
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.initContext " + contexts.length + " ", context.getName());
- },
- destroyContext: function(context)
- {
- // For any spies that are in progress, remove our listeners so that they don't leak
- this.detachObserver(context, null);
- if (FBTrace.DBG_SPY && context.spies.length)
- FBTrace.sysout("spy.destroyContext; ERROR There are leaking Spies ("
- + context.spies.length + ") " + context.getName());
- delete context.spies;
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.destroyContext " + contexts.length + " ", context.getName());
- },
- watchWindow: function(context, win)
- {
- if (Firebug.showXMLHttpRequests && Firebug.Console.isAlwaysEnabled())
- this.attachObserver(context, win);
- },
- unwatchWindow: function(context, win)
- {
- try
- {
- // This make sure that the existing context is properly removed from "contexts" array.
- this.detachObserver(context, win);
- }
- catch (ex)
- {
- // Get exceptions here sometimes, so let's just ignore them
- // since the window is going away anyhow
- ERROR(ex);
- }
- },
- updateOption: function(name, value)
- {
- // XXXjjb Honza, if Console.isEnabled(context) false, then this can't be called,
- // but somehow seems not correct
- if (name == "showXMLHttpRequests")
- {
- var tach = value ? this.attachObserver : this.detachObserver;
- for (var i = 0; i < TabWatcher.contexts.length; ++i)
- {
- var context = TabWatcher.contexts[i];
- iterateWindows(context.window, function(win)
- {
- tach.apply(this, [context, win]);
- });
- }
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Attaching Spy to XHR requests.
- /**
- * Returns false if Spy should not be attached to XHRs executed by the specified window.
- */
- skipSpy: function(win)
- {
- if (!win)
- return true;
- // Don't attach spy to chrome.
- var uri = safeGetWindowLocation(win);
- if (uri && (uri.indexOf("about:") == 0 || uri.indexOf("chrome:") == 0))
- return true;
- },
- attachObserver: function(context, win)
- {
- if (Firebug.Spy.skipSpy(win))
- return;
- for (var i=0; i<contexts.length; ++i)
- {
- if ((contexts[i].context == context) && (contexts[i].win == win))
- return;
- }
- // Register HTTP observers only once.
- if (contexts.length == 0)
- {
- httpObserver.addObserver(SpyHttpObserver, "firebug-http-event", false);
- SpyHttpActivityObserver.registerObserver();
- }
- contexts.push({context: context, win: win});
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.attachObserver (HTTP) " + contexts.length + " ", context.getName());
- },
- detachObserver: function(context, win)
- {
- for (var i=0; i<contexts.length; ++i)
- {
- if (contexts[i].context == context)
- {
- if (win && (contexts[i].win != win))
- continue;
- contexts.splice(i, 1);
- // If no context is using spy, remvove the (only one) HTTP observer.
- if (contexts.length == 0)
- {
- httpObserver.removeObserver(SpyHttpObserver, "firebug-http-event");
- SpyHttpActivityObserver.unregisterObserver();
- }
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.detachObserver (HTTP) " + contexts.length + " ",
- context.getName());
- return;
- }
- }
- },
- /**
- * Return XHR object that is associated with specified request <i>nsIHttpChannel</i>.
- * Returns null if the request doesn't represent XHR.
- */
- getXHR: function(request)
- {
- // Does also query-interface for nsIHttpChannel.
- if (!(request instanceof Ci.nsIHttpChannel))
- return null;
- try
- {
- var callbacks = request.notificationCallbacks;
- return (callbacks ? callbacks.getInterface(Ci.nsIXMLHttpRequest) : null);
- }
- catch (exc)
- {
- if (exc.name == "NS_NOINTERFACE")
- {
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.getXHR; Request is not nsIXMLHttpRequest: " +
- safeGetRequestName(request));
- }
- }
- return null;
- }
- });
- // ************************************************************************************************
- /*
- function getSpyForXHR(request, xhrRequest, context, noCreate)
- {
- var spy = null;
- // Iterate all existing spy objects in this context and look for one that is
- // already created for this request.
- var length = context.spies.length;
- for (var i=0; i<length; i++)
- {
- spy = context.spies[i];
- if (spy.request == request)
- return spy;
- }
- if (noCreate)
- return null;
- spy = new Firebug.Spy.XMLHttpRequestSpy(request, xhrRequest, context);
- context.spies.push(spy);
- var name = request.URI.asciiSpec;
- var origName = request.originalURI.asciiSpec;
- // Attach spy only to the original request. Notice that there can be more network requests
- // made by the same XHR if redirects are involved.
- if (name == origName)
- spy.attach();
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.getSpyForXHR; New spy object created (" +
- (name == origName ? "new XHR" : "redirected XHR") + ") for: " + name, spy);
- return spy;
- }
- /**/
- // ************************************************************************************************
- /**
- * @class This class represents a Spy object that is attached to XHR. This object
- * registers various listeners into the XHR in order to monitor various events fired
- * during the request process (onLoad, onAbort, etc.)
- */
- /*
- Firebug.Spy.XMLHttpRequestSpy = function(request, xhrRequest, context)
- {
- this.request = request;
- this.xhrRequest = xhrRequest;
- this.context = context;
- this.responseText = "";
- // For compatibility with the Net templates.
- this.isXHR = true;
- // Support for activity-observer
- this.transactionStarted = false;
- this.transactionClosed = false;
- };
- /**/
- //Firebug.Spy.XMLHttpRequestSpy.prototype =
- /** @lends Firebug.Spy.XMLHttpRequestSpy */
- /*
- {
- attach: function()
- {
- var spy = this;
- this.onReadyStateChange = function(event) { onHTTPSpyReadyStateChange(spy, event); };
- this.onLoad = function() { onHTTPSpyLoad(spy); };
- this.onError = function() { onHTTPSpyError(spy); };
- this.onAbort = function() { onHTTPSpyAbort(spy); };
- // xxxHonza: #502959 is still failing on Fx 3.5
- // Use activity distributor to identify 3.6
- if (SpyHttpActivityObserver.getActivityDistributor())
- {
- this.onreadystatechange = this.xhrRequest.onreadystatechange;
- this.xhrRequest.onreadystatechange = this.onReadyStateChange;
- }
- this.xhrRequest.addEventListener("load", this.onLoad, false);
- this.xhrRequest.addEventListener("error", this.onError, false);
- this.xhrRequest.addEventListener("abort", this.onAbort, false);
- // xxxHonza: should be removed from FB 3.6
- if (!SpyHttpActivityObserver.getActivityDistributor())
- this.context.sourceCache.addListener(this);
- },
- detach: function()
- {
- // Bubble out if already detached.
- if (!this.onLoad)
- return;
- // If the activity distributor is available, let's detach it when the XHR
- // transaction is closed. Since, in case of multipart XHRs the onLoad method
- // (readyState == 4) can be called mutliple times.
- // Keep in mind:
- // 1) It can happen that that the TRANSACTION_CLOSE event comes before
- // the onLoad (if the XHR is made as part of the page load) so, detach if
- // it's already closed.
- // 2) In case of immediate cache responses, the transaction doesn't have to
- // be started at all (or the activity observer is no available in Firefox 3.5).
- // So, also detach in this case.
- if (this.transactionStarted && !this.transactionClosed)
- return;
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.detach; " + this.href);
- // Remove itself from the list of active spies.
- remove(this.context.spies, this);
- if (this.onreadystatechange)
- this.xhrRequest.onreadystatechange = this.onreadystatechange;
- try { this.xhrRequest.removeEventListener("load", this.onLoad, false); } catch (e) {}
- try { this.xhrRequest.removeEventListener("error", this.onError, false); } catch (e) {}
- try { this.xhrRequest.removeEventListener("abort", this.onAbort, false); } catch (e) {}
- this.onreadystatechange = null;
- this.onLoad = null;
- this.onError = null;
- this.onAbort = null;
- // xxxHonza: shouuld be removed from FB 1.6
- if (!SpyHttpActivityObserver.getActivityDistributor())
- this.context.sourceCache.removeListener(this);
- },
- getURL: function()
- {
- return this.xhrRequest.channel ? this.xhrRequest.channel.name : this.href;
- },
- // Cache listener
- onStopRequest: function(context, request, responseText)
- {
- if (!responseText)
- return;
- if (request == this.request)
- this.responseText = responseText;
- },
- };
- /**/
- // ************************************************************************************************
- /*
- function onHTTPSpyReadyStateChange(spy, event)
- {
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.onHTTPSpyReadyStateChange " + spy.xhrRequest.readyState +
- " (multipart: " + spy.xhrRequest.multipart + ")");
- // Remember just in case spy is detached (readyState == 4).
- var originalHandler = spy.onreadystatechange;
- // Force response text to be updated in the UI (in case the console entry
- // has been already expanded and the response tab selected).
- if (spy.logRow && spy.xhrRequest.readyState >= 3)
- {
- var netInfoBox = getChildByClass(spy.logRow, "spyHead", "netInfoBody");
- if (netInfoBox)
- {
- netInfoBox.htmlPresented = false;
- netInfoBox.responsePresented = false;
- }
- }
- // If the request is loading update the end time.
- if (spy.xhrRequest.readyState == 3)
- {
- spy.responseTime = spy.endTime - spy.sendTime;
- updateTime(spy);
- }
- // Request loaded. Get all the info from the request now, just in case the
- // XHR would be aborted in the original onReadyStateChange handler.
- if (spy.xhrRequest.readyState == 4)
- {
- // Cumulate response so, multipart response content is properly displayed.
- if (SpyHttpActivityObserver.getActivityDistributor())
- spy.responseText += spy.xhrRequest.responseText;
- else
- {
- // xxxHonza: remove from FB 1.6
- if (!spy.responseText)
- spy.responseText = spy.xhrRequest.responseText;
- }
- // The XHR is loaded now (used also by the activity observer).
- spy.loaded = true;
- // Update UI.
- updateHttpSpyInfo(spy);
- // Notify Net pane about a request beeing loaded.
- // xxxHonza: I don't think this is necessary.
- var netProgress = spy.context.netProgress;
- if (netProgress)
- netProgress.post(netProgress.stopFile, [spy.request, spy.endTime, spy.postText, spy.responseText]);
- // Notify registered listeners about finish of the XHR.
- dispatch(Firebug.Spy.fbListeners, "onLoad", [spy.context, spy]);
- }
- // Pass the event to the original page handler.
- callPageHandler(spy, event, originalHandler);
- }
- function onHTTPSpyLoad(spy)
- {
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.onHTTPSpyLoad: " + spy.href, spy);
- // Detach must be done in onLoad (not in onreadystatechange) otherwise
- // onAbort would not be handled.
- spy.detach();
- // xxxHonza: Still needed for Fx 3.5 (#502959)
- if (!SpyHttpActivityObserver.getActivityDistributor())
- onHTTPSpyReadyStateChange(spy, null);
- }
- function onHTTPSpyError(spy)
- {
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.onHTTPSpyError; " + spy.href, spy);
- spy.detach();
- spy.loaded = true;
- if (spy.logRow)
- {
- removeClass(spy.logRow, "loading");
- setClass(spy.logRow, "error");
- }
- }
- function onHTTPSpyAbort(spy)
- {
- if (FBTrace.DBG_SPY)
- FBTrace.sysout("spy.onHTTPSpyAbort: " + spy.href, spy);
- spy.detach();
- spy.loaded = true;
- if (spy.logRow)
- {
- removeClass(spy.logRow, "loading");
- setClass(spy.logRow, "error");
- }
- spy.statusText = "Aborted";
- updateLogRow(spy);
- // Notify Net pane about a request beeing aborted.
- // xxxHonza: the net panel shoud find out this itself.
- var netProgress = spy.context.netProgress;
- if (netProgress)
- netProgress.post(netProgress.abortFile, [spy.request, spy.endTime, spy.postText, spy.responseText]);
- }
- /**/
- // ************************************************************************************************
- /**
- * @domplate Represents a template for XHRs logged in the Console panel. The body of the
- * log (displayed when expanded) is rendered using {@link Firebug.NetMonitor.NetInfoBody}.
- */
- Firebug.Spy.XHR = domplate(Firebug.Rep,
- /** @lends Firebug.Spy.XHR */
- {
- tag:
- DIV({"class": "spyHead", _repObject: "$object"},
- TABLE({"class": "spyHeadTable focusRow outerFocusRow", cellpadding: 0, cellspacing: 0,
- "role": "listitem", "aria-expanded": "false"},
- TBODY({"role": "presentation"},
- TR({"class": "spyRow"},
- TD({"class": "spyTitleCol spyCol", onclick: "$onToggleBody"},
- DIV({"class": "spyTitle"},
- "$object|getCaption"
- ),
- DIV({"class": "spyFullTitle spyTitle"},
- "$object|getFullUri"
- )
- ),
- TD({"class": "spyCol"},
- DIV({"class": "spyStatus"}, "$object|getStatus")
- ),
- TD({"class": "spyCol"},
- SPAN({"class": "spyIcon"})
- ),
- TD({"class": "spyCol"},
- SPAN({"class": "spyTime"})
- ),
- TD({"class": "spyCol"},
- TAG(FirebugReps.SourceLink.tag, {object: "$object.sourceLink"})
- )
- )
- )
- )
- ),
- getCaption: function(spy)
- {
- return spy.method.toUpperCase() + " " + cropString(spy.getURL(), 100);
- },
- getFullUri: function(spy)
- {
- return spy.method.toUpperCase() + " " + spy.getURL();
- },
- getStatus: function(spy)
- {
- var text = "";
- if (spy.statusCode)
- text += spy.statusCode + " ";
- if (spy.statusText)
- return text += spy.statusText;
- return text;
- },
- onToggleBody: function(event)
- {
- var target = event.currentTarget || event.srcElement;
- var logRow = getAncestorByClass(target, "logRow-spy");
- if (isLeftClick(event))
- {
- toggleClass(logRow, "opened");
- var spy = getChildByClass(logRow, "spyHead").repObject;
- var spyHeadTable = getAncestorByClass(target, "spyHeadTable");
- if (hasClass(logRow, "opened"))
- {
- updateHttpSpyInfo(spy, logRow);
- if (spyHeadTable)
- spyHeadTable.setAttribute('aria-expanded', 'true');
- }
- else
- {
- //var netInfoBox = getChildByClass(spy.logRow, "spyHead", "netInfoBody");
- //dispatch(Firebug.NetMonitor.NetInfoBody.fbListeners, "destroyTabBody", [netInfoBox, spy]);
- //if (spyHeadTable)
- // spyHeadTable.setAttribute('aria-expanded', 'false');
- }
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- copyURL: function(spy)
- {
- copyToClipboard(spy.getURL());
- },
- copyParams: function(spy)
- {
- var text = spy.postText;
- if (!text)
- return;
- var url = reEncodeURL(spy, text, true);
- copyToClipboard(url);
- },
- copyResponse: function(spy)
- {
- copyToClipboard(spy.responseText);
- },
- openInTab: function(spy)
- {
- openNewTab(spy.getURL(), spy.postText);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- supportsObject: function(object)
- {
- // TODO: xxxpedro spy xhr
- return false;
- return object instanceof Firebug.Spy.XMLHttpRequestSpy;
- },
- browseObject: function(spy, context)
- {
- var url = spy.getURL();
- openNewTab(url);
- return true;
- },
- getRealObject: function(spy, context)
- {
- return spy.xhrRequest;
- },
- getContextMenuItems: function(spy)
- {
- var items = [
- {label: "CopyLocation", command: bindFixed(this.copyURL, this, spy) }
- ];
- if (spy.postText)
- {
- items.push(
- {label: "CopyLocationParameters", command: bindFixed(this.copyParams, this, spy) }
- );
- }
- items.push(
- {label: "CopyResponse", command: bindFixed(this.copyResponse, this, spy) },
- "-",
- {label: "OpenInTab", command: bindFixed(this.openInTab, this, spy) }
- );
- return items;
- }
- });
- // ************************************************************************************************
- function updateTime(spy)
- {
- var timeBox = spy.logRow.getElementsByClassName("spyTime").item(0);
- if (spy.responseTime)
- timeBox.textContent = " " + formatTime(spy.responseTime);
- }
- function updateLogRow(spy)
- {
- updateTime(spy);
- var statusBox = spy.logRow.getElementsByClassName("spyStatus").item(0);
- statusBox.textContent = Firebug.Spy.XHR.getStatus(spy);
- removeClass(spy.logRow, "loading");
- setClass(spy.logRow, "loaded");
- try
- {
- var errorRange = Math.floor(spy.xhrRequest.status/100);
- if (errorRange == 4 || errorRange == 5)
- setClass(spy.logRow, "error");
- }
- catch (exc)
- {
- }
- }
- var updateHttpSpyInfo = function updateHttpSpyInfo(spy, logRow)
- {
- if (!spy.logRow && logRow)
- spy.logRow = logRow;
- if (!spy.logRow || !hasClass(spy.logRow, "opened"))
- return;
- if (!spy.params)
- //spy.params = parseURLParams(spy.href+"");
- spy.params = parseURLParams(spy.href+"");
- if (!spy.requestHeaders)
- spy.requestHeaders = getRequestHeaders(spy);
- if (!spy.responseHeaders && spy.loaded)
- spy.responseHeaders = getResponseHeaders(spy);
- var template = Firebug.NetMonitor.NetInfoBody;
- var netInfoBox = getChildByClass(spy.logRow, "spyHead", "netInfoBody");
- if (!netInfoBox)
- {
- var head = getChildByClass(spy.logRow, "spyHead");
- netInfoBox = template.tag.append({"file": spy}, head);
- dispatch(template.fbListeners, "initTabBody", [netInfoBox, spy]);
- template.selectTabByName(netInfoBox, "Response");
- }
- else
- {
- template.updateInfo(netInfoBox, spy, spy.context);
- }
- };
- // ************************************************************************************************
- function getRequestHeaders(spy)
- {
- var headers = [];
- var channel = spy.xhrRequest.channel;
- if (channel instanceof Ci.nsIHttpChannel)
- {
- channel.visitRequestHeaders({
- visitHeader: function(name, value)
- {
- headers.push({name: name, value: value});
- }
- });
- }
- return headers;
- }
- function getResponseHeaders(spy)
- {
- var headers = [];
- try
- {
- var channel = spy.xhrRequest.channel;
- if (channel instanceof Ci.nsIHttpChannel)
- {
- channel.visitResponseHeaders({
- visitHeader: function(name, value)
- {
- headers.push({name: name, value: value});
- }
- });
- }
- }
- catch (exc)
- {
- if (FBTrace.DBG_SPY || FBTrace.DBG_ERRORS)
- FBTrace.sysout("spy.getResponseHeaders; EXCEPTION " +
- safeGetRequestName(spy.request), exc);
- }
- return headers;
- }
- // ************************************************************************************************
- // Registration
- Firebug.registerModule(Firebug.Spy);
- //Firebug.registerRep(Firebug.Spy.XHR);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // List of JSON content types.
- var contentTypes =
- {
- "text/plain": 1,
- "text/javascript": 1,
- "text/x-javascript": 1,
- "text/json": 1,
- "text/x-json": 1,
- "application/json": 1,
- "application/x-json": 1,
- "application/javascript": 1,
- "application/x-javascript": 1,
- "application/json-rpc": 1
- };
- // ************************************************************************************************
- // Model implementation
- Firebug.JSONViewerModel = extend(Firebug.Module,
- {
- dispatchName: "jsonViewer",
- initialize: function()
- {
- Firebug.NetMonitor.NetInfoBody.addListener(this);
- // Used by Firebug.DOMPanel.DirTable domplate.
- this.toggles = {};
- },
- shutdown: function()
- {
- Firebug.NetMonitor.NetInfoBody.removeListener(this);
- },
- initTabBody: function(infoBox, file)
- {
- if (FBTrace.DBG_JSONVIEWER)
- FBTrace.sysout("jsonviewer.initTabBody", infoBox);
- // Let listeners to parse the JSON.
- dispatch(this.fbListeners, "onParseJSON", [file]);
- // The JSON is still no there, try to parse most common cases.
- if (!file.jsonObject)
- {
- ///if (this.isJSON(safeGetContentType(file.request), file.responseText))
- if (this.isJSON(file.mimeType, file.responseText))
- file.jsonObject = this.parseJSON(file);
- }
- // The jsonObject is created so, the JSON tab can be displayed.
- if (file.jsonObject && hasProperties(file.jsonObject))
- {
- Firebug.NetMonitor.NetInfoBody.appendTab(infoBox, "JSON",
- ///$STR("jsonviewer.tab.JSON"));
- $STR("JSON"));
- if (FBTrace.DBG_JSONVIEWER)
- FBTrace.sysout("jsonviewer.initTabBody; JSON object available " +
- (typeof(file.jsonObject) != "undefined"), file.jsonObject);
- }
- },
- isJSON: function(contentType, data)
- {
- // Workaround for JSON responses without proper content type
- // Let's consider all responses starting with "{" as JSON. In the worst
- // case there will be an exception when parsing. This means that no-JSON
- // responses (and post data) (with "{") can be parsed unnecessarily,
- // which represents a little overhead, but this happens only if the request
- // is actually expanded by the user in the UI (Net & Console panels).
- ///var responseText = data ? trimLeft(data) : null;
- ///if (responseText && responseText.indexOf("{") == 0)
- /// return true;
- var responseText = data ? trim(data) : null;
- if (responseText && responseText.indexOf("{") == 0)
- return true;
- if (!contentType)
- return false;
- contentType = contentType.split(";")[0];
- contentType = trim(contentType);
- return contentTypes[contentType];
- },
- // Update listener for TabView
- updateTabBody: function(infoBox, file, context)
- {
- var tab = infoBox.selectedTab;
- ///var tabBody = infoBox.getElementsByClassName("netInfoJSONText").item(0);
- var tabBody = $$(".netInfoJSONText", infoBox)[0];
- if (!hasClass(tab, "netInfoJSONTab") || tabBody.updated)
- return;
- tabBody.updated = true;
- if (file.jsonObject) {
- Firebug.DOMPanel.DirTable.tag.replace(
- {object: file.jsonObject, toggles: this.toggles}, tabBody);
- }
- },
- parseJSON: function(file)
- {
- var jsonString = new String(file.responseText);
- ///return parseJSONString(jsonString, "http://" + file.request.originalURI.host);
- return parseJSONString(jsonString);
- }
- });
- // ************************************************************************************************
- // Registration
- Firebug.registerModule(Firebug.JSONViewerModel);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // Constants
- // List of XML related content types.
- var xmlContentTypes =
- [
- "text/xml",
- "application/xml",
- "application/xhtml+xml",
- "application/rss+xml",
- "application/atom+xml",,
- "application/vnd.mozilla.maybe.feed",
- "application/rdf+xml",
- "application/vnd.mozilla.xul+xml"
- ];
- // ************************************************************************************************
- // Model implementation
- /**
- * @module Implements viewer for XML based network responses. In order to create a new
- * tab wihin network request detail, a listener is registered into
- * <code>Firebug.NetMonitor.NetInfoBody</code> object.
- */
- Firebug.XMLViewerModel = extend(Firebug.Module,
- {
- dispatchName: "xmlViewer",
- initialize: function()
- {
- ///Firebug.ActivableModule.initialize.apply(this, arguments);
- Firebug.Module.initialize.apply(this, arguments);
- Firebug.NetMonitor.NetInfoBody.addListener(this);
- },
- shutdown: function()
- {
- ///Firebug.ActivableModule.shutdown.apply(this, arguments);
- Firebug.Module.shutdown.apply(this, arguments);
- Firebug.NetMonitor.NetInfoBody.removeListener(this);
- },
- /**
- * Check response's content-type and if it's a XML, create a new tab with XML preview.
- */
- initTabBody: function(infoBox, file)
- {
- if (FBTrace.DBG_XMLVIEWER)
- FBTrace.sysout("xmlviewer.initTabBody", infoBox);
- // If the response is XML let's display a pretty preview.
- ///if (this.isXML(safeGetContentType(file.request)))
- if (this.isXML(file.mimeType, file.responseText))
- {
- Firebug.NetMonitor.NetInfoBody.appendTab(infoBox, "XML",
- ///$STR("xmlviewer.tab.XML"));
- $STR("XML"));
- if (FBTrace.DBG_XMLVIEWER)
- FBTrace.sysout("xmlviewer.initTabBody; XML response available");
- }
- },
- isXML: function(contentType)
- {
- if (!contentType)
- return false;
- // Look if the response is XML based.
- for (var i=0; i<xmlContentTypes.length; i++)
- {
- if (contentType.indexOf(xmlContentTypes[i]) == 0)
- return true;
- }
- return false;
- },
- /**
- * Parse XML response and render pretty printed preview.
- */
- updateTabBody: function(infoBox, file, context)
- {
- var tab = infoBox.selectedTab;
- ///var tabBody = infoBox.getElementsByClassName("netInfoXMLText").item(0);
- var tabBody = $$(".netInfoXMLText", infoBox)[0];
- if (!hasClass(tab, "netInfoXMLTab") || tabBody.updated)
- return;
- tabBody.updated = true;
- this.insertXML(tabBody, Firebug.NetMonitor.Utils.getResponseText(file, context));
- },
- insertXML: function(parentNode, text)
- {
- var xmlText = text.replace(/^\s*<?.+?>\s*/, "");
- var div = parentNode.ownerDocument.createElement("div");
- div.innerHTML = xmlText;
- var root = div.getElementsByTagName("*")[0];
- /***
- var parser = CCIN("@mozilla.org/xmlextras/domparser;1", "nsIDOMParser");
- var doc = parser.parseFromString(text, "text/xml");
- var root = doc.documentElement;
- // Error handling
- var nsURI = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
- if (root.namespaceURI == nsURI && root.nodeName == "parsererror")
- {
- this.ParseError.tag.replace({error: {
- message: root.firstChild.nodeValue,
- source: root.lastChild.textContent
- }}, parentNode);
- return;
- }
- /**/
- if (FBTrace.DBG_XMLVIEWER)
- FBTrace.sysout("xmlviewer.updateTabBody; XML response parsed", doc);
- // Override getHidden in these templates. The parsed XML documen is
- // hidden, but we want to display it using 'visible' styling.
- /*
- var templates = [
- Firebug.HTMLPanel.CompleteElement,
- Firebug.HTMLPanel.Element,
- Firebug.HTMLPanel.TextElement,
- Firebug.HTMLPanel.EmptyElement,
- Firebug.HTMLPanel.XEmptyElement,
- ];
- var originals = [];
- for (var i=0; i<templates.length; i++)
- {
- originals[i] = templates[i].getHidden;
- templates[i].getHidden = function() {
- return "";
- }
- }
- /**/
- // Generate XML preview.
- ///Firebug.HTMLPanel.CompleteElement.tag.replace({object: doc.documentElement}, parentNode);
- // TODO: xxxpedro html3
- ///Firebug.HTMLPanel.CompleteElement.tag.replace({object: root}, parentNode);
- var html = [];
- Firebug.Reps.appendNode(root, html);
- parentNode.innerHTML = html.join("");
- /*
- for (var i=0; i<originals.length; i++)
- templates[i].getHidden = originals[i];/**/
- }
- });
- // ************************************************************************************************
- // Domplate
- /**
- * @domplate Represents a template for displaying XML parser errors. Used by
- * <code>Firebug.XMLViewerModel</code>.
- */
- Firebug.XMLViewerModel.ParseError = domplate(Firebug.Rep,
- {
- tag:
- DIV({"class": "xmlInfoError"},
- DIV({"class": "xmlInfoErrorMsg"}, "$error.message"),
- PRE({"class": "xmlInfoErrorSource"}, "$error|getSource")
- ),
- getSource: function(error)
- {
- var parts = error.source.split("\n");
- if (parts.length != 2)
- return error.source;
- var limit = 50;
- var column = parts[1].length;
- if (column >= limit) {
- parts[0] = "..." + parts[0].substr(column - limit);
- parts[1] = "..." + parts[1].substr(column - limit);
- }
- if (parts[0].length > 80)
- parts[0] = parts[0].substr(0, 80) + "...";
- return parts.join("\n");
- }
- });
- // ************************************************************************************************
- // Registration
- Firebug.registerModule(Firebug.XMLViewerModel);
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Globals
- var ElementCache = Firebug.Lite.Cache.Element;
- var cacheID = Firebug.Lite.Cache.ID;
- var ignoreHTMLProps =
- {
- // ignores the attributes injected by Sizzle, otherwise it will
- // be visible on IE (when enumerating element.attributes)
- sizcache: 1,
- sizset: 1
- };
- // ignores also the cache property injected by firebug
- ignoreHTMLProps[cacheID] = 1;
- // ************************************************************************************************
- // HTML Module
- Firebug.HTML = extend(Firebug.Module,
- {
- appendTreeNode: function(nodeArray, html)
- {
- var reTrim = /^\s+|\s+$/g;
- if (!nodeArray.length) nodeArray = [nodeArray];
- for (var n=0, node; node=nodeArray[n]; n++)
- {
- if (node.nodeType == 1)
- {
- if (Firebug.ignoreFirebugElements && node.firebugIgnore) continue;
- var uid = ElementCache(node);
- var child = node.childNodes;
- var childLength = child.length;
- var nodeName = node.nodeName.toLowerCase();
- var nodeVisible = isVisible(node);
- var hasSingleTextChild = childLength == 1 && node.firstChild.nodeType == 3 &&
- nodeName != "script" && nodeName != "style";
- var nodeControl = !hasSingleTextChild && childLength > 0 ?
- ('<div class="nodeControl"></div>') : '';
- var isIE = false;
- if(isIE && nodeControl)
- html.push(nodeControl);
- if (typeof uid != 'undefined')
- html.push(
- '<div class="objectBox-element" ',
- 'id="', uid,
- '">',
- !isIE && nodeControl ? nodeControl: "",
- '<span ',
- cacheID,
- '="', uid,
- '" class="nodeBox',
- nodeVisible ? "" : " nodeHidden",
- '"><<span class="nodeTag">', nodeName, '</span>'
- );
- else
- html.push(
- '<div class="objectBox-element"><span class="nodeBox',
- nodeVisible ? "" : " nodeHidden",
- '"><<span class="nodeTag">',
- nodeName, '</span>'
- );
- for (var i = 0; i < node.attributes.length; ++i)
- {
- var attr = node.attributes[i];
- if (!attr.specified || Firebug.ignoreFirebugElements &&
- ignoreHTMLProps.hasOwnProperty(attr.nodeName))
- continue;
- var name = attr.nodeName.toLowerCase();
- var value = name == "style" ? formatStyles(node.style.cssText) : attr.nodeValue;
- html.push(' <span class="nodeName">', name,
- '</span>="<span class="nodeValue">', escapeHTML(value),
- '</span>"')
- }
- /*
- // source code nodes
- if (nodeName == 'script' || nodeName == 'style')
- {
- if(document.all){
- var src = node.innerHTML+'\n';
- }else {
- var src = '\n'+node.innerHTML+'\n';
- }
- var match = src.match(/\n/g);
- var num = match ? match.length : 0;
- var s = [], sl = 0;
- for(var c=1; c<num; c++){
- s[sl++] = '<div line="'+c+'">' + c + '</div>';
- }
- html.push('></div><div class="nodeGroup"><div class="nodeChildren"><div class="lineNo">',
- s.join(''),
- '</div><pre class="nodeCode">',
- escapeHTML(src),
- '</pre>',
- '</div><div class="objectBox-element"></<span class="nodeTag">',
- nodeName,
- '</span>></div>',
- '</div>'
- );
- }/**/
- // Just a single text node child
- if (hasSingleTextChild)
- {
- var value = child[0].nodeValue.replace(reTrim, '');
- if(value)
- {
- html.push(
- '><span class="nodeText">',
- escapeHTML(value),
- '</span></<span class="nodeTag">',
- nodeName,
- '</span>></span></div>'
- );
- }
- else
- html.push('/></span></div>'); // blank text, print as childless node
- }
- else if (childLength > 0)
- {
- html.push('></span></div>');
- }
- else
- html.push('/></span></div>');
- }
- else if (node.nodeType == 3)
- {
- if ( node.parentNode && ( node.parentNode.nodeName.toLowerCase() == "script" ||
- node.parentNode.nodeName.toLowerCase() == "style" ) )
- {
- var value = node.nodeValue.replace(reTrim, '');
- if(isIE){
- var src = value+'\n';
- }else {
- var src = '\n'+value+'\n';
- }
- var match = src.match(/\n/g);
- var num = match ? match.length : 0;
- var s = [], sl = 0;
- for(var c=1; c<num; c++){
- s[sl++] = '<div line="'+c+'">' + c + '</div>';
- }
- html.push('<div class="lineNo">',
- s.join(''),
- '</div><pre class="sourceCode">',
- escapeHTML(src),
- '</pre>'
- );
- }
- else
- {
- var value = node.nodeValue.replace(reTrim, '');
- if (value)
- html.push('<div class="nodeText">', escapeHTML(value),'</div>');
- }
- }
- }
- },
- appendTreeChildren: function(treeNode)
- {
- var doc = Firebug.chrome.document;
- var uid = treeNode.id;
- var parentNode = ElementCache.get(uid);
- if (parentNode.childNodes.length == 0) return;
- var treeNext = treeNode.nextSibling;
- var treeParent = treeNode.parentNode;
- var isIE = false;
- var control = isIE ? treeNode.previousSibling : treeNode.firstChild;
- control.className = 'nodeControl nodeMaximized';
- var html = [];
- var children = doc.createElement("div");
- children.className = "nodeChildren";
- this.appendTreeNode(parentNode.childNodes, html);
- children.innerHTML = html.join("");
- treeParent.insertBefore(children, treeNext);
- var closeElement = doc.createElement("div");
- closeElement.className = "objectBox-element";
- closeElement.innerHTML = '</<span class="nodeTag">' +
- parentNode.nodeName.toLowerCase() + '></span>'
- treeParent.insertBefore(closeElement, treeNext);
- },
- removeTreeChildren: function(treeNode)
- {
- var children = treeNode.nextSibling;
- var closeTag = children.nextSibling;
- var isIE = false;
- var control = isIE ? treeNode.previousSibling : treeNode.firstChild;
- control.className = 'nodeControl';
- children.parentNode.removeChild(children);
- closeTag.parentNode.removeChild(closeTag);
- },
- isTreeNodeVisible: function(id)
- {
- return $(id);
- },
- select: function(el)
- {
- var id = el && ElementCache(el);
- if (id)
- this.selectTreeNode(id);
- },
- selectTreeNode: function(id)
- {
- id = ""+id;
- var node, stack = [];
- while(id && !this.isTreeNodeVisible(id))
- {
- stack.push(id);
- var node = ElementCache.get(id).parentNode;
- if (node)
- id = ElementCache(node);
- else
- break;
- }
- stack.push(id);
- while(stack.length > 0)
- {
- id = stack.pop();
- node = $(id);
- if (stack.length > 0 && ElementCache.get(id).childNodes.length > 0)
- this.appendTreeChildren(node);
- }
- selectElement(node);
- // TODO: xxxpedro
- if (fbPanel1)
- fbPanel1.scrollTop = Math.round(node.offsetTop - fbPanel1.clientHeight/2);
- }
- });
- Firebug.registerModule(Firebug.HTML);
- // ************************************************************************************************
- // HTML Panel
- function HTMLPanel(){};
- HTMLPanel.prototype = extend(Firebug.Panel,
- {
- name: "HTML",
- title: "HTML",
- options: {
- hasSidePanel: true,
- //hasToolButtons: true,
- isPreRendered: true,
- innerHTMLSync: true
- },
- create: function(){
- Firebug.Panel.create.apply(this, arguments);
- this.panelNode.style.padding = "4px 3px 1px 15px";
- this.panelNode.style.minWidth = "500px";
- if (Env.Options.enablePersistent || Firebug.chrome.type != "popup")
- this.createUI();
- if(!this.sidePanelBar.selectedPanel)
- {
- this.sidePanelBar.selectPanel("css");
- }
- },
- destroy: function()
- {
- selectedElement = null
- fbPanel1 = null;
- selectedSidePanelTS = null;
- selectedSidePanelTimer = null;
- Firebug.Panel.destroy.apply(this, arguments);
- },
- createUI: function()
- {
- var rootNode = Firebug.browser.document.documentElement;
- var html = [];
- Firebug.HTML.appendTreeNode(rootNode, html);
- this.panelNode.innerHTML = html.join("");
- },
- initialize: function()
- {
- Firebug.Panel.initialize.apply(this, arguments);
- addEvent(this.panelNode, 'click', Firebug.HTML.onTreeClick);
- fbPanel1 = $("fbPanel1");
- if(!selectedElement)
- {
- Firebug.HTML.selectTreeNode(ElementCache(Firebug.browser.document.body));
- }
- // TODO: xxxpedro
- addEvent(fbPanel1, 'mousemove', Firebug.HTML.onListMouseMove);
- addEvent($("fbContent"), 'mouseout', Firebug.HTML.onListMouseMove);
- addEvent(Firebug.chrome.node, 'mouseout', Firebug.HTML.onListMouseMove);
- },
- shutdown: function()
- {
- // TODO: xxxpedro
- removeEvent(fbPanel1, 'mousemove', Firebug.HTML.onListMouseMove);
- removeEvent($("fbContent"), 'mouseout', Firebug.HTML.onListMouseMove);
- removeEvent(Firebug.chrome.node, 'mouseout', Firebug.HTML.onListMouseMove);
- removeEvent(this.panelNode, 'click', Firebug.HTML.onTreeClick);
- fbPanel1 = null;
- Firebug.Panel.shutdown.apply(this, arguments);
- },
- reattach: function()
- {
- // TODO: panel reattach
- if(FirebugChrome.selectedHTMLElementId)
- Firebug.HTML.selectTreeNode(FirebugChrome.selectedHTMLElementId);
- },
- updateSelection: function(object)
- {
- var id = ElementCache(object);
- if (id)
- {
- Firebug.HTML.selectTreeNode(id);
- }
- }
- });
- Firebug.registerPanel(HTMLPanel);
- // ************************************************************************************************
- var formatStyles = function(styles)
- {
- return isIE ?
- // IE return CSS property names in upper case, so we need to convert them
- styles.replace(/([^\s]+)\s*:/g, function(m,g){return g.toLowerCase()+":"}) :
- // other browsers are just fine
- styles;
- };
- // ************************************************************************************************
- var selectedElement = null
- var fbPanel1 = null;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var selectedSidePanelTS, selectedSidePanelTimer;
- var selectElement= function selectElement(e)
- {
- if (e != selectedElement)
- {
- if (selectedElement)
- selectedElement.className = "objectBox-element";
- e.className = e.className + " selectedElement";
- if (FBL.isFirefox)
- e.style.MozBorderRadius = "2px";
- else if (FBL.isSafari)
- e.style.WebkitBorderRadius = "2px";
- selectedElement = e;
- FirebugChrome.selectedHTMLElementId = e.id;
- var target = ElementCache.get(e.id);
- var selectedSidePanel = Firebug.chrome.getPanel("HTML").sidePanelBar.selectedPanel;
- var stack = FirebugChrome.htmlSelectionStack;
- stack.unshift(target);
- if (stack.length > 2)
- stack.pop();
- var lazySelect = function()
- {
- selectedSidePanelTS = new Date().getTime();
- selectedSidePanel.select(target, true);
- };
- if (selectedSidePanelTimer)
- {
- clearTimeout(selectedSidePanelTimer);
- selectedSidePanelTimer = null;
- }
- if (new Date().getTime() - selectedSidePanelTS > 100)
- setTimeout(lazySelect, 0)
- else
- selectedSidePanelTimer = setTimeout(lazySelect, 150);
- }
- }
- // ************************************************************************************************
- // *** TODO: REFACTOR **************************************************************************
- // ************************************************************************************************
- Firebug.HTML.onTreeClick = function (e)
- {
- e = e || event;
- var targ;
- if (e.target) targ = e.target;
- else if (e.srcElement) targ = e.srcElement;
- if (targ.nodeType == 3) // defeat Safari bug
- targ = targ.parentNode;
- if (targ.className.indexOf('nodeControl') != -1 || targ.className == 'nodeTag')
- {
- var isIE = false;
- if(targ.className == 'nodeTag')
- {
- var control = isIE ? (targ.parentNode.previousSibling || targ) :
- (targ.parentNode.previousSibling || targ);
- selectElement(targ.parentNode.parentNode);
- if (control.className.indexOf('nodeControl') == -1)
- return;
- } else
- control = targ;
- FBL.cancelEvent(e);
- var treeNode = isIE ? control.nextSibling : control.parentNode;
- //FBL.Firebug.Console.log(treeNode);
- if (control.className.indexOf(' nodeMaximized') != -1) {
- FBL.Firebug.HTML.removeTreeChildren(treeNode);
- } else {
- FBL.Firebug.HTML.appendTreeChildren(treeNode);
- }
- }
- else if (targ.className == 'nodeValue' || targ.className == 'nodeName')
- {
- /*
- var input = FBL.Firebug.chrome.document.getElementById('treeInput');
- input.style.display = "block";
- input.style.left = targ.offsetLeft + 'px';
- input.style.top = FBL.topHeight + targ.offsetTop - FBL.fbPanel1.scrollTop + 'px';
- input.style.width = targ.offsetWidth + 6 + 'px';
- input.value = targ.textContent || targ.innerText;
- input.focus();
- /**/
- }
- }
- function onListMouseOut(e)
- {
- e = e || event || window;
- var targ;
- if (e.target) targ = e.target;
- else if (e.srcElement) targ = e.srcElement;
- if (targ.nodeType == 3) // defeat Safari bug
- targ = targ.parentNode;
- if (hasClass(targ, "fbPanel")) {
- FBL.Firebug.Inspector.hideBoxModel();
- hoverElement = null;
- }
- };
- var hoverElement = null;
- var hoverElementTS = 0;
- Firebug.HTML.onListMouseMove = function onListMouseMove(e)
- {
- try
- {
- e = e || event || window;
- var targ;
- if (e.target) targ = e.target;
- else if (e.srcElement) targ = e.srcElement;
- if (targ.nodeType == 3) // defeat Safari bug
- targ = targ.parentNode;
- var found = false;
- while (targ && !found) {
- if (!/\snodeBox\s|\sobjectBox-selector\s/.test(" " + targ.className + " "))
- targ = targ.parentNode;
- else
- found = true;
- }
- if (!targ)
- {
- FBL.Firebug.Inspector.hideBoxModel();
- hoverElement = null;
- return;
- }
- /*
- if (typeof targ.attributes[cacheID] == 'undefined') return;
- var uid = targ.attributes[cacheID];
- if (!uid) return;
- /**/
- if (typeof targ.attributes[cacheID] == 'undefined') return;
- var uid = targ.attributes[cacheID];
- if (!uid) return;
- var el = ElementCache.get(uid.value);
- var nodeName = el.nodeName.toLowerCase();
- if (FBL.isIE && " meta title script link ".indexOf(" "+nodeName+" ") != -1)
- return;
- if (!/\snodeBox\s|\sobjectBox-selector\s/.test(" " + targ.className + " ")) return;
- if (el.id == "FirebugUI" || " html head body br script link iframe ".indexOf(" "+nodeName+" ") != -1) {
- FBL.Firebug.Inspector.hideBoxModel();
- hoverElement = null;
- return;
- }
- if ((new Date().getTime() - hoverElementTS > 40) && hoverElement != el) {
- hoverElementTS = new Date().getTime();
- hoverElement = el;
- FBL.Firebug.Inspector.drawBoxModel(el);
- }
- }
- catch(E)
- {
- }
- }
- // ************************************************************************************************
- Firebug.Reps = {
- appendText: function(object, html)
- {
- html.push(escapeHTML(objectToString(object)));
- },
- appendNull: function(object, html)
- {
- html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
- },
- appendString: function(object, html)
- {
- html.push('<span class="objectBox-string">"', escapeHTML(objectToString(object)),
- '"</span>');
- },
- appendInteger: function(object, html)
- {
- html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
- },
- appendFloat: function(object, html)
- {
- html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
- },
- appendFunction: function(object, html)
- {
- var reName = /function ?(.*?)\(/;
- var m = reName.exec(objectToString(object));
- var name = m && m[1] ? m[1] : "function";
- html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>');
- },
- appendObject: function(object, html)
- {
- /*
- var rep = Firebug.getRep(object);
- var outputs = [];
- rep.tag.tag.compile();
- var str = rep.tag.renderHTML({object: object}, outputs);
- html.push(str);
- /**/
- try
- {
- if (object == undefined)
- this.appendNull("undefined", html);
- else if (object == null)
- this.appendNull("null", html);
- else if (typeof object == "string")
- this.appendString(object, html);
- else if (typeof object == "number")
- this.appendInteger(object, html);
- else if (typeof object == "boolean")
- this.appendInteger(object, html);
- else if (typeof object == "function")
- this.appendFunction(object, html);
- else if (object.nodeType == 1)
- this.appendSelector(object, html);
- else if (typeof object == "object")
- {
- if (typeof object.length != "undefined")
- this.appendArray(object, html);
- else
- this.appendObjectFormatted(object, html);
- }
- else
- this.appendText(object, html);
- }
- catch (exc)
- {
- }
- /**/
- },
- appendObjectFormatted: function(object, html)
- {
- var text = objectToString(object);
- var reObject = /\[object (.*?)\]/;
- var m = reObject.exec(text);
- html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>')
- },
- appendSelector: function(object, html)
- {
- var uid = ElementCache(object);
- var uidString = uid ? [cacheID, '="', uid, '"'].join("") : "";
- html.push('<span class="objectBox-selector"', uidString, '>');
- html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
- if (object.id)
- html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
- if (object.className)
- html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
- html.push('</span>');
- },
- appendNode: function(node, html)
- {
- if (node.nodeType == 1)
- {
- var uid = ElementCache(node);
- var uidString = uid ? [cacheID, '="', uid, '"'].join("") : "";
- html.push(
- '<div class="objectBox-element"', uidString, '">',
- '<span ', cacheID, '="', uid, '" class="nodeBox">',
- '<<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
- for (var i = 0; i < node.attributes.length; ++i)
- {
- var attr = node.attributes[i];
- if (!attr.specified || attr.nodeName == cacheID)
- continue;
- var name = attr.nodeName.toLowerCase();
- var value = name == "style" ? node.style.cssText : attr.nodeValue;
- html.push(' <span class="nodeName">', name,
- '</span>="<span class="nodeValue">', escapeHTML(value),
- '</span>"')
- }
- if (node.firstChild)
- {
- html.push('></div><div class="nodeChildren">');
- for (var child = node.firstChild; child; child = child.nextSibling)
- this.appendNode(child, html);
- html.push('</div><div class="objectBox-element"></<span class="nodeTag">',
- node.nodeName.toLowerCase(), '></span></span></div>');
- }
- else
- html.push('/></span></div>');
- }
- else if (node.nodeType == 3)
- {
- var value = trim(node.nodeValue);
- if (value)
- html.push('<div class="nodeText">', escapeHTML(value),'</div>');
- }
- },
- appendArray: function(object, html)
- {
- html.push('<span class="objectBox-array"><b>[</b> ');
- for (var i = 0, l = object.length, obj; i < l; ++i)
- {
- this.appendObject(object[i], html);
- if (i < l-1)
- html.push(', ');
- }
- html.push(' <b>]</b></span>');
- }
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- /*
- Hack:
- Firebug.chrome.currentPanel = Firebug.chrome.selectedPanel;
- Firebug.showInfoTips = true;
- Firebug.InfoTip.initializeBrowser(Firebug.chrome);
- /**/
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // Constants
- var maxWidth = 100, maxHeight = 80;
- var infoTipMargin = 10;
- var infoTipWindowPadding = 25;
- // ************************************************************************************************
- Firebug.InfoTip = extend(Firebug.Module,
- {
- dispatchName: "infoTip",
- tags: domplate(
- {
- infoTipTag: DIV({"class": "infoTip"}),
- colorTag:
- DIV({style: "background: $rgbValue; width: 100px; height: 40px"}, " "),
- imgTag:
- DIV({"class": "infoTipImageBox infoTipLoading"},
- IMG({"class": "infoTipImage", src: "$urlValue", repeat: "$repeat",
- onload: "$onLoadImage"}),
- IMG({"class": "infoTipBgImage", collapsed: true, src: "blank.gif"}),
- DIV({"class": "infoTipCaption"})
- ),
- onLoadImage: function(event)
- {
- var img = event.currentTarget || event.srcElement;
- ///var bgImg = img.nextSibling;
- ///if (!bgImg)
- /// return; // Sometimes gets called after element is dead
- ///var caption = bgImg.nextSibling;
- var innerBox = img.parentNode;
- /// TODO: xxxpedro infoTip hack
- var caption = getElementByClass(innerBox, "infoTipCaption");
- var bgImg = getElementByClass(innerBox, "infoTipBgImage");
- if (!bgImg)
- return; // Sometimes gets called after element is dead
- // TODO: xxxpedro infoTip IE and timing issue
- // TODO: use offline document to avoid flickering
- if (isIE)
- removeClass(innerBox, "infoTipLoading");
- var updateInfoTip = function(){
- var w = img.naturalWidth || img.width || 10,
- h = img.naturalHeight || img.height || 10;
- var repeat = img.getAttribute("repeat");
- if (repeat == "repeat-x" || (w == 1 && h > 1))
- {
- collapse(img, true);
- collapse(bgImg, false);
- bgImg.style.background = "url(" + img.src + ") repeat-x";
- bgImg.style.width = maxWidth + "px";
- if (h > maxHeight)
- bgImg.style.height = maxHeight + "px";
- else
- bgImg.style.height = h + "px";
- }
- else if (repeat == "repeat-y" || (h == 1 && w > 1))
- {
- collapse(img, true);
- collapse(bgImg, false);
- bgImg.style.background = "url(" + img.src + ") repeat-y";
- bgImg.style.height = maxHeight + "px";
- if (w > maxWidth)
- bgImg.style.width = maxWidth + "px";
- else
- bgImg.style.width = w + "px";
- }
- else if (repeat == "repeat" || (w == 1 && h == 1))
- {
- collapse(img, true);
- collapse(bgImg, false);
- bgImg.style.background = "url(" + img.src + ") repeat";
- bgImg.style.width = maxWidth + "px";
- bgImg.style.height = maxHeight + "px";
- }
- else
- {
- if (w > maxWidth || h > maxHeight)
- {
- if (w > h)
- {
- img.style.width = maxWidth + "px";
- img.style.height = Math.round((h / w) * maxWidth) + "px";
- }
- else
- {
- img.style.width = Math.round((w / h) * maxHeight) + "px";
- img.style.height = maxHeight + "px";
- }
- }
- }
- //caption.innerHTML = $STRF("Dimensions", [w, h]);
- caption.innerHTML = $STRF(w + " x " + h);
- };
- if (isIE)
- setTimeout(updateInfoTip, 0);
- else
- {
- updateInfoTip();
- removeClass(innerBox, "infoTipLoading");
- }
- ///
- }
- /*
- /// onLoadImage original
- onLoadImage: function(event)
- {
- var img = event.currentTarget;
- var bgImg = img.nextSibling;
- if (!bgImg)
- return; // Sometimes gets called after element is dead
- var caption = bgImg.nextSibling;
- var innerBox = img.parentNode;
- var w = img.naturalWidth, h = img.naturalHeight;
- var repeat = img.getAttribute("repeat");
- if (repeat == "repeat-x" || (w == 1 && h > 1))
- {
- collapse(img, true);
- collapse(bgImg, false);
- bgImg.style.background = "url(" + img.src + ") repeat-x";
- bgImg.style.width = maxWidth + "px";
- if (h > maxHeight)
- bgImg.style.height = maxHeight + "px";
- else
- bgImg.style.height = h + "px";
- }
- else if (repeat == "repeat-y" || (h == 1 && w > 1))
- {
- collapse(img, true);
- collapse(bgImg, false);
- bgImg.style.background = "url(" + img.src + ") repeat-y";
- bgImg.style.height = maxHeight + "px";
- if (w > maxWidth)
- bgImg.style.width = maxWidth + "px";
- else
- bgImg.style.width = w + "px";
- }
- else if (repeat == "repeat" || (w == 1 && h == 1))
- {
- collapse(img, true);
- collapse(bgImg, false);
- bgImg.style.background = "url(" + img.src + ") repeat";
- bgImg.style.width = maxWidth + "px";
- bgImg.style.height = maxHeight + "px";
- }
- else
- {
- if (w > maxWidth || h > maxHeight)
- {
- if (w > h)
- {
- img.style.width = maxWidth + "px";
- img.style.height = Math.round((h / w) * maxWidth) + "px";
- }
- else
- {
- img.style.width = Math.round((w / h) * maxHeight) + "px";
- img.style.height = maxHeight + "px";
- }
- }
- }
- caption.innerHTML = $STRF("Dimensions", [w, h]);
- removeClass(innerBox, "infoTipLoading");
- }
- /**/
- }),
- initializeBrowser: function(browser)
- {
- browser.onInfoTipMouseOut = bind(this.onMouseOut, this, browser);
- browser.onInfoTipMouseMove = bind(this.onMouseMove, this, browser);
- ///var doc = browser.contentDocument;
- var doc = browser.document;
- if (!doc)
- return;
- ///doc.addEventListener("mouseover", browser.onInfoTipMouseMove, true);
- ///doc.addEventListener("mouseout", browser.onInfoTipMouseOut, true);
- ///doc.addEventListener("mousemove", browser.onInfoTipMouseMove, true);
- addEvent(doc, "mouseover", browser.onInfoTipMouseMove);
- addEvent(doc, "mouseout", browser.onInfoTipMouseOut);
- addEvent(doc, "mousemove", browser.onInfoTipMouseMove);
- return browser.infoTip = this.tags.infoTipTag.append({}, getBody(doc));
- },
- uninitializeBrowser: function(browser)
- {
- if (browser.infoTip)
- {
- ///var doc = browser.contentDocument;
- var doc = browser.document;
- ///doc.removeEventListener("mouseover", browser.onInfoTipMouseMove, true);
- ///doc.removeEventListener("mouseout", browser.onInfoTipMouseOut, true);
- ///doc.removeEventListener("mousemove", browser.onInfoTipMouseMove, true);
- removeEvent(doc, "mouseover", browser.onInfoTipMouseMove);
- removeEvent(doc, "mouseout", browser.onInfoTipMouseOut);
- removeEvent(doc, "mousemove", browser.onInfoTipMouseMove);
- browser.infoTip.parentNode.removeChild(browser.infoTip);
- delete browser.infoTip;
- delete browser.onInfoTipMouseMove;
- }
- },
- showInfoTip: function(infoTip, panel, target, x, y, rangeParent, rangeOffset)
- {
- if (!Firebug.showInfoTips)
- return;
- var scrollParent = getOverflowParent(target);
- var scrollX = x + (scrollParent ? scrollParent.scrollLeft : 0);
- if (panel.showInfoTip(infoTip, target, scrollX, y, rangeParent, rangeOffset))
- {
- var htmlElt = infoTip.ownerDocument.documentElement;
- var panelWidth = htmlElt.clientWidth;
- var panelHeight = htmlElt.clientHeight;
- if (x+infoTip.offsetWidth+infoTipMargin > panelWidth)
- {
- infoTip.style.left = Math.max(0, panelWidth-(infoTip.offsetWidth+infoTipMargin)) + "px";
- infoTip.style.right = "auto";
- }
- else
- {
- infoTip.style.left = (x+infoTipMargin) + "px";
- infoTip.style.right = "auto";
- }
- if (y+infoTip.offsetHeight+infoTipMargin > panelHeight)
- {
- infoTip.style.top = Math.max(0, panelHeight-(infoTip.offsetHeight+infoTipMargin)) + "px";
- infoTip.style.bottom = "auto";
- }
- else
- {
- infoTip.style.top = (y+infoTipMargin) + "px";
- infoTip.style.bottom = "auto";
- }
- if (FBTrace.DBG_INFOTIP)
- FBTrace.sysout("infotip.showInfoTip; top: " + infoTip.style.top +
- ", left: " + infoTip.style.left + ", bottom: " + infoTip.style.bottom +
- ", right:" + infoTip.style.right + ", offsetHeight: " + infoTip.offsetHeight +
- ", offsetWidth: " + infoTip.offsetWidth +
- ", x: " + x + ", panelWidth: " + panelWidth +
- ", y: " + y + ", panelHeight: " + panelHeight);
- infoTip.setAttribute("active", "true");
- }
- else
- this.hideInfoTip(infoTip);
- },
- hideInfoTip: function(infoTip)
- {
- if (infoTip)
- infoTip.removeAttribute("active");
- },
- onMouseOut: function(event, browser)
- {
- if (!event.relatedTarget)
- this.hideInfoTip(browser.infoTip);
- },
- onMouseMove: function(event, browser)
- {
- // Ignore if the mouse is moving over the existing info tip.
- if (getAncestorByClass(event.target, "infoTip"))
- return;
- if (browser.currentPanel)
- {
- var x = event.clientX, y = event.clientY, target = event.target || event.srcElement;
- this.showInfoTip(browser.infoTip, browser.currentPanel, target, x, y, event.rangeParent, event.rangeOffset);
- }
- else
- this.hideInfoTip(browser.infoTip);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- populateColorInfoTip: function(infoTip, color)
- {
- this.tags.colorTag.replace({rgbValue: color}, infoTip);
- return true;
- },
- populateImageInfoTip: function(infoTip, url, repeat)
- {
- if (!repeat)
- repeat = "no-repeat";
- this.tags.imgTag.replace({urlValue: url, repeat: repeat}, infoTip);
- return true;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Module
- disable: function()
- {
- // XXXjoe For each browser, call uninitializeBrowser
- },
- showPanel: function(browser, panel)
- {
- if (panel)
- {
- var infoTip = panel.panelBrowser.infoTip;
- if (!infoTip)
- infoTip = this.initializeBrowser(panel.panelBrowser);
- this.hideInfoTip(infoTip);
- }
- },
- showSidePanel: function(browser, panel)
- {
- this.showPanel(browser, panel);
- }
- });
- // ************************************************************************************************
- Firebug.registerModule(Firebug.InfoTip);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- // move to FBL
- (function() {
- // ************************************************************************************************
- // XPath
- /**
- * Gets an XPath for an element which describes its hierarchical location.
- */
- this.getElementXPath = function(element)
- {
- if (element && element.id)
- return '//*[@id="' + element.id + '"]';
- else
- return this.getElementTreeXPath(element);
- };
- this.getElementTreeXPath = function(element)
- {
- var paths = [];
- for (; element && element.nodeType == 1; element = element.parentNode)
- {
- var index = 0;
- for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
- {
- if (sibling.nodeName == element.nodeName)
- ++index;
- }
- var tagName = element.nodeName.toLowerCase();
- var pathIndex = (index ? "[" + (index+1) + "]" : "");
- paths.splice(0, 0, tagName + pathIndex);
- }
- return paths.length ? "/" + paths.join("/") : null;
- };
- this.getElementsByXPath = function(doc, xpath)
- {
- var nodes = [];
- try {
- var result = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null);
- for (var item = result.iterateNext(); item; item = result.iterateNext())
- nodes.push(item);
- }
- catch (exc)
- {
- // Invalid xpath expressions make their way here sometimes. If that happens,
- // we still want to return an empty set without an exception.
- }
- return nodes;
- };
- this.getRuleMatchingElements = function(rule, doc)
- {
- var css = rule.selectorText;
- var xpath = this.cssToXPath(css);
- return this.getElementsByXPath(doc, xpath);
- };
- }).call(FBL);
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- var toCamelCase = function toCamelCase(s)
- {
- return s.replace(reSelectorCase, toCamelCaseReplaceFn);
- };
- var toSelectorCase = function toSelectorCase(s)
- {
- return s.replace(reCamelCase, "-$1").toLowerCase();
- };
- var reCamelCase = /([A-Z])/g;
- var reSelectorCase = /\-(.)/g;
- var toCamelCaseReplaceFn = function toCamelCaseReplaceFn(m,g)
- {
- return g.toUpperCase();
- };
- // ************************************************************************************************
- var ElementCache = Firebug.Lite.Cache.Element;
- var StyleSheetCache = Firebug.Lite.Cache.StyleSheet;
- var globalCSSRuleIndex;
- var externalStyleSheetURLs = [];
- var externalStyleSheetWarning = domplate(Firebug.Rep,
- {
- tag:
- DIV({"class": "warning focusRow", style: "font-weight:normal;", role: 'listitem'},
- SPAN("$object|STR"),
- A({"href": "$href", target:"_blank"}, "$link|STR")
- )
- });
- var processAllStyleSheetsTimeout = null;
- var loadExternalStylesheet = function(doc, styleSheetIterator, styleSheet)
- {
- var url = styleSheet.href;
- styleSheet.firebugIgnore = true;
- var source = Firebug.Lite.Proxy.load(url);
- // TODO: check for null and error responses
- // remove comments
- //var reMultiComment = /(\/\*([^\*]|\*(?!\/))*\*\/)/g;
- //source = source.replace(reMultiComment, "");
- // convert relative addresses to absolute ones
- source = source.replace(/url\(([^\)]+)\)/g, function(a,name){
- var hasDomain = /\w+:\/\/./.test(name);
- if (!hasDomain)
- {
- name = name.replace(/^(["'])(.+)\1$/, "$2");
- var first = name.charAt(0);
- // relative path, based on root
- if (first == "/")
- {
- // TODO: xxxpedro move to lib or Firebug.Lite.something
- // getURLRoot
- var m = /^([^:]+:\/{1,3}[^\/]+)/.exec(url);
- return m ?
- "url(" + m[1] + name + ")" :
- "url(" + name + ")";
- }
- // relative path, based on current location
- else
- {
- // TODO: xxxpedro move to lib or Firebug.Lite.something
- // getURLPath
- var path = url.replace(/[^\/]+\.[\w\d]+(\?.+|#.+)?$/g, "");
- path = path + name;
- var reBack = /[^\/]+\/\.\.\//;
- while(reBack.test(path))
- {
- path = path.replace(reBack, "");
- }
- //console.log("url(" + path + ")");
- return "url(" + path + ")";
- }
- }
- // if it is an absolute path, there is nothing to do
- return a;
- });
- var oldStyle = styleSheet.ownerNode;
- if (!oldStyle) return;
- if (!oldStyle.parentNode) return;
- var style = createGlobalElement("style");
- style.setAttribute("charset","utf-8");
- style.setAttribute("type", "text/css");
- style.innerHTML = source;
- //debugger;
- oldStyle.parentNode.insertBefore(style, oldStyle.nextSibling);
- oldStyle.parentNode.removeChild(oldStyle);
- //doc.getElementsByTagName("head")[0].appendChild(style);
- doc.styleSheets[doc.styleSheets.length-1].externalURL = url;
- console.log(url, "call " + externalStyleSheetURLs.length, source);
- externalStyleSheetURLs.pop();
- if (processAllStyleSheetsTimeout)
- {
- clearTimeout(processAllStyleSheetsTimeout);
- }
- processAllStyleSheetsTimeout = setTimeout(function(){
- console.log("processing");
- FBL.processAllStyleSheets(doc, styleSheetIterator);
- processAllStyleSheetsTimeout = null;
- },200);
- };
- FBL.processAllStyleSheets = function(doc, styleSheetIterator)
- {
- styleSheetIterator = styleSheetIterator || processStyleSheet;
- globalCSSRuleIndex = -1;
- var styleSheets = doc.styleSheets;
- var importedStyleSheets = [];
- if (FBTrace.DBG_CSS)
- var start = new Date().getTime();
- for(var i=0, length=styleSheets.length; i<length; i++)
- {
- try
- {
- var styleSheet = styleSheets[i];
- if ("firebugIgnore" in styleSheet) continue;
- // we must read the length to make sure we have permission to read
- // the stylesheet's content. If an error occurs here, we cannot
- // read the stylesheet due to access restriction policy
- var rules = isIE ? styleSheet.rules : styleSheet.cssRules;
- rules.length;
- }
- catch(e)
- {
- externalStyleSheetURLs.push(styleSheet.href);
- styleSheet.restricted = true;
- var ssid = StyleSheetCache(styleSheet);
- /// TODO: xxxpedro external css
- //loadExternalStylesheet(doc, styleSheetIterator, styleSheet);
- }
- // process internal and external styleSheets
- styleSheetIterator(doc, styleSheet);
- var importedStyleSheet, importedRules;
- // process imported styleSheets in IE
- if (isIE)
- {
- var imports = styleSheet.imports;
- for(var j=0, importsLength=imports.length; j<importsLength; j++)
- {
- try
- {
- importedStyleSheet = imports[j];
- // we must read the length to make sure we have permission
- // to read the imported stylesheet's content.
- importedRules = importedStyleSheet.rules;
- importedRules.length;
- }
- catch(e)
- {
- externalStyleSheetURLs.push(styleSheet.href);
- importedStyleSheet.restricted = true;
- var ssid = StyleSheetCache(importedStyleSheet);
- }
- styleSheetIterator(doc, importedStyleSheet);
- }
- }
- // process imported styleSheets in other browsers
- else if (rules)
- {
- for(var j=0, rulesLength=rules.length; j<rulesLength; j++)
- {
- try
- {
- var rule = rules[j];
- importedStyleSheet = rule.styleSheet;
- if (importedStyleSheet)
- {
- // we must read the length to make sure we have permission
- // to read the imported stylesheet's content.
- importedRules = importedStyleSheet.cssRules;
- importedRules.length;
- }
- else
- break;
- }
- catch(e)
- {
- externalStyleSheetURLs.push(styleSheet.href);
- importedStyleSheet.restricted = true;
- var ssid = StyleSheetCache(importedStyleSheet);
- }
- styleSheetIterator(doc, importedStyleSheet);
- }
- }
- };
- if (FBTrace.DBG_CSS)
- {
- FBTrace.sysout("FBL.processAllStyleSheets", "all stylesheet rules processed in " + (new Date().getTime() - start) + "ms");
- }
- };
- var CSSRuleMap = {};
- var ElementCSSRulesMap = {};
- var processStyleSheet = function(doc, styleSheet)
- {
- if (styleSheet.restricted)
- return;
- var rules = isIE ? styleSheet.rules : styleSheet.cssRules;
- var ssid = StyleSheetCache(styleSheet);
- for (var i=0, length=rules.length; i<length; i++)
- {
- var rid = ssid + ":" + i;
- var rule = rules[i];
- var selector = rule.selectorText;
- if (isIE)
- {
- selector = selector.replace(reSelectorTag, function(s){return s.toLowerCase();});
- }
- // TODO: xxxpedro break grouped rules (,) into individual rules, otherwise
- // it will result in a overestimated value for getCSSRuleSpecificity
- CSSRuleMap[rid] =
- {
- styleSheetId: ssid,
- styleSheetIndex: i,
- order: ++globalCSSRuleIndex,
- // if it is a grouped selector, do not calculate the specificity
- // because the correct value will depend of the matched element.
- // The proper specificity value for grouped selectors are calculated
- // via getElementCSSRules(element)
- specificity: selector && selector.indexOf(",") != -1 ?
- getCSSRuleSpecificity(selector) :
- 0,
- rule: rule,
- selector: selector,
- cssText: rule.style ? rule.style.cssText : rule.cssText ? rule.cssText : ""
- };
- var elements = Firebug.Selector(selector, doc);
- for (var j=0, elementsLength=elements.length; j<elementsLength; j++)
- {
- var element = elements[j];
- var eid = ElementCache(element);
- if (!ElementCSSRulesMap[eid])
- ElementCSSRulesMap[eid] = [];
- ElementCSSRulesMap[eid].push(rid);
- }
- //console.log(selector, elements);
- }
- // TODO: xxxpedro. remove this, we don't need this anymore with the new getElementCSSRules
- /*
- for (var name in ElementCSSRulesMap)
- {
- if (ElementCSSRulesMap.hasOwnProperty(name))
- {
- var rules = ElementCSSRulesMap[name];
- rules.sort(sortElementRules);
- //rules.sort(solveRulesTied);
- }
- }
- /**/
- };
- FBL.getElementCSSRules = function(element)
- {
- var eid = ElementCache(element);
- var rules = ElementCSSRulesMap[eid];
- if (!rules) return;
- var arr = [element];
- var Selector = Firebug.Selector;
- var ruleId, rule;
- // for the case of grouped selectors, we need to calculate the highest
- // specificity within the selectors of the group that matches the element,
- // so we can sort the rules properly without over estimating the specificity
- // of grouped selectors
- for (var i = 0, length = rules.length; i < length; i++)
- {
- ruleId = rules[i];
- rule = CSSRuleMap[ruleId];
- // check if it is a grouped selector
- if (rule.selector.indexOf(",") != -1)
- {
- var selectors = rule.selector.split(",");
- var maxSpecificity = -1;
- var sel, spec, mostSpecificSelector;
- // loop over all selectors in the group
- for (var j, len = selectors.length; j < len; j++)
- {
- sel = selectors[j];
- // find if the selector matches the element
- if (Selector.matches(sel, arr).length == 1)
- {
- spec = getCSSRuleSpecificity(sel);
- // find the most specific selector that macthes the element
- if (spec > maxSpecificity)
- {
- maxSpecificity = spec;
- mostSpecificSelector = sel;
- }
- }
- }
- rule.specificity = maxSpecificity;
- }
- }
- rules.sort(sortElementRules);
- //rules.sort(solveRulesTied);
- return rules;
- };
- var sortElementRules = function(a, b)
- {
- var ruleA = CSSRuleMap[a];
- var ruleB = CSSRuleMap[b];
- var specificityA = ruleA.specificity;
- var specificityB = ruleB.specificity;
- if (specificityA > specificityB)
- return 1;
- else if (specificityA < specificityB)
- return -1;
- else
- return ruleA.order > ruleB.order ? 1 : -1;
- };
- var solveRulesTied = function(a, b)
- {
- var ruleA = CSSRuleMap[a];
- var ruleB = CSSRuleMap[b];
- if (ruleA.specificity == ruleB.specificity)
- return ruleA.order > ruleB.order ? 1 : -1;
- return null;
- };
- var reSelectorTag = /(^|\s)(?:\w+)/g;
- var reSelectorClass = /\.[\w\d_-]+/g;
- var reSelectorId = /#[\w\d_-]+/g;
- var getCSSRuleSpecificity = function(selector)
- {
- var match = selector.match(reSelectorTag);
- var tagCount = match ? match.length : 0;
- match = selector.match(reSelectorClass);
- var classCount = match ? match.length : 0;
- match = selector.match(reSelectorId);
- var idCount = match ? match.length : 0;
- return tagCount + 10*classCount + 100*idCount;
- };
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // ************************************************************************************************
- // Constants
- //const Cc = Components.classes;
- //const Ci = Components.interfaces;
- //const nsIDOMCSSStyleRule = Ci.nsIDOMCSSStyleRule;
- //const nsIInterfaceRequestor = Ci.nsIInterfaceRequestor;
- //const nsISelectionDisplay = Ci.nsISelectionDisplay;
- //const nsISelectionController = Ci.nsISelectionController;
- // See: http://mxr.mozilla.org/mozilla1.9.2/source/content/events/public/nsIEventStateManager.h#153
- //const STATE_ACTIVE = 0x01;
- //const STATE_FOCUS = 0x02;
- //const STATE_HOVER = 0x04;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- Firebug.SourceBoxPanel = Firebug.Panel;
- var domUtils = null;
- var textContent = isIE ? "innerText" : "textContent";
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var CSSDomplateBase = {
- isEditable: function(rule)
- {
- return !rule.isSystemSheet;
- },
- isSelectorEditable: function(rule)
- {
- return rule.isSelectorEditable && this.isEditable(rule);
- }
- };
- var CSSPropTag = domplate(CSSDomplateBase, {
- tag: DIV({"class": "cssProp focusRow", $disabledStyle: "$prop.disabled",
- $editGroup: "$rule|isEditable",
- $cssOverridden: "$prop.overridden", role : "option"},
- A({"class": "cssPropDisable"}, " "),
- SPAN({"class": "cssPropName", $editable: "$rule|isEditable"}, "$prop.name"),
- SPAN({"class": "cssColon"}, ":"),
- SPAN({"class": "cssPropValue", $editable: "$rule|isEditable"}, "$prop.value$prop.important"),
- SPAN({"class": "cssSemi"}, ";")
- )
- });
- var CSSRuleTag =
- TAG("$rule.tag", {rule: "$rule"});
- var CSSImportRuleTag = domplate({
- tag: DIV({"class": "cssRule insertInto focusRow importRule", _repObject: "$rule.rule"},
- "@import "",
- A({"class": "objectLink", _repObject: "$rule.rule.styleSheet"}, "$rule.rule.href"),
- "";"
- )
- });
- var CSSStyleRuleTag = domplate(CSSDomplateBase, {
- tag: DIV({"class": "cssRule insertInto",
- $cssEditableRule: "$rule|isEditable",
- $editGroup: "$rule|isSelectorEditable",
- _repObject: "$rule.rule",
- "ruleId": "$rule.id", role : 'presentation'},
- DIV({"class": "cssHead focusRow", role : 'listitem'},
- SPAN({"class": "cssSelector", $editable: "$rule|isSelectorEditable"}, "$rule.selector"), " {"
- ),
- DIV({role : 'group'},
- DIV({"class": "cssPropertyListBox", role : 'listbox'},
- FOR("prop", "$rule.props",
- TAG(CSSPropTag.tag, {rule: "$rule", prop: "$prop"})
- )
- )
- ),
- DIV({"class": "editable insertBefore", role:"presentation"}, "}")
- )
- });
- var reSplitCSS = /(url\("?[^"\)]+?"?\))|(rgb\(.*?\))|(#[\dA-Fa-f]+)|(-?\d+(\.\d+)?(%|[a-z]{1,2})?)|([^,\s]+)|"(.*?)"/;
- var reURL = /url\("?([^"\)]+)?"?\)/;
- var reRepeat = /no-repeat|repeat-x|repeat-y|repeat/;
- //const sothinkInstalled = !!$("swfcatcherKey_sidebar");
- var sothinkInstalled = false;
- var styleGroups =
- {
- text: [
- "font-family",
- "font-size",
- "font-weight",
- "font-style",
- "color",
- "text-transform",
- "text-decoration",
- "letter-spacing",
- "word-spacing",
- "line-height",
- "text-align",
- "vertical-align",
- "direction",
- "column-count",
- "column-gap",
- "column-width"
- ],
- background: [
- "background-color",
- "background-image",
- "background-repeat",
- "background-position",
- "background-attachment",
- "opacity"
- ],
- box: [
- "width",
- "height",
- "top",
- "right",
- "bottom",
- "left",
- "margin-top",
- "margin-right",
- "margin-bottom",
- "margin-left",
- "padding-top",
- "padding-right",
- "padding-bottom",
- "padding-left",
- "border-top-width",
- "border-right-width",
- "border-bottom-width",
- "border-left-width",
- "border-top-color",
- "border-right-color",
- "border-bottom-color",
- "border-left-color",
- "border-top-style",
- "border-right-style",
- "border-bottom-style",
- "border-left-style",
- "-moz-border-top-radius",
- "-moz-border-right-radius",
- "-moz-border-bottom-radius",
- "-moz-border-left-radius",
- "outline-top-width",
- "outline-right-width",
- "outline-bottom-width",
- "outline-left-width",
- "outline-top-color",
- "outline-right-color",
- "outline-bottom-color",
- "outline-left-color",
- "outline-top-style",
- "outline-right-style",
- "outline-bottom-style",
- "outline-left-style"
- ],
- layout: [
- "position",
- "display",
- "visibility",
- "z-index",
- "overflow-x", // http://www.w3.org/TR/2002/WD-css3-box-20021024/#overflow
- "overflow-y",
- "overflow-clip",
- "white-space",
- "clip",
- "float",
- "clear",
- "-moz-box-sizing"
- ],
- other: [
- "cursor",
- "list-style-image",
- "list-style-position",
- "list-style-type",
- "marker-offset",
- "user-focus",
- "user-select",
- "user-modify",
- "user-input"
- ]
- };
- var styleGroupTitles =
- {
- text: "Text",
- background: "Background",
- box: "Box Model",
- layout: "Layout",
- other: "Other"
- };
- Firebug.CSSModule = extend(Firebug.Module,
- {
- freeEdit: function(styleSheet, value)
- {
- if (!styleSheet.editStyleSheet)
- {
- var ownerNode = getStyleSheetOwnerNode(styleSheet);
- styleSheet.disabled = true;
- var url = CCSV("@mozilla.org/network/standard-url;1", Components.interfaces.nsIURL);
- url.spec = styleSheet.href;
- var editStyleSheet = ownerNode.ownerDocument.createElementNS(
- "http://www.w3.org/1999/xhtml",
- "style");
- unwrapObject(editStyleSheet).firebugIgnore = true;
- editStyleSheet.setAttribute("type", "text/css");
- editStyleSheet.setAttributeNS(
- "http://www.w3.org/XML/1998/namespace",
- "base",
- url.directory);
- if (ownerNode.hasAttribute("media"))
- {
- editStyleSheet.setAttribute("media", ownerNode.getAttribute("media"));
- }
- // Insert the edited stylesheet directly after the old one to ensure the styles
- // cascade properly.
- ownerNode.parentNode.insertBefore(editStyleSheet, ownerNode.nextSibling);
- styleSheet.editStyleSheet = editStyleSheet;
- }
- styleSheet.editStyleSheet.innerHTML = value;
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("css.saveEdit styleSheet.href:"+styleSheet.href+" got innerHTML:"+value+"\n");
- dispatch(this.fbListeners, "onCSSFreeEdit", [styleSheet, value]);
- },
- insertRule: function(styleSheet, cssText, ruleIndex)
- {
- if (FBTrace.DBG_CSS) FBTrace.sysout("Insert: " + ruleIndex + " " + cssText);
- var insertIndex = styleSheet.insertRule(cssText, ruleIndex);
- dispatch(this.fbListeners, "onCSSInsertRule", [styleSheet, cssText, ruleIndex]);
- return insertIndex;
- },
- deleteRule: function(styleSheet, ruleIndex)
- {
- if (FBTrace.DBG_CSS) FBTrace.sysout("deleteRule: " + ruleIndex + " " + styleSheet.cssRules.length, styleSheet.cssRules);
- dispatch(this.fbListeners, "onCSSDeleteRule", [styleSheet, ruleIndex]);
- styleSheet.deleteRule(ruleIndex);
- },
- setProperty: function(rule, propName, propValue, propPriority)
- {
- var style = rule.style || rule;
- // Record the original CSS text for the inline case so we can reconstruct at a later
- // point for diffing purposes
- var baseText = style.cssText;
- // good browsers
- if (style.getPropertyValue)
- {
- var prevValue = style.getPropertyValue(propName);
- var prevPriority = style.getPropertyPriority(propName);
- // XXXjoe Gecko bug workaround: Just changing priority doesn't have any effect
- // unless we remove the property first
- style.removeProperty(propName);
- style.setProperty(propName, propValue, propPriority);
- }
- // sad browsers
- else
- {
- // TODO: xxxpedro parse CSS rule to find property priority in IE?
- //console.log(propName, propValue);
- style[toCamelCase(propName)] = propValue;
- }
- if (propName) {
- dispatch(this.fbListeners, "onCSSSetProperty", [style, propName, propValue, propPriority, prevValue, prevPriority, rule, baseText]);
- }
- },
- removeProperty: function(rule, propName, parent)
- {
- var style = rule.style || rule;
- // Record the original CSS text for the inline case so we can reconstruct at a later
- // point for diffing purposes
- var baseText = style.cssText;
- if (style.getPropertyValue)
- {
- var prevValue = style.getPropertyValue(propName);
- var prevPriority = style.getPropertyPriority(propName);
- style.removeProperty(propName);
- }
- else
- {
- style[toCamelCase(propName)] = "";
- }
- if (propName) {
- dispatch(this.fbListeners, "onCSSRemoveProperty", [style, propName, prevValue, prevPriority, rule, baseText]);
- }
- }/*,
- cleanupSheets: function(doc, context)
- {
- // Due to the manner in which the layout engine handles multiple
- // references to the same sheet we need to kick it a little bit.
- // The injecting a simple stylesheet then removing it will force
- // Firefox to regenerate it's CSS hierarchy.
- //
- // WARN: This behavior was determined anecdotally.
- // See http://code.google.com/p/fbug/issues/detail?id=2440
- var style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style");
- style.setAttribute("charset","utf-8");
- unwrapObject(style).firebugIgnore = true;
- style.setAttribute("type", "text/css");
- style.innerHTML = "#fbIgnoreStyleDO_NOT_USE {}";
- addStyleSheet(doc, style);
- style.parentNode.removeChild(style);
- // https://bugzilla.mozilla.org/show_bug.cgi?id=500365
- // This voodoo touches each style sheet to force some Firefox internal change to allow edits.
- var styleSheets = getAllStyleSheets(context);
- for(var i = 0; i < styleSheets.length; i++)
- {
- try
- {
- var rules = styleSheets[i].cssRules;
- if (rules.length > 0)
- var touch = rules[0];
- if (FBTrace.DBG_CSS && touch)
- FBTrace.sysout("css.show() touch "+typeof(touch)+" in "+(styleSheets[i].href?styleSheets[i].href:context.getName()));
- }
- catch(e)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("css.show: sheet.cssRules FAILS for "+(styleSheets[i]?styleSheets[i].href:"null sheet")+e, e);
- }
- }
- },
- cleanupSheetHandler: function(event, context)
- {
- var target = event.target || event.srcElement,
- tagName = (target.tagName || "").toLowerCase();
- if (tagName == "link")
- {
- this.cleanupSheets(target.ownerDocument, context);
- }
- },
- watchWindow: function(context, win)
- {
- var cleanupSheets = bind(this.cleanupSheets, this),
- cleanupSheetHandler = bind(this.cleanupSheetHandler, this, context),
- doc = win.document;
- //doc.addEventListener("DOMAttrModified", cleanupSheetHandler, false);
- //doc.addEventListener("DOMNodeInserted", cleanupSheetHandler, false);
- },
- loadedContext: function(context)
- {
- var self = this;
- iterateWindows(context.browser.contentWindow, function(subwin)
- {
- self.cleanupSheets(subwin.document, context);
- });
- }
- /**/
- });
- // ************************************************************************************************
- Firebug.CSSStyleSheetPanel = function() {};
- Firebug.CSSStyleSheetPanel.prototype = extend(Firebug.SourceBoxPanel,
- {
- template: domplate(
- {
- tag:
- DIV({"class": "cssSheet insertInto a11yCSSView"},
- FOR("rule", "$rules",
- CSSRuleTag
- ),
- DIV({"class": "cssSheet editable insertBefore"}, "")
- )
- }),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- refresh: function()
- {
- if (this.location)
- this.updateLocation(this.location);
- else if (this.selection)
- this.updateSelection(this.selection);
- },
- toggleEditing: function()
- {
- if (!this.stylesheetEditor)
- this.stylesheetEditor = new StyleSheetEditor(this.document);
- if (this.editing)
- Firebug.Editor.stopEditing();
- else
- {
- if (!this.location)
- return;
- var styleSheet = this.location.editStyleSheet
- ? this.location.editStyleSheet.sheet
- : this.location;
- var css = getStyleSheetCSS(styleSheet, this.context);
- //var topmost = getTopmostRuleLine(this.panelNode);
- this.stylesheetEditor.styleSheet = this.location;
- Firebug.Editor.startEditing(this.panelNode, css, this.stylesheetEditor);
- //this.stylesheetEditor.scrollToLine(topmost.line, topmost.offset);
- }
- },
- getStylesheetURL: function(rule)
- {
- if (this.location.href)
- return this.location.href;
- else
- return this.context.window.location.href;
- },
- getRuleByLine: function(styleSheet, line)
- {
- if (!domUtils)
- return null;
- var cssRules = styleSheet.cssRules;
- for (var i = 0; i < cssRules.length; ++i)
- {
- var rule = cssRules[i];
- if (rule instanceof CSSStyleRule)
- {
- var ruleLine = domUtils.getRuleLine(rule);
- if (ruleLine >= line)
- return rule;
- }
- }
- },
- highlightRule: function(rule)
- {
- var ruleElement = Firebug.getElementByRepObject(this.panelNode.firstChild, rule);
- if (ruleElement)
- {
- scrollIntoCenterView(ruleElement, this.panelNode);
- setClassTimed(ruleElement, "jumpHighlight", this.context);
- }
- },
- getStyleSheetRules: function(context, styleSheet)
- {
- var isSystemSheet = isSystemStyleSheet(styleSheet);
- function appendRules(cssRules)
- {
- for (var i = 0; i < cssRules.length; ++i)
- {
- var rule = cssRules[i];
- // TODO: xxxpedro opera instanceof stylesheet remove the following comments when
- // the issue with opera and style sheet Classes has been solved.
- //if (rule instanceof CSSStyleRule)
- if (instanceOf(rule, "CSSStyleRule"))
- {
- var props = this.getRuleProperties(context, rule);
- //var line = domUtils.getRuleLine(rule);
- var line = null;
- var selector = rule.selectorText;
- if (isIE)
- {
- selector = selector.replace(reSelectorTag,
- function(s){return s.toLowerCase();});
- }
- var ruleId = rule.selectorText+"/"+line;
- rules.push({tag: CSSStyleRuleTag.tag, rule: rule, id: ruleId,
- selector: selector, props: props,
- isSystemSheet: isSystemSheet,
- isSelectorEditable: true});
- }
- //else if (rule instanceof CSSImportRule)
- else if (instanceOf(rule, "CSSImportRule"))
- rules.push({tag: CSSImportRuleTag.tag, rule: rule});
- //else if (rule instanceof CSSMediaRule)
- else if (instanceOf(rule, "CSSMediaRule"))
- appendRules.apply(this, [rule.cssRules]);
- else
- {
- if (FBTrace.DBG_ERRORS || FBTrace.DBG_CSS)
- FBTrace.sysout("css getStyleSheetRules failed to classify a rule ", rule);
- }
- }
- }
- var rules = [];
- appendRules.apply(this, [styleSheet.cssRules || styleSheet.rules]);
- return rules;
- },
- parseCSSProps: function(style, inheritMode)
- {
- var props = [];
- if (Firebug.expandShorthandProps)
- {
- var count = style.length-1,
- index = style.length;
- while (index--)
- {
- var propName = style.item(count - index);
- this.addProperty(propName, style.getPropertyValue(propName), !!style.getPropertyPriority(propName), false, inheritMode, props);
- }
- }
- else
- {
- var lines = style.cssText.match(/(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g);
- var propRE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(! important)?;?$/;
- var line,i=0;
- // TODO: xxxpedro port to firebug: variable leaked into global namespace
- var m;
- while(line=lines[i++]){
- m = propRE.exec(line);
- if(!m)
- continue;
- //var name = m[1], value = m[2], important = !!m[3];
- if (m[2])
- this.addProperty(m[1], m[2], !!m[3], false, inheritMode, props);
- };
- }
- return props;
- },
- getRuleProperties: function(context, rule, inheritMode)
- {
- var props = this.parseCSSProps(rule.style, inheritMode);
- // TODO: xxxpedro port to firebug: variable leaked into global namespace
- //var line = domUtils.getRuleLine(rule);
- var line;
- var ruleId = rule.selectorText+"/"+line;
- this.addOldProperties(context, ruleId, inheritMode, props);
- sortProperties(props);
- return props;
- },
- addOldProperties: function(context, ruleId, inheritMode, props)
- {
- if (context.selectorMap && context.selectorMap.hasOwnProperty(ruleId) )
- {
- var moreProps = context.selectorMap[ruleId];
- for (var i = 0; i < moreProps.length; ++i)
- {
- var prop = moreProps[i];
- this.addProperty(prop.name, prop.value, prop.important, true, inheritMode, props);
- }
- }
- },
- addProperty: function(name, value, important, disabled, inheritMode, props)
- {
- name = name.toLowerCase();
- if (inheritMode && !inheritedStyleNames[name])
- return;
- name = this.translateName(name, value);
- if (name)
- {
- value = stripUnits(rgbToHex(value));
- important = important ? " !important" : "";
- var prop = {name: name, value: value, important: important, disabled: disabled};
- props.push(prop);
- }
- },
- translateName: function(name, value)
- {
- // Don't show these proprietary Mozilla properties
- if ((value == "-moz-initial"
- && (name == "-moz-background-clip" || name == "-moz-background-origin"
- || name == "-moz-background-inline-policy"))
- || (value == "physical"
- && (name == "margin-left-ltr-source" || name == "margin-left-rtl-source"
- || name == "margin-right-ltr-source" || name == "margin-right-rtl-source"))
- || (value == "physical"
- && (name == "padding-left-ltr-source" || name == "padding-left-rtl-source"
- || name == "padding-right-ltr-source" || name == "padding-right-rtl-source")))
- return null;
- // Translate these back to the form the user probably expects
- if (name == "margin-left-value")
- return "margin-left";
- else if (name == "margin-right-value")
- return "margin-right";
- else if (name == "margin-top-value")
- return "margin-top";
- else if (name == "margin-bottom-value")
- return "margin-bottom";
- else if (name == "padding-left-value")
- return "padding-left";
- else if (name == "padding-right-value")
- return "padding-right";
- else if (name == "padding-top-value")
- return "padding-top";
- else if (name == "padding-bottom-value")
- return "padding-bottom";
- // XXXjoe What about border!
- else
- return name;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- editElementStyle: function()
- {
- ///var rulesBox = this.panelNode.getElementsByClassName("cssElementRuleContainer")[0];
- var rulesBox = $$(".cssElementRuleContainer", this.panelNode)[0];
- var styleRuleBox = rulesBox && Firebug.getElementByRepObject(rulesBox, this.selection);
- if (!styleRuleBox)
- {
- var rule = {rule: this.selection, inherited: false, selector: "element.style", props: []};
- if (!rulesBox)
- {
- // The element did not have any displayed styles. We need to create the whole tree and remove
- // the no styles message
- styleRuleBox = this.template.cascadedTag.replace({
- rules: [rule], inherited: [], inheritLabel: "Inherited from" // $STR("InheritedFrom")
- }, this.panelNode);
- ///styleRuleBox = styleRuleBox.getElementsByClassName("cssElementRuleContainer")[0];
- styleRuleBox = $$(".cssElementRuleContainer", styleRuleBox)[0];
- }
- else
- styleRuleBox = this.template.ruleTag.insertBefore({rule: rule}, rulesBox);
- ///styleRuleBox = styleRuleBox.getElementsByClassName("insertInto")[0];
- styleRuleBox = $$(".insertInto", styleRuleBox)[0];
- }
- Firebug.Editor.insertRowForObject(styleRuleBox);
- },
- insertPropertyRow: function(row)
- {
- Firebug.Editor.insertRowForObject(row);
- },
- insertRule: function(row)
- {
- var location = getAncestorByClass(row, "cssRule");
- if (!location)
- {
- location = getChildByClass(this.panelNode, "cssSheet");
- Firebug.Editor.insertRowForObject(location);
- }
- else
- {
- Firebug.Editor.insertRow(location, "before");
- }
- },
- editPropertyRow: function(row)
- {
- var propValueBox = getChildByClass(row, "cssPropValue");
- Firebug.Editor.startEditing(propValueBox);
- },
- deletePropertyRow: function(row)
- {
- var rule = Firebug.getRepObject(row);
- var propName = getChildByClass(row, "cssPropName")[textContent];
- Firebug.CSSModule.removeProperty(rule, propName);
- // Remove the property from the selector map, if it was disabled
- var ruleId = Firebug.getRepNode(row).getAttribute("ruleId");
- if ( this.context.selectorMap && this.context.selectorMap.hasOwnProperty(ruleId) )
- {
- var map = this.context.selectorMap[ruleId];
- for (var i = 0; i < map.length; ++i)
- {
- if (map[i].name == propName)
- {
- map.splice(i, 1);
- break;
- }
- }
- }
- if (this.name == "stylesheet")
- dispatch([Firebug.A11yModel], 'onInlineEditorClose', [this, row.firstChild, true]);
- row.parentNode.removeChild(row);
- this.markChange(this.name == "stylesheet");
- },
- disablePropertyRow: function(row)
- {
- toggleClass(row, "disabledStyle");
- var rule = Firebug.getRepObject(row);
- var propName = getChildByClass(row, "cssPropName")[textContent];
- if (!this.context.selectorMap)
- this.context.selectorMap = {};
- // XXXjoe Generate unique key for elements too
- var ruleId = Firebug.getRepNode(row).getAttribute("ruleId");
- if (!(this.context.selectorMap.hasOwnProperty(ruleId)))
- this.context.selectorMap[ruleId] = [];
- var map = this.context.selectorMap[ruleId];
- var propValue = getChildByClass(row, "cssPropValue")[textContent];
- var parsedValue = parsePriority(propValue);
- if (hasClass(row, "disabledStyle"))
- {
- Firebug.CSSModule.removeProperty(rule, propName);
- map.push({"name": propName, "value": parsedValue.value,
- "important": parsedValue.priority});
- }
- else
- {
- Firebug.CSSModule.setProperty(rule, propName, parsedValue.value, parsedValue.priority);
- var index = findPropByName(map, propName);
- map.splice(index, 1);
- }
- this.markChange(this.name == "stylesheet");
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onMouseDown: function(event)
- {
- //console.log("onMouseDown", event.target || event.srcElement, event);
- // xxxpedro adjusting coordinates because the panel isn't a window yet
- var offset = event.clientX - this.panelNode.parentNode.offsetLeft;
- // XXjoe Hack to only allow clicking on the checkbox
- if (!isLeftClick(event) || offset > 20)
- return;
- var target = event.target || event.srcElement;
- if (hasClass(target, "textEditor"))
- return;
- var row = getAncestorByClass(target, "cssProp");
- if (row && hasClass(row, "editGroup"))
- {
- this.disablePropertyRow(row);
- cancelEvent(event);
- }
- },
- onDoubleClick: function(event)
- {
- //console.log("onDoubleClick", event.target || event.srcElement, event);
- // xxxpedro adjusting coordinates because the panel isn't a window yet
- var offset = event.clientX - this.panelNode.parentNode.offsetLeft;
- if (!isLeftClick(event) || offset <= 20)
- return;
- var target = event.target || event.srcElement;
- //console.log("ok", target, hasClass(target, "textEditorInner"), !isLeftClick(event), offset <= 20);
- // if the inline editor was clicked, don't insert a new rule
- if (hasClass(target, "textEditorInner"))
- return;
- var row = getAncestorByClass(target, "cssRule");
- if (row && !getAncestorByClass(target, "cssPropName")
- && !getAncestorByClass(target, "cssPropValue"))
- {
- this.insertPropertyRow(row);
- cancelEvent(event);
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- name: "stylesheet",
- title: "CSS",
- parentPanel: null,
- searchable: true,
- dependents: ["css", "stylesheet", "dom", "domSide", "layout"],
- options:
- {
- hasToolButtons: true
- },
- create: function()
- {
- Firebug.Panel.create.apply(this, arguments);
- this.onMouseDown = bind(this.onMouseDown, this);
- this.onDoubleClick = bind(this.onDoubleClick, this);
- if (this.name == "stylesheet")
- {
- this.onChangeSelect = bind(this.onChangeSelect, this);
- var doc = Firebug.browser.document;
- var selectNode = this.selectNode = createElement("select");
- processAllStyleSheets(doc, function(doc, styleSheet)
- {
- var key = StyleSheetCache.key(styleSheet);
- var fileName = getFileName(styleSheet.href) || getFileName(doc.location.href);
- var option = createElement("option", {value: key});
- option.appendChild(Firebug.chrome.document.createTextNode(fileName));
- selectNode.appendChild(option);
- });
- this.toolButtonsNode.appendChild(selectNode);
- }
- /**/
- },
- onChangeSelect: function(event)
- {
- event = event || window.event;
- var target = event.srcElement || event.currentTarget;
- var key = target.value;
- var styleSheet = StyleSheetCache.get(key);
- this.updateLocation(styleSheet);
- },
- initialize: function()
- {
- Firebug.Panel.initialize.apply(this, arguments);
- //if (!domUtils)
- //{
- // try {
- // domUtils = CCSV("@mozilla.org/inspector/dom-utils;1", "inIDOMUtils");
- // } catch (exc) {
- // if (FBTrace.DBG_ERRORS)
- // FBTrace.sysout("@mozilla.org/inspector/dom-utils;1 FAILED to load: "+exc, exc);
- // }
- //}
- //TODO: xxxpedro
- this.context = Firebug.chrome; // TODO: xxxpedro css2
- this.document = Firebug.chrome.document; // TODO: xxxpedro css2
- this.initializeNode();
- if (this.name == "stylesheet")
- {
- var styleSheets = Firebug.browser.document.styleSheets;
- if (styleSheets.length > 0)
- {
- addEvent(this.selectNode, "change", this.onChangeSelect);
- this.updateLocation(styleSheets[0]);
- }
- }
- //Firebug.SourceBoxPanel.initialize.apply(this, arguments);
- },
- shutdown: function()
- {
- // must destroy the editor when we leave the panel to avoid problems (Issue 2981)
- Firebug.Editor.stopEditing();
- if (this.name == "stylesheet")
- {
- removeEvent(this.selectNode, "change", this.onChangeSelect);
- }
- this.destroyNode();
- Firebug.Panel.shutdown.apply(this, arguments);
- },
- destroy: function(state)
- {
- //state.scrollTop = this.panelNode.scrollTop ? this.panelNode.scrollTop : this.lastScrollTop;
- //persistObjects(this, state);
- // xxxpedro we are stopping the editor in the shutdown method already
- //Firebug.Editor.stopEditing();
- Firebug.Panel.destroy.apply(this, arguments);
- },
- initializeNode: function(oldPanelNode)
- {
- addEvent(this.panelNode, "mousedown", this.onMouseDown);
- addEvent(this.panelNode, "dblclick", this.onDoubleClick);
- //Firebug.SourceBoxPanel.initializeNode.apply(this, arguments);
- //dispatch([Firebug.A11yModel], 'onInitializeNode', [this, 'css']);
- },
- destroyNode: function()
- {
- removeEvent(this.panelNode, "mousedown", this.onMouseDown);
- removeEvent(this.panelNode, "dblclick", this.onDoubleClick);
- //Firebug.SourceBoxPanel.destroyNode.apply(this, arguments);
- //dispatch([Firebug.A11yModel], 'onDestroyNode', [this, 'css']);
- },
- ishow: function(state)
- {
- Firebug.Inspector.stopInspecting(true);
- this.showToolbarButtons("fbCSSButtons", true);
- if (this.context.loaded && !this.location) // wait for loadedContext to restore the panel
- {
- restoreObjects(this, state);
- if (!this.location)
- this.location = this.getDefaultLocation();
- if (state && state.scrollTop)
- this.panelNode.scrollTop = state.scrollTop;
- }
- },
- ihide: function()
- {
- this.showToolbarButtons("fbCSSButtons", false);
- this.lastScrollTop = this.panelNode.scrollTop;
- },
- supportsObject: function(object)
- {
- if (object instanceof CSSStyleSheet)
- return 1;
- else if (object instanceof CSSStyleRule)
- return 2;
- else if (object instanceof CSSStyleDeclaration)
- return 2;
- else if (object instanceof SourceLink && object.type == "css" && reCSS.test(object.href))
- return 2;
- else
- return 0;
- },
- updateLocation: function(styleSheet)
- {
- if (!styleSheet)
- return;
- if (styleSheet.editStyleSheet)
- styleSheet = styleSheet.editStyleSheet.sheet;
- // if it is a restricted stylesheet, show the warning message and abort the update process
- if (styleSheet.restricted)
- {
- FirebugReps.Warning.tag.replace({object: "AccessRestricted"}, this.panelNode);
- // TODO: xxxpedro remove when there the external resource problem is fixed
- externalStyleSheetWarning.tag.append({
- object: "The stylesheet could not be loaded due to access restrictions. ",
- link: "more...",
- href: "http://getfirebug.com/wiki/index.php/Firebug_Lite_FAQ#I_keep_seeing_.22Access_to_restricted_URI_denied.22"
- }, this.panelNode);
- return;
- }
- var rules = this.getStyleSheetRules(this.context, styleSheet);
- var result;
- if (rules.length)
- result = this.template.tag.replace({rules: rules}, this.panelNode);
- else
- result = FirebugReps.Warning.tag.replace({object: "EmptyStyleSheet"}, this.panelNode);
- // TODO: xxxpedro need to fix showToolbarButtons function
- //this.showToolbarButtons("fbCSSButtons", !isSystemStyleSheet(this.location));
- //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, this.panelNode]);
- },
- updateSelection: function(object)
- {
- this.selection = null;
- if (object instanceof CSSStyleDeclaration) {
- object = object.parentRule;
- }
- if (object instanceof CSSStyleRule)
- {
- this.navigate(object.parentStyleSheet);
- this.highlightRule(object);
- }
- else if (object instanceof CSSStyleSheet)
- {
- this.navigate(object);
- }
- else if (object instanceof SourceLink)
- {
- try
- {
- var sourceLink = object;
- var sourceFile = getSourceFileByHref(sourceLink.href, this.context);
- if (sourceFile)
- {
- clearNode(this.panelNode); // replace rendered stylesheets
- this.showSourceFile(sourceFile);
- var lineNo = object.line;
- if (lineNo)
- this.scrollToLine(lineNo, this.jumpHighlightFactory(lineNo, this.context));
- }
- else // XXXjjb we should not be taking this path
- {
- var stylesheet = getStyleSheetByHref(sourceLink.href, this.context);
- if (stylesheet)
- this.navigate(stylesheet);
- else
- {
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("css.updateSelection no sourceFile for "+sourceLink.href, sourceLink);
- }
- }
- }
- catch(exc) {
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("css.upDateSelection FAILS "+exc, exc);
- }
- }
- },
- updateOption: function(name, value)
- {
- if (name == "expandShorthandProps")
- this.refresh();
- },
- getLocationList: function()
- {
- var styleSheets = getAllStyleSheets(this.context);
- return styleSheets;
- },
- getOptionsMenuItems: function()
- {
- return [
- {label: "Expand Shorthand Properties", type: "checkbox", checked: Firebug.expandShorthandProps,
- command: bindFixed(Firebug.togglePref, Firebug, "expandShorthandProps") },
- "-",
- {label: "Refresh", command: bind(this.refresh, this) }
- ];
- },
- getContextMenuItems: function(style, target)
- {
- var items = [];
- if (this.infoTipType == "color")
- {
- items.push(
- {label: "CopyColor",
- command: bindFixed(copyToClipboard, FBL, this.infoTipObject) }
- );
- }
- else if (this.infoTipType == "image")
- {
- items.push(
- {label: "CopyImageLocation",
- command: bindFixed(copyToClipboard, FBL, this.infoTipObject) },
- {label: "OpenImageInNewTab",
- command: bindFixed(openNewTab, FBL, this.infoTipObject) }
- );
- }
- ///if (this.selection instanceof Element)
- if (isElement(this.selection))
- {
- items.push(
- //"-",
- {label: "EditStyle",
- command: bindFixed(this.editElementStyle, this) }
- );
- }
- else if (!isSystemStyleSheet(this.selection))
- {
- items.push(
- //"-",
- {label: "NewRule",
- command: bindFixed(this.insertRule, this, target) }
- );
- }
- var cssRule = getAncestorByClass(target, "cssRule");
- if (cssRule && hasClass(cssRule, "cssEditableRule"))
- {
- items.push(
- "-",
- {label: "NewProp",
- command: bindFixed(this.insertPropertyRow, this, target) }
- );
- var propRow = getAncestorByClass(target, "cssProp");
- if (propRow)
- {
- var propName = getChildByClass(propRow, "cssPropName")[textContent];
- var isDisabled = hasClass(propRow, "disabledStyle");
- items.push(
- {label: $STRF("EditProp", [propName]), nol10n: true,
- command: bindFixed(this.editPropertyRow, this, propRow) },
- {label: $STRF("DeleteProp", [propName]), nol10n: true,
- command: bindFixed(this.deletePropertyRow, this, propRow) },
- {label: $STRF("DisableProp", [propName]), nol10n: true,
- type: "checkbox", checked: isDisabled,
- command: bindFixed(this.disablePropertyRow, this, propRow) }
- );
- }
- }
- items.push(
- "-",
- {label: "Refresh", command: bind(this.refresh, this) }
- );
- return items;
- },
- browseObject: function(object)
- {
- if (this.infoTipType == "image")
- {
- openNewTab(this.infoTipObject);
- return true;
- }
- },
- showInfoTip: function(infoTip, target, x, y)
- {
- var propValue = getAncestorByClass(target, "cssPropValue");
- if (propValue)
- {
- var offset = getClientOffset(propValue);
- var offsetX = x-offset.x;
- var text = propValue[textContent];
- var charWidth = propValue.offsetWidth/text.length;
- var charOffset = Math.floor(offsetX/charWidth);
- var cssValue = parseCSSValue(text, charOffset);
- if (cssValue)
- {
- if (cssValue.value == this.infoTipValue)
- return true;
- this.infoTipValue = cssValue.value;
- if (cssValue.type == "rgb" || (!cssValue.type && isColorKeyword(cssValue.value)))
- {
- this.infoTipType = "color";
- this.infoTipObject = cssValue.value;
- return Firebug.InfoTip.populateColorInfoTip(infoTip, cssValue.value);
- }
- else if (cssValue.type == "url")
- {
- ///var propNameNode = target.parentNode.getElementsByClassName("cssPropName").item(0);
- var propNameNode = getElementByClass(target.parentNode, "cssPropName");
- if (propNameNode && isImageRule(propNameNode[textContent]))
- {
- var rule = Firebug.getRepObject(target);
- var baseURL = this.getStylesheetURL(rule);
- var relURL = parseURLValue(cssValue.value);
- var absURL = isDataURL(relURL) ? relURL:absoluteURL(relURL, baseURL);
- var repeat = parseRepeatValue(text);
- this.infoTipType = "image";
- this.infoTipObject = absURL;
- return Firebug.InfoTip.populateImageInfoTip(infoTip, absURL, repeat);
- }
- }
- }
- }
- delete this.infoTipType;
- delete this.infoTipValue;
- delete this.infoTipObject;
- },
- getEditor: function(target, value)
- {
- if (target == this.panelNode
- || hasClass(target, "cssSelector") || hasClass(target, "cssRule")
- || hasClass(target, "cssSheet"))
- {
- if (!this.ruleEditor)
- this.ruleEditor = new CSSRuleEditor(this.document);
- return this.ruleEditor;
- }
- else
- {
- if (!this.editor)
- this.editor = new CSSEditor(this.document);
- return this.editor;
- }
- },
- getDefaultLocation: function()
- {
- try
- {
- var styleSheets = this.context.window.document.styleSheets;
- if (styleSheets.length)
- {
- var sheet = styleSheets[0];
- return (Firebug.filterSystemURLs && isSystemURL(getURLForStyleSheet(sheet))) ? null : sheet;
- }
- }
- catch (exc)
- {
- if (FBTrace.DBG_LOCATIONS)
- FBTrace.sysout("css.getDefaultLocation FAILS "+exc, exc);
- }
- },
- getObjectDescription: function(styleSheet)
- {
- var url = getURLForStyleSheet(styleSheet);
- var instance = getInstanceForStyleSheet(styleSheet);
- var baseDescription = splitURLBase(url);
- if (instance) {
- baseDescription.name = baseDescription.name + " #" + (instance + 1);
- }
- return baseDescription;
- },
- search: function(text, reverse)
- {
- var curDoc = this.searchCurrentDoc(!Firebug.searchGlobal, text, reverse);
- if (!curDoc && Firebug.searchGlobal)
- {
- return this.searchOtherDocs(text, reverse);
- }
- return curDoc;
- },
- searchOtherDocs: function(text, reverse)
- {
- var scanRE = Firebug.Search.getTestingRegex(text);
- function scanDoc(styleSheet) {
- // we don't care about reverse here as we are just looking for existence,
- // if we do have a result we will handle the reverse logic on display
- for (var i = 0; i < styleSheet.cssRules.length; i++)
- {
- if (scanRE.test(styleSheet.cssRules[i].cssText))
- {
- return true;
- }
- }
- }
- if (this.navigateToNextDocument(scanDoc, reverse))
- {
- return this.searchCurrentDoc(true, text, reverse);
- }
- },
- searchCurrentDoc: function(wrapSearch, text, reverse)
- {
- if (!text)
- {
- delete this.currentSearch;
- return false;
- }
- var row;
- if (this.currentSearch && text == this.currentSearch.text)
- {
- row = this.currentSearch.findNext(wrapSearch, false, reverse, Firebug.Search.isCaseSensitive(text));
- }
- else
- {
- if (this.editing)
- {
- this.currentSearch = new TextSearch(this.stylesheetEditor.box);
- row = this.currentSearch.find(text, reverse, Firebug.Search.isCaseSensitive(text));
- if (row)
- {
- var sel = this.document.defaultView.getSelection();
- sel.removeAllRanges();
- sel.addRange(this.currentSearch.range);
- scrollSelectionIntoView(this);
- return true;
- }
- else
- return false;
- }
- else
- {
- function findRow(node) { return node.nodeType == 1 ? node : node.parentNode; }
- this.currentSearch = new TextSearch(this.panelNode, findRow);
- row = this.currentSearch.find(text, reverse, Firebug.Search.isCaseSensitive(text));
- }
- }
- if (row)
- {
- this.document.defaultView.getSelection().selectAllChildren(row);
- scrollIntoCenterView(row, this.panelNode);
- dispatch([Firebug.A11yModel], 'onCSSSearchMatchFound', [this, text, row]);
- return true;
- }
- else
- {
- dispatch([Firebug.A11yModel], 'onCSSSearchMatchFound', [this, text, null]);
- return false;
- }
- },
- getSearchOptionsMenuItems: function()
- {
- return [
- Firebug.Search.searchOptionMenu("search.Case_Sensitive", "searchCaseSensitive"),
- Firebug.Search.searchOptionMenu("search.Multiple_Files", "searchGlobal")
- ];
- }
- });
- /**/
- // ************************************************************************************************
- function CSSElementPanel() {}
- CSSElementPanel.prototype = extend(Firebug.CSSStyleSheetPanel.prototype,
- {
- template: domplate(
- {
- cascadedTag:
- DIV({"class": "a11yCSSView", role : 'presentation'},
- DIV({role : 'list', 'aria-label' : $STR('aria.labels.style rules') },
- FOR("rule", "$rules",
- TAG("$ruleTag", {rule: "$rule"})
- )
- ),
- DIV({role : "list", 'aria-label' :$STR('aria.labels.inherited style rules')},
- FOR("section", "$inherited",
- H1({"class": "cssInheritHeader groupHeader focusRow", role : 'listitem' },
- SPAN({"class": "cssInheritLabel"}, "$inheritLabel"),
- TAG(FirebugReps.Element.shortTag, {object: "$section.element"})
- ),
- DIV({role : 'group'},
- FOR("rule", "$section.rules",
- TAG("$ruleTag", {rule: "$rule"})
- )
- )
- )
- )
- ),
- ruleTag:
- isIE ?
- // IE needs the sourceLink first, otherwise it will be rendered outside the panel
- DIV({"class": "cssElementRuleContainer"},
- TAG(FirebugReps.SourceLink.tag, {object: "$rule.sourceLink"}),
- TAG(CSSStyleRuleTag.tag, {rule: "$rule"})
- )
- :
- // other browsers need the sourceLink last, otherwise it will cause an extra space
- // before the rule representation
- DIV({"class": "cssElementRuleContainer"},
- TAG(CSSStyleRuleTag.tag, {rule: "$rule"}),
- TAG(FirebugReps.SourceLink.tag, {object: "$rule.sourceLink"})
- )
- }),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- updateCascadeView: function(element)
- {
- //dispatch([Firebug.A11yModel], 'onBeforeCSSRulesAdded', [this]);
- var rules = [], sections = [], usedProps = {};
- this.getInheritedRules(element, sections, usedProps);
- this.getElementRules(element, rules, usedProps);
- if (rules.length || sections.length)
- {
- var inheritLabel = "Inherited from"; // $STR("InheritedFrom");
- var result = this.template.cascadedTag.replace({rules: rules, inherited: sections,
- inheritLabel: inheritLabel}, this.panelNode);
- //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, result]);
- }
- else
- {
- var result = FirebugReps.Warning.tag.replace({object: "EmptyElementCSS"}, this.panelNode);
- //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, result]);
- }
- // TODO: xxxpedro remove when there the external resource problem is fixed
- if (externalStyleSheetURLs.length > 0)
- externalStyleSheetWarning.tag.append({
- object: "The results here may be inaccurate because some " +
- "stylesheets could not be loaded due to access restrictions. ",
- link: "more...",
- href: "http://getfirebug.com/wiki/index.php/Firebug_Lite_FAQ#I_keep_seeing_.22This_element_has_no_style_rules.22"
- }, this.panelNode);
- },
- getStylesheetURL: function(rule)
- {
- // if the parentStyleSheet.href is null, CSS std says its inline style.
- // TODO: xxxpedro IE doesn't have rule.parentStyleSheet so we must fall back to the doc.location
- if (rule && rule.parentStyleSheet && rule.parentStyleSheet.href)
- return rule.parentStyleSheet.href;
- else
- return this.selection.ownerDocument.location.href;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getInheritedRules: function(element, sections, usedProps)
- {
- var parent = element.parentNode;
- if (parent && parent.nodeType == 1)
- {
- this.getInheritedRules(parent, sections, usedProps);
- var rules = [];
- this.getElementRules(parent, rules, usedProps, true);
- if (rules.length)
- sections.splice(0, 0, {element: parent, rules: rules});
- }
- },
- getElementRules: function(element, rules, usedProps, inheritMode)
- {
- var inspectedRules, displayedRules = {};
- // TODO: xxxpedro remove document specificity issue
- //var eid = ElementCache(element);
- //inspectedRules = ElementCSSRulesMap[eid];
- inspectedRules = getElementCSSRules(element);
- if (inspectedRules)
- {
- for (var i = 0, length=inspectedRules.length; i < length; ++i)
- {
- var ruleId = inspectedRules[i];
- var ruleData = CSSRuleMap[ruleId];
- var rule = ruleData.rule;
- var ssid = ruleData.styleSheetId;
- var parentStyleSheet = StyleSheetCache.get(ssid);
- var href = parentStyleSheet.externalURL ? parentStyleSheet.externalURL : parentStyleSheet.href; // Null means inline
- var instance = null;
- //var instance = getInstanceForStyleSheet(rule.parentStyleSheet, element.ownerDocument);
- var isSystemSheet = false;
- //var isSystemSheet = isSystemStyleSheet(rule.parentStyleSheet);
- if (!Firebug.showUserAgentCSS && isSystemSheet) // This removes user agent rules
- continue;
- if (!href)
- href = element.ownerDocument.location.href; // http://code.google.com/p/fbug/issues/detail?id=452
- var props = this.getRuleProperties(this.context, rule, inheritMode);
- if (inheritMode && !props.length)
- continue;
- //
- //var line = domUtils.getRuleLine(rule);
- var line;
- var ruleId = rule.selectorText+"/"+line;
- var sourceLink = new SourceLink(href, line, "css", rule, instance);
- this.markOverridenProps(props, usedProps, inheritMode);
- rules.splice(0, 0, {rule: rule, id: ruleId,
- selector: ruleData.selector, sourceLink: sourceLink,
- props: props, inherited: inheritMode,
- isSystemSheet: isSystemSheet});
- }
- }
- if (element.style)
- this.getStyleProperties(element, rules, usedProps, inheritMode);
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("getElementRules "+rules.length+" rules for "+getElementXPath(element), rules);
- },
- /*
- getElementRules: function(element, rules, usedProps, inheritMode)
- {
- var inspectedRules, displayedRules = {};
- try
- {
- inspectedRules = domUtils ? domUtils.getCSSStyleRules(element) : null;
- } catch (exc) {}
- if (inspectedRules)
- {
- for (var i = 0; i < inspectedRules.Count(); ++i)
- {
- var rule = QI(inspectedRules.GetElementAt(i), nsIDOMCSSStyleRule);
- var href = rule.parentStyleSheet.href; // Null means inline
- var instance = getInstanceForStyleSheet(rule.parentStyleSheet, element.ownerDocument);
- var isSystemSheet = isSystemStyleSheet(rule.parentStyleSheet);
- if (!Firebug.showUserAgentCSS && isSystemSheet) // This removes user agent rules
- continue;
- if (!href)
- href = element.ownerDocument.location.href; // http://code.google.com/p/fbug/issues/detail?id=452
- var props = this.getRuleProperties(this.context, rule, inheritMode);
- if (inheritMode && !props.length)
- continue;
- var line = domUtils.getRuleLine(rule);
- var ruleId = rule.selectorText+"/"+line;
- var sourceLink = new SourceLink(href, line, "css", rule, instance);
- this.markOverridenProps(props, usedProps, inheritMode);
- rules.splice(0, 0, {rule: rule, id: ruleId,
- selector: rule.selectorText, sourceLink: sourceLink,
- props: props, inherited: inheritMode,
- isSystemSheet: isSystemSheet});
- }
- }
- if (element.style)
- this.getStyleProperties(element, rules, usedProps, inheritMode);
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("getElementRules "+rules.length+" rules for "+getElementXPath(element), rules);
- },
- /**/
- markOverridenProps: function(props, usedProps, inheritMode)
- {
- for (var i = 0; i < props.length; ++i)
- {
- var prop = props[i];
- if ( usedProps.hasOwnProperty(prop.name) )
- {
- var deadProps = usedProps[prop.name]; // all previous occurrences of this property
- for (var j = 0; j < deadProps.length; ++j)
- {
- var deadProp = deadProps[j];
- if (!deadProp.disabled && !deadProp.wasInherited && deadProp.important && !prop.important)
- prop.overridden = true; // new occurrence overridden
- else if (!prop.disabled)
- deadProp.overridden = true; // previous occurrences overridden
- }
- }
- else
- usedProps[prop.name] = [];
- prop.wasInherited = inheritMode ? true : false;
- usedProps[prop.name].push(prop); // all occurrences of a property seen so far, by name
- }
- },
- getStyleProperties: function(element, rules, usedProps, inheritMode)
- {
- var props = this.parseCSSProps(element.style, inheritMode);
- this.addOldProperties(this.context, getElementXPath(element), inheritMode, props);
- sortProperties(props);
- this.markOverridenProps(props, usedProps, inheritMode);
- if (props.length)
- rules.splice(0, 0,
- {rule: element, id: getElementXPath(element),
- selector: "element.style", props: props, inherited: inheritMode});
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- name: "css",
- title: "Style",
- parentPanel: "HTML",
- order: 0,
- initialize: function()
- {
- this.context = Firebug.chrome; // TODO: xxxpedro css2
- this.document = Firebug.chrome.document; // TODO: xxxpedro css2
- Firebug.CSSStyleSheetPanel.prototype.initialize.apply(this, arguments);
- // TODO: xxxpedro css2
- var selection = ElementCache.get(FirebugChrome.selectedHTMLElementId);
- if (selection)
- this.select(selection, true);
- //this.updateCascadeView(document.getElementsByTagName("h1")[0]);
- //this.updateCascadeView(document.getElementById("build"));
- /*
- this.onStateChange = bindFixed(this.contentStateCheck, this);
- this.onHoverChange = bindFixed(this.contentStateCheck, this, STATE_HOVER);
- this.onActiveChange = bindFixed(this.contentStateCheck, this, STATE_ACTIVE);
- /**/
- },
- ishow: function(state)
- {
- },
- watchWindow: function(win)
- {
- if (domUtils)
- {
- // Normally these would not be required, but in order to update after the state is set
- // using the options menu we need to monitor these global events as well
- var doc = win.document;
- ///addEvent(doc, "mouseover", this.onHoverChange);
- ///addEvent(doc, "mousedown", this.onActiveChange);
- }
- },
- unwatchWindow: function(win)
- {
- var doc = win.document;
- ///removeEvent(doc, "mouseover", this.onHoverChange);
- ///removeEvent(doc, "mousedown", this.onActiveChange);
- if (isAncestor(this.stateChangeEl, doc))
- {
- this.removeStateChangeHandlers();
- }
- },
- supportsObject: function(object)
- {
- return object instanceof Element ? 1 : 0;
- },
- updateView: function(element)
- {
- this.updateCascadeView(element);
- if (domUtils)
- {
- this.contentState = safeGetContentState(element);
- this.addStateChangeHandlers(element);
- }
- },
- updateSelection: function(element)
- {
- if ( !instanceOf(element , "Element") ) // html supports SourceLink
- return;
- if (sothinkInstalled)
- {
- FirebugReps.Warning.tag.replace({object: "SothinkWarning"}, this.panelNode);
- return;
- }
- /*
- if (!domUtils)
- {
- FirebugReps.Warning.tag.replace({object: "DOMInspectorWarning"}, this.panelNode);
- return;
- }
- /**/
- if (!element)
- return;
- this.updateView(element);
- },
- updateOption: function(name, value)
- {
- if (name == "showUserAgentCSS" || name == "expandShorthandProps")
- this.refresh();
- },
- getOptionsMenuItems: function()
- {
- var ret = [
- {label: "Show User Agent CSS", type: "checkbox", checked: Firebug.showUserAgentCSS,
- command: bindFixed(Firebug.togglePref, Firebug, "showUserAgentCSS") },
- {label: "Expand Shorthand Properties", type: "checkbox", checked: Firebug.expandShorthandProps,
- command: bindFixed(Firebug.togglePref, Firebug, "expandShorthandProps") }
- ];
- if (domUtils && this.selection)
- {
- var state = safeGetContentState(this.selection);
- ret.push("-");
- ret.push({label: ":active", type: "checkbox", checked: state & STATE_ACTIVE,
- command: bindFixed(this.updateContentState, this, STATE_ACTIVE, state & STATE_ACTIVE)});
- ret.push({label: ":hover", type: "checkbox", checked: state & STATE_HOVER,
- command: bindFixed(this.updateContentState, this, STATE_HOVER, state & STATE_HOVER)});
- }
- return ret;
- },
- updateContentState: function(state, remove)
- {
- domUtils.setContentState(remove ? this.selection.ownerDocument.documentElement : this.selection, state);
- this.refresh();
- },
- addStateChangeHandlers: function(el)
- {
- this.removeStateChangeHandlers();
- /*
- addEvent(el, "focus", this.onStateChange);
- addEvent(el, "blur", this.onStateChange);
- addEvent(el, "mouseup", this.onStateChange);
- addEvent(el, "mousedown", this.onStateChange);
- addEvent(el, "mouseover", this.onStateChange);
- addEvent(el, "mouseout", this.onStateChange);
- /**/
- this.stateChangeEl = el;
- },
- removeStateChangeHandlers: function()
- {
- var sel = this.stateChangeEl;
- if (sel)
- {
- /*
- removeEvent(sel, "focus", this.onStateChange);
- removeEvent(sel, "blur", this.onStateChange);
- removeEvent(sel, "mouseup", this.onStateChange);
- removeEvent(sel, "mousedown", this.onStateChange);
- removeEvent(sel, "mouseover", this.onStateChange);
- removeEvent(sel, "mouseout", this.onStateChange);
- /**/
- }
- },
- contentStateCheck: function(state)
- {
- if (!state || this.contentState & state)
- {
- var timeoutRunner = bindFixed(function()
- {
- var newState = safeGetContentState(this.selection);
- if (newState != this.contentState)
- {
- this.context.invalidatePanels(this.name);
- }
- }, this);
- // Delay exec until after the event has processed and the state has been updated
- setTimeout(timeoutRunner, 0);
- }
- }
- });
- function safeGetContentState(selection)
- {
- try
- {
- return domUtils.getContentState(selection);
- }
- catch (e)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("css.safeGetContentState; EXCEPTION", e);
- }
- }
- // ************************************************************************************************
- function CSSComputedElementPanel() {}
- CSSComputedElementPanel.prototype = extend(CSSElementPanel.prototype,
- {
- template: domplate(
- {
- computedTag:
- DIV({"class": "a11yCSSView", role : "list", "aria-label" : $STR('aria.labels.computed styles')},
- FOR("group", "$groups",
- H1({"class": "cssInheritHeader groupHeader focusRow", role : "listitem"},
- SPAN({"class": "cssInheritLabel"}, "$group.title")
- ),
- TABLE({width: "100%", role : 'group'},
- TBODY({role : 'presentation'},
- FOR("prop", "$group.props",
- TR({"class": 'focusRow computedStyleRow', role : 'listitem'},
- TD({"class": "stylePropName", role : 'presentation'}, "$prop.name"),
- TD({"class": "stylePropValue", role : 'presentation'}, "$prop.value")
- )
- )
- )
- )
- )
- )
- }),
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- updateComputedView: function(element)
- {
- var win = isIE ?
- element.ownerDocument.parentWindow :
- element.ownerDocument.defaultView;
- var style = isIE ?
- element.currentStyle :
- win.getComputedStyle(element, "");
- var groups = [];
- for (var groupName in styleGroups)
- {
- // TODO: xxxpedro i18n $STR
- //var title = $STR("StyleGroup-" + groupName);
- var title = styleGroupTitles[groupName];
- var group = {title: title, props: []};
- groups.push(group);
- var props = styleGroups[groupName];
- for (var i = 0; i < props.length; ++i)
- {
- var propName = props[i];
- var propValue = style.getPropertyValue ?
- style.getPropertyValue(propName) :
- ""+style[toCamelCase(propName)];
- if (propValue === undefined || propValue === null)
- continue;
- propValue = stripUnits(rgbToHex(propValue));
- if (propValue)
- group.props.push({name: propName, value: propValue});
- }
- }
- var result = this.template.computedTag.replace({groups: groups}, this.panelNode);
- //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, result]);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- name: "computed",
- title: "Computed",
- parentPanel: "HTML",
- order: 1,
- updateView: function(element)
- {
- this.updateComputedView(element);
- },
- getOptionsMenuItems: function()
- {
- return [
- {label: "Refresh", command: bind(this.refresh, this) }
- ];
- }
- });
- // ************************************************************************************************
- // CSSEditor
- function CSSEditor(doc)
- {
- this.initializeInline(doc);
- }
- CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype,
- {
- insertNewRow: function(target, insertWhere)
- {
- var rule = Firebug.getRepObject(target);
- var emptyProp =
- {
- // TODO: xxxpedro - uses charCode(255) to force the element being rendered,
- // allowing webkit to get the correct position of the property name "span",
- // when inserting a new CSS rule?
- name: "",
- value: "",
- important: ""
- };
- if (insertWhere == "before")
- return CSSPropTag.tag.insertBefore({prop: emptyProp, rule: rule}, target);
- else
- return CSSPropTag.tag.insertAfter({prop: emptyProp, rule: rule}, target);
- },
- saveEdit: function(target, value, previousValue)
- {
- // We need to check the value first in order to avoid a problem in IE8
- // See Issue 3038: Empty (null) styles when adding CSS styles in Firebug Lite
- if (!value) return;
- target.innerHTML = escapeForCss(value);
- var row = getAncestorByClass(target, "cssProp");
- if (hasClass(row, "disabledStyle"))
- toggleClass(row, "disabledStyle");
- var rule = Firebug.getRepObject(target);
- if (hasClass(target, "cssPropName"))
- {
- if (value && previousValue != value) // name of property has changed.
- {
- var propValue = getChildByClass(row, "cssPropValue")[textContent];
- var parsedValue = parsePriority(propValue);
- if (propValue && propValue != "undefined") {
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("CSSEditor.saveEdit : "+previousValue+"->"+value+" = "+propValue+"\n");
- if (previousValue)
- Firebug.CSSModule.removeProperty(rule, previousValue);
- Firebug.CSSModule.setProperty(rule, value, parsedValue.value, parsedValue.priority);
- }
- }
- else if (!value) // name of the property has been deleted, so remove the property.
- Firebug.CSSModule.removeProperty(rule, previousValue);
- }
- else if (getAncestorByClass(target, "cssPropValue"))
- {
- var propName = getChildByClass(row, "cssPropName")[textContent];
- var propValue = getChildByClass(row, "cssPropValue")[textContent];
- if (FBTrace.DBG_CSS)
- {
- FBTrace.sysout("CSSEditor.saveEdit propName=propValue: "+propName +" = "+propValue+"\n");
- // FBTrace.sysout("CSSEditor.saveEdit BEFORE style:",style);
- }
- if (value && value != "null")
- {
- var parsedValue = parsePriority(value);
- Firebug.CSSModule.setProperty(rule, propName, parsedValue.value, parsedValue.priority);
- }
- else if (previousValue && previousValue != "null")
- Firebug.CSSModule.removeProperty(rule, propName);
- }
- this.panel.markChange(this.panel.name == "stylesheet");
- },
- advanceToNext: function(target, charCode)
- {
- if (charCode == 58 /*":"*/ && hasClass(target, "cssPropName"))
- return true;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- getAutoCompleteRange: function(value, offset)
- {
- if (hasClass(this.target, "cssPropName"))
- return {start: 0, end: value.length-1};
- else
- return parseCSSValue(value, offset);
- },
- getAutoCompleteList: function(preExpr, expr, postExpr)
- {
- if (hasClass(this.target, "cssPropName"))
- {
- return getCSSPropertyNames();
- }
- else
- {
- var row = getAncestorByClass(this.target, "cssProp");
- var propName = getChildByClass(row, "cssPropName")[textContent];
- return getCSSKeywordsByProperty(propName);
- }
- }
- });
- //************************************************************************************************
- //CSSRuleEditor
- function CSSRuleEditor(doc)
- {
- this.initializeInline(doc);
- this.completeAsYouType = false;
- }
- CSSRuleEditor.uniquifier = 0;
- CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype,
- {
- insertNewRow: function(target, insertWhere)
- {
- var emptyRule = {
- selector: "",
- id: "",
- props: [],
- isSelectorEditable: true
- };
- if (insertWhere == "before")
- return CSSStyleRuleTag.tag.insertBefore({rule: emptyRule}, target);
- else
- return CSSStyleRuleTag.tag.insertAfter({rule: emptyRule}, target);
- },
- saveEdit: function(target, value, previousValue)
- {
- if (FBTrace.DBG_CSS)
- FBTrace.sysout("CSSRuleEditor.saveEdit: '" + value + "' '" + previousValue + "'", target);
- target.innerHTML = escapeForCss(value);
- if (value === previousValue) return;
- var row = getAncestorByClass(target, "cssRule");
- var styleSheet = this.panel.location;
- styleSheet = styleSheet.editStyleSheet ? styleSheet.editStyleSheet.sheet : styleSheet;
- var cssRules = styleSheet.cssRules;
- var rule = Firebug.getRepObject(target), oldRule = rule;
- var ruleIndex = cssRules.length;
- if (rule || Firebug.getRepObject(row.nextSibling))
- {
- var searchRule = rule || Firebug.getRepObject(row.nextSibling);
- for (ruleIndex=0; ruleIndex<cssRules.length && searchRule!=cssRules[ruleIndex]; ruleIndex++) {}
- }
- // Delete in all cases except for new add
- // We want to do this before the insert to ease change tracking
- if (oldRule)
- {
- Firebug.CSSModule.deleteRule(styleSheet, ruleIndex);
- }
- // Firefox does not follow the spec for the update selector text case.
- // When attempting to update the value, firefox will silently fail.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=37468 for the quite
- // old discussion of this bug.
- // As a result we need to recreate the style every time the selector
- // changes.
- if (value)
- {
- var cssText = [ value, "{" ];
- var props = row.getElementsByClassName("cssProp");
- for (var i = 0; i < props.length; i++) {
- var propEl = props[i];
- if (!hasClass(propEl, "disabledStyle")) {
- cssText.push(getChildByClass(propEl, "cssPropName")[textContent]);
- cssText.push(":");
- cssText.push(getChildByClass(propEl, "cssPropValue")[textContent]);
- cssText.push(";");
- }
- }
- cssText.push("}");
- cssText = cssText.join("");
- try
- {
- var insertLoc = Firebug.CSSModule.insertRule(styleSheet, cssText, ruleIndex);
- rule = cssRules[insertLoc];
- ruleIndex++;
- }
- catch (err)
- {
- if (FBTrace.DBG_CSS || FBTrace.DBG_ERRORS)
- FBTrace.sysout("CSS Insert Error: "+err, err);
- target.innerHTML = escapeForCss(previousValue);
- row.repObject = undefined;
- return;
- }
- } else {
- rule = undefined;
- }
- // Update the rep object
- row.repObject = rule;
- if (!oldRule)
- {
- // Who knows what the domutils will return for rule line
- // for a recently created rule. To be safe we just generate
- // a unique value as this is only used as an internal key.
- var ruleId = "new/"+value+"/"+(++CSSRuleEditor.uniquifier);
- row.setAttribute("ruleId", ruleId);
- }
- this.panel.markChange(this.panel.name == "stylesheet");
- }
- });
- // ************************************************************************************************
- // StyleSheetEditor
- function StyleSheetEditor(doc)
- {
- this.box = this.tag.replace({}, doc, this);
- this.input = this.box.firstChild;
- }
- StyleSheetEditor.prototype = domplate(Firebug.BaseEditor,
- {
- multiLine: true,
- tag: DIV(
- TEXTAREA({"class": "styleSheetEditor fullPanelEditor", oninput: "$onInput"})
- ),
- getValue: function()
- {
- return this.input.value;
- },
- setValue: function(value)
- {
- return this.input.value = value;
- },
- show: function(target, panel, value, textSize, targetSize)
- {
- this.target = target;
- this.panel = panel;
- this.panel.panelNode.appendChild(this.box);
- this.input.value = value;
- this.input.focus();
- var command = Firebug.chrome.$("cmd_toggleCSSEditing");
- command.setAttribute("checked", true);
- },
- hide: function()
- {
- var command = Firebug.chrome.$("cmd_toggleCSSEditing");
- command.setAttribute("checked", false);
- if (this.box.parentNode == this.panel.panelNode)
- this.panel.panelNode.removeChild(this.box);
- delete this.target;
- delete this.panel;
- delete this.styleSheet;
- },
- saveEdit: function(target, value, previousValue)
- {
- Firebug.CSSModule.freeEdit(this.styleSheet, value);
- },
- endEditing: function()
- {
- this.panel.refresh();
- return true;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onInput: function()
- {
- Firebug.Editor.update();
- },
- scrollToLine: function(line, offset)
- {
- this.startMeasuring(this.input);
- var lineHeight = this.measureText().height;
- this.stopMeasuring();
- this.input.scrollTop = (line * lineHeight) + offset;
- }
- });
- // ************************************************************************************************
- // Local Helpers
- var rgbToHex = function rgbToHex(value)
- {
- return value.replace(/\brgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)/gi, rgbToHexReplacer);
- };
- var rgbToHexReplacer = function(_, r, g, b) {
- return '#' + ((1 << 24) + (r << 16) + (g << 8) + (b << 0)).toString(16).substr(-6).toUpperCase();
- };
- var stripUnits = function stripUnits(value)
- {
- // remove units from '0px', '0em' etc. leave non-zero units in-tact.
- return value.replace(/(url\(.*?\)|[^0]\S*\s*)|0(%|em|ex|px|in|cm|mm|pt|pc)(\s|$)/gi, stripUnitsReplacer);
- };
- var stripUnitsReplacer = function(_, skip, remove, whitespace) {
- return skip || ('0' + whitespace);
- };
- function parsePriority(value)
- {
- var rePriority = /(.*?)\s*(!important)?$/;
- var m = rePriority.exec(value);
- var propValue = m ? m[1] : "";
- var priority = m && m[2] ? "important" : "";
- return {value: propValue, priority: priority};
- }
- function parseURLValue(value)
- {
- var m = reURL.exec(value);
- return m ? m[1] : "";
- }
- function parseRepeatValue(value)
- {
- var m = reRepeat.exec(value);
- return m ? m[0] : "";
- }
- function parseCSSValue(value, offset)
- {
- var start = 0;
- var m;
- while (1)
- {
- m = reSplitCSS.exec(value);
- if (m && m.index+m[0].length < offset)
- {
- value = value.substr(m.index+m[0].length);
- start += m.index+m[0].length;
- offset -= m.index+m[0].length;
- }
- else
- break;
- }
- if (m)
- {
- var type;
- if (m[1])
- type = "url";
- else if (m[2] || m[3])
- type = "rgb";
- else if (m[4])
- type = "int";
- return {value: m[0], start: start+m.index, end: start+m.index+(m[0].length-1), type: type};
- }
- }
- function findPropByName(props, name)
- {
- for (var i = 0; i < props.length; ++i)
- {
- if (props[i].name == name)
- return i;
- }
- }
- function sortProperties(props)
- {
- props.sort(function(a, b)
- {
- return a.name > b.name ? 1 : -1;
- });
- }
- function getTopmostRuleLine(panelNode)
- {
- for (var child = panelNode.firstChild; child; child = child.nextSibling)
- {
- if (child.offsetTop+child.offsetHeight > panelNode.scrollTop)
- {
- var rule = child.repObject;
- if (rule)
- return {
- line: domUtils.getRuleLine(rule),
- offset: panelNode.scrollTop-child.offsetTop
- };
- }
- }
- return 0;
- }
- function getStyleSheetCSS(sheet, context)
- {
- if (sheet.ownerNode instanceof HTMLStyleElement)
- return sheet.ownerNode.innerHTML;
- else
- return context.sourceCache.load(sheet.href).join("");
- }
- function getStyleSheetOwnerNode(sheet) {
- for (; sheet && !sheet.ownerNode; sheet = sheet.parentStyleSheet);
- return sheet.ownerNode;
- }
- function scrollSelectionIntoView(panel)
- {
- var selCon = getSelectionController(panel);
- selCon.scrollSelectionIntoView(
- nsISelectionController.SELECTION_NORMAL,
- nsISelectionController.SELECTION_FOCUS_REGION, true);
- }
- function getSelectionController(panel)
- {
- var browser = Firebug.chrome.getPanelBrowser(panel);
- return browser.docShell.QueryInterface(nsIInterfaceRequestor)
- .getInterface(nsISelectionDisplay)
- .QueryInterface(nsISelectionController);
- }
- // ************************************************************************************************
- Firebug.registerModule(Firebug.CSSModule);
- Firebug.registerPanel(Firebug.CSSStyleSheetPanel);
- Firebug.registerPanel(CSSElementPanel);
- Firebug.registerPanel(CSSComputedElementPanel);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Script Module
- Firebug.Script = extend(Firebug.Module,
- {
- getPanel: function()
- {
- return Firebug.chrome ? Firebug.chrome.getPanel("Script") : null;
- },
- selectSourceCode: function(index)
- {
- this.getPanel().selectSourceCode(index);
- }
- });
- Firebug.registerModule(Firebug.Script);
- // ************************************************************************************************
- // Script Panel
- function ScriptPanel(){};
- ScriptPanel.prototype = extend(Firebug.Panel,
- {
- name: "Script",
- title: "Script",
- selectIndex: 0, // index of the current selectNode's option
- sourceIndex: -1, // index of the script node, based in doc.getElementsByTagName("script")
- options: {
- hasToolButtons: true
- },
- create: function()
- {
- Firebug.Panel.create.apply(this, arguments);
- this.onChangeSelect = bind(this.onChangeSelect, this);
- var doc = Firebug.browser.document;
- var scripts = doc.getElementsByTagName("script");
- var selectNode = this.selectNode = createElement("select");
- for(var i=0, script; script=scripts[i]; i++)
- {
- // Don't show Firebug Lite source code in the list of options
- if (Firebug.ignoreFirebugElements && script.getAttribute("firebugIgnore"))
- continue;
- var fileName = getFileName(script.src) || getFileName(doc.location.href);
- var option = createElement("option", {value:i});
- option.appendChild(Firebug.chrome.document.createTextNode(fileName));
- selectNode.appendChild(option);
- };
- this.toolButtonsNode.appendChild(selectNode);
- },
- initialize: function()
- {
- // we must render the code first, so the persistent state can be restore
- this.selectSourceCode(this.selectIndex);
- Firebug.Panel.initialize.apply(this, arguments);
- addEvent(this.selectNode, "change", this.onChangeSelect);
- },
- shutdown: function()
- {
- removeEvent(this.selectNode, "change", this.onChangeSelect);
- Firebug.Panel.shutdown.apply(this, arguments);
- },
- detach: function(oldChrome, newChrome)
- {
- Firebug.Panel.detach.apply(this, arguments);
- var oldPanel = oldChrome.getPanel("Script");
- var index = oldPanel.selectIndex;
- this.selectNode.selectedIndex = index;
- this.selectIndex = index;
- this.sourceIndex = -1;
- },
- onChangeSelect: function(event)
- {
- var select = this.selectNode;
- this.selectIndex = select.selectedIndex;
- var option = select.options[select.selectedIndex];
- if (!option)
- return;
- var selectedSourceIndex = parseInt(option.value);
- this.renderSourceCode(selectedSourceIndex);
- },
- selectSourceCode: function(index)
- {
- var select = this.selectNode;
- select.selectedIndex = index;
- var option = select.options[index];
- if (!option)
- return;
- var selectedSourceIndex = parseInt(option.value);
- this.renderSourceCode(selectedSourceIndex);
- },
- renderSourceCode: function(index)
- {
- if (this.sourceIndex != index)
- {
- var renderProcess = function renderProcess(src)
- {
- var html = [],
- hl = 0;
- src = isIE && !isExternal ?
- src+'\n' : // IE put an extra line when reading source of local resources
- '\n'+src;
- // find the number of lines of code
- src = src.replace(/\n\r|\r\n/g, "\n");
- var match = src.match(/[\n]/g);
- var lines=match ? match.length : 0;
- // render the full source code + line numbers html
- html[hl++] = '<div><div class="sourceBox" style="left:';
- html[hl++] = 35 + 7*(lines+'').length;
- html[hl++] = 'px;"><pre class="sourceCode">';
- html[hl++] = escapeHTML(src);
- html[hl++] = '</pre></div><div class="lineNo">';
- // render the line number divs
- for(var l=1, lines; l<=lines; l++)
- {
- html[hl++] = '<div line="';
- html[hl++] = l;
- html[hl++] = '">';
- html[hl++] = l;
- html[hl++] = '</div>';
- }
- html[hl++] = '</div></div>';
- updatePanel(html);
- };
- var updatePanel = function(html)
- {
- self.panelNode.innerHTML = html.join("");
- // IE needs this timeout, otherwise the panel won't scroll
- setTimeout(function(){
- self.synchronizeUI();
- },0);
- };
- var onFailure = function()
- {
- FirebugReps.Warning.tag.replace({object: "AccessRestricted"}, self.panelNode);
- };
- var self = this;
- var doc = Firebug.browser.document;
- var script = doc.getElementsByTagName("script")[index];
- var url = getScriptURL(script);
- var isExternal = url && url != doc.location.href;
- try
- {
- if (isExternal)
- {
- Ajax.request({url: url, onSuccess: renderProcess, onFailure: onFailure});
- }
- else
- {
- var src = script.innerHTML;
- renderProcess(src);
- }
- }
- catch(e)
- {
- onFailure();
- }
- this.sourceIndex = index;
- }
- }
- });
- Firebug.registerPanel(ScriptPanel);
- // ************************************************************************************************
- var getScriptURL = function getScriptURL(script)
- {
- var reFile = /([^\/\?#]+)(#.+)?$/;
- var rePath = /^(.*\/)/;
- var reProtocol = /^\w+:\/\//;
- var path = null;
- var doc = Firebug.browser.document;
- var file = reFile.exec(script.src);
- if (file)
- {
- var fileName = file[1];
- var fileOptions = file[2];
- // absolute path
- if (reProtocol.test(script.src)) {
- path = rePath.exec(script.src)[1];
- }
- // relative path
- else
- {
- var r = rePath.exec(script.src);
- var src = r ? r[1] : script.src;
- var backDir = /^((?:\.\.\/)+)(.*)/.exec(src);
- var reLastDir = /^(.*\/)[^\/]+\/$/;
- path = rePath.exec(doc.location.href)[1];
- // "../some/path"
- if (backDir)
- {
- var j = backDir[1].length/3;
- var p;
- while (j-- > 0)
- path = reLastDir.exec(path)[1];
- path += backDir[2];
- }
- else if(src.indexOf("/") != -1)
- {
- // "./some/path"
- if(/^\.\/./.test(src))
- {
- path += src.substring(2);
- }
- // "/some/path"
- else if(/^\/./.test(src))
- {
- var domain = /^(\w+:\/\/[^\/]+)/.exec(path);
- path = domain[1] + src;
- }
- // "some/path"
- else
- {
- path += src;
- }
- }
- }
- }
- var m = path && path.match(/([^\/]+)\/$/) || null;
- if (path && m)
- {
- return path + fileName;
- }
- };
- var getFileName = function getFileName(path)
- {
- if (!path) return "";
- var match = path && path.match(/[^\/]+(\?.*)?(#.*)?$/);
- return match && match[0] || path;
- };
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var ElementCache = Firebug.Lite.Cache.Element;
- var insertSliceSize = 18;
- var insertInterval = 40;
- var ignoreVars =
- {
- "__firebug__": 1,
- "eval": 1,
- // We are forced to ignore Java-related variables, because
- // trying to access them causes browser freeze
- "java": 1,
- "sun": 1,
- "Packages": 1,
- "JavaArray": 1,
- "JavaMember": 1,
- "JavaObject": 1,
- "JavaClass": 1,
- "JavaPackage": 1,
- "_firebug": 1,
- "_FirebugConsole": 1,
- "_FirebugCommandLine": 1
- };
- if (Firebug.ignoreFirebugElements)
- ignoreVars[Firebug.Lite.Cache.ID] = 1;
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- var memberPanelRep =
- isIE6 ?
- {"class": "memberLabel $member.type\\Label", href: "javacript:void(0)"}
- :
- {"class": "memberLabel $member.type\\Label"};
- var RowTag =
- TR({"class": "memberRow $member.open $member.type\\Row", $hasChildren: "$member.hasChildren", role : 'presentation',
- level: "$member.level"},
- TD({"class": "memberLabelCell", style: "padding-left: $member.indent\\px", role : 'presentation'},
- A(memberPanelRep,
- SPAN({}, "$member.name")
- )
- ),
- TD({"class": "memberValueCell", role : 'presentation'},
- TAG("$member.tag", {object: "$member.value"})
- )
- );
- var WatchRowTag =
- TR({"class": "watchNewRow", level: 0},
- TD({"class": "watchEditCell", colspan: 2},
- DIV({"class": "watchEditBox a11yFocusNoTab", role: "button", 'tabindex' : '0',
- 'aria-label' : $STR('press enter to add new watch expression')},
- $STR("NewWatch")
- )
- )
- );
- var SizerRow =
- TR({role : 'presentation'},
- TD({width: "30%"}),
- TD({width: "70%"})
- );
- var domTableClass = isIElt8 ? "domTable domTableIE" : "domTable";
- var DirTablePlate = domplate(Firebug.Rep,
- {
- tag:
- TABLE({"class": domTableClass, cellpadding: 0, cellspacing: 0, onclick: "$onClick", role :"tree"},
- TBODY({role: 'presentation'},
- SizerRow,
- FOR("member", "$object|memberIterator", RowTag)
- )
- ),
- watchTag:
- TABLE({"class": domTableClass, cellpadding: 0, cellspacing: 0,
- _toggles: "$toggles", _domPanel: "$domPanel", onclick: "$onClick", role : 'tree'},
- TBODY({role : 'presentation'},
- SizerRow,
- WatchRowTag
- )
- ),
- tableTag:
- TABLE({"class": domTableClass, cellpadding: 0, cellspacing: 0,
- _toggles: "$toggles", _domPanel: "$domPanel", onclick: "$onClick", role : 'tree'},
- TBODY({role : 'presentation'},
- SizerRow
- )
- ),
- rowTag:
- FOR("member", "$members", RowTag),
- memberIterator: function(object, level)
- {
- return getMembers(object, level);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onClick: function(event)
- {
- if (!isLeftClick(event))
- return;
- var target = event.target || event.srcElement;
- var row = getAncestorByClass(target, "memberRow");
- var label = getAncestorByClass(target, "memberLabel");
- if (label && hasClass(row, "hasChildren"))
- {
- var row = label.parentNode.parentNode;
- this.toggleRow(row);
- }
- else
- {
- var object = Firebug.getRepObject(target);
- if (typeof(object) == "function")
- {
- Firebug.chrome.select(object, "script");
- cancelEvent(event);
- }
- else if (event.detail == 2 && !object)
- {
- var panel = row.parentNode.parentNode.domPanel;
- if (panel)
- {
- var rowValue = panel.getRowPropertyValue(row);
- if (typeof(rowValue) == "boolean")
- panel.setPropertyValue(row, !rowValue);
- else
- panel.editProperty(row);
- cancelEvent(event);
- }
- }
- }
- return false;
- },
- toggleRow: function(row)
- {
- var level = parseInt(row.getAttribute("level"));
- var toggles = row.parentNode.parentNode.toggles;
- if (hasClass(row, "opened"))
- {
- removeClass(row, "opened");
- if (toggles)
- {
- var path = getPath(row);
- // Remove the path from the toggle tree
- for (var i = 0; i < path.length; ++i)
- {
- if (i == path.length-1)
- delete toggles[path[i]];
- else
- toggles = toggles[path[i]];
- }
- }
- var rowTag = this.rowTag;
- var tbody = row.parentNode;
- setTimeout(function()
- {
- for (var firstRow = row.nextSibling; firstRow; firstRow = row.nextSibling)
- {
- if (parseInt(firstRow.getAttribute("level")) <= level)
- break;
- tbody.removeChild(firstRow);
- }
- }, row.insertTimeout ? row.insertTimeout : 0);
- }
- else
- {
- setClass(row, "opened");
- if (toggles)
- {
- var path = getPath(row);
- // Mark the path in the toggle tree
- for (var i = 0; i < path.length; ++i)
- {
- var name = path[i];
- if (toggles.hasOwnProperty(name))
- toggles = toggles[name];
- else
- toggles = toggles[name] = {};
- }
- }
- var value = row.lastChild.firstChild.repObject;
- var members = getMembers(value, level+1);
- var rowTag = this.rowTag;
- var lastRow = row;
- var delay = 0;
- //var setSize = members.length;
- //var rowCount = 1;
- while (members.length)
- {
- with({slice: members.splice(0, insertSliceSize), isLast: !members.length})
- {
- setTimeout(function()
- {
- if (lastRow.parentNode)
- {
- var result = rowTag.insertRows({members: slice}, lastRow);
- lastRow = result[1];
- //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [null, result, rowCount, setSize]);
- //rowCount += insertSliceSize;
- }
- if (isLast)
- row.removeAttribute("insertTimeout");
- }, delay);
- }
- delay += insertInterval;
- }
- row.insertTimeout = delay;
- }
- }
- });
- // ************************************************************************************************
- Firebug.DOMBasePanel = function() {}
- Firebug.DOMBasePanel.prototype = extend(Firebug.Panel,
- {
- tag: DirTablePlate.tableTag,
- getRealObject: function(object)
- {
- // TODO: Move this to some global location
- // TODO: Unwrapping should be centralized rather than sprinkling it around ad hoc.
- // TODO: We might be able to make this check more authoritative with QueryInterface.
- if (!object) return object;
- if (object.wrappedJSObject) return object.wrappedJSObject;
- return object;
- },
- rebuild: function(update, scrollTop)
- {
- //dispatch([Firebug.A11yModel], 'onBeforeDomUpdateSelection', [this]);
- var members = getMembers(this.selection);
- expandMembers(members, this.toggles, 0, 0);
- this.showMembers(members, update, scrollTop);
- //TODO: xxxpedro statusbar
- if (!this.parentPanel)
- updateStatusBar(this);
- },
- showMembers: function(members, update, scrollTop)
- {
- // If we are still in the midst of inserting rows, cancel all pending
- // insertions here - this is a big speedup when stepping in the debugger
- if (this.timeouts)
- {
- for (var i = 0; i < this.timeouts.length; ++i)
- this.context.clearTimeout(this.timeouts[i]);
- delete this.timeouts;
- }
- if (!members.length)
- return this.showEmptyMembers();
- var panelNode = this.panelNode;
- var priorScrollTop = scrollTop == undefined ? panelNode.scrollTop : scrollTop;
- // If we are asked to "update" the current view, then build the new table
- // offscreen and swap it in when it's done
- var offscreen = update && panelNode.firstChild;
- var dest = offscreen ? panelNode.ownerDocument : panelNode;
- var table = this.tag.replace({domPanel: this, toggles: this.toggles}, dest);
- var tbody = table.lastChild;
- var rowTag = DirTablePlate.rowTag;
- // Insert the first slice immediately
- //var slice = members.splice(0, insertSliceSize);
- //var result = rowTag.insertRows({members: slice}, tbody.lastChild);
- //var setSize = members.length;
- //var rowCount = 1;
- var panel = this;
- var result;
- //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]);
- var timeouts = [];
- var delay = 0;
- // enable to measure rendering performance
- var renderStart = new Date().getTime();
- while (members.length)
- {
- with({slice: members.splice(0, insertSliceSize), isLast: !members.length})
- {
- timeouts.push(this.context.setTimeout(function()
- {
- // TODO: xxxpedro can this be a timing error related to the
- // "iteration number" approach insted of "duration time"?
- // avoid error in IE8
- if (!tbody.lastChild) return;
- result = rowTag.insertRows({members: slice}, tbody.lastChild);
- //rowCount += insertSliceSize;
- //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]);
- if ((panelNode.scrollHeight+panelNode.offsetHeight) >= priorScrollTop)
- panelNode.scrollTop = priorScrollTop;
- // enable to measure rendering performance
- //if (isLast) alert(new Date().getTime() - renderStart + "ms");
- }, delay));
- delay += insertInterval;
- }
- }
- if (offscreen)
- {
- timeouts.push(this.context.setTimeout(function()
- {
- if (panelNode.firstChild)
- panelNode.replaceChild(table, panelNode.firstChild);
- else
- panelNode.appendChild(table);
- // Scroll back to where we were before
- panelNode.scrollTop = priorScrollTop;
- }, delay));
- }
- else
- {
- timeouts.push(this.context.setTimeout(function()
- {
- panelNode.scrollTop = scrollTop == undefined ? 0 : scrollTop;
- }, delay));
- }
- this.timeouts = timeouts;
- },
- /*
- // new
- showMembers: function(members, update, scrollTop)
- {
- // If we are still in the midst of inserting rows, cancel all pending
- // insertions here - this is a big speedup when stepping in the debugger
- if (this.timeouts)
- {
- for (var i = 0; i < this.timeouts.length; ++i)
- this.context.clearTimeout(this.timeouts[i]);
- delete this.timeouts;
- }
- if (!members.length)
- return this.showEmptyMembers();
- var panelNode = this.panelNode;
- var priorScrollTop = scrollTop == undefined ? panelNode.scrollTop : scrollTop;
- // If we are asked to "update" the current view, then build the new table
- // offscreen and swap it in when it's done
- var offscreen = update && panelNode.firstChild;
- var dest = offscreen ? panelNode.ownerDocument : panelNode;
- var table = this.tag.replace({domPanel: this, toggles: this.toggles}, dest);
- var tbody = table.lastChild;
- var rowTag = DirTablePlate.rowTag;
- // Insert the first slice immediately
- //var slice = members.splice(0, insertSliceSize);
- //var result = rowTag.insertRows({members: slice}, tbody.lastChild);
- //var setSize = members.length;
- //var rowCount = 1;
- var panel = this;
- var result;
- //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]);
- var timeouts = [];
- var delay = 0;
- var _insertSliceSize = insertSliceSize;
- var _insertInterval = insertInterval;
- // enable to measure rendering performance
- var renderStart = new Date().getTime();
- var lastSkip = renderStart, now;
- while (members.length)
- {
- with({slice: members.splice(0, _insertSliceSize), isLast: !members.length})
- {
- var _tbody = tbody;
- var _rowTag = rowTag;
- var _panelNode = panelNode;
- var _priorScrollTop = priorScrollTop;
- timeouts.push(this.context.setTimeout(function()
- {
- // TODO: xxxpedro can this be a timing error related to the
- // "iteration number" approach insted of "duration time"?
- // avoid error in IE8
- if (!_tbody.lastChild) return;
- result = _rowTag.insertRows({members: slice}, _tbody.lastChild);
- //rowCount += _insertSliceSize;
- //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]);
- if ((_panelNode.scrollHeight + _panelNode.offsetHeight) >= _priorScrollTop)
- _panelNode.scrollTop = _priorScrollTop;
- // enable to measure rendering performance
- //alert("gap: " + (new Date().getTime() - lastSkip));
- //lastSkip = new Date().getTime();
- //if (isLast) alert("new: " + (new Date().getTime() - renderStart) + "ms");
- }, delay));
- delay += _insertInterval;
- }
- }
- if (offscreen)
- {
- timeouts.push(this.context.setTimeout(function()
- {
- if (panelNode.firstChild)
- panelNode.replaceChild(table, panelNode.firstChild);
- else
- panelNode.appendChild(table);
- // Scroll back to where we were before
- panelNode.scrollTop = priorScrollTop;
- }, delay));
- }
- else
- {
- timeouts.push(this.context.setTimeout(function()
- {
- panelNode.scrollTop = scrollTop == undefined ? 0 : scrollTop;
- }, delay));
- }
- this.timeouts = timeouts;
- },
- /**/
- showEmptyMembers: function()
- {
- FirebugReps.Warning.tag.replace({object: "NoMembersWarning"}, this.panelNode);
- },
- findPathObject: function(object)
- {
- var pathIndex = -1;
- for (var i = 0; i < this.objectPath.length; ++i)
- {
- // IE needs === instead of == or otherwise some objects will
- // be considered equal to different objects, returning the
- // wrong index of the objectPath array
- if (this.getPathObject(i) === object)
- return i;
- }
- return -1;
- },
- getPathObject: function(index)
- {
- var object = this.objectPath[index];
- if (object instanceof Property)
- return object.getObject();
- else
- return object;
- },
- getRowObject: function(row)
- {
- var object = getRowOwnerObject(row);
- return object ? object : this.selection;
- },
- getRowPropertyValue: function(row)
- {
- var object = this.getRowObject(row);
- object = this.getRealObject(object);
- if (object)
- {
- var propName = getRowName(row);
- if (object instanceof jsdIStackFrame)
- return Firebug.Debugger.evaluate(propName, this.context);
- else
- return object[propName];
- }
- },
- /*
- copyProperty: function(row)
- {
- var value = this.getRowPropertyValue(row);
- copyToClipboard(value);
- },
- editProperty: function(row, editValue)
- {
- if (hasClass(row, "watchNewRow"))
- {
- if (this.context.stopped)
- Firebug.Editor.startEditing(row, "");
- else if (Firebug.Console.isAlwaysEnabled()) // not stopped in debugger, need command line
- {
- if (Firebug.CommandLine.onCommandLineFocus())
- Firebug.Editor.startEditing(row, "");
- else
- row.innerHTML = $STR("warning.Command line blocked?");
- }
- else
- row.innerHTML = $STR("warning.Console must be enabled");
- }
- else if (hasClass(row, "watchRow"))
- Firebug.Editor.startEditing(row, getRowName(row));
- else
- {
- var object = this.getRowObject(row);
- this.context.thisValue = object;
- if (!editValue)
- {
- var propValue = this.getRowPropertyValue(row);
- var type = typeof(propValue);
- if (type == "undefined" || type == "number" || type == "boolean")
- editValue = propValue;
- else if (type == "string")
- editValue = "\"" + escapeJS(propValue) + "\"";
- else if (propValue == null)
- editValue = "null";
- else if (object instanceof Window || object instanceof jsdIStackFrame)
- editValue = getRowName(row);
- else
- editValue = "this." + getRowName(row);
- }
- Firebug.Editor.startEditing(row, editValue);
- }
- },
- deleteProperty: function(row)
- {
- if (hasClass(row, "watchRow"))
- this.deleteWatch(row);
- else
- {
- var object = getRowOwnerObject(row);
- if (!object)
- object = this.selection;
- object = this.getRealObject(object);
- if (object)
- {
- var name = getRowName(row);
- try
- {
- delete object[name];
- }
- catch (exc)
- {
- return;
- }
- this.rebuild(true);
- this.markChange();
- }
- }
- },
- setPropertyValue: function(row, value) // value must be string
- {
- if(FBTrace.DBG_DOM)
- {
- FBTrace.sysout("row: "+row);
- FBTrace.sysout("value: "+value+" type "+typeof(value), value);
- }
- var name = getRowName(row);
- if (name == "this")
- return;
- var object = this.getRowObject(row);
- object = this.getRealObject(object);
- if (object && !(object instanceof jsdIStackFrame))
- {
- // unwrappedJSObject.property = unwrappedJSObject
- Firebug.CommandLine.evaluate(value, this.context, object, this.context.getGlobalScope(),
- function success(result, context)
- {
- if (FBTrace.DBG_DOM)
- FBTrace.sysout("setPropertyValue evaluate success object["+name+"]="+result+" type "+typeof(result), result);
- object[name] = result;
- },
- function failed(exc, context)
- {
- try
- {
- if (FBTrace.DBG_DOM)
- FBTrace.sysout("setPropertyValue evaluate failed with exc:"+exc+" object["+name+"]="+value+" type "+typeof(value), exc);
- // If the value doesn't parse, then just store it as a string. Some users will
- // not realize they're supposed to enter a JavaScript expression and just type
- // literal text
- object[name] = String(value); // unwrappedJSobject.property = string
- }
- catch (exc)
- {
- return;
- }
- }
- );
- }
- else if (this.context.stopped)
- {
- try
- {
- Firebug.CommandLine.evaluate(name+"="+value, this.context);
- }
- catch (exc)
- {
- try
- {
- // See catch block above...
- object[name] = String(value); // unwrappedJSobject.property = string
- }
- catch (exc)
- {
- return;
- }
- }
- }
- this.rebuild(true);
- this.markChange();
- },
- highlightRow: function(row)
- {
- if (this.highlightedRow)
- cancelClassTimed(this.highlightedRow, "jumpHighlight", this.context);
- this.highlightedRow = row;
- if (row)
- setClassTimed(row, "jumpHighlight", this.context);
- },/**/
- onMouseMove: function(event)
- {
- var target = event.srcElement || event.target;
- var object = getAncestorByClass(target, "objectLink-element");
- object = object ? object.repObject : null;
- if(object && instanceOf(object, "Element") && object.nodeType == 1)
- {
- if(object != lastHighlightedObject)
- {
- Firebug.Inspector.drawBoxModel(object);
- object = lastHighlightedObject;
- }
- }
- else
- Firebug.Inspector.hideBoxModel();
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- create: function()
- {
- // TODO: xxxpedro
- this.context = Firebug.browser;
- this.objectPath = [];
- this.propertyPath = [];
- this.viewPath = [];
- this.pathIndex = -1;
- this.toggles = {};
- Firebug.Panel.create.apply(this, arguments);
- this.panelNode.style.padding = "0 1px";
- },
- initialize: function(){
- Firebug.Panel.initialize.apply(this, arguments);
- addEvent(this.panelNode, "mousemove", this.onMouseMove);
- },
- shutdown: function()
- {
- removeEvent(this.panelNode, "mousemove", this.onMouseMove);
- Firebug.Panel.shutdown.apply(this, arguments);
- },
- /*
- destroy: function(state)
- {
- var view = this.viewPath[this.pathIndex];
- if (view && this.panelNode.scrollTop)
- view.scrollTop = this.panelNode.scrollTop;
- if (this.pathIndex)
- state.pathIndex = this.pathIndex;
- if (this.viewPath)
- state.viewPath = this.viewPath;
- if (this.propertyPath)
- state.propertyPath = this.propertyPath;
- if (this.propertyPath.length > 0 && !this.propertyPath[1])
- state.firstSelection = persistObject(this.getPathObject(1), this.context);
- Firebug.Panel.destroy.apply(this, arguments);
- },
- /**/
- ishow: function(state)
- {
- if (this.context.loaded && !this.selection)
- {
- if (!state)
- {
- this.select(null);
- return;
- }
- if (state.viewPath)
- this.viewPath = state.viewPath;
- if (state.propertyPath)
- this.propertyPath = state.propertyPath;
- var defaultObject = this.getDefaultSelection(this.context);
- var selectObject = defaultObject;
- if (state.firstSelection)
- {
- var restored = state.firstSelection(this.context);
- if (restored)
- {
- selectObject = restored;
- this.objectPath = [defaultObject, restored];
- }
- else
- this.objectPath = [defaultObject];
- }
- else
- this.objectPath = [defaultObject];
- if (this.propertyPath.length > 1)
- {
- for (var i = 1; i < this.propertyPath.length; ++i)
- {
- var name = this.propertyPath[i];
- if (!name)
- continue;
- var object = selectObject;
- try
- {
- selectObject = object[name];
- }
- catch (exc)
- {
- selectObject = null;
- }
- if (selectObject)
- {
- this.objectPath.push(new Property(object, name));
- }
- else
- {
- // If we can't access a property, just stop
- this.viewPath.splice(i);
- this.propertyPath.splice(i);
- this.objectPath.splice(i);
- selectObject = this.getPathObject(this.objectPath.length-1);
- break;
- }
- }
- }
- var selection = state.pathIndex <= this.objectPath.length-1
- ? this.getPathObject(state.pathIndex)
- : this.getPathObject(this.objectPath.length-1);
- this.select(selection);
- }
- },
- /*
- hide: function()
- {
- var view = this.viewPath[this.pathIndex];
- if (view && this.panelNode.scrollTop)
- view.scrollTop = this.panelNode.scrollTop;
- },
- /**/
- supportsObject: function(object)
- {
- if (object == null)
- return 1000;
- if (typeof(object) == "undefined")
- return 1000;
- else if (object instanceof SourceLink)
- return 0;
- else
- return 1; // just agree to support everything but not agressively.
- },
- refresh: function()
- {
- this.rebuild(true);
- },
- updateSelection: function(object)
- {
- var previousIndex = this.pathIndex;
- var previousView = previousIndex == -1 ? null : this.viewPath[previousIndex];
- var newPath = this.pathToAppend;
- delete this.pathToAppend;
- var pathIndex = this.findPathObject(object);
- if (newPath || pathIndex == -1)
- {
- this.toggles = {};
- if (newPath)
- {
- // Remove everything after the point where we are inserting, so we
- // essentially replace it with the new path
- if (previousView)
- {
- if (this.panelNode.scrollTop)
- previousView.scrollTop = this.panelNode.scrollTop;
- var start = previousIndex + 1,
- // Opera needs the length argument in splice(), otherwise
- // it will consider that only one element should be removed
- length = this.objectPath.length - start;
- this.objectPath.splice(start, length);
- this.propertyPath.splice(start, length);
- this.viewPath.splice(start, length);
- }
- var value = this.getPathObject(previousIndex);
- if (!value)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("dom.updateSelection no pathObject for "+previousIndex+"\n");
- return;
- }
- for (var i = 0, length = newPath.length; i < length; ++i)
- {
- var name = newPath[i];
- var object = value;
- try
- {
- value = value[name];
- }
- catch(exc)
- {
- if (FBTrace.DBG_ERRORS)
- FBTrace.sysout("dom.updateSelection FAILS at path_i="+i+" for name:"+name+"\n");
- return;
- }
- ++this.pathIndex;
- this.objectPath.push(new Property(object, name));
- this.propertyPath.push(name);
- this.viewPath.push({toggles: this.toggles, scrollTop: 0});
- }
- }
- else
- {
- this.toggles = {};
- var win = Firebug.browser.window;
- //var win = this.context.getGlobalScope();
- if (object === win)
- {
- this.pathIndex = 0;
- this.objectPath = [win];
- this.propertyPath = [null];
- this.viewPath = [{toggles: this.toggles, scrollTop: 0}];
- }
- else
- {
- this.pathIndex = 1;
- this.objectPath = [win, object];
- this.propertyPath = [null, null];
- this.viewPath = [
- {toggles: {}, scrollTop: 0},
- {toggles: this.toggles, scrollTop: 0}
- ];
- }
- }
- this.panelNode.scrollTop = 0;
- this.rebuild();
- }
- else
- {
- this.pathIndex = pathIndex;
- var view = this.viewPath[pathIndex];
- this.toggles = view.toggles;
- // Persist the current scroll location
- if (previousView && this.panelNode.scrollTop)
- previousView.scrollTop = this.panelNode.scrollTop;
- this.rebuild(false, view.scrollTop);
- }
- },
- getObjectPath: function(object)
- {
- return this.objectPath;
- },
- getDefaultSelection: function()
- {
- return Firebug.browser.window;
- //return this.context.getGlobalScope();
- }/*,
- updateOption: function(name, value)
- {
- const optionMap = {showUserProps: 1, showUserFuncs: 1, showDOMProps: 1,
- showDOMFuncs: 1, showDOMConstants: 1};
- if ( optionMap.hasOwnProperty(name) )
- this.rebuild(true);
- },
- getOptionsMenuItems: function()
- {
- return [
- optionMenu("ShowUserProps", "showUserProps"),
- optionMenu("ShowUserFuncs", "showUserFuncs"),
- optionMenu("ShowDOMProps", "showDOMProps"),
- optionMenu("ShowDOMFuncs", "showDOMFuncs"),
- optionMenu("ShowDOMConstants", "showDOMConstants"),
- "-",
- {label: "Refresh", command: bindFixed(this.rebuild, this, true) }
- ];
- },
- getContextMenuItems: function(object, target)
- {
- var row = getAncestorByClass(target, "memberRow");
- var items = [];
- if (row)
- {
- var rowName = getRowName(row);
- var rowObject = this.getRowObject(row);
- var rowValue = this.getRowPropertyValue(row);
- var isWatch = hasClass(row, "watchRow");
- var isStackFrame = rowObject instanceof jsdIStackFrame;
- if (typeof(rowValue) == "string" || typeof(rowValue) == "number")
- {
- // Functions already have a copy item in their context menu
- items.push(
- "-",
- {label: "CopyValue",
- command: bindFixed(this.copyProperty, this, row) }
- );
- }
- items.push(
- "-",
- {label: isWatch ? "EditWatch" : (isStackFrame ? "EditVariable" : "EditProperty"),
- command: bindFixed(this.editProperty, this, row) }
- );
- if (isWatch || (!isStackFrame && !isDOMMember(rowObject, rowName)))
- {
- items.push(
- {label: isWatch ? "DeleteWatch" : "DeleteProperty",
- command: bindFixed(this.deleteProperty, this, row) }
- );
- }
- }
- items.push(
- "-",
- {label: "Refresh", command: bindFixed(this.rebuild, this, true) }
- );
- return items;
- },
- getEditor: function(target, value)
- {
- if (!this.editor)
- this.editor = new DOMEditor(this.document);
- return this.editor;
- }/**/
- });
- // ************************************************************************************************
- // TODO: xxxpedro statusbar
- var updateStatusBar = function(panel)
- {
- var path = panel.propertyPath;
- var index = panel.pathIndex;
- var r = [];
- for (var i=0, l=path.length; i<l; i++)
- {
- r.push(i==index ? '<a class="fbHover fbButton fbBtnSelected" ' : '<a class="fbHover fbButton" ');
- r.push('pathIndex=');
- r.push(i);
- if(isIE6)
- r.push(' href="javascript:void(0)"');
- r.push('>');
- r.push(i==0 ? "window" : path[i] || "Object");
- r.push('</a>');
- if(i < l-1)
- r.push('<span class="fbStatusSeparator">></span>');
- }
- panel.statusBarNode.innerHTML = r.join("");
- };
- var DOMMainPanel = Firebug.DOMPanel = function () {};
- Firebug.DOMPanel.DirTable = DirTablePlate;
- DOMMainPanel.prototype = extend(Firebug.DOMBasePanel.prototype,
- {
- onClickStatusBar: function(event)
- {
- var target = event.srcElement || event.target;
- var element = getAncestorByClass(target, "fbHover");
- if(element)
- {
- var pathIndex = element.getAttribute("pathIndex");
- if(pathIndex)
- {
- this.select(this.getPathObject(pathIndex));
- }
- }
- },
- selectRow: function(row, target)
- {
- if (!target)
- target = row.lastChild.firstChild;
- if (!target || !target.repObject)
- return;
- this.pathToAppend = getPath(row);
- // If the object is inside an array, look up its index
- var valueBox = row.lastChild.firstChild;
- if (hasClass(valueBox, "objectBox-array"))
- {
- var arrayIndex = FirebugReps.Arr.getItemIndex(target);
- this.pathToAppend.push(arrayIndex);
- }
- // Make sure we get a fresh status path for the object, since otherwise
- // it might find the object in the existing path and not refresh it
- //Firebug.chrome.clearStatusPath();
- this.select(target.repObject, true);
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onClick: function(event)
- {
- var target = event.srcElement || event.target;
- var repNode = Firebug.getRepNode(target);
- if (repNode)
- {
- var row = getAncestorByClass(target, "memberRow");
- if (row)
- {
- this.selectRow(row, repNode);
- cancelEvent(event);
- }
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- name: "DOM",
- title: "DOM",
- searchable: true,
- statusSeparator: ">",
- options: {
- hasToolButtons: true,
- hasStatusBar: true
- },
- create: function()
- {
- Firebug.DOMBasePanel.prototype.create.apply(this, arguments);
- this.onClick = bind(this.onClick, this);
- //TODO: xxxpedro
- this.onClickStatusBar = bind(this.onClickStatusBar, this);
- this.panelNode.style.padding = "0 1px";
- },
- initialize: function(oldPanelNode)
- {
- //this.panelNode.addEventListener("click", this.onClick, false);
- //dispatch([Firebug.A11yModel], 'onInitializeNode', [this, 'console']);
- Firebug.DOMBasePanel.prototype.initialize.apply(this, arguments);
- addEvent(this.panelNode, "click", this.onClick);
- // TODO: xxxpedro dom
- this.ishow();
- //TODO: xxxpedro
- addEvent(this.statusBarNode, "click", this.onClickStatusBar);
- },
- shutdown: function()
- {
- //this.panelNode.removeEventListener("click", this.onClick, false);
- //dispatch([Firebug.A11yModel], 'onDestroyNode', [this, 'console']);
- removeEvent(this.panelNode, "click", this.onClick);
- Firebug.DOMBasePanel.prototype.shutdown.apply(this, arguments);
- }/*,
- search: function(text, reverse)
- {
- if (!text)
- {
- delete this.currentSearch;
- this.highlightRow(null);
- return false;
- }
- var row;
- if (this.currentSearch && text == this.currentSearch.text)
- row = this.currentSearch.findNext(true, undefined, reverse, Firebug.searchCaseSensitive);
- else
- {
- function findRow(node) { return getAncestorByClass(node, "memberRow"); }
- this.currentSearch = new TextSearch(this.panelNode, findRow);
- row = this.currentSearch.find(text, reverse, Firebug.searchCaseSensitive);
- }
- if (row)
- {
- var sel = this.document.defaultView.getSelection();
- sel.removeAllRanges();
- sel.addRange(this.currentSearch.range);
- scrollIntoCenterView(row, this.panelNode);
- this.highlightRow(row);
- dispatch([Firebug.A11yModel], 'onDomSearchMatchFound', [this, text, row]);
- return true;
- }
- else
- {
- dispatch([Firebug.A11yModel], 'onDomSearchMatchFound', [this, text, null]);
- return false;
- }
- }/**/
- });
- Firebug.registerPanel(DOMMainPanel);
- // ************************************************************************************************
- // ************************************************************************************************
- // Local Helpers
- var getMembers = function getMembers(object, level) // we expect object to be user-level object wrapped in security blanket
- {
- if (!level)
- level = 0;
- var ordinals = [], userProps = [], userClasses = [], userFuncs = [],
- domProps = [], domFuncs = [], domConstants = [];
- try
- {
- var domMembers = getDOMMembers(object);
- //var domMembers = {}; // TODO: xxxpedro
- //var domConstantMap = {}; // TODO: xxxpedro
- if (object.wrappedJSObject)
- var insecureObject = object.wrappedJSObject;
- else
- var insecureObject = object;
- // IE function prototype is not listed in (for..in)
- if (isIE && isFunction(object))
- addMember("user", userProps, "prototype", object.prototype, level);
- for (var name in insecureObject) // enumeration is safe
- {
- if (ignoreVars[name] == 1) // javascript.options.strict says ignoreVars is undefined.
- continue;
- var val;
- try
- {
- val = insecureObject[name]; // getter is safe
- }
- catch (exc)
- {
- // Sometimes we get exceptions trying to access certain members
- if (FBTrace.DBG_ERRORS && FBTrace.DBG_DOM)
- FBTrace.sysout("dom.getMembers cannot access "+name, exc);
- }
- var ordinal = parseInt(name);
- if (ordinal || ordinal == 0)
- {
- addMember("ordinal", ordinals, name, val, level);
- }
- else if (isFunction(val))
- {
- if (isClassFunction(val) && !(name in domMembers))
- addMember("userClass", userClasses, name, val, level);
- else if (name in domMembers)
- addMember("domFunction", domFuncs, name, val, level, domMembers[name]);
- else
- addMember("userFunction", userFuncs, name, val, level);
- }
- else
- {
- //TODO: xxxpedro
- /*
- var getterFunction = insecureObject.__lookupGetter__(name),
- setterFunction = insecureObject.__lookupSetter__(name),
- prefix = "";
- if(getterFunction && !setterFunction)
- prefix = "get ";
- /**/
- var prefix = "";
- if (name in domMembers && !(name in domConstantMap))
- addMember("dom", domProps, (prefix+name), val, level, domMembers[name]);
- else if (name in domConstantMap)
- addMember("dom", domConstants, (prefix+name), val, level);
- else
- addMember("user", userProps, (prefix+name), val, level);
- }
- }
- }
- catch (exc)
- {
- // Sometimes we get exceptions just from trying to iterate the members
- // of certain objects, like StorageList, but don't let that gum up the works
- throw exc;
- if (FBTrace.DBG_ERRORS && FBTrace.DBG_DOM)
- FBTrace.sysout("dom.getMembers FAILS: ", exc);
- //throw exc;
- }
- function sortName(a, b) { return a.name > b.name ? 1 : -1; }
- function sortOrder(a, b) { return a.order > b.order ? 1 : -1; }
- var members = [];
- members.push.apply(members, ordinals);
- Firebug.showUserProps = true; // TODO: xxxpedro
- Firebug.showUserFuncs = true; // TODO: xxxpedro
- Firebug.showDOMProps = true;
- Firebug.showDOMFuncs = true;
- Firebug.showDOMConstants = true;
- if (Firebug.showUserProps)
- {
- userProps.sort(sortName);
- members.push.apply(members, userProps);
- }
- if (Firebug.showUserFuncs)
- {
- userClasses.sort(sortName);
- members.push.apply(members, userClasses);
- userFuncs.sort(sortName);
- members.push.apply(members, userFuncs);
- }
- if (Firebug.showDOMProps)
- {
- domProps.sort(sortName);
- members.push.apply(members, domProps);
- }
- if (Firebug.showDOMFuncs)
- {
- domFuncs.sort(sortName);
- members.push.apply(members, domFuncs);
- }
- if (Firebug.showDOMConstants)
- members.push.apply(members, domConstants);
- return members;
- }
- function expandMembers(members, toggles, offset, level) // recursion starts with offset=0, level=0
- {
- var expanded = 0;
- for (var i = offset; i < members.length; ++i)
- {
- var member = members[i];
- if (member.level > level)
- break;
- if ( toggles.hasOwnProperty(member.name) )
- {
- member.open = "opened"; // member.level <= level && member.name in toggles.
- var newMembers = getMembers(member.value, level+1); // sets newMembers.level to level+1
- var args = [i+1, 0];
- args.push.apply(args, newMembers);
- members.splice.apply(members, args);
- /*
- if (FBTrace.DBG_DOM)
- {
- FBTrace.sysout("expandMembers member.name", member.name);
- FBTrace.sysout("expandMembers toggles", toggles);
- FBTrace.sysout("expandMembers toggles[member.name]", toggles[member.name]);
- FBTrace.sysout("dom.expandedMembers level: "+level+" member", member);
- }
- /**/
- expanded += newMembers.length;
- i += newMembers.length + expandMembers(members, toggles[member.name], i+1, level+1);
- }
- }
- return expanded;
- }
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function isClassFunction(fn)
- {
- try
- {
- for (var name in fn.prototype)
- return true;
- } catch (exc) {}
- return false;
- }
- var hasProperties = function hasProperties(ob)
- {
- try
- {
- for (var name in ob)
- return true;
- } catch (exc) {}
- // IE function prototype is not listed in (for..in)
- if (isFunction(ob)) return true;
- return false;
- }
- FBL.ErrorCopy = function(message)
- {
- this.message = message;
- };
- var addMember = function addMember(type, props, name, value, level, order)
- {
- var rep = Firebug.getRep(value); // do this first in case a call to instanceof reveals contents
- var tag = rep.shortTag ? rep.shortTag : rep.tag;
- var ErrorCopy = function(){}; //TODO: xxxpedro
- var valueType = typeof(value);
- var hasChildren = hasProperties(value) && !(value instanceof ErrorCopy) &&
- (isFunction(value) || (valueType == "object" && value != null)
- || (valueType == "string" && value.length > Firebug.stringCropLength));
- props.push({
- name: name,
- value: value,
- type: type,
- rowClass: "memberRow-"+type,
- open: "",
- order: order,
- level: level,
- indent: level*16,
- hasChildren: hasChildren,
- tag: tag
- });
- }
- var getWatchRowIndex = function getWatchRowIndex(row)
- {
- var index = -1;
- for (; row && hasClass(row, "watchRow"); row = row.previousSibling)
- ++index;
- return index;
- }
- var getRowName = function getRowName(row)
- {
- var node = row.firstChild;
- return node.textContent ? node.textContent : node.innerText;
- }
- var getRowValue = function getRowValue(row)
- {
- return row.lastChild.firstChild.repObject;
- }
- var getRowOwnerObject = function getRowOwnerObject(row)
- {
- var parentRow = getParentRow(row);
- if (parentRow)
- return getRowValue(parentRow);
- }
- var getParentRow = function getParentRow(row)
- {
- var level = parseInt(row.getAttribute("level"))-1;
- for (row = row.previousSibling; row; row = row.previousSibling)
- {
- if (parseInt(row.getAttribute("level")) == level)
- return row;
- }
- }
- var getPath = function getPath(row)
- {
- var name = getRowName(row);
- var path = [name];
- var level = parseInt(row.getAttribute("level"))-1;
- for (row = row.previousSibling; row; row = row.previousSibling)
- {
- if (parseInt(row.getAttribute("level")) == level)
- {
- var name = getRowName(row);
- path.splice(0, 0, name);
- --level;
- }
- }
- return path;
- }
- // ************************************************************************************************
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // ************************************************************************************************
- // DOM Module
- Firebug.DOM = extend(Firebug.Module,
- {
- getPanel: function()
- {
- return Firebug.chrome ? Firebug.chrome.getPanel("DOM") : null;
- }
- });
- Firebug.registerModule(Firebug.DOM);
- // ************************************************************************************************
- // DOM Panel
- var lastHighlightedObject;
- function DOMSidePanel(){};
- DOMSidePanel.prototype = extend(Firebug.DOMBasePanel.prototype,
- {
- selectRow: function(row, target)
- {
- if (!target)
- target = row.lastChild.firstChild;
- if (!target || !target.repObject)
- return;
- this.pathToAppend = getPath(row);
- // If the object is inside an array, look up its index
- var valueBox = row.lastChild.firstChild;
- if (hasClass(valueBox, "objectBox-array"))
- {
- var arrayIndex = FirebugReps.Arr.getItemIndex(target);
- this.pathToAppend.push(arrayIndex);
- }
- // Make sure we get a fresh status path for the object, since otherwise
- // it might find the object in the existing path and not refresh it
- //Firebug.chrome.clearStatusPath();
- var object = target.repObject;
- if (instanceOf(object, "Element"))
- {
- Firebug.HTML.selectTreeNode(ElementCache(object));
- }
- else
- {
- Firebug.chrome.selectPanel("DOM");
- Firebug.chrome.getPanel("DOM").select(object, true);
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- onClick: function(event)
- {
- /*
- var target = event.srcElement || event.target;
- var object = getAncestorByClass(target, "objectLink");
- object = object ? object.repObject : null;
- if(!object) return;
- if (instanceOf(object, "Element"))
- {
- Firebug.HTML.selectTreeNode(ElementCache(object));
- }
- else
- {
- Firebug.chrome.selectPanel("DOM");
- Firebug.chrome.getPanel("DOM").select(object, true);
- }
- /**/
- var target = event.srcElement || event.target;
- var repNode = Firebug.getRepNode(target);
- if (repNode)
- {
- var row = getAncestorByClass(target, "memberRow");
- if (row)
- {
- this.selectRow(row, repNode);
- cancelEvent(event);
- }
- }
- /**/
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
- name: "DOMSidePanel",
- parentPanel: "HTML",
- title: "DOM",
- options: {
- hasToolButtons: true
- },
- isInitialized: false,
- create: function()
- {
- Firebug.DOMBasePanel.prototype.create.apply(this, arguments);
- this.onClick = bind(this.onClick, this);
- },
- initialize: function(){
- Firebug.DOMBasePanel.prototype.initialize.apply(this, arguments);
- addEvent(this.panelNode, "click", this.onClick);
- // TODO: xxxpedro css2
- var selection = ElementCache.get(FirebugChrome.selectedHTMLElementId);
- if (selection)
- this.select(selection, true);
- },
- shutdown: function()
- {
- removeEvent(this.panelNode, "click", this.onClick);
- Firebug.DOMBasePanel.prototype.shutdown.apply(this, arguments);
- },
- reattach: function(oldChrome)
- {
- //this.isInitialized = oldChrome.getPanel("DOM").isInitialized;
- this.toggles = oldChrome.getPanel("DOMSidePanel").toggles;
- }
- });
- Firebug.registerPanel(DOMSidePanel);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.FBTrace = {};
- (function() {
- // ************************************************************************************************
- var traceOptions = {
- DBG_TIMESTAMP: 1,
- DBG_INITIALIZE: 1,
- DBG_CHROME: 1,
- DBG_ERRORS: 1,
- DBG_DISPATCH: 1,
- DBG_CSS: 1
- };
- this.module = null;
- this.initialize = function()
- {
- if (!this.messageQueue)
- this.messageQueue = [];
- for (var name in traceOptions)
- this[name] = traceOptions[name];
- };
- // ************************************************************************************************
- // FBTrace API
- this.sysout = function()
- {
- return this.logFormatted(arguments, "");
- };
- this.dumpProperties = function(title, object)
- {
- return this.logFormatted("dumpProperties() not supported.", "warning");
- };
- this.dumpStack = function()
- {
- return this.logFormatted("dumpStack() not supported.", "warning");
- };
- this.flush = function(module)
- {
- this.module = module;
- var queue = this.messageQueue;
- this.messageQueue = [];
- for (var i = 0; i < queue.length; ++i)
- this.writeMessage(queue[i][0], queue[i][1], queue[i][2]);
- };
- this.getPanel = function()
- {
- return this.module ? this.module.getPanel() : null;
- };
- //*************************************************************************************************
- this.logFormatted = function(objects, className)
- {
- var html = this.DBG_TIMESTAMP ? [getTimestamp(), " | "] : [];
- var length = objects.length;
- for (var i = 0; i < length; ++i)
- {
- appendText(" ", html);
- var object = objects[i];
- if (i == 0)
- {
- html.push("<b>");
- appendText(object, html);
- html.push("</b>");
- }
- else
- appendText(object, html);
- }
- return this.logRow(html, className);
- };
- this.logRow = function(message, className)
- {
- var panel = this.getPanel();
- if (panel && panel.panelNode)
- this.writeMessage(message, className);
- else
- {
- this.messageQueue.push([message, className]);
- }
- return this.LOG_COMMAND;
- };
- this.writeMessage = function(message, className)
- {
- var container = this.getPanel().containerNode;
- var isScrolledToBottom =
- container.scrollTop + container.offsetHeight >= container.scrollHeight;
- this.writeRow.call(this, message, className);
- if (isScrolledToBottom)
- container.scrollTop = container.scrollHeight - container.offsetHeight;
- };
- this.appendRow = function(row)
- {
- var container = this.getPanel().panelNode;
- container.appendChild(row);
- };
- this.writeRow = function(message, className)
- {
- var row = this.getPanel().panelNode.ownerDocument.createElement("div");
- row.className = "logRow" + (className ? " logRow-"+className : "");
- row.innerHTML = message.join("");
- this.appendRow(row);
- };
- //*************************************************************************************************
- function appendText(object, html)
- {
- html.push(escapeHTML(objectToString(object)));
- };
- function getTimestamp()
- {
- var now = new Date();
- var ms = "" + (now.getMilliseconds() / 1000).toFixed(3);
- ms = ms.substr(2);
- return now.toLocaleTimeString() + "." + ms;
- };
- //*************************************************************************************************
- var HTMLtoEntity =
- {
- "<": "<",
- ">": ">",
- "&": "&",
- "'": "'",
- '"': """
- };
- function replaceChars(ch)
- {
- return HTMLtoEntity[ch];
- };
- function escapeHTML(value)
- {
- return (value+"").replace(/[<>&"']/g, replaceChars);
- };
- //*************************************************************************************************
- function objectToString(object)
- {
- try
- {
- return object+"";
- }
- catch (exc)
- {
- return null;
- }
- };
- // ************************************************************************************************
- }).apply(FBL.FBTrace);
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // If application isn't in trace mode, the FBTrace panel won't be loaded
- if (!Env.Options.enableTrace) return;
- // ************************************************************************************************
- // FBTrace Module
- Firebug.Trace = extend(Firebug.Module,
- {
- getPanel: function()
- {
- return Firebug.chrome ? Firebug.chrome.getPanel("Trace") : null;
- },
- clear: function()
- {
- this.getPanel().panelNode.innerHTML = "";
- }
- });
- Firebug.registerModule(Firebug.Trace);
- // ************************************************************************************************
- // FBTrace Panel
- function TracePanel(){};
- TracePanel.prototype = extend(Firebug.Panel,
- {
- name: "Trace",
- title: "Trace",
- options: {
- hasToolButtons: true,
- innerHTMLSync: true
- },
- create: function(){
- Firebug.Panel.create.apply(this, arguments);
- this.clearButton = new Button({
- caption: "Clear",
- title: "Clear FBTrace logs",
- owner: Firebug.Trace,
- onClick: Firebug.Trace.clear
- });
- },
- initialize: function(){
- Firebug.Panel.initialize.apply(this, arguments);
- this.clearButton.initialize();
- }
- });
- Firebug.registerPanel(TracePanel);
- // ************************************************************************************************
- }});
- /* See license.txt for terms of usage */
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- // ************************************************************************************************
- // Globals
- var modules = [];
- var panelTypes = [];
- var panelTypeMap = {};
- var parentPanelMap = {};
- var registerModule = Firebug.registerModule;
- var registerPanel = Firebug.registerPanel;
- // ************************************************************************************************
- append(Firebug,
- {
- extend: function(fn)
- {
- if (Firebug.chrome && Firebug.chrome.addPanel)
- {
- var namespace = ns(fn);
- fn.call(namespace, FBL);
- }
- else
- {
- setTimeout(function(){Firebug.extend(fn);},100);
- }
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Registration
- registerModule: function()
- {
- registerModule.apply(Firebug, arguments);
- modules.push.apply(modules, arguments);
- dispatch(modules, "initialize", []);
- if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.registerModule");
- },
- registerPanel: function()
- {
- registerPanel.apply(Firebug, arguments);
- panelTypes.push.apply(panelTypes, arguments);
- for (var i = 0, panelType; panelType = arguments[i]; ++i)
- {
- // TODO: xxxpedro investigate why Dev Panel throws an error
- if (panelType.prototype.name == "Dev") continue;
- panelTypeMap[panelType.prototype.name] = arguments[i];
- var parentPanelName = panelType.prototype.parentPanel;
- if (parentPanelName)
- {
- parentPanelMap[parentPanelName] = 1;
- }
- else
- {
- var panelName = panelType.prototype.name;
- var chrome = Firebug.chrome;
- chrome.addPanel(panelName);
- // tab click handler
- var onTabClick = function onTabClick()
- {
- chrome.selectPanel(panelName);
- return false;
- };
- chrome.addController([chrome.panelMap[panelName].tabNode, "mousedown", onTabClick]);
- }
- }
- if (FBTrace.DBG_INITIALIZE)
- for (var i = 0; i < arguments.length; ++i)
- FBTrace.sysout("Firebug.registerPanel", arguments[i].prototype.name);
- }
- });
- // ************************************************************************************************
- }});
- FBL.ns(function() { with (FBL) {
- // ************************************************************************************************
- FirebugChrome.Skin =
- {
- CSS: '.collapsed{display:none;}[collapsed="true"]{display:none;}#fbCSS{padding:0 !important;}.cssPropDisable{float:left;display:block;width:2em;cursor:default;}.infoTip{z-index:2147483647;position:fixed;padding:2px 3px;border:1px solid #CBE087;background:LightYellow;font-family:Monaco,monospace;color:#000000;display:none;white-space:nowrap;pointer-events:none;}.infoTip[active="true"]{display:block;}.infoTipLoading{width:16px;height:16px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/loading_16.gif) no-repeat;}.infoTipImageBox{font-size:11px;min-width:100px;text-align:center;}.infoTipCaption{font-size:11px;font:Monaco,monospace;}.infoTipLoading > .infoTipImage,.infoTipLoading > .infoTipCaption{display:none;}h1.groupHeader{padding:2px 4px;margin:0 0 4px 0;border-top:1px solid #CCCCCC;border-bottom:1px solid #CCCCCC;background:#eee url(https://getfirebug.com/releases/lite/latest/skin/xp/group.gif) repeat-x;font-size:11px;font-weight:bold;_position:relative;}.inlineEditor,.fixedWidthEditor{z-index:2147483647;position:absolute;display:none;}.inlineEditor{margin-left:-6px;margin-top:-3px;}.textEditorInner,.fixedWidthEditor{margin:0 0 0 0 !important;padding:0;border:none !important;font:inherit;text-decoration:inherit;background-color:#FFFFFF;}.fixedWidthEditor{border-top:1px solid #888888 !important;border-bottom:1px solid #888888 !important;}.textEditorInner{position:relative;top:-7px;left:-5px;outline:none;resize:none;}.textEditorInner1{padding-left:11px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.png) repeat-y;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.gif) repeat-y;_overflow:hidden;}.textEditorInner2{position:relative;padding-right:2px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.png) repeat-y 100% 0;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.gif) repeat-y 100% 0;_position:fixed;}.textEditorTop1{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat 100% 0;margin-left:11px;height:10px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat 100% 0;_overflow:hidden;}.textEditorTop2{position:relative;left:-11px;width:11px;height:10px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat;}.textEditorBottom1{position:relative;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat 100% 100%;margin-left:11px;height:12px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat 100% 100%;}.textEditorBottom2{position:relative;left:-11px;width:11px;height:12px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat 0 100%;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat 0 100%;}.panelNode-css{overflow-x:hidden;}.cssSheet > .insertBefore{height:1.5em;}.cssRule{position:relative;margin:0;padding:1em 0 0 6px;font-family:Monaco,monospace;color:#000000;}.cssRule:first-child{padding-top:6px;}.cssElementRuleContainer{position:relative;}.cssHead{padding-right:150px;}.cssProp{}.cssPropName{color:DarkGreen;}.cssPropValue{margin-left:8px;color:DarkBlue;}.cssOverridden span{text-decoration:line-through;}.cssInheritedRule{}.cssInheritLabel{margin-right:0.5em;font-weight:bold;}.cssRule .objectLink-sourceLink{top:0;}.cssProp.editGroup:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disable.png) no-repeat 2px 1px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disable.gif) no-repeat 2px 1px;}.cssProp.editGroup.editing{background:none;}.cssProp.disabledStyle{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disableHover.png) no-repeat 2px 1px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disableHover.gif) no-repeat 2px 1px;opacity:1;color:#CCCCCC;}.disabledStyle .cssPropName,.disabledStyle .cssPropValue{color:#CCCCCC;}.cssPropValue.editing + .cssSemi,.inlineExpander + .cssSemi{display:none;}.cssPropValue.editing{white-space:nowrap;}.stylePropName{font-weight:bold;padding:0 4px 4px 4px;width:50%;}.stylePropValue{width:50%;}.panelNode-net{overflow-x:hidden;}.netTable{width:100%;}.hideCategory-undefined .category-undefined,.hideCategory-html .category-html,.hideCategory-css .category-css,.hideCategory-js .category-js,.hideCategory-image .category-image,.hideCategory-xhr .category-xhr,.hideCategory-flash .category-flash,.hideCategory-txt .category-txt,.hideCategory-bin .category-bin{display:none;}.netHeadRow{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/group.gif) repeat-x #FFFFFF;}.netHeadCol{border-bottom:1px solid #CCCCCC;padding:2px 4px 2px 18px;font-weight:bold;}.netHeadLabel{white-space:nowrap;overflow:hidden;}.netHeaderRow{height:16px;}.netHeaderCell{cursor:pointer;-moz-user-select:none;border-bottom:1px solid #9C9C9C;padding:0 !important;font-weight:bold;background:#BBBBBB url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeader.gif) repeat-x;white-space:nowrap;}.netHeaderRow > .netHeaderCell:first-child > .netHeaderCellBox{padding:2px 14px 2px 18px;}.netHeaderCellBox{padding:2px 14px 2px 10px;border-left:1px solid #D9D9D9;border-right:1px solid #9C9C9C;}.netHeaderCell:hover:active{background:#959595 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeaderActive.gif) repeat-x;}.netHeaderSorted{background:#7D93B2 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeaderSorted.gif) repeat-x;}.netHeaderSorted > .netHeaderCellBox{border-right-color:#6B7C93;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/arrowDown.png) no-repeat right;}.netHeaderSorted.sortedAscending > .netHeaderCellBox{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/arrowUp.png);}.netHeaderSorted:hover:active{background:#536B90 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeaderSortedActive.gif) repeat-x;}.panelNode-net .netRowHeader{display:block;}.netRowHeader{cursor:pointer;display:none;height:15px;margin-right:0 !important;}.netRow .netRowHeader{background-position:5px 1px;}.netRow[breakpoint="true"] .netRowHeader{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/breakpoint.png);}.netRow[breakpoint="true"][disabledBreakpoint="true"] .netRowHeader{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/breakpointDisabled.png);}.netRow.category-xhr:hover .netRowHeader{background-color:#F6F6F6;}#netBreakpointBar{max-width:38px;}#netHrefCol > .netHeaderCellBox{border-left:0px;}.netRow .netRowHeader{width:3px;}.netInfoRow .netRowHeader{display:table-cell;}.netTable[hiddenCols~=netHrefCol] TD[id="netHrefCol"],.netTable[hiddenCols~=netHrefCol] TD.netHrefCol,.netTable[hiddenCols~=netStatusCol] TD[id="netStatusCol"],.netTable[hiddenCols~=netStatusCol] TD.netStatusCol,.netTable[hiddenCols~=netDomainCol] TD[id="netDomainCol"],.netTable[hiddenCols~=netDomainCol] TD.netDomainCol,.netTable[hiddenCols~=netSizeCol] TD[id="netSizeCol"],.netTable[hiddenCols~=netSizeCol] TD.netSizeCol,.netTable[hiddenCols~=netTimeCol] TD[id="netTimeCol"],.netTable[hiddenCols~=netTimeCol] TD.netTimeCol{display:none;}.netRow{background:LightYellow;}.netRow.loaded{background:#FFFFFF;}.netRow.loaded:hover{background:#EFEFEF;}.netCol{padding:0;vertical-align:top;border-bottom:1px solid #EFEFEF;white-space:nowrap;height:17px;}.netLabel{width:100%;}.netStatusCol{padding-left:10px;color:rgb(128,128,128);}.responseError > .netStatusCol{color:red;}.netDomainCol{padding-left:5px;}.netSizeCol{text-align:right;padding-right:10px;}.netHrefLabel{-moz-box-sizing:padding-box;overflow:hidden;z-index:10;position:absolute;padding-left:18px;padding-top:1px;max-width:15%;font-weight:bold;}.netFullHrefLabel{display:none;-moz-user-select:none;padding-right:10px;padding-bottom:3px;max-width:100%;background:#FFFFFF;z-index:200;}.netHrefCol:hover > .netFullHrefLabel{display:block;}.netRow.loaded:hover .netCol > .netFullHrefLabel{background-color:#EFEFEF;}.useA11y .a11yShowFullLabel{display:block;background-image:none !important;border:1px solid #CBE087;background-color:LightYellow;font-family:Monaco,monospace;color:#000000;font-size:10px;z-index:2147483647;}.netSizeLabel{padding-left:6px;}.netStatusLabel,.netDomainLabel,.netSizeLabel,.netBar{padding:1px 0 2px 0 !important;}.responseError{color:red;}.hasHeaders .netHrefLabel:hover{cursor:pointer;color:blue;text-decoration:underline;}.netLoadingIcon{position:absolute;border:0;margin-left:14px;width:16px;height:16px;background:transparent no-repeat 0 0;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/loading_16.gif);display:inline-block;}.loaded .netLoadingIcon{display:none;}.netBar,.netSummaryBar{position:relative;border-right:50px solid transparent;}.netResolvingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarResolving.gif) repeat-x;z-index:60;}.netConnectingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarConnecting.gif) repeat-x;z-index:50;}.netBlockingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarWaiting.gif) repeat-x;z-index:40;}.netSendingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarSending.gif) repeat-x;z-index:30;}.netWaitingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarResponded.gif) repeat-x;z-index:20;min-width:1px;}.netReceivingBar{position:absolute;left:0;top:0;bottom:0;background:#38D63B url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarLoading.gif) repeat-x;z-index:10;}.netWindowLoadBar,.netContentLoadBar{position:absolute;left:0;top:0;bottom:0;width:1px;background-color:red;z-index:70;opacity:0.5;display:none;margin-bottom:-1px;}.netContentLoadBar{background-color:Blue;}.netTimeLabel{-moz-box-sizing:padding-box;position:absolute;top:1px;left:100%;padding-left:6px;color:#444444;min-width:16px;}.loaded .netReceivingBar,.loaded.netReceivingBar{background:#B6B6B6 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarLoaded.gif) repeat-x;border-color:#B6B6B6;}.fromCache .netReceivingBar,.fromCache.netReceivingBar{background:#D6D6D6 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarCached.gif) repeat-x;border-color:#D6D6D6;}.netSummaryRow .netTimeLabel,.loaded .netTimeLabel{background:transparent;}.timeInfoTip{width:150px; height:40px}.timeInfoTipBar,.timeInfoTipEventBar{position:relative;display:block;margin:0;opacity:1;height:15px;width:4px;}.timeInfoTipEventBar{width:1px !important;}.timeInfoTipCell.startTime{padding-right:8px;}.timeInfoTipCell.elapsedTime{text-align:right;padding-right:8px;}.sizeInfoLabelCol{font-weight:bold;padding-right:10px;font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;}.sizeInfoSizeCol{font-weight:bold;}.sizeInfoDetailCol{color:gray;text-align:right;}.sizeInfoDescCol{font-style:italic;}.netSummaryRow .netReceivingBar{background:#BBBBBB;border:none;}.netSummaryLabel{color:#222222;}.netSummaryRow{background:#BBBBBB !important;font-weight:bold;}.netSummaryRow .netBar{border-right-color:#BBBBBB;}.netSummaryRow > .netCol{border-top:1px solid #999999;border-bottom:2px solid;-moz-border-bottom-colors:#EFEFEF #999999;padding-top:1px;padding-bottom:2px;}.netSummaryRow > .netHrefCol:hover{background:transparent !important;}.netCountLabel{padding-left:18px;}.netTotalSizeCol{text-align:right;padding-right:10px;}.netTotalTimeCol{text-align:right;}.netCacheSizeLabel{position:absolute;z-index:1000;left:0;top:0;}.netLimitRow{background:rgb(255,255,225) !important;font-weight:normal;color:black;font-weight:normal;}.netLimitLabel{padding-left:18px;}.netLimitRow > .netCol{border-bottom:2px solid;-moz-border-bottom-colors:#EFEFEF #999999;vertical-align:middle !important;padding-top:2px;padding-bottom:2px;}.netLimitButton{font-size:11px;padding-top:1px;padding-bottom:1px;}.netInfoCol{border-top:1px solid #EEEEEE;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/group.gif) repeat-x #FFFFFF;}.netInfoBody{margin:10px 0 4px 10px;}.netInfoTabs{position:relative;padding-left:17px;}.netInfoTab{position:relative;top:-3px;margin-top:10px;padding:4px 6px;border:1px solid transparent;border-bottom:none;_border:none;font-weight:bold;color:#565656;cursor:pointer;}.netInfoTabSelected{cursor:default !important;border:1px solid #D7D7D7 !important;border-bottom:none !important;-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;background-color:#FFFFFF;}.logRow-netInfo.error .netInfoTitle{color:red;}.logRow-netInfo.loading .netInfoResponseText{font-style:italic;color:#888888;}.loading .netInfoResponseHeadersTitle{display:none;}.netInfoResponseSizeLimit{font-family:Lucida Grande,Tahoma,sans-serif;padding-top:10px;font-size:11px;}.netInfoText{display:none;margin:0;border:1px solid #D7D7D7;border-right:none;padding:8px;background-color:#FFFFFF;font-family:Monaco,monospace;white-space:pre-wrap;}.netInfoTextSelected{display:block;}.netInfoParamName{padding-right:10px;font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;vertical-align:top;text-align:right;white-space:nowrap;}.netInfoPostText .netInfoParamName{width:1px;}.netInfoParamValue{width:100%;}.netInfoHeadersText,.netInfoPostText,.netInfoPutText{padding-top:0;}.netInfoHeadersGroup,.netInfoPostParams,.netInfoPostSource{margin-bottom:4px;border-bottom:1px solid #D7D7D7;padding-top:8px;padding-bottom:2px;font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;color:#565656;}.netInfoPostParamsTable,.netInfoPostPartsTable,.netInfoPostJSONTable,.netInfoPostXMLTable,.netInfoPostSourceTable{margin-bottom:10px;width:100%;}.netInfoPostContentType{color:#bdbdbd;padding-left:50px;font-weight:normal;}.netInfoHtmlPreview{border:0;width:100%;height:100%;}.netHeadersViewSource{color:#bdbdbd;margin-left:200px;font-weight:normal;}.netHeadersViewSource:hover{color:blue;cursor:pointer;}.netActivationRow,.netPageSeparatorRow{background:rgb(229,229,229) !important;font-weight:normal;color:black;}.netActivationLabel{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/infoIcon.png) no-repeat 3px 2px;padding-left:22px;}.netPageSeparatorRow{height:5px !important;}.netPageSeparatorLabel{padding-left:22px;height:5px !important;}.netPageRow{background-color:rgb(255,255,255);}.netPageRow:hover{background:#EFEFEF;}.netPageLabel{padding:1px 0 2px 18px !important;font-weight:bold;}.netActivationRow > .netCol{border-bottom:2px solid;-moz-border-bottom-colors:#EFEFEF #999999;padding-top:2px;padding-bottom:3px;}.twisty,.logRow-errorMessage > .hasTwisty > .errorTitle,.logRow-log > .objectBox-array.hasTwisty,.logRow-spy .spyHead .spyTitle,.logGroup > .logRow,.memberRow.hasChildren > .memberLabelCell > .memberLabel,.hasHeaders .netHrefLabel,.netPageRow > .netCol > .netPageTitle{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_open.gif);background-repeat:no-repeat;background-position:2px 2px;min-height:12px;}.logRow-errorMessage > .hasTwisty.opened > .errorTitle,.logRow-log > .objectBox-array.hasTwisty.opened,.logRow-spy.opened .spyHead .spyTitle,.logGroup.opened > .logRow,.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,.nodeBox.highlightOpen > .nodeLabel > .twisty,.nodeBox.open > .nodeLabel > .twisty,.netRow.opened > .netCol > .netHrefLabel,.netPageRow.opened > .netCol > .netPageTitle{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_close.gif);}.twisty{background-position:4px 4px;}* html .logRow-spy .spyHead .spyTitle,* html .logGroup .logGroupLabel,* html .hasChildren .memberLabelCell .memberLabel,* html .hasHeaders .netHrefLabel{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_open.gif);background-repeat:no-repeat;background-position:2px 2px;}* html .opened .spyHead .spyTitle,* html .opened .logGroupLabel,* html .opened .memberLabelCell .memberLabel{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_close.gif);background-repeat:no-repeat;background-position:2px 2px;}.panelNode-console{overflow-x:hidden;}.objectLink{text-decoration:none;}.objectLink:hover{cursor:pointer;text-decoration:underline;}.logRow{position:relative;margin:0;border-bottom:1px solid #D7D7D7;padding:2px 4px 1px 6px;background-color:#FFFFFF;overflow:hidden !important;}.useA11y .logRow:focus{border-bottom:1px solid #000000 !important;outline:none !important;background-color:#FFFFAD !important;}.useA11y .logRow:focus a.objectLink-sourceLink{background-color:#FFFFAD;}.useA11y .a11yFocus:focus,.useA11y .objectBox:focus{outline:2px solid #FF9933;background-color:#FFFFAD;}.useA11y .objectBox-null:focus,.useA11y .objectBox-undefined:focus{background-color:#888888 !important;}.useA11y .logGroup.opened > .logRow{border-bottom:1px solid #ffffff;}.logGroup{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/group.gif) repeat-x #FFFFFF;padding:0 !important;border:none !important;}.logGroupBody{display:none;margin-left:16px;border-left:1px solid #D7D7D7;border-top:1px solid #D7D7D7;background:#FFFFFF;}.logGroup > .logRow{background-color:transparent !important;font-weight:bold;}.logGroup.opened > .logRow{border-bottom:none;}.logGroup.opened > .logGroupBody{display:block;}.logRow-command > .objectBox-text{font-family:Monaco,monospace;color:#0000FF;white-space:pre-wrap;}.logRow-info,.logRow-warn,.logRow-error,.logRow-assert,.logRow-warningMessage,.logRow-errorMessage{padding-left:22px;background-repeat:no-repeat;background-position:4px 2px;}.logRow-assert,.logRow-warningMessage,.logRow-errorMessage{padding-top:0;padding-bottom:0;}.logRow-info,.logRow-info .objectLink-sourceLink{background-color:#FFFFFF;}.logRow-warn,.logRow-warningMessage,.logRow-warn .objectLink-sourceLink,.logRow-warningMessage .objectLink-sourceLink{background-color:cyan;}.logRow-error,.logRow-assert,.logRow-errorMessage,.logRow-error .objectLink-sourceLink,.logRow-errorMessage .objectLink-sourceLink{background-color:LightYellow;}.logRow-error,.logRow-assert,.logRow-errorMessage{color:#FF0000;}.logRow-info{}.logRow-warn,.logRow-warningMessage{}.logRow-error,.logRow-assert,.logRow-errorMessage{}.objectBox-string,.objectBox-text,.objectBox-number,.objectLink-element,.objectLink-textNode,.objectLink-function,.objectBox-stackTrace,.objectLink-profile{font-family:Monaco,monospace;}.objectBox-string,.objectBox-text,.objectLink-textNode{white-space:pre-wrap;}.objectBox-number,.objectLink-styleRule,.objectLink-element,.objectLink-textNode{color:#000088;}.objectBox-string{color:#FF0000;}.objectLink-function,.objectBox-stackTrace,.objectLink-profile{color:DarkGreen;}.objectBox-null,.objectBox-undefined{padding:0 2px;border:1px solid #666666;background-color:#888888;color:#FFFFFF;}.objectBox-exception{padding:0 2px 0 18px;color:red;}.objectLink-sourceLink{position:absolute;right:4px;top:2px;padding-left:8px;font-family:Lucida Grande,sans-serif;font-weight:bold;color:#0000FF;}.errorTitle{margin-top:0px;margin-bottom:1px;padding-top:2px;padding-bottom:2px;}.errorTrace{margin-left:17px;}.errorSourceBox{margin:2px 0;}.errorSource-none{display:none;}.errorSource-syntax > .errorBreak{visibility:hidden;}.errorSource{cursor:pointer;font-family:Monaco,monospace;color:DarkGreen;}.errorSource:hover{text-decoration:underline;}.errorBreak{cursor:pointer;display:none;margin:0 6px 0 0;width:13px;height:14px;vertical-align:bottom;opacity:0.1;}.hasBreakSwitch .errorBreak{display:inline;}.breakForError .errorBreak{opacity:1;}.assertDescription{margin:0;}.logRow-profile > .logRow > .objectBox-text{font-family:Lucida Grande,Tahoma,sans-serif;color:#000000;}.logRow-profile > .logRow > .objectBox-text:last-child{color:#555555;font-style:italic;}.logRow-profile.opened > .logRow{padding-bottom:4px;}.profilerRunning > .logRow{padding-left:22px !important;}.profileSizer{width:100%;overflow-x:auto;overflow-y:scroll;}.profileTable{border-bottom:1px solid #D7D7D7;padding:0 0 4px 0;}.profileTable tr[odd="1"]{background-color:#F5F5F5;vertical-align:middle;}.profileTable a{vertical-align:middle;}.profileTable td{padding:1px 4px 0 4px;}.headerCell{cursor:pointer;-moz-user-select:none;border-bottom:1px solid #9C9C9C;padding:0 !important;font-weight:bold;}.headerCellBox{padding:2px 4px;border-left:1px solid #D9D9D9;border-right:1px solid #9C9C9C;}.headerCell:hover:active{}.headerSorted{}.headerSorted > .headerCellBox{border-right-color:#6B7C93;}.headerSorted.sortedAscending > .headerCellBox{}.headerSorted:hover:active{}.linkCell{text-align:right;}.linkCell > .objectLink-sourceLink{position:static;}.logRow-stackTrace{padding-top:0;background:#f8f8f8;}.logRow-stackTrace > .objectBox-stackFrame{position:relative;padding-top:2px;}.objectLink-object{font-family:Lucida Grande,sans-serif;font-weight:bold;color:DarkGreen;white-space:pre-wrap;}.objectProp-object{color:DarkGreen;}.objectProps{color:#000;font-weight:normal;}.objectPropName{color:#777;}.objectProps .objectProp-string{color:#f55;}.objectProps .objectProp-number{color:#55a;}.objectProps .objectProp-object{color:#585;}.selectorTag,.selectorId,.selectorClass{font-family:Monaco,monospace;font-weight:normal;}.selectorTag{color:#0000FF;}.selectorId{color:DarkBlue;}.selectorClass{color:red;}.selectorHidden > .selectorTag{color:#5F82D9;}.selectorHidden > .selectorId{color:#888888;}.selectorHidden > .selectorClass{color:#D86060;}.selectorValue{font-family:Lucida Grande,sans-serif;font-style:italic;color:#555555;}.panelNode.searching .logRow{display:none;}.logRow.matched{display:block !important;}.logRow.matching{position:absolute;left:-1000px;top:-1000px;max-width:0;max-height:0;overflow:hidden;}.objectLeftBrace,.objectRightBrace,.objectEqual,.objectComma,.arrayLeftBracket,.arrayRightBracket,.arrayComma{font-family:Monaco,monospace;}.objectLeftBrace,.objectRightBrace,.arrayLeftBracket,.arrayRightBracket{font-weight:bold;}.objectLeftBrace,.arrayLeftBracket{margin-right:4px;}.objectRightBrace,.arrayRightBracket{margin-left:4px;}.logRow-dir{padding:0;}.logRow-errorMessage .hasTwisty .errorTitle,.logRow-spy .spyHead .spyTitle,.logGroup .logRow{cursor:pointer;padding-left:18px;background-repeat:no-repeat;background-position:3px 3px;}.logRow-errorMessage > .hasTwisty > .errorTitle{background-position:2px 3px;}.logRow-errorMessage > .hasTwisty > .errorTitle:hover,.logRow-spy .spyHead .spyTitle:hover,.logGroup > .logRow:hover{text-decoration:underline;}.logRow-spy{padding:0 !important;}.logRow-spy,.logRow-spy .objectLink-sourceLink{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/group.gif) repeat-x #FFFFFF;padding-right:4px;right:0;}.logRow-spy.opened{padding-bottom:4px;border-bottom:none;}.spyTitle{color:#000000;font-weight:bold;-moz-box-sizing:padding-box;overflow:hidden;z-index:100;padding-left:18px;}.spyCol{padding:0;white-space:nowrap;height:16px;}.spyTitleCol:hover > .objectLink-sourceLink,.spyTitleCol:hover > .spyTime,.spyTitleCol:hover > .spyStatus,.spyTitleCol:hover > .spyTitle{display:none;}.spyFullTitle{display:none;-moz-user-select:none;max-width:100%;background-color:Transparent;}.spyTitleCol:hover > .spyFullTitle{display:block;}.spyStatus{padding-left:10px;color:rgb(128,128,128);}.spyTime{margin-left:4px;margin-right:4px;color:rgb(128,128,128);}.spyIcon{margin-right:4px;margin-left:4px;width:16px;height:16px;vertical-align:middle;background:transparent no-repeat 0 0;display:none;}.loading .spyHead .spyRow .spyIcon{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/loading_16.gif);display:block;}.logRow-spy.loaded:not(.error) .spyHead .spyRow .spyIcon{width:0;margin:0;}.logRow-spy.error .spyHead .spyRow .spyIcon{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon-sm.png);display:block;background-position:2px 2px;}.logRow-spy .spyHead .netInfoBody{display:none;}.logRow-spy.opened .spyHead .netInfoBody{margin-top:10px;display:block;}.logRow-spy.error .spyTitle,.logRow-spy.error .spyStatus,.logRow-spy.error .spyTime{color:red;}.logRow-spy.loading .spyResponseText{font-style:italic;color:#888888;}.caption{font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;color:#444444;}.warning{padding:10px;font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;color:#888888;}.panelNode-dom{overflow-x:hidden !important;}.domTable{font-size:1em;width:100%;table-layout:fixed;background:#fff;}.domTableIE{width:auto;}.memberLabelCell{padding:2px 0 2px 0;vertical-align:top;}.memberValueCell{padding:1px 0 1px 5px;display:block;overflow:hidden;}.memberLabel{display:block;cursor:default;-moz-user-select:none;overflow:hidden;padding-left:18px;background-color:#FFFFFF;text-decoration:none;}.memberRow.hasChildren .memberLabelCell .memberLabel:hover{cursor:pointer;color:blue;text-decoration:underline;}.userLabel{color:#000000;font-weight:bold;}.userClassLabel{color:#E90000;font-weight:bold;}.userFunctionLabel{color:#025E2A;font-weight:bold;}.domLabel{color:#000000;}.domFunctionLabel{color:#025E2A;}.ordinalLabel{color:SlateBlue;font-weight:bold;}.scopesRow{padding:2px 18px;background-color:LightYellow;border-bottom:5px solid #BEBEBE;color:#666666;}.scopesLabel{background-color:LightYellow;}.watchEditCell{padding:2px 18px;background-color:LightYellow;border-bottom:1px solid #BEBEBE;color:#666666;}.editor-watchNewRow,.editor-memberRow{font-family:Monaco,monospace !important;}.editor-memberRow{padding:1px 0 !important;}.editor-watchRow{padding-bottom:0 !important;}.watchRow > .memberLabelCell{font-family:Monaco,monospace;padding-top:1px;padding-bottom:1px;}.watchRow > .memberLabelCell > .memberLabel{background-color:transparent;}.watchRow > .memberValueCell{padding-top:2px;padding-bottom:2px;}.watchRow > .memberLabelCell,.watchRow > .memberValueCell{background-color:#F5F5F5;border-bottom:1px solid #BEBEBE;}.watchToolbox{z-index:2147483647;position:absolute;right:0;padding:1px 2px;}#fbConsole{overflow-x:hidden !important;}#fbCSS{font:1em Monaco,monospace;padding:0 7px;}#fbstylesheetButtons select,#fbScriptButtons select{font:11px Lucida Grande,Tahoma,sans-serif;margin-top:1px;padding-left:3px;background:#fafafa;border:1px inset #fff;width:220px;outline:none;}.Selector{margin-top:10px}.CSSItem{margin-left:4%}.CSSText{padding-left:20px;}.CSSProperty{color:#005500;}.CSSValue{padding-left:5px; color:#000088;}#fbHTMLStatusBar{display:inline;}.fbToolbarButtons{display:none;}.fbStatusSeparator{display:block;float:left;padding-top:4px;}#fbStatusBarBox{display:none;}#fbToolbarContent{display:block;position:absolute;_position:absolute;top:0;padding-top:4px;height:23px;clip:rect(0,2048px,27px,0);}.fbTabMenuTarget{display:none !important;float:left;width:10px;height:10px;margin-top:6px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuTarget.png);}.fbTabMenuTarget:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuTargetHover.png);}.fbShadow{float:left;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/shadowAlpha.png) no-repeat bottom right !important;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/shadow2.gif) no-repeat bottom right;margin:10px 0 0 10px !important;margin:10px 0 0 5px;}.fbShadowContent{display:block;position:relative;background-color:#fff;border:1px solid #a9a9a9;top:-6px;left:-6px;}.fbMenu{display:none;position:absolute;font-size:11px;z-index:2147483647;}.fbMenuContent{padding:2px;}.fbMenuSeparator{display:block;position:relative;padding:1px 18px 0;text-decoration:none;color:#000;cursor:default;background:#ACA899;margin:4px 0;}.fbMenuOption{display:block;position:relative;padding:2px 18px;text-decoration:none;color:#000;cursor:default;}.fbMenuOption:hover{color:#fff;background:#316AC5;}.fbMenuGroup{background:transparent url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuPin.png) no-repeat right 0;}.fbMenuGroup:hover{background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuPin.png) no-repeat right -17px;}.fbMenuGroupSelected{color:#fff;background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuPin.png) no-repeat right -17px;}.fbMenuChecked{background:transparent url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuCheckbox.png) no-repeat 4px 0;}.fbMenuChecked:hover{background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuCheckbox.png) no-repeat 4px -17px;}.fbMenuRadioSelected{background:transparent url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuRadio.png) no-repeat 4px 0;}.fbMenuRadioSelected:hover{background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuRadio.png) no-repeat 4px -17px;}.fbMenuShortcut{padding-right:85px;}.fbMenuShortcutKey{position:absolute;right:0;top:2px;width:77px;}#fbFirebugMenu{top:22px;left:0;}.fbMenuDisabled{color:#ACA899 !important;}#fbFirebugSettingsMenu{left:245px;top:99px;}#fbConsoleMenu{top:42px;left:48px;}.fbIconButton{display:block;}.fbIconButton{display:block;}.fbIconButton{display:block;float:left;height:20px;width:20px;color:#000;margin-right:2px;text-decoration:none;cursor:default;}.fbIconButton:hover{position:relative;top:-1px;left:-1px;margin-right:0;_margin-right:1px;color:#333;border:1px solid #fff;border-bottom:1px solid #bbb;border-right:1px solid #bbb;}.fbIconPressed{position:relative;margin-right:0;_margin-right:1px;top:0 !important;left:0 !important;height:19px;color:#333 !important;border:1px solid #bbb !important;border-bottom:1px solid #cfcfcf !important;border-right:1px solid #ddd !important;}#fbErrorPopup{position:absolute;right:0;bottom:0;height:19px;width:75px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;z-index:999;}#fbErrorPopupContent{position:absolute;right:0;top:1px;height:18px;width:75px;_width:74px;border-left:1px solid #aca899;}#fbErrorIndicator{position:absolute;top:2px;right:5px;}.fbBtnInspectActive{background:#aaa;color:#fff !important;}.fbBody{margin:0;padding:0;overflow:hidden;font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;background:#fff;}.clear{clear:both;}#fbMiniChrome{display:none;right:0;height:27px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;margin-left:1px;}#fbMiniContent{display:block;position:relative;left:-1px;right:0;top:1px;height:25px;border-left:1px solid #aca899;}#fbToolbarSearch{float:right;border:1px solid #ccc;margin:0 5px 0 0;background:#fff url(https://getfirebug.com/releases/lite/latest/skin/xp/search.png) no-repeat 4px 2px !important;background:#fff url(https://getfirebug.com/releases/lite/latest/skin/xp/search.gif) no-repeat 4px 2px;padding-left:20px;font-size:11px;}#fbToolbarErrors{float:right;margin:1px 4px 0 0;font-size:11px;}#fbLeftToolbarErrors{float:left;margin:7px 0px 0 5px;font-size:11px;}.fbErrors{padding-left:20px;height:14px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.png) no-repeat !important;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.gif) no-repeat;color:#f00;font-weight:bold;}#fbMiniErrors{display:inline;display:none;float:right;margin:5px 2px 0 5px;}#fbMiniIcon{float:right;margin:3px 4px 0;height:20px;width:20px;float:right;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -135px;cursor:pointer;}#fbChrome{font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;position:absolute;_position:static;top:0;left:0;height:100%;width:100%;border-collapse:collapse;border-spacing:0;background:#fff;overflow:hidden;}#fbChrome > tbody > tr > td{padding:0;}#fbTop{height:49px;}#fbToolbar{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;height:27px;font-size:11px;}#fbPanelBarBox{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #dbd9c9 0 -27px;height:22px;}#fbContent{height:100%;vertical-align:top;}#fbBottom{height:18px;background:#fff;}#fbToolbarIcon{float:left;padding:0 5px 0;}#fbToolbarIcon a{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -135px;}#fbToolbarButtons{padding:0 2px 0 5px;}#fbToolbarButtons{padding:0 2px 0 5px;}.fbButton{text-decoration:none;display:block;float:left;color:#000;padding:4px 6px 4px 7px;cursor:default;}.fbButton:hover{color:#333;background:#f5f5ef url(https://getfirebug.com/releases/lite/latest/skin/xp/buttonBg.png);padding:3px 5px 3px 6px;border:1px solid #fff;border-bottom:1px solid #bbb;border-right:1px solid #bbb;}.fbBtnPressed{background:#e3e3db url(https://getfirebug.com/releases/lite/latest/skin/xp/buttonBgHover.png) !important;padding:3px 4px 2px 6px !important;margin:1px 0 0 1px !important;border:1px solid #ACA899 !important;border-color:#ACA899 #ECEBE3 #ECEBE3 #ACA899 !important;}#fbStatusBarBox{top:4px;cursor:default;}.fbToolbarSeparator{overflow:hidden;border:1px solid;border-color:transparent #fff transparent #777;_border-color:#eee #fff #eee #777;height:7px;margin:6px 3px;float:left;}.fbBtnSelected{font-weight:bold;}.fbStatusBar{color:#aca899;}.fbStatusBar a{text-decoration:none;color:black;}.fbStatusBar a:hover{color:blue;cursor:pointer;}#fbWindowButtons{position:absolute;white-space:nowrap;right:0;top:0;height:17px;width:48px;padding:5px;z-index:6;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;}#fbPanelBar1{width:1024px; z-index:8;left:0;white-space:nowrap;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #dbd9c9 0 -27px;position:absolute;left:4px;}#fbPanelBar2Box{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #dbd9c9 0 -27px;position:absolute;height:22px;width:300px; z-index:9;right:0;}#fbPanelBar2{position:absolute;width:290px; height:22px;padding-left:4px;}.fbPanel{display:none;}#fbPanelBox1,#fbPanelBox2{max-height:inherit;height:100%;font-size:1em;}#fbPanelBox2{background:#fff;}#fbPanelBox2{width:300px;background:#fff;}#fbPanel2{margin-left:6px;background:#fff;}#fbLargeCommandLine{display:none;position:absolute;z-index:9;top:27px;right:0;width:294px;height:201px;border-width:0;margin:0;padding:2px 0 0 2px;resize:none;outline:none;font-size:11px;overflow:auto;border-top:1px solid #B9B7AF;_right:-1px;_border-left:1px solid #fff;}#fbLargeCommandButtons{display:none;background:#ECE9D8;bottom:0;right:0;width:294px;height:21px;padding-top:1px;position:fixed;border-top:1px solid #ACA899;z-index:9;}#fbSmallCommandLineIcon{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/down.png) no-repeat;position:absolute;right:2px;bottom:3px;z-index:99;}#fbSmallCommandLineIcon:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/downHover.png) no-repeat;}.hide{overflow:hidden !important;position:fixed !important;display:none !important;visibility:hidden !important;}#fbCommand{height:18px;}#fbCommandBox{position:fixed;_position:absolute;width:100%;height:18px;bottom:0;overflow:hidden;z-index:9;background:#fff;border:0;border-top:1px solid #ccc;}#fbCommandIcon{position:absolute;color:#00f;top:2px;left:6px;display:inline;font:11px Monaco,monospace;z-index:10;}#fbCommandLine{position:absolute;width:100%;top:0;left:0;border:0;margin:0;padding:2px 0 2px 32px;font:11px Monaco,monospace;z-index:9;outline:none;}#fbLargeCommandLineIcon{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/up.png) no-repeat;position:absolute;right:1px;bottom:1px;z-index:10;}#fbLargeCommandLineIcon:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/upHover.png) no-repeat;}div.fbFitHeight{overflow:auto;position:relative;}.fbSmallButton{overflow:hidden;width:16px;height:16px;display:block;text-decoration:none;cursor:default;}#fbWindowButtons .fbSmallButton{float:right;}#fbWindow_btClose{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/min.png);}#fbWindow_btClose:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/minHover.png);}#fbWindow_btDetach{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/detach.png);}#fbWindow_btDetach:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/detachHover.png);}#fbWindow_btDeactivate{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/off.png);}#fbWindow_btDeactivate:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/offHover.png);}.fbTab{text-decoration:none;display:none;float:left;width:auto;float:left;cursor:default;font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;font-weight:bold;height:22px;color:#565656;}.fbPanelBar span{float:left;}.fbPanelBar .fbTabL,.fbPanelBar .fbTabR{height:22px;width:8px;}.fbPanelBar .fbTabText{padding:4px 1px 0;}a.fbTab:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -73px;}a.fbTab:hover .fbTabL{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) -16px -96px;}a.fbTab:hover .fbTabR{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) -24px -96px;}.fbSelectedTab{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 -50px !important;color:#000;}.fbSelectedTab .fbTabL{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -96px !important;}.fbSelectedTab .fbTabR{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) -8px -96px !important;}#fbHSplitter{position:fixed;_position:absolute;left:0;top:0;width:100%;height:5px;overflow:hidden;cursor:n-resize !important;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/pixel_transparent.gif);z-index:9;}#fbHSplitter.fbOnMovingHSplitter{height:100%;z-index:100;}.fbVSplitter{background:#ece9d8;color:#000;border:1px solid #716f64;border-width:0 1px;border-left-color:#aca899;width:4px;cursor:e-resize;overflow:hidden;right:294px;text-decoration:none;z-index:10;position:absolute;height:100%;top:27px;}div.lineNo{font:1em Monaco,monospace;position:relative;float:left;top:0;left:0;margin:0 5px 0 0;padding:0 5px 0 10px;background:#eee;color:#888;border-right:1px solid #ccc;text-align:right;}.sourceBox{position:absolute;}.sourceCode{font:1em Monaco,monospace;overflow:hidden;white-space:pre;display:inline;}.nodeControl{margin-top:3px;margin-left:-14px;float:left;width:9px;height:9px;overflow:hidden;cursor:default;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_open.gif);_float:none;_display:inline;_position:absolute;}div.nodeMaximized{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_close.gif);}div.objectBox-element{padding:1px 3px;}.objectBox-selector{cursor:default;}.selectedElement{background:highlight;color:#fff !important;}.selectedElement span{color:#fff !important;}* html .selectedElement{position:relative;}@media screen and (-webkit-min-device-pixel-ratio:0){.selectedElement{background:#316AC5;color:#fff !important;}}.logRow *{font-size:1em;}.logRow{position:relative;border-bottom:1px solid #D7D7D7;padding:2px 4px 1px 6px;zbackground-color:#FFFFFF;}.logRow-command{font-family:Monaco,monospace;color:blue;}.objectBox-string,.objectBox-text,.objectBox-number,.objectBox-function,.objectLink-element,.objectLink-textNode,.objectLink-function,.objectBox-stackTrace,.objectLink-profile{font-family:Monaco,monospace;}.objectBox-null{padding:0 2px;border:1px solid #666666;background-color:#888888;color:#FFFFFF;}.objectBox-string{color:red;}.objectBox-number{color:#000088;}.objectBox-function{color:DarkGreen;}.objectBox-object{color:DarkGreen;font-weight:bold;font-family:Lucida Grande,sans-serif;}.objectBox-array{color:#000;}.logRow-info,.logRow-error,.logRow-warn{background:#fff no-repeat 2px 2px;padding-left:20px;padding-bottom:3px;}.logRow-info{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/infoIcon.png) !important;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/infoIcon.gif);}.logRow-warn{background-color:cyan;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/warningIcon.png) !important;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/warningIcon.gif);}.logRow-error{background-color:LightYellow;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.png) !important;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.gif);color:#f00;}.errorMessage{vertical-align:top;color:#f00;}.objectBox-sourceLink{position:absolute;right:4px;top:2px;padding-left:8px;font-family:Lucida Grande,sans-serif;font-weight:bold;color:#0000FF;}.selectorTag,.selectorId,.selectorClass{font-family:Monaco,monospace;font-weight:normal;}.selectorTag{color:#0000FF;}.selectorId{color:DarkBlue;}.selectorClass{color:red;}.objectBox-element{font-family:Monaco,monospace;color:#000088;}.nodeChildren{padding-left:26px;}.nodeTag{color:blue;cursor:pointer;}.nodeValue{color:#FF0000;font-weight:normal;}.nodeText,.nodeComment{margin:0 2px;vertical-align:top;}.nodeText{color:#333333;font-family:Monaco,monospace;}.nodeComment{color:DarkGreen;}.nodeHidden,.nodeHidden *{color:#888888;}.nodeHidden .nodeTag{color:#5F82D9;}.nodeHidden .nodeValue{color:#D86060;}.selectedElement .nodeHidden,.selectedElement .nodeHidden *{color:SkyBlue !important;}.log-object{}.property{position:relative;clear:both;height:15px;}.propertyNameCell{vertical-align:top;float:left;width:28%;position:absolute;left:0;z-index:0;}.propertyValueCell{float:right;width:68%;background:#fff;position:absolute;padding-left:5px;display:table-cell;right:0;z-index:1;}.propertyName{font-weight:bold;}.FirebugPopup{height:100% !important;}.FirebugPopup #fbWindowButtons{display:none !important;}.FirebugPopup #fbHSplitter{display:none !important;}',
- HTML: '<table id="fbChrome" cellpadding="0" cellspacing="0" border="0"><tbody><tr><td id="fbTop" colspan="2"><div id="fbWindowButtons"><a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </a><a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window"> </a><a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug"> </a></div><div id="fbToolbar"><div id="fbToolbarContent"><span id="fbToolbarIcon"><a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a></span><span id="fbToolbarButtons"><span id="fbFixedButtons"><a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a></span><span id="fbConsoleButtons" class="fbToolbarButtons"><a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a></span></span><span id="fbStatusBarBox"><span class="fbToolbarSeparator"></span></span></div></div><div id="fbPanelBarBox"><div id="fbPanelBar1" class="fbPanelBar"><a id="fbConsoleTab" class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">Console</span><span class="fbTabMenuTarget"></span><span class="fbTabR"></span></a><a id="fbHTMLTab" class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">HTML</span><span class="fbTabR"></span></a><a class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">CSS</span><span class="fbTabR"></span></a><a class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">Script</span><span class="fbTabR"></span></a><a class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">DOM</span><span class="fbTabR"></span></a></div><div id="fbPanelBar2Box" class="hide"><div id="fbPanelBar2" class="fbPanelBar"></div></div></div><div id="fbHSplitter"> </div></td></tr><tr id="fbContent"><td id="fbPanelBox1"><div id="fbPanel1" class="fbFitHeight"><div id="fbConsole" class="fbPanel"></div><div id="fbHTML" class="fbPanel"></div></div></td><td id="fbPanelBox2" class="hide"><div id="fbVSplitter" class="fbVSplitter"> </div><div id="fbPanel2" class="fbFitHeight"><div id="fbHTML_Style" class="fbPanel"></div><div id="fbHTML_Layout" class="fbPanel"></div><div id="fbHTML_DOM" class="fbPanel"></div></div><textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea><div id="fbLargeCommandButtons"><a id="fbCommand_btRun" class="fbButton fbHover">Run</a><a id="fbCommand_btClear" class="fbButton fbHover">Clear</a><a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a></div></td></tr><tr id="fbBottom" class="hide"><td id="fbCommand" colspan="2"><div id="fbCommandBox"><div id="fbCommandIcon">>>></div><input id="fbCommandLine" name="fbCommandLine" type="text"/><a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a></div></td></tr></tbody></table><span id="fbMiniChrome"><span id="fbMiniContent"><span id="fbMiniIcon" title="Open Firebug Lite"></span><span id="fbMiniErrors" class="fbErrors">2 errors</span></span></span>'
- };
- // ************************************************************************************************
- }});
- // ************************************************************************************************
- FBL.initialize();
- // ************************************************************************************************
- })();
|