diff options
author | 2017-05-04 07:48:42 -0400 | |
---|---|---|
committer | 2017-05-04 12:28:17 -0400 | |
commit | b54df0ddd0c6a0372327c5aa3668e5a6458fcd64 (patch) | |
tree | e69cfa9b314a801bd187cf0145d1d4306436229c /ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js | |
parent | 39d1e62c84041831bfc52cca73b5ed5efaf57d27 (diff) |
[PORTAL-7] Rebase
This rebasing includes common libraries and common overlays projects
abstraction of components
Change-Id: I9a24a338665c7cd058978e8636bc412d9e2fdce8
Signed-off-by: st782s <statta@research.att.com>
Diffstat (limited to 'ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js')
-rw-r--r-- | ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js | 31176 |
1 files changed, 0 insertions, 31176 deletions
diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js deleted file mode 100644 index 40b1ae70..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js +++ /dev/null @@ -1,31176 +0,0 @@ -(function(){ - -/*!************************************************************* - * - * Firebug Lite 1.4.0 - * - * 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 */ - -// FIXME: xxxpedro if we use "var FBL = {}" the FBL won't appear in the DOM Panel in IE -var FBL = {}; - -( /** @scope s_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 = {}; - - // 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... - // The problem is that we don't have the Firebug object yet, so we can't use - // Firebug.loadPrefs. We're using the Store module directly instead. - var prefs = FBL.Store.get("FirebugLite") || {}; - FBL.Env.DefaultOptions = FBL.Env.Options; - FBL.Env.Options = FBL.extend(FBL.Env.Options, prefs.options || {}); - - 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"); - } - - FBL.Ajax.initialize(); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // finish environment initialization - FBL.Firebug.loadPrefs(); - - 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: true, - - saveWindowPosition: false, - saveCommandLineHistory: false, - - startOpened: false, - startInNewWindow: false, - showIconWhenHidden: true, - - overrideConsole: true, - ignoreFirebugElements: true, - disableWhenFirebugActive: true, - - disableXHRListener: false, - disableResourceFetching: 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 reGetFirebugSite = /(?:http|https):\/\/getfirebug.com\//; - var isGetFirebugSite; - - var rePath = /^(.*\/)/; - var reProtocol = /^\w+:\/\//; - var path = null; - var doc = document; - - // Firebug Lite 1.3.0 bookmarklet identification - var script = doc.getElementById("FirebugLite"); - - var scriptSrc; - var hasSrcAttribute = true; - - // If the script was loaded via bookmarklet, we already have the script tag - if (script) - { - scriptSrc = script.src; - file = reFirebugFile.exec(scriptSrc); - - var version = script.getAttribute("FirebugLite"); - var number = version ? parseInt(version) : 0; - - if (!version || !number || number < bookmarkletVersion) - { - FBL.Env.bookmarkletOutdated = true; - } - } - // otherwise we must search for the correct script tag - else - { - for(var i=0, s=doc.getElementsByTagName("script"), si; si=s[i]; i++) - { - var file = null; - if ( si.nodeName.toLowerCase() == "script" ) - { - if (file = reFirebugFile.exec(si.getAttribute("firebugSrc"))) - { - scriptSrc = si.getAttribute("firebugSrc"); - hasSrcAttribute = false; - } - else if (file = reFirebugFile.exec(si.src)) - { - scriptSrc = si.src; - } - else - continue; - - script = si; - break; - } - } - } - - // mark the script tag to be ignored by Firebug Lite - if (script) - script.firebugIgnore = true; - - if (file) - { - var fileName = file[1]; - var fileOptions = file[2]; - - // absolute path - if (reProtocol.test(scriptSrc)) { - path = rePath.exec(scriptSrc)[1]; - - } - // relative path - else - { - var r = rePath.exec(scriptSrc); - var src = r ? r[1] : scriptSrc; - 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}"}; - } - - isGetFirebugSite = reGetFirebugSite.test(path); - - if (isGetFirebugSite && path.indexOf("/releases/lite/") == -1) - { - // See Issue 4587 - If we are loading the script from getfirebug.com shortcut, like - // https://getfirebug.com/firebug-lite.js, then we must manually add the full path, - // otherwise the Env.Location will hold the wrong path, which will in turn lead to - // undesirable effects like the problem in Issue 4587 - path += "releases/lite/" + (fileName == "firebug-lite-beta.js" ? "beta/" : "latest/"); - } - - 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 && - // but we cannot use the locan skin when loaded from getfirebug.com, otherwise - // the bookmarklet won't work when visiting getfirebug.com - !isGetFirebugSite; - - // 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 - if (hasSrcAttribute) - { - 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; - } - } - } - } - - if (!Env.Options.saveCookies) - FBL.Store.remove("FirebugLite"); - - // 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) - { - try - { - // FIXME: xxxpedro this is failing in IE for the global "external" object - return ob + ""; - } - catch(E) - { - FBTrace.sysout("Lib.safeToString() failed for ", ob); - return ""; - } - } - - 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, ""); - var chrome = Firebug.chrome; - - if (elt.offsetLeft) - ///coords.x += elt.offsetLeft + parseInt(style.borderLeftWidth); - coords.x += elt.offsetLeft + chrome.getMeasurementInPixels(elt, "borderLeft"); - if (elt.offsetTop) - ///coords.y += elt.offsetTop + parseInt(style.borderTopWidth); - coords.y += elt.offsetTop + chrome.getMeasurementInPixels(elt, "borderTop"); - - if (p) - { - if (p.nodeType == 1) - addOffset(p, coords, view); - } - else - { - var otherView = isIE ? elt.ownerDocument.parentWindow : elt.ownerDocument.defaultView; - // IE will fail when reading the frameElement property of a popup window. - // We don't need it anyway once it is outside the (popup) viewport, so we're - // ignoring the frameElement check when the window is a popup - if (!otherView.opener && 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; - - try - { - // FIXME: xxxpedro this is failing in IE for the global "external" object - return toString.call(object) === "[object Function]" || - this.isIE && typeof object != "string" && reFunction.test(""+object); - } - catch (E) - { - FBTrace.sysout("Lib.isFunction() failed for ", object); - return false; - } -}; - - -// ************************************************************************************************ -// 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 = FBL.getNativeXHRObject(); - }, - - 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 s_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 s_firebug */ function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Globals - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Internals - -var modules = []; -var panelTypes = []; -var panelTypeMap = {}; -var reps = []; - -var parentPanelMap = {}; - - -// ************************************************************************************************ -// Firebug - -/** - * @namespace describe Firebug - * @exports FBL.Firebug as Firebug - */ -FBL.Firebug = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - version: "Firebug Lite 1.4.0", - revision: "$Revision$", - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - 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; - - Firebug.loadPrefs(); - Firebug.context.persistedState.isOpen = false; - - // Document must be cached before chrome initialization - cacheDocument(); - - if (Firebug.Inspector && Firebug.Inspector.create) - Firebug.Inspector.create(); - - if (FBL.CssAnalyzer && FBL.CssAnalyzer.processAllStyleSheets) - FBL.CssAnalyzer.processAllStyleSheets(Firebug.browser.document); - - FirebugChrome.initialize(); - - dispatch(modules, "initialize", []); - - if (Firebug.disableResourceFetching) - Firebug.Console.logFormatted(["Some Firebug Lite features are not working because " + - "resource fetching is disabled. To enabled it set the Firebug Lite option " + - "\"disableResourceFetching\" to \"false\". More info at " + - "http://getfirebug.com/firebuglite#Options"], - Firebug.context, "warn"); - - if (Env.onLoad) - { - var onLoad = Env.onLoad; - delete Env.onLoad; - - setTimeout(onLoad, 200); - } - }, - - shutdown: function() - { - if (Firebug.saveCookies) - Firebug.savePrefs(); - - if (Firebug.Inspector) - Firebug.Inspector.destroy(); - - dispatch(modules, "shutdown", []); - - var chromeMap = FirebugChrome.chromeMap; - - for (var name in chromeMap) - { - if (chromeMap.hasOwnProperty(name)) - { - try - { - chromeMap[name].destroy(); - } - catch(E) - { - if (FBTrace.DBG_ERRORS) FBTrace.sysout("chrome.destroy() failed to: " + name); - } - } - } - - 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; - - Firebug.savePrefs(); - }, - - setPrefs: function(prefs) - { - for (var name in prefs) - { - if (prefs.hasOwnProperty(name)) - Firebug[name] = prefs[name]; - } - - Firebug.savePrefs(); - }, - - restorePrefs: function() - { - var Options = Env.DefaultOptions; - - for (var name in Options) - { - Firebug[name] = Options[name]; - } - }, - - loadPrefs: function() - { - this.restorePrefs(); - - var prefs = Store.get("FirebugLite") || {}; - var options = prefs.options; - var persistedState = prefs.persistedState || FBL.defaultPersistedState; - - for (var name in options) - { - if (options.hasOwnProperty(name)) - Firebug[name] = options[name]; - } - - if (Firebug.context && persistedState) - Firebug.context.persistedState = persistedState; - }, - - savePrefs: function() - { - var prefs = { - options: {} - }; - - var EnvOptions = Env.Options; - var options = prefs.options; - for (var name in EnvOptions) - { - if (EnvOptions.hasOwnProperty(name)) - { - options[name] = Firebug[name]; - } - } - - var persistedState = Firebug.context.persistedState; - if (!persistedState) - { - persistedState = Firebug.context.persistedState = FBL.defaultPersistedState; - } - - prefs.persistedState = persistedState; - - Store.set("FirebugLite", prefs); - }, - - erasePrefs: function() - { - Store.remove("FirebugLite"); - this.restorePrefs(); - } -}; - -Firebug.restorePrefs(); - -// xxxpedro should we remove this? -window.Firebug = FBL.Firebug; - -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; - if (Firebug.InfoTip) - Firebug.InfoTip.initializeBrowser(Firebug.chrome); - }, - - shutdown: function() - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.shutdown", this.name); - - /// TODO: xxxpedro infoTip Hack - if (Firebug.InfoTip) - 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 && oldChrome.selectedPanel && 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 s_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) - Firebug.context.persistedState.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 s_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) - { - // 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 isObjectLiteral = trim(expr).indexOf("{") == 0, - cmd, - result; - - // if the context is the "window" object, we don't need a closure - if (context == "window") - { - // If it is an object literal, then wrap the expression with parenthesis so we can - // capture the return value - if (isObjectLiteral) - { - cmd = api ? - "with("+api+"){ ("+expr+") }" : - "(" + expr + ")"; - } - else - { - cmd = api ? - "with("+api+"){ "+expr+" }" : - expr; - } - } - else - { - 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); - - else if (unit == "em") - return this.emToPixels(el, value); - - else if (unit == "%") - return this.percentToPixels(el, value); - - else if (unit == "ex") - return this.exToPixels(el, value); - - // TODO: add other units. Maybe create a better general way - // to calculate measurements in different units. - }, - - 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: 350 // obsolete - }, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// 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 - -FBL.defaultPersistedState = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - isOpen: false, - height: 300, - sidePanelWidth: 350, - - selectedPanelName: "Console", - selectedHTMLElementId: null, - - htmlSelectionStack: [] - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -}; - -/**@namespace*/ -FBL.FirebugChrome = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - //isOpen: false, - //height: 300, - //sidePanelWidth: 350, - - //selectedPanelName: "Console", - //selectedHTMLElementId: null, - - chromeMap: {}, - - htmlSelectionStack: [], - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - 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 browserWin = Env.browser.window; - var browserContext = new Context(browserWin); - var prefs = Store.get("FirebugLite"); - var persistedState = prefs && prefs.persistedState || defaultPersistedState; - - 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; - } - - var browserWinSize = browserContext.getWindowSize(); - var height = persistedState.height || 300; - - height = Math.min(browserWinSize.height, height); - height = Math.max(200, height); - - 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 = 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 = persistedState.popupHeight || 300; - var browserWinSize = browserContext.getWindowSize(); - - var browserWinLeft = typeof browserWin.screenX == "number" ? - browserWin.screenX : browserWin.screenLeft; - - var popupLeft = typeof persistedState.popupLeft == "number" ? - persistedState.popupLeft : browserWinLeft; - - var browserWinTop = typeof browserWin.screenY == "number" ? - browserWin.screenY : browserWin.screenTop; - - var popupTop = typeof persistedState.popupTop == "number" ? - persistedState.popupTop : - Math.max( - 0, - Math.min( - browserWinTop + browserWinSize.height - height, - // Google Chrome bug - screen.availHeight - height - 61 - ) - ); - - var popupWidth = typeof persistedState.popupWidth == "number" ? - persistedState.popupWidth : - Math.max( - 0, - Math.min( - browserWinSize.width, - // Opera opens popup in a new tab if it's too big! - screen.availWidth-10 - ) - ); - - var popupHeight = typeof persistedState.popupHeight == "number" ? - persistedState.popupHeight : 300; - - var options = [ - "true,top=", popupTop, - ",left=", popupLeft, - ",height=", popupHeight, - ",width=", popupWidth, - ",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); - }, useLocalSkin ? 200 : 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]); - - 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: "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: "Disable Resource Fetching", - type: "checkbox", - value: "disableResourceFetching", - checked: Firebug.disableResourceFetching, - 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); - }, - - restorePrefs: function(target) - { - Firebug.erasePrefs(); - - if (target) - this.updateMenu(target); - }, - - 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(Firebug.context.persistedState.selectedPanelName); - - if (Firebug.context.persistedState.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 || !Firebug.context.persistedState.isOpen; - - if(shouldOpen) - this.open(); - else - this.close(); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - detach: function() - { - if(!FirebugChrome.chromeMap.popup) - { - this.close(); - 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 - Firebug.context.persistedState.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 ? Firebug.context.persistedState.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() - { - var size = Firebug.chrome.getWindowSize(); - - Firebug.context.persistedState.height = size.height; - - if (Firebug.saveCookies) - Firebug.savePrefs(); - - 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 (!Firebug.context.persistedState.isOpen) - { - Firebug.context.persistedState.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; - /// TODO: xxxpedro FOUC - node.style.visibility = "visible"; - setTimeout(function(){ - ///node.style.visibility = "visible"; - - //dispatch(Firebug.modules, "initialize", []); - self.initialize(); - - if (noFixedPosition) - self.fixIEPosition(); - - self.draw(); - - }, 10); - } - }, - - close: function() - { - if (Firebug.context.persistedState.isOpen) - { - if (this.isInitialized) - { - //dispatch(Firebug.modules, "shutdown", []); - this.shutdown(); - } - - Firebug.context.persistedState.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 = Firebug.context.persistedState.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 = Firebug.context.persistedState.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] - //[Firebug.chrome.window, "beforeunload", 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() - { - var chromeWin = Firebug.chrome.window; - var left = chromeWin.screenX || chromeWin.screenLeft; - var top = chromeWin.screenY || chromeWin.screenTop; - var size = Firebug.chrome.getWindowSize(); - - Firebug.context.persistedState.popupTop = top; - Firebug.context.persistedState.popupLeft = left; - Firebug.context.persistedState.popupWidth = size.width; - Firebug.context.persistedState.popupHeight = size.height; - - if (Firebug.saveCookies) - Firebug.savePrefs(); - - // 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); - Firebug.loadPrefs(); - - 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(); - - Firebug.Console.logFormatted( - ["Firebug could not capture console calls during " + - persistDelay + "ms"], - Firebug.context, - "info" - ); - - setTimeout(function(){ - var htmlPanel = chrome.getPanel("HTML"); - htmlPanel.createUI(); - },50); - - } - 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.defaultView || 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); - - Firebug.context.persistedState.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); - - Firebug.context.persistedState.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.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 data = {}; - - 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 = getValidatedKey(element); - - if (!id) - { - id = ++cacheUID; - element[CID] = id; - } - - if (!map.hasOwnProperty(id)) - { - map[id] = element; - data[id] = {}; - } - - return id; - }, - - unset: function(element) - { - var id = getValidatedKey(element); - - if (!id) return; - - if (supportsDeleteExpando) - { - delete element[CID]; - } - else if (element.removeAttribute) - { - element.removeAttribute(CID); - } - - delete map[id]; - delete data[id]; - - }, - - key: function(element) - { - return getValidatedKey(element); - }, - - has: function(element) - { - var id = getValidatedKey(element); - return id && map.hasOwnProperty(id); - }, - - each: function(callback) - { - for (var key in map) - { - if (map.hasOwnProperty(key)) - { - callback(key, map[key]); - } - } - }, - - data: function(element, name, value) - { - // set data - if (value) - { - if (!name) return null; - - var id = cacheAPI.set(element); - - return data[id][name] = value; - } - // get data - else - { - var id = cacheAPI.key(element); - - return data.hasOwnProperty(id) && data[id].hasOwnProperty(name) ? - data[id][name] : - null; - } - }, - - clear: function() - { - for (var id in map) - { - var element = map[id]; - cacheAPI.unset(element); - } - } - }; - - var getValidatedKey = function(element) - { - var id = element[CID]; - - // If a cached element is cloned in IE, the expando property CID will be also - // cloned (differently than other browsers) resulting in a bug: Firebug Lite - // will think the new cloned node is the old one. To prevent this problem we're - // checking if the cached element matches the given element. - if ( - !supportsDeleteExpando && // the problem happens when supportsDeleteExpando is false - id && // the element has the expando property - map.hasOwnProperty(id) && // there is a cached element with the same id - map[id] != element // but it is a different element than the current one - ) - { - // remove the problematic property - element.removeAttribute(CID); - - id = null; - } - - return id; - }; - - 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(); - -// TODO: xxxpedro -Firebug.Lite.Cache.Event = createCache(); - - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -var sourceMap = {}; - -// ************************************************************************************************ -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); - }); - } -}; - -// ************************************************************************************************ - -Firebug.Lite.Proxy.fetchResourceDisabledMessage = - "/* Firebug Lite resource fetching is disabled.\n" + - "To enabled it set the Firebug Lite option \"disableResourceFetching\" to \"false\".\n" + - "More info at http://getfirebug.com/firebuglite#Options */"; - -var fetchResource = function(url) -{ - if (Firebug.disableResourceFetching) - { - var source = sourceMap[url] = Firebug.Lite.Proxy.fetchResourceDisabledMessage; - return source; - } - - if (sourceMap.hasOwnProperty(url)) - return sourceMap[url]; - - // Getting the native XHR object so our calls won't be logged in the Console Panel - var xhr = FBL.getNativeXHRObject(); - xhr.open("get", url, false); - xhr.send(); - - var source = sourceMap[url] = xhr.responseText; - return source; -}; - -var fetchProxyResource = function(url) -{ - if (sourceMap.hasOwnProperty(url)) - return sourceMap[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."; - } - - var source = data ? data.contents : ""; - return source; -}; - - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -Firebug.Lite.Style = -{ -}; - -// ************************************************************************************************ -}}); - - -/* 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.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 */ - -/* - http://www.JSON.org/json2.js - 2010-03-20 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - - - This file creates a global JSON object containing two methods: stringify - and parse. - - JSON.stringify(value, replacer, space) - value any JavaScript value, usually an object or array. - - replacer an optional parameter that determines how object - values are stringified for objects. It can be a - function or an array of strings. - - space an optional parameter that specifies the indentation - of nested structures. If it is omitted, the text will - be packed without extra whitespace. If it is a number, - it will specify the number of spaces to indent at each - level. If it is a string (such as '\t' or ' '), - it contains the characters used to indent at each level. - - This method produces a JSON text from a JavaScript value. - - When an object value is found, if the object contains a toJSON - method, its toJSON method will be called and the result will be - stringified. A toJSON method does not serialize: it returns the - value represented by the name/value pair that should be serialized, - or undefined if nothing should be serialized. The toJSON method - will be passed the key associated with the value, and this will be - bound to the value - - For example, this would serialize Dates as ISO strings. - - Date.prototype.toJSON = function (key) { - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - You can provide an optional replacer method. It will be passed the - key and value of each member, with this bound to the containing - object. The value that is returned from your method will be - serialized. If your method returns undefined, then the member will - be excluded from the serialization. - - If the replacer parameter is an array of strings, then it will be - used to select the members to be serialized. It filters the results - such that only members with keys listed in the replacer array are - stringified. - - Values that do not have JSON representations, such as undefined or - functions, will not be serialized. Such values in objects will be - dropped; in arrays they will be replaced with null. You can use - a replacer function to replace those with JSON values. - JSON.stringify(undefined) returns undefined. - - The optional space parameter produces a stringification of the - value that is filled with line breaks and indentation to make it - easier to read. - - If the space parameter is a non-empty string, then that string will - be used for indentation. If the space parameter is a number, then - the indentation will be that many spaces. - - Example: - - text = JSON.stringify(['e', {pluribus: 'unum'}]); - // text is '["e",{"pluribus":"unum"}]' - - - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - - text = JSON.stringify([new Date()], function (key, value) { - return this[key] instanceof Date ? - 'Date(' + this[key] + ')' : value; - }); - // text is '["Date(---current time---)"]' - - - JSON.parse(text, reviver) - This method parses a JSON text to produce an object or array. - It can throw a SyntaxError exception. - - The optional reviver parameter is a function that can filter and - transform the results. It receives each of the keys and values, - and its return value is used instead of the original value. - If it returns what it received, then the structure is not modified. - If it returns undefined then the member is deleted. - - Example: - - // Parse the text. Values that look like ISO date strings will - // be converted to Date objects. - - myData = JSON.parse(text, function (key, value) { - var a; - if (typeof value === 'string') { - a = -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if (a) { - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], - +a[5], +a[6])); - } - } - return value; - }); - - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { - var d; - if (typeof value === 'string' && - value.slice(0, 5) === 'Date(' && - value.slice(-1) === ')') { - d = new Date(value.slice(5, -1)); - if (d) { - return d; - } - } - return value; - }); - - - This is a reference implementation. You are free to copy, modify, or - redistribute. -*/ - -/*jslint evil: true, strict: false */ - -/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, - call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -// ************************************************************************************************ - -var JSON = window.JSON || {}; - -// ************************************************************************************************ - -(function () { - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function (key) { - - return isFinite(this.valueOf()) ? - this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' : null; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function (key) { - return this.valueOf(); - }; - } - - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - gap, - indent, - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? - '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' ? c : - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : - '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 ? '[]' : - gap ? '[\n' + gap + - partial.join(',\n' + gap) + '\n' + - mind + ']' : - '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - k = rep[i]; - if (typeof k === 'string') { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 ? '{}' : - gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + - mind + '}' : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[\],:{}\s]*$/. -test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). -replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). -replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' ? - walk({'': j}, '') : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } - -// ************************************************************************************************ -// registration - -FBL.JSON = JSON; - -// ************************************************************************************************ -}()); - -/* See license.txt for terms of usage */ - -(function(){ -// ************************************************************************************************ - -/* Copyright (c) 2010-2011 Marcus Westin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -var store = (function(){ - var api = {}, - win = window, - doc = win.document, - localStorageName = 'localStorage', - globalStorageName = 'globalStorage', - namespace = '__firebug__storejs__', - storage - - api.disabled = false - api.set = function(key, value) {} - api.get = function(key) {} - api.remove = function(key) {} - api.clear = function() {} - api.transact = function(key, transactionFn) { - var val = api.get(key) - if (typeof val == 'undefined') { val = {} } - transactionFn(val) - api.set(key, val) - } - - api.serialize = function(value) { - return JSON.stringify(value) - } - api.deserialize = function(value) { - if (typeof value != 'string') { return undefined } - return JSON.parse(value) - } - - // Functions to encapsulate questionable FireFox 3.6.13 behavior - // when about.config::dom.storage.enabled === false - // See https://github.com/marcuswestin/store.js/issues#issue/13 - function isLocalStorageNameSupported() { - try { return (localStorageName in win && win[localStorageName]) } - catch(err) { return false } - } - - function isGlobalStorageNameSupported() { - try { return (globalStorageName in win && win[globalStorageName] && win[globalStorageName][win.location.hostname]) } - catch(err) { return false } - } - - if (isLocalStorageNameSupported()) { - storage = win[localStorageName] - api.set = function(key, val) { storage.setItem(key, api.serialize(val)) } - api.get = function(key) { return api.deserialize(storage.getItem(key)) } - api.remove = function(key) { storage.removeItem(key) } - api.clear = function() { storage.clear() } - - } else if (isGlobalStorageNameSupported()) { - storage = win[globalStorageName][win.location.hostname] - api.set = function(key, val) { storage[key] = api.serialize(val) } - api.get = function(key) { return api.deserialize(storage[key] && storage[key].value) } - api.remove = function(key) { delete storage[key] } - api.clear = function() { for (var key in storage ) { delete storage[key] } } - - } else if (doc.documentElement.addBehavior) { - var storage = doc.createElement('div') - function withIEStorage(storeFunction) { - return function() { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift(storage) - // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx - // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx - // TODO: xxxpedro doc.body is not always available so we must use doc.documentElement. - // We need to make sure this change won't affect the behavior of this library. - doc.documentElement.appendChild(storage) - storage.addBehavior('#default#userData') - storage.load(localStorageName) - var result = storeFunction.apply(api, args) - doc.documentElement.removeChild(storage) - return result - } - } - api.set = withIEStorage(function(storage, key, val) { - storage.setAttribute(key, api.serialize(val)) - storage.save(localStorageName) - }) - api.get = withIEStorage(function(storage, key) { - return api.deserialize(storage.getAttribute(key)) - }) - api.remove = withIEStorage(function(storage, key) { - storage.removeAttribute(key) - storage.save(localStorageName) - }) - api.clear = withIEStorage(function(storage) { - var attributes = storage.XMLDocument.documentElement.attributes - storage.load(localStorageName) - for (var i=0, attr; attr = attributes[i]; i++) { - storage.removeAttribute(attr.name) - } - storage.save(localStorageName) - }) - } - - try { - api.set(namespace, namespace) - if (api.get(namespace) != namespace) { api.disabled = true } - api.remove(namespace) - } catch(e) { - api.disabled = true - } - - return api -})(); - -if (typeof module != 'undefined') { module.exports = store } - - -// ************************************************************************************************ -// registration - -FBL.Store = store; - -// ************************************************************************************************ -})(); - -/* See license.txt for terms of usage */ - -FBL.ns( /**@scope s_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; - -/**#@-*/ - -// ************************************************************************************************ -}}); - -/* 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(); - - if (Firebug.HTML) - 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" ? Firebug.context.persistedState.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 - - - - -// ************************************************************************************************ -}}); - -// 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 */ - -( /** @scope s_domplate */ function() { - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** @class */ -FBL.DomplateTag = function DomplateTag(tagName) -{ - this.tagName = tagName; -}; - -/** - * @class - * @extends FBL.DomplateTag - */ -FBL.DomplateEmbed = function DomplateEmbed() -{ -}; - -/** - * @class - * @extends FBL.DomplateTag - */ -FBL.DomplateLoop = function DomplateLoop() -{ -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var DomplateTag = FBL.DomplateTag; -var DomplateEmbed = FBL.DomplateEmbed; -var DomplateLoop = FBL.DomplateLoop; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var womb = null; - -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; -}; - -var domplate = FBL.domplate; - -FBL.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); -}; - -FBL.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(); - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -FBL.DomplateEmbed.prototype = copyObject(FBL.DomplateTag.prototype, -/** @lends FBL.DomplateEmbed.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; - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -FBL.DomplateLoop.prototype = copyObject(FBL.DomplateTag.prototype, -/** @lends FBL.DomplateLoop.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; - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** @class */ -function Variable(name, format) -{ - this.name = name; - this.format = format; -} - -/** @class */ -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); -} - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** @class */ -function ArrayIterator(array) -{ - var index = -1; - - this.next = function() - { - if (++index >= array.length) - throw StopIteration; - - return array[index]; - }; -} - -/** @class */ -function StopIteration() {} - -FBL.$break = function() -{ - throw StopIteration; -}; - -// ************************************************************************************************ - -/** @namespace */ -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)", - // workaround to show XPath (a better approach would use the tooltip on mouseover, - // so the XPath information would be calculated dynamically, but we need to create - // a tooltip class/wrapper around Menu or InfoTip) - title: "$object|FBL.getElementXPath", - _repObject: "$object" - }) - : // Other browsers - A({ - "class": "objectLink objectLink-$className a11yFocus", - // workaround to show XPath (a better approach would use the tooltip on mouseover, - // so the XPath information would be calculated dynamically, but we need to create - // a tooltip class/wrapper around Menu or InfoTip) - title: "$object|FBL.getElementXPath", - _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]; - - // we must check if the attribute is specified otherwise IE will show them - if (!attr.specified || attr.nodeName && attr.nodeName.indexOf("firebug-") != -1) - continue; - else if (attr.nodeName == "id") - idAttr = attr; - else if (attr.nodeName == "class") - classAttr = attr; - else if (attr.nodeName == "style") - attrs.push({ - nodeName: attr.nodeName, - nodeValue: attr.nodeValue || - // IE won't recognize the attr.nodeValue of <style> nodes ... - // and will return CSS property names in upper case, so we need to convert them - elt.style.cssText.replace(/([^\s]+)\s*:/g, - function(m,g){return g.toLowerCase()+":"}) - }); - 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) { -// ************************************************************************************************ - -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(); - }; -} - -//************************************************************************************************ - -FBL.getNativeXHRObject = 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; - } -}; - -// ************************************************************************************************ -}}); - - -/* 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 = -{ - // TODO: create issue: jsonViewer will not try to evaluate the contents of the requested file - // if the content-type is set to "text/plain" - //"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 */ - -// 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) - { - if (!Firebug.Inspector) return; - - 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 sandbox; - - if (win.console) - { - if (Env.Options.overrideConsole) - sandbox = new win.Function("arguments.callee.install(window.console={})"); - else - // if there's a console object and overrideConsole is false we should just quit - return; - } - else - { - try - { - // try overriding the console object - sandbox = new win.Function("arguments.callee.install(window.console={})"); - } - catch(E) - { - // if something goes wrong create the firebug object instead - sandbox = new win.Function("arguments.callee.install(window.firebug={})"); - } - } - - 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; - - Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement); - }; - - 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() -{ - 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) -{ - Firebug.context.persistedState.commandHistory.push(command); - Firebug.context.persistedState.commandPointer = - Firebug.context.persistedState.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(); - - Firebug.context.persistedState.commandHistory = - Firebug.context.persistedState.commandHistory || []; - - Firebug.context.persistedState.commandPointer = - Firebug.context.persistedState.commandPointer || -1; - - 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 (Firebug.context.persistedState.commandPointer > 0 && - Firebug.context.persistedState.commandHistory.length > 0) - { - this.element.value = Firebug.context.persistedState.commandHistory - [--Firebug.context.persistedState.commandPointer]; - } - }, - - nextCommand: function() - { - var element = this.element; - - var limit = Firebug.context.persistedState.commandHistory.length -1; - var i = Firebug.context.persistedState.commandPointer; - - if (i < limit) - element.value = Firebug.context.persistedState.commandHistory - [++Firebug.context.persistedState.commandPointer]; - - else if (i == limit) - { - ++Firebug.context.persistedState.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; - - Firebug.Console.log(o, Firebug.context, "dirxml", Firebug.HTMLPanel.SoloElement); - } -}; - -// ************************************************************************************************ - -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) { -// ************************************************************************************************ - -// ************************************************************************************************ -// 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 -}; - -if (Firebug.ignoreFirebugElements) - // 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>') : ''; - - // FIXME xxxpedro remove this - //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 || - // Issue 4432: Firebug Lite: HTML is mixed-up with functions - // The problem here is that expando properties added to DOM elements in - // IE < 9 will behave like DOM attributes and so they'll show up when - // looking at element.attributes list. - isIE && (browserVersion-0<9) && typeof attr.nodeValue != "string" || - 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; - - // FIXME xxxpedro remove this - //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; - - // FIXME xxxpedro remove this - //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: !Firebug.flexChromeEnabled /* FIXME xxxpedro chromenew */, - 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 && !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.context.persistedState.selectedHTMLElementId = - Firebug.context.persistedState.selectedHTMLElementId && - ElementCache.get(Firebug.context.persistedState.selectedHTMLElementId) ? - Firebug.context.persistedState.selectedHTMLElementId : - ElementCache(Firebug.browser.document.body); - - Firebug.HTML.selectTreeNode(Firebug.context.persistedState.selectedHTMLElementId); - } - - // 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(Firebug.context.persistedState.selectedHTMLElementId) - Firebug.HTML.selectTreeNode(Firebug.context.persistedState.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"; - - e.style.borderRadius = "2px"; - - selectedElement = e; - - Firebug.context.persistedState.selectedHTMLElementId = e.id; - - var target = ElementCache.get(e.id); - var sidePanelBar = Firebug.chrome.getPanel("HTML").sidePanelBar; - var selectedSidePanel = sidePanelBar ? sidePanelBar.selectedPanel : null; - - var stack = FirebugChrome.htmlSelectionStack; - - stack.unshift(target); - - if (stack.length > 2) - stack.pop(); - - var lazySelect = function() - { - selectedSidePanelTS = new Date().getTime(); - - if (selectedSidePanel) - 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') - { - // FIXME xxxpedro remove this - //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 */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -var CssParser = null; - -// ************************************************************************************************ - -// Simple CSS stylesheet parser from: -// https://github.com/sergeche/webkit-css - -/** - * Simple CSS stylesheet parser that remembers rule's lines in file - * @author Sergey Chikuyonok (serge.che@gmail.com) - * @link http://chikuyonok.ru - */ -CssParser = (function(){ - /** - * Returns rule object - * @param {Number} start Character index where CSS rule definition starts - * @param {Number} body_start Character index where CSS rule's body starts - * @param {Number} end Character index where CSS rule definition ends - */ - function rule(start, body_start, end) { - return { - start: start || 0, - body_start: body_start || 0, - end: end || 0, - line: -1, - selector: null, - parent: null, - - /** @type {rule[]} */ - children: [], - - addChild: function(start, body_start, end) { - var r = rule(start, body_start, end); - r.parent = this; - this.children.push(r); - return r; - }, - /** - * Returns last child element - * @return {rule} - */ - lastChild: function() { - return this.children[this.children.length - 1]; - } - }; - } - - /** - * Replaces all occurances of substring defined by regexp - * @param {String} str - * @return {RegExp} re - * @return {String} - */ - function removeAll(str, re) { - var m; - while (m = str.match(re)) { - str = str.substring(m[0].length); - } - - return str; - } - - /** - * Trims whitespace from the beginning and the end of string - * @param {String} str - * @return {String} - */ - function trim(str) { - return str.replace(/^\s+|\s+$/g, ''); - } - - /** - * Normalizes CSS rules selector - * @param {String} selector - */ - function normalizeSelector(selector) { - // remove newlines - selector = selector.replace(/[\n\r]/g, ' '); - - selector = trim(selector); - - // remove spaces after commas - selector = selector.replace(/\s*,\s*/g, ','); - - return selector; - } - - /** - * Preprocesses parsed rules: adjusts char indexes, skipping whitespace and - * newlines, saves rule selector, removes comments, etc. - * @param {String} text CSS stylesheet - * @param {rule} rule_node CSS rule node - * @return {rule[]} - */ - function preprocessRules(text, rule_node) { - for (var i = 0, il = rule_node.children.length; i < il; i++) { - var r = rule_node.children[i], - rule_start = text.substring(r.start, r.body_start), - cur_len = rule_start.length; - - // remove newlines for better regexp matching - rule_start = rule_start.replace(/[\n\r]/g, ' '); - - // remove @import rules -// rule_start = removeAll(rule_start, /^\s*@import\s*url\((['"])?.+?\1?\)\;?/g); - - // remove comments - rule_start = removeAll(rule_start, /^\s*\/\*.*?\*\/[\s\t]*/); - - // remove whitespace - rule_start = rule_start.replace(/^[\s\t]+/, ''); - - r.start += (cur_len - rule_start.length); - r.selector = normalizeSelector(rule_start); - } - - return rule_node; - } - - /** - * Saves all lise starting indexes for faster search - * @param {String} text CSS stylesheet - * @return {Number[]} - */ - function saveLineIndexes(text) { - var result = [0], - i = 0, - il = text.length, - ch, ch2; - - while (i < il) { - ch = text.charAt(i); - - if (ch == '\n' || ch == '\r') { - if (ch == '\r' && i < il - 1 && text.charAt(i + 1) == '\n') { - // windows line ending: CRLF. Skip next character - i++; - } - - result.push(i + 1); - } - - i++; - } - - return result; - } - - /** - * Saves line number for parsed rules - * @param {String} text CSS stylesheet - * @param {rule} rule_node Rule node - * @return {rule[]} - */ - function saveLineNumbers(text, rule_node, line_indexes, startLine) { - preprocessRules(text, rule_node); - - startLine = startLine || 0; - - // remember lines start indexes, preserving line ending characters - if (!line_indexes) - var line_indexes = saveLineIndexes(text); - - // now find each rule's line - for (var i = 0, il = rule_node.children.length; i < il; i++) { - var r = rule_node.children[i]; - r.line = line_indexes.length + startLine; - for (var j = 0, jl = line_indexes.length - 1; j < jl; j++) { - var line_ix = line_indexes[j]; - if (r.start >= line_indexes[j] && r.start < line_indexes[j + 1]) { - r.line = j + 1 + startLine; - break; - } - } - - saveLineNumbers(text, r, line_indexes); - } - - return rule_node; - } - - return { - /** - * Parses text as CSS stylesheet, remembring each rule position inside - * text - * @param {String} text CSS stylesheet to parse - */ - read: function(text, startLine) { - var rule_start = [], - rule_body_start = [], - rules = [], - in_comment = 0, - root = rule(), - cur_parent = root, - last_rule = null, - stack = [], - ch, ch2; - - stack.last = function() { - return this[this.length - 1]; - }; - - function hasStr(pos, substr) { - return text.substr(pos, substr.length) == substr; - } - - for (var i = 0, il = text.length; i < il; i++) { - ch = text.charAt(i); - ch2 = i < il - 1 ? text.charAt(i + 1) : ''; - - if (!rule_start.length) - rule_start.push(i); - - switch (ch) { - case '@': - if (!in_comment) { - if (hasStr(i, '@import')) { - var m = text.substr(i).match(/^@import\s*url\((['"])?.+?\1?\)\;?/); - if (m) { - cur_parent.addChild(i, i + 7, i + m[0].length); - i += m[0].length; - rule_start.pop(); - } - break; - } - } - case '/': - // xxxpedro allowing comment inside comment - if (!in_comment && ch2 == '*') { // comment start - in_comment++; - } - break; - - case '*': - if (ch2 == '/') { // comment end - in_comment--; - } - break; - - case '{': - if (!in_comment) { - rule_body_start.push(i); - - cur_parent = cur_parent.addChild(rule_start.pop()); - stack.push(cur_parent); - } - break; - - case '}': - // found the end of the rule - if (!in_comment) { - /** @type {rule} */ - var last_rule = stack.pop(); - rule_start.pop(); - last_rule.body_start = rule_body_start.pop(); - last_rule.end = i; - cur_parent = last_rule.parent || root; - } - break; - } - - } - - return saveLineNumbers(text, root, null, startLine); - }, - - normalizeSelector: normalizeSelector, - - /** - * Find matched rule by selector. - * @param {rule} rule_node Parsed rule node - * @param {String} selector CSS selector - * @param {String} source CSS stylesheet source code - * - * @return {rule[]|null} Array of matched rules, sorted by priority (most - * recent on top) - */ - findBySelector: function(rule_node, selector, source) { - var selector = normalizeSelector(selector), - result = []; - - if (rule_node) { - for (var i = 0, il = rule_node.children.length; i < il; i++) { - /** @type {rule} */ - var r = rule_node.children[i]; - if (r.selector == selector) { - result.push(r); - } - } - } - - if (result.length) { - return result; - } else { - return null; - } - } - }; -})(); - - -// ************************************************************************************************ - -FBL.CssParser = CssParser; - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// StyleSheet Parser - -var CssAnalyzer = {}; - -// ************************************************************************************************ -// Locals - -var CSSRuleMap = {}; -var ElementCSSRulesMap = {}; - -var internalStyleSheetIndex = -1; - -var reSelectorTag = /(^|\s)(?:\w+)/g; -var reSelectorClass = /\.[\w\d_-]+/g; -var reSelectorId = /#[\w\d_-]+/g; - -var globalCSSRuleIndex; - -var processAllStyleSheetsTimeout = null; - -var externalStyleSheetURLs = []; - -var ElementCache = Firebug.Lite.Cache.Element; -var StyleSheetCache = Firebug.Lite.Cache.StyleSheet; - -//************************************************************************************************ -// CSS Analyzer templates - -CssAnalyzer.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") - ) -}); - -// ************************************************************************************************ -// CSS Analyzer methods - -CssAnalyzer.processAllStyleSheets = function(doc, styleSheetIterator) -{ - try - { - processAllStyleSheets(doc, styleSheetIterator); - } - catch(e) - { - // TODO: FBTrace condition - FBTrace.sysout("CssAnalyzer.processAllStyleSheets fails: ", e); - } -}; - -/** - * - * @param element - * @returns {String[]} Array of IDs of CSS Rules - */ -CssAnalyzer.getElementCSSRules = function(element) -{ - try - { - return getElementCSSRules(element); - } - catch(e) - { - // TODO: FBTrace condition - FBTrace.sysout("CssAnalyzer.getElementCSSRules fails: ", e); - } -}; - -CssAnalyzer.getRuleData = function(ruleId) -{ - return CSSRuleMap[ruleId]; -}; - -// TODO: do we need this? -CssAnalyzer.getRuleLine = function() -{ -}; - -CssAnalyzer.hasExternalStyleSheet = function() -{ - return externalStyleSheetURLs.length > 0; -}; - -CssAnalyzer.parseStyleSheet = function(href) -{ - var sourceData = extractSourceData(href); - var parsedObj = CssParser.read(sourceData.source, sourceData.startLine); - var parsedRules = parsedObj.children; - - // See: Issue 4776: [Firebug lite] CSS Media Types - // - // Ignore all special selectors like @media and @page - for(var i=0; i < parsedRules.length; ) - { - if (parsedRules[i].selector.indexOf("@") != -1) - { - parsedRules.splice(i, 1); - } - else - i++; - } - - return parsedRules; -}; - -//************************************************************************************************ -// Internals -//************************************************************************************************ - -// ************************************************************************************************ -// StyleSheet processing - -var 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 processStyleSheet = function(doc, styleSheet) -{ - if (styleSheet.restricted) - return; - - var rules = isIE ? styleSheet.rules : styleSheet.cssRules; - - var ssid = StyleSheetCache(styleSheet); - - var href = styleSheet.href; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // CSS Parser - var shouldParseCSS = typeof CssParser != "undefined" && !Firebug.disableResourceFetching; - if (shouldParseCSS) - { - try - { - var parsedRules = CssAnalyzer.parseStyleSheet(href); - } - catch(e) - { - if (FBTrace.DBG_ERRORS) FBTrace.sysout("processStyleSheet FAILS", e.message || e); - shouldParseCSS = false; - } - finally - { - var parsedRulesIndex = 0; - - var dontSupportGroupedRules = isIE && browserVersion < 9; - var group = []; - var groupItem; - } - } - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - for (var i=0, length=rules.length; i<length; i++) - { - // TODO: xxxpedro is there a better way to cache CSS Rules? The problem is that - // we cannot add expando properties in the rule object in IE - var rid = ssid + ":" + i; - var rule = rules[i]; - var selector = rule.selectorText || ""; - var lineNo = null; - - // See: Issue 4776: [Firebug lite] CSS Media Types - // - // Ignore all special selectors like @media and @page - if (!selector || selector.indexOf("@") != -1) - continue; - - if (isIE) - selector = selector.replace(reSelectorTag, function(s){return s.toLowerCase();}); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // CSS Parser - if (shouldParseCSS) - { - var parsedRule = parsedRules[parsedRulesIndex]; - var parsedSelector = parsedRule.selector; - - if (dontSupportGroupedRules && parsedSelector.indexOf(",") != -1 && group.length == 0) - group = parsedSelector.split(","); - - if (dontSupportGroupedRules && group.length > 0) - { - groupItem = group.shift(); - - if (CssParser.normalizeSelector(selector) == groupItem) - lineNo = parsedRule.line; - - if (group.length == 0) - parsedRulesIndex++; - } - else if (CssParser.normalizeSelector(selector) == parsedRule.selector) - { - lineNo = parsedRule.line; - parsedRulesIndex++; - } - } - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - CSSRuleMap[rid] = - { - styleSheetId: ssid, - styleSheetIndex: i, - order: ++globalCSSRuleIndex, - specificity: - // See: Issue 4777: [Firebug lite] Specificity of CSS Rules - // - // if it is a normal selector then calculate the specificity - selector && selector.indexOf(",") == -1 ? - getCSSRuleSpecificity(selector) : - // See: Issue 3262: [Firebug lite] Specificity of grouped CSS Rules - // - // 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) - 0, - - rule: rule, - lineNo: lineNo, - selector: selector, - cssText: rule.style ? rule.style.cssText : rule.cssText ? rule.cssText : "" - }; - - // TODO: what happens with elements added after this? Need to create a test case. - // Maybe we should place this at getElementCSSRules() but it will make the function - // a lot more expensive. - // - // Maybe add a "refresh" button? - 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); - } -}; - -// ************************************************************************************************ -// External StyleSheet Loader - -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.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); - -}; - -//************************************************************************************************ -// getElementCSSRules - -var 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; -}; - -// ************************************************************************************************ -// Rule Specificity - -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 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; -}; - -// ************************************************************************************************ -// StyleSheet data - -var extractSourceData = function(href) -{ - var sourceData = - { - source: null, - startLine: 0 - }; - - if (href) - { - sourceData.source = Firebug.Lite.Proxy.load(href); - } - else - { - // TODO: create extractInternalSourceData(index) - // TODO: pre process the position of the inline styles so this will happen only once - // in case of having multiple inline styles - var index = 0; - var ssIndex = ++internalStyleSheetIndex; - var reStyleTag = /\<\s*style.*\>/gi; - var reEndStyleTag = /\<\/\s*style.*\>/gi; - - var source = Firebug.Lite.Proxy.load(Env.browser.location.href); - source = source.replace(/\n\r|\r\n/g, "\n"); // normalize line breaks - - var startLine = 0; - - do - { - var matchStyleTag = source.match(reStyleTag); - var i0 = source.indexOf(matchStyleTag[0]) + matchStyleTag[0].length; - - for (var i=0; i < i0; i++) - { - if (source.charAt(i) == "\n") - startLine++; - } - - source = source.substr(i0); - - index++; - } - while (index <= ssIndex); - - var matchEndStyleTag = source.match(reEndStyleTag); - var i1 = source.indexOf(matchEndStyleTag[0]); - - var extractedSource = source.substr(0, i1); - - sourceData.source = extractedSource; - sourceData.startLine = startLine; - } - - return sourceData; -}; - -// ************************************************************************************************ -// Registration - -FBL.CssAnalyzer = CssAnalyzer; - -// ************************************************************************************************ -}}); - - -/* 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) -{ - try - { - if (element && element.id) - return '//*[@id="' + element.id + '"]'; - else - return this.getElementTreeXPath(element); - } - catch(E) - { - // xxxpedro: trying to detect the mysterious error: - // Security error" code: "1000 - //debugger; - } -}; - -this.getElementTreeXPath = function(element) -{ - var paths = []; - - for (; element && element.nodeType == 1; element = element.parentNode) - { - var index = 0; - var nodeName = element.nodeName; - - for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling) - { - if (sibling.nodeType != 1) continue; - - if (sibling.nodeName == 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; - -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ - - -// ************************************************************************************************ -// 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 reSelectorTag = /(^|\s)(?:\w+)/g; - -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"); - - CssAnalyzer.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 - CssAnalyzer.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) - // FIXME xxxpedro chromenew this is making iPad's Safari to crash - 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 (CssAnalyzer.hasExternalStyleSheet()) - CssAnalyzer.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 = {}; - - inspectedRules = CssAnalyzer.getElementCSSRules(element); - - if (inspectedRules) - { - for (var i = 0, length=inspectedRules.length; i < length; ++i) - { - var ruleId = inspectedRules[i]; - var ruleData = CssAnalyzer.getRuleData(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); - // TODO: xxxpedro CSS line number - var line = ruleData.lineNo; - - 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(Firebug.context.persistedState.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 (Firebug.disableResourceFetching) - { - renderProcess(Firebug.Lite.Proxy.fetchResourceDisabledMessage); - } - else 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; -} - -// FIXME: xxxpedro This function is already defined in Lib. If we keep this definition here, it -// will crash IE9 when not running the IE Developer Tool with JavaScript Debugging enabled!!! -// Check if this function is in fact defined in Firebug for Firefox. If so, we should remove -// this from here. The only difference of this function is the IE hack to show up the prototype -// of functions, but Firebug no longer shows the prototype for simple functions. -//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(Firebug.context.persistedState.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(); - }, - - shutdown: function() - { - this.clearButton.shutdown(); - - Firebug.Panel.shutdown.apply(this, arguments); - } - -}); - -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: '.obscured{left:-999999px !important;}.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;line-height:13px;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;line-height:13px;}#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;line-height:13px;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/1.4545em 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"></span></span></span>' -}; - -// ************************************************************************************************ -}}); - -// ************************************************************************************************ -FBL.initialize(); -// ************************************************************************************************ - -})();
\ No newline at end of file |