зеркало из https://github.com/mozilla/pjs.git
Bug 582596 - Style view centered around answering common CSS questions, f=l10n, r=dolske, msucan
This commit is contained in:
Родитель
7fdd00c2c2
Коммит
49aa83fb77
|
@ -1015,6 +1015,9 @@ pref("devtools.errorconsole.enabled", false);
|
|||
// Enable the Inspector
|
||||
pref("devtools.inspector.enabled", true);
|
||||
|
||||
// Enable the style inspector
|
||||
pref("devtools.styleinspector.enabled", true);
|
||||
|
||||
// Enable the Scratchpad tool.
|
||||
pref("devtools.scratchpad.enabled", true);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Rob Campbell <rcampbell@mozilla.com>
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -49,6 +50,8 @@ DIRS = \
|
|||
webconsole \
|
||||
scratchpad \
|
||||
sourceeditor \
|
||||
styleinspector \
|
||||
shared \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
|
|
@ -2,5 +2,6 @@ browser.jar:
|
|||
content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
|
||||
* content/browser/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
* content/browser/scratchpad.js (scratchpad/scratchpad.js)
|
||||
content/browser/csshtmltree.xhtml (styleinspector/csshtmltree.xhtml)
|
||||
content/browser/orion.js (sourceeditor/orion/orion.js)
|
||||
content/browser/orion.css (sourceeditor/orion/orion.css)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is HUDService code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com> (Original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
# DIRS += test # no tests yet
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/Templater.jsm $(FINAL_TARGET)/modules/devtools
|
|
@ -0,0 +1,398 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Bespin.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker (jwalker@mozilla.com) (original author)
|
||||
* Mike Ratcliffe (mratcliffe@mozilla.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// WARNING: do not 'use_strict' without reading the notes in envEval;
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Templater"];
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/**
|
||||
* A templater that allows one to quickly template DOM nodes.
|
||||
*/
|
||||
function Templater() {
|
||||
this.scope = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive function to walk the tree processing the attributes as it goes.
|
||||
* @param node the node to process.
|
||||
* @param data the data to use for node processing.
|
||||
*/
|
||||
Templater.prototype.processNode = function(node, data) {
|
||||
this.scope.push(node.nodeName + (node.id ? '#' + node.id : ''));
|
||||
try {
|
||||
// Process attributes
|
||||
if (node.attributes && node.attributes.length) {
|
||||
// We need to handle 'foreach' and 'if' first because they might stop
|
||||
// some types of processing from happening, and foreach must come first
|
||||
// because it defines new data on which 'if' might depend.
|
||||
if (node.hasAttribute('foreach')) {
|
||||
this.processForEach(node, data);
|
||||
return;
|
||||
}
|
||||
if (node.hasAttribute('if')) {
|
||||
if (!this.processIf(node, data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Only make the node available once we know it's not going away
|
||||
data.__element = node;
|
||||
// It's good to clean up the attributes when we've processed them,
|
||||
// but if we do it straight away, we mess up the array index
|
||||
var attrs = Array.prototype.slice.call(node.attributes);
|
||||
for (let i = 0, attLen = attrs.length; i < attLen; i++) {
|
||||
var value = attrs[i].value;
|
||||
var name = attrs[i].name;
|
||||
this.scope.push(name);
|
||||
try {
|
||||
if (name === 'save') {
|
||||
// Save attributes are a setter using the node
|
||||
value = this.stripBraces(value);
|
||||
this.property(value, data, node);
|
||||
node.removeAttribute('save');
|
||||
} else if (name.substring(0, 2) === 'on') {
|
||||
// Event registration relies on property doing a bind
|
||||
value = this.stripBraces(value);
|
||||
var func = this.property(value, data);
|
||||
if (typeof func !== 'function') {
|
||||
this.handleError('Expected ' + value +
|
||||
' to resolve to a function, but got ' + typeof func);
|
||||
}
|
||||
node.removeAttribute(name);
|
||||
var capture = node.hasAttribute('capture' + name.substring(2));
|
||||
node.addEventListener(name.substring(2), func, capture);
|
||||
if (capture) {
|
||||
node.removeAttribute('capture' + name.substring(2));
|
||||
}
|
||||
} else {
|
||||
// Replace references in all other attributes
|
||||
var self = this;
|
||||
var newValue = value.replace(/\$\{[^}]*\}/g, function(path) {
|
||||
return self.envEval(path.slice(2, -1), data, value);
|
||||
});
|
||||
// Remove '_' prefix of attribute names so the DOM won't try
|
||||
// to use them before we've processed the template
|
||||
if (name.charAt(0) === '_') {
|
||||
node.removeAttribute(name);
|
||||
node.setAttribute(name.substring(1), newValue);
|
||||
} else if (value !== newValue) {
|
||||
attrs[i].value = newValue;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.scope.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through our children calling processNode. First clone them, so the
|
||||
// set of nodes that we visit will be unaffected by additions or removals.
|
||||
var children = Array.prototype.slice.call(node.childNodes);
|
||||
for (let j = 0, numChildren = children.length; j < numChildren; j++) {
|
||||
this.processNode(children[j], data);
|
||||
}
|
||||
|
||||
if (node.nodeType === Ci.nsIDOMNode.TEXT_NODE) {
|
||||
this.processTextNode(node, data);
|
||||
}
|
||||
} finally {
|
||||
this.scope.pop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle <x if="${...}">
|
||||
* @param node An element with an 'if' attribute
|
||||
* @param data The data to use with envEval
|
||||
* @returns true if processing should continue, false otherwise
|
||||
*/
|
||||
Templater.prototype.processIf = function(node, data) {
|
||||
this.scope.push('if');
|
||||
try {
|
||||
var originalValue = node.getAttribute('if');
|
||||
var value = this.stripBraces(originalValue);
|
||||
var recurse = true;
|
||||
try {
|
||||
var reply = this.envEval(value, data, originalValue);
|
||||
recurse = !!reply;
|
||||
} catch (ex) {
|
||||
this.handleError('Error with \'' + value + '\'', ex);
|
||||
recurse = false;
|
||||
}
|
||||
if (!recurse) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
node.removeAttribute('if');
|
||||
return recurse;
|
||||
} finally {
|
||||
this.scope.pop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle <x foreach="param in ${array}"> and the special case of
|
||||
* <loop foreach="param in ${array}">
|
||||
* @param node An element with a 'foreach' attribute
|
||||
* @param data The data to use with envEval
|
||||
*/
|
||||
Templater.prototype.processForEach = function(node, data) {
|
||||
this.scope.push('foreach');
|
||||
try {
|
||||
var originalValue = node.getAttribute('foreach');
|
||||
var value = originalValue;
|
||||
|
||||
var paramName = 'param';
|
||||
if (value.charAt(0) === '$') {
|
||||
// No custom loop variable name. Use the default: 'param'
|
||||
value = this.stripBraces(value);
|
||||
} else {
|
||||
// Extract the loop variable name from 'NAME in ${ARRAY}'
|
||||
var nameArr = value.split(' in ');
|
||||
paramName = nameArr[0].trim();
|
||||
value = this.stripBraces(nameArr[1].trim());
|
||||
}
|
||||
node.removeAttribute('foreach');
|
||||
try {
|
||||
var self = this;
|
||||
// Process a single iteration of a loop
|
||||
var processSingle = function(member, node, ref) {
|
||||
var clone = node.cloneNode(true);
|
||||
clone.removeAttribute('foreach');
|
||||
ref.parentNode.insertBefore(clone, ref);
|
||||
data[paramName] = member;
|
||||
self.processNode(clone, data);
|
||||
delete data[paramName];
|
||||
};
|
||||
|
||||
// processSingle is no good for <loop> nodes where we want to work on
|
||||
// the children rather than the node itself
|
||||
var processAll = function(scope, member) {
|
||||
self.scope.push(scope);
|
||||
try {
|
||||
if (node.nodeName === 'loop') {
|
||||
for (let i = 0, numChildren = node.children.length; i < numChildren; i++) {
|
||||
processSingle(member, node.children[i], node);
|
||||
}
|
||||
} else {
|
||||
processSingle(member, node, node);
|
||||
}
|
||||
} finally {
|
||||
self.scope.pop();
|
||||
}
|
||||
};
|
||||
|
||||
let reply = this.envEval(value, data, originalValue);
|
||||
if (Array.isArray(reply)) {
|
||||
reply.forEach(function(data, i) {
|
||||
processAll('' + i, data)
|
||||
}, this);
|
||||
} else {
|
||||
for (let param in reply) {
|
||||
if (reply.hasOwnProperty(param)) {
|
||||
processAll(param, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
node.parentNode.removeChild(node);
|
||||
} catch (ex) {
|
||||
this.handleError('Error with \'' + value + '\'', ex);
|
||||
}
|
||||
} finally {
|
||||
this.scope.pop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Take a text node and replace it with another text node with the ${...}
|
||||
* sections parsed out. We replace the node by altering node.parentNode but
|
||||
* we could probably use a DOM Text API to achieve the same thing.
|
||||
* @param node The Text node to work on
|
||||
* @param data The data to use in calls to envEval
|
||||
*/
|
||||
Templater.prototype.processTextNode = function(node, data) {
|
||||
// Replace references in other attributes
|
||||
var value = node.data;
|
||||
// We can't use the string.replace() with function trick (see generic
|
||||
// attribute processing in processNode()) because we need to support
|
||||
// functions that return DOM nodes, so we can't have the conversion to a
|
||||
// string.
|
||||
// Instead we process the string as an array of parts. In order to split
|
||||
// the string up, we first replace '${' with '\uF001$' and '}' with '\uF002'
|
||||
// We can then split using \uF001 or \uF002 to get an array of strings
|
||||
// where scripts are prefixed with $.
|
||||
// \uF001 and \uF002 are just unicode chars reserved for private use.
|
||||
value = value.replace(/\$\{([^}]*)\}/g, '\uF001$$$1\uF002');
|
||||
var parts = value.split(/\uF001|\uF002/);
|
||||
if (parts.length > 1) {
|
||||
parts.forEach(function(part) {
|
||||
if (part === null || part === undefined || part === '') {
|
||||
return;
|
||||
}
|
||||
if (part.charAt(0) === '$') {
|
||||
part = this.envEval(part.slice(1), data, node.data);
|
||||
}
|
||||
// It looks like this was done a few lines above but see envEval
|
||||
if (part === null) {
|
||||
part = "null";
|
||||
}
|
||||
if (part === undefined) {
|
||||
part = "undefined";
|
||||
}
|
||||
// if (isDOMElement(part)) { ... }
|
||||
if (typeof part.cloneNode !== 'function') {
|
||||
part = node.ownerDocument.createTextNode(part.toString());
|
||||
}
|
||||
node.parentNode.insertBefore(part, node);
|
||||
}, this);
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Warn of string does not begin '${' and end '}'
|
||||
* @param str the string to check.
|
||||
* @return The string stripped of ${ and }, or untouched if it does not match
|
||||
*/
|
||||
Templater.prototype.stripBraces = function(str) {
|
||||
if (!str.match(/\$\{.*\}/g)) {
|
||||
this.handleError('Expected ' + str + ' to match ${...}');
|
||||
return str;
|
||||
}
|
||||
return str.slice(2, -1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Combined getter and setter that works with a path through some data set.
|
||||
* For example:
|
||||
* <ul>
|
||||
* <li>property('a.b', { a: { b: 99 }}); // returns 99
|
||||
* <li>property('a', { a: { b: 99 }}); // returns { b: 99 }
|
||||
* <li>property('a', { a: { b: 99 }}, 42); // returns 99 and alters the
|
||||
* input data to be { a: { b: 42 }}
|
||||
* </ul>
|
||||
* @param path An array of strings indicating the path through the data, or
|
||||
* a string to be cut into an array using <tt>split('.')</tt>
|
||||
* @param data An object to look in for the <tt>path</tt> argument
|
||||
* @param newValue (optional) If defined, this value will replace the
|
||||
* original value for the data at the path specified.
|
||||
* @return The value pointed to by <tt>path</tt> before any
|
||||
* <tt>newValue</tt> is applied.
|
||||
*/
|
||||
Templater.prototype.property = function(path, data, newValue) {
|
||||
this.scope.push(path);
|
||||
try {
|
||||
if (typeof path === 'string') {
|
||||
path = path.split('.');
|
||||
}
|
||||
var value = data[path[0]];
|
||||
if (path.length === 1) {
|
||||
if (newValue !== undefined) {
|
||||
data[path[0]] = newValue;
|
||||
}
|
||||
if (typeof value === 'function') {
|
||||
return value.bind(data);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (!value) {
|
||||
this.handleError('Can\'t find path=' + path);
|
||||
return null;
|
||||
}
|
||||
return this.property(path.slice(1), value, newValue);
|
||||
} finally {
|
||||
this.scope.pop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Like eval, but that creates a context of the variables in <tt>env</tt> in
|
||||
* which the script is evaluated.
|
||||
* WARNING: This script uses 'with' which is generally regarded to be evil.
|
||||
* The alternative is to create a Function at runtime that takes X parameters
|
||||
* according to the X keys in the env object, and then call that function using
|
||||
* the values in the env object. This is likely to be slow, but workable.
|
||||
* @param script The string to be evaluated.
|
||||
* @param env The environment in which to eval the script.
|
||||
* @param context Optional debugging string in case of failure
|
||||
* @return The return value of the script, or the error message if the script
|
||||
* execution failed.
|
||||
*/
|
||||
Templater.prototype.envEval = function(script, env, context) {
|
||||
with (env) {
|
||||
try {
|
||||
this.scope.push(context);
|
||||
return eval(script);
|
||||
} catch (ex) {
|
||||
this.handleError('Template error evaluating \'' + script + '\'', ex);
|
||||
return script;
|
||||
} finally {
|
||||
this.scope.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A generic way of reporting errors, for easy overloading in different
|
||||
* environments.
|
||||
* @param message the error message to report.
|
||||
* @param ex optional associated exception.
|
||||
*/
|
||||
Templater.prototype.handleError = function(message, ex) {
|
||||
this.logError(message);
|
||||
this.logError('In: ' + this.scope.join(' > '));
|
||||
if (ex) {
|
||||
this.logError(ex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A generic way of reporting errors, for easy overloading in different
|
||||
* environments.
|
||||
* @param message the error message to report.
|
||||
*/
|
||||
Templater.prototype.logError = function(message) {
|
||||
Services.console.logStringMessage(message);
|
||||
};
|
||||
|
|
@ -0,0 +1,842 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla Inspector Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker (jwalker@mozilla.com) (original author)
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PluralForm.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/CssLogic.jsm");
|
||||
Cu.import("resource:///modules/devtools/Templater.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["CssHtmlTree"];
|
||||
|
||||
/**
|
||||
* CssHtmlTree is a panel that manages the display of a table sorted by style.
|
||||
* There should be one instance of CssHtmlTree per style display (of which there
|
||||
* will generally only be one).
|
||||
*
|
||||
* @params {Document} aStyleWin The main XUL browser document
|
||||
* @params {CssLogic} aCssLogic How we dig into the CSS. See CssLogic.jsm
|
||||
* @constructor
|
||||
*/
|
||||
function CssHtmlTree(aStyleWin, aCssLogic, aPanel)
|
||||
{
|
||||
this.styleWin = aStyleWin;
|
||||
this.cssLogic = aCssLogic;
|
||||
this.doc = aPanel.ownerDocument;
|
||||
this.win = this.doc.defaultView;
|
||||
this.getRTLAttr = CssHtmlTree.getRTLAttr;
|
||||
|
||||
// The document in which we display the results (csshtmltree.xhtml).
|
||||
this.styleDocument = this.styleWin.contentWindow.document;
|
||||
|
||||
// Nodes used in templating
|
||||
this.root = this.styleDocument.getElementById("root");
|
||||
this.templateRoot = this.styleDocument.getElementById("templateRoot");
|
||||
this.panel = aPanel;
|
||||
|
||||
// The element that we're inspecting, and the document that it comes from.
|
||||
this.viewedElement = null;
|
||||
this.viewedDocument = null;
|
||||
|
||||
this.createStyleGroupViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* Memonized lookup of a l10n string from a string bundle.
|
||||
* @param {string} aName The key to lookup.
|
||||
* @returns A localized version of the given key.
|
||||
*/
|
||||
CssHtmlTree.l10n = function CssHtmlTree_l10n(aName)
|
||||
{
|
||||
try {
|
||||
return CssHtmlTree._strings.GetStringFromName(aName);
|
||||
} catch (ex) {
|
||||
Services.console.logStringMessage("Error reading '" + aName + "'");
|
||||
throw new Error("l10n error with " + aName);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone the given template node, and process it by resolving ${} references
|
||||
* in the template.
|
||||
*
|
||||
* @param {nsIDOMElement} aTemplate the template note to use.
|
||||
* @param {nsIDOMElement} aDestination the destination node where the
|
||||
* processed nodes will be displayed.
|
||||
* @param {object} aData the data to pass to the template.
|
||||
*/
|
||||
CssHtmlTree.processTemplate = function CssHtmlTree_processTemplate(aTemplate, aDestination, aData)
|
||||
{
|
||||
aDestination.innerHTML = "";
|
||||
|
||||
// All the templater does is to populate a given DOM tree with the given
|
||||
// values, so we need to clone the template first.
|
||||
let duplicated = aTemplate.cloneNode(true);
|
||||
new Templater().processNode(duplicated, aData);
|
||||
while (duplicated.firstChild) {
|
||||
aDestination.appendChild(duplicated.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether the UI is RTL
|
||||
* @return {Boolean} true or false
|
||||
*/
|
||||
CssHtmlTree.isRTL = function CssHtmlTree_isRTL()
|
||||
{
|
||||
return CssHtmlTree.getRTLAttr == "rtl";
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether the UI is RTL
|
||||
* @return {String} "ltr" or "rtl"
|
||||
*/
|
||||
XPCOMUtils.defineLazyGetter(CssHtmlTree, "getRTLAttr", function() {
|
||||
let mainWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
return mainWindow.getComputedStyle(mainWindow.gBrowser).direction;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
|
||||
.createBundle("chrome://browser/locale/styleinspector.properties"));
|
||||
|
||||
CssHtmlTree.prototype = {
|
||||
/**
|
||||
* Focus the output display on a specific element.
|
||||
* @param {nsIDOMElement} aElement The highlighted node to get styles for.
|
||||
*/
|
||||
highlight: function CssHtmlTree_highlight(aElement)
|
||||
{
|
||||
this.viewedElement = aElement;
|
||||
|
||||
// Reset the style groups. Without this previously expanded groups
|
||||
// will fail to expand when inspecting subsequent nodes
|
||||
let close = !aElement;
|
||||
this.styleGroups.forEach(function(group) group.reset(close));
|
||||
|
||||
if (this.viewedElement) {
|
||||
this.viewedDocument = this.viewedElement.ownerDocument;
|
||||
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
|
||||
} else {
|
||||
this.viewedDocument = null;
|
||||
this.root.innerHTML = "";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the user clicks on a parent element in the "current element"
|
||||
* path.
|
||||
*
|
||||
* @param {Event} aEvent the DOM Event object.
|
||||
*/
|
||||
pathClick: function CssHtmlTree_pathClick(aEvent)
|
||||
{
|
||||
aEvent.preventDefault();
|
||||
if (aEvent.target && aEvent.target.pathElement) {
|
||||
if (this.win.InspectorUI.selection) {
|
||||
if (aEvent.target.pathElement != this.win.InspectorUI.selection) {
|
||||
this.win.InspectorUI.inspectNode(aEvent.target.pathElement);
|
||||
}
|
||||
} else {
|
||||
this.panel.selectNode(aEvent.target.pathElement);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Provide access to the path to get from document.body to the selected
|
||||
* element.
|
||||
*
|
||||
* @return {array} the array holding the path from document.body to the
|
||||
* selected element.
|
||||
*/
|
||||
get pathElements()
|
||||
{
|
||||
return CssLogic.getShortNamePath(this.viewedElement);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns arrays of categorized properties.
|
||||
*/
|
||||
_getPropertiesByGroup: function CssHtmlTree_getPropertiesByGroup()
|
||||
{
|
||||
return {
|
||||
text: [
|
||||
"color", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"color-interpolation", //
|
||||
"color-interpolation-filters", //
|
||||
"direction", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"fill", //
|
||||
"fill-opacity", //
|
||||
"fill-rule", //
|
||||
"filter", //
|
||||
"flood-color", //
|
||||
"flood-opacity", //
|
||||
"font-family", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"font-size", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"font-size-adjust", // inherit http://www.w3.org/TR/WD-font/#font-size-props
|
||||
"font-stretch", // inherit http://www.w3.org/TR/WD-font/#font-stretch
|
||||
"font-style", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"font-variant", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"font-weight", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"ime-mode", //
|
||||
"letter-spacing", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"lighting-color", //
|
||||
"line-height", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"opacity", // no http://www.w3.org/TR/css3-color/#transparency
|
||||
"quotes", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"stop-color", //
|
||||
"stop-opacity", //
|
||||
"stroke-opacity", //
|
||||
"text-align", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"text-anchor", //
|
||||
"text-decoration", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"text-indent", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"text-overflow", //
|
||||
"text-rendering", // inherit http://www.w3.org/TR/SVG/painting.html#TextRenderingProperty !
|
||||
"text-shadow", // inherit http://www.w3.org/TR/css3-text/#text-shadow
|
||||
"text-transform", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"vertical-align", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"white-space", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"word-spacing", // inherit http://www.w3.org/TR/css3-text/#word-spacing
|
||||
"word-wrap", // inherit http://www.w3.org/TR/css3-text/#word-wrap
|
||||
"-moz-column-count", // no http://www.w3.org/TR/css3-multicol/#column-count
|
||||
"-moz-column-gap", // no http://www.w3.org/TR/css3-multicol/#column-gap
|
||||
"-moz-column-rule-color", // no http://www.w3.org/TR/css3-multicol/#crc
|
||||
"-moz-column-rule-style", // no http://www.w3.org/TR/css3-multicol/#column-rule-style
|
||||
"-moz-column-rule-width", // no http://www.w3.org/TR/css3-multicol/#column-rule-width
|
||||
"-moz-column-width", // no http://www.w3.org/TR/css3-multicol/#column-width
|
||||
"-moz-font-feature-settings", //
|
||||
"-moz-font-language-override", //
|
||||
"-moz-hyphens", //
|
||||
"-moz-text-decoration-color", //
|
||||
"-moz-text-decoration-style", //
|
||||
"-moz-text-decoration-line", //
|
||||
"-moz-text-blink", //
|
||||
"-moz-tab-size", //
|
||||
],
|
||||
list: [
|
||||
"list-style-image", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"list-style-position", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"list-style-type", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"marker-end", //
|
||||
"marker-mid", //
|
||||
"marker-offset", //
|
||||
"marker-start", //
|
||||
],
|
||||
background: [
|
||||
"background-attachment", // no http://www.w3.org/TR/css3-background/#background-attachment
|
||||
"background-clip", // no http://www.w3.org/TR/css3-background/#background-clip
|
||||
"background-color", // no http://www.w3.org/TR/css3-background/#background-color
|
||||
"background-image", // no http://www.w3.org/TR/css3-background/#background-image
|
||||
"background-origin", // no http://www.w3.org/TR/css3-background/#background-origin
|
||||
"background-position", // no http://www.w3.org/TR/css3-background/#background-position
|
||||
"background-repeat", // no http://www.w3.org/TR/css3-background/#background-repeat
|
||||
"background-size", // no http://www.w3.org/TR/css3-background/#background-size
|
||||
"-moz-appearance", //
|
||||
"-moz-background-inline-policy", //
|
||||
],
|
||||
dims: [
|
||||
"width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"height", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"max-width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"max-height", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"min-width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"min-height", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"margin-top", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"margin-right", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"margin-bottom", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"margin-left", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"padding-top", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"padding-right", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"padding-bottom", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"padding-left", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"clip", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"clip-path", //
|
||||
"clip-rule", //
|
||||
"resize", // no http://www.w3.org/TR/css3-ui/#resize
|
||||
"stroke-width", //
|
||||
"-moz-box-flex", //
|
||||
"-moz-box-sizing", // no http://www.w3.org/TR/css3-ui/#box-sizing
|
||||
],
|
||||
pos: [
|
||||
"top", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"right", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"bottom", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"left", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"display", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"float", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"clear", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"position", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"visibility", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"overflow", //
|
||||
"overflow-x", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"overflow-y", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"z-index", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"dominant-baseline", //
|
||||
"page-break-after", //
|
||||
"page-break-before", //
|
||||
"stroke-dashoffset", //
|
||||
"unicode-bidi", //
|
||||
"-moz-box-align", //
|
||||
"-moz-box-direction", //
|
||||
"-moz-box-ordinal-group", //
|
||||
"-moz-box-orient", //
|
||||
"-moz-box-pack", //
|
||||
"-moz-float-edge", //
|
||||
"-moz-orient", //
|
||||
"-moz-stack-sizing", //
|
||||
],
|
||||
border: [
|
||||
"border-top-width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-right-width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-bottom-width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-left-width", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-top-color", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-right-color", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-bottom-color", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-left-color", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-top-style", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-right-style", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-bottom-style", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-left-style", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-collapse", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"border-spacing", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"outline-offset", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"outline-style", //
|
||||
"outline-color", //
|
||||
"outline-width", //
|
||||
"border-top-left-radius", // no http://www.w3.org/TR/css3-background/#border-radius
|
||||
"border-top-right-radius", // no http://www.w3.org/TR/css3-background/#border-radius
|
||||
"border-bottom-right-radius", // no http://www.w3.org/TR/css3-background/#border-radius
|
||||
"border-bottom-left-radius", // no http://www.w3.org/TR/css3-background/#border-radius
|
||||
"-moz-border-bottom-colors", //
|
||||
"-moz-border-image", //
|
||||
"-moz-border-left-colors", //
|
||||
"-moz-border-right-colors", //
|
||||
"-moz-border-top-colors", //
|
||||
"-moz-outline-radius-topleft", // no http://www.w3.org/TR/CSS2/ui.html#dynamic-outlines ?
|
||||
"-moz-outline-radius-topright", // no http://www.w3.org/TR/CSS2/ui.html#dynamic-outlines ?
|
||||
"-moz-outline-radius-bottomright", // no http://www.w3.org/TR/CSS2/ui.html#dynamic-outlines ?
|
||||
"-moz-outline-radius-bottomleft", // no http://www.w3.org/TR/CSS2/ui.html#dynamic-outlines ?
|
||||
],
|
||||
other: [
|
||||
"box-shadow", // no http://www.w3.org/TR/css3-background/#box-shadow
|
||||
"caption-side", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"content", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"counter-increment", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"counter-reset", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"cursor", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"empty-cells", // inherit http://www.w3.org/TR/CSS21/propidx.html
|
||||
"image-rendering", // inherit http://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty
|
||||
"mask", //
|
||||
"pointer-events", // inherit http://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty
|
||||
"shape-rendering", //
|
||||
"stroke", //
|
||||
"stroke-dasharray", //
|
||||
"stroke-linecap", //
|
||||
"stroke-linejoin", //
|
||||
"stroke-miterlimit", //
|
||||
"table-layout", // no http://www.w3.org/TR/CSS21/propidx.html
|
||||
"-moz-animation-delay", //
|
||||
"-moz-animation-direction", //
|
||||
"-moz-animation-duration", //
|
||||
"-moz-animation-fill-mode", //
|
||||
"-moz-animation-iteration-count", //
|
||||
"-moz-animation-name", //
|
||||
"-moz-animation-play-state", //
|
||||
"-moz-animation-timing-function", //
|
||||
"-moz-backface-visibility", //
|
||||
"-moz-binding", //
|
||||
"-moz-force-broken-image-icon", //
|
||||
"-moz-image-region", //
|
||||
"-moz-perspective", //
|
||||
"-moz-perspective-origin", //
|
||||
"-moz-transform", // no http://www.w3.org/TR/css3-2d-transforms/#transform-property
|
||||
"-moz-transform-origin", //
|
||||
"-moz-transition-delay", //
|
||||
"-moz-transition-duration", //
|
||||
"-moz-transition-property", //
|
||||
"-moz-transition-timing-function", //
|
||||
"-moz-user-focus", // inherit http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-focus
|
||||
"-moz-user-input", // inherit http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-input
|
||||
"-moz-user-modify", // inherit http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-modify
|
||||
"-moz-user-select", // no http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-select
|
||||
"-moz-window-shadow", //
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* The CSS groups as displayed by the UI.
|
||||
*/
|
||||
createStyleGroupViews: function CssHtmlTree_createStyleGroupViews()
|
||||
{
|
||||
if (!CssHtmlTree.propertiesByGroup) {
|
||||
let pbg = CssHtmlTree.propertiesByGroup = this._getPropertiesByGroup();
|
||||
|
||||
// Add any supported properties that are not categorized to the "other" group
|
||||
let mergedArray = Array.concat(
|
||||
pbg.text,
|
||||
pbg.list,
|
||||
pbg.background,
|
||||
pbg.dims,
|
||||
pbg.pos,
|
||||
pbg.border,
|
||||
pbg.other
|
||||
);
|
||||
|
||||
// Here we build and cache a list of css properties supported by the browser
|
||||
// and store a list to check against. We could use any element but let's
|
||||
// use the inspector style panel
|
||||
let styles = this.styleWin.contentWindow.getComputedStyle(this.styleDocument.body);
|
||||
CssHtmlTree.supportedPropertyLookup = {};
|
||||
for (let i = 0, numStyles = styles.length; i < numStyles; i++) {
|
||||
let prop = styles.item(i);
|
||||
CssHtmlTree.supportedPropertyLookup[prop] = true;
|
||||
|
||||
if (mergedArray.indexOf(prop) == -1) {
|
||||
pbg.other.push(prop);
|
||||
}
|
||||
}
|
||||
|
||||
this.propertiesByGroup = CssHtmlTree.propertiesByGroup;
|
||||
}
|
||||
|
||||
let pbg = CssHtmlTree.propertiesByGroup;
|
||||
|
||||
// These group titles are localized by their ID. See the styleinspector.properties file.
|
||||
this.styleGroups = [
|
||||
new StyleGroupView(this, "Text_Fonts_and_Color", pbg.text),
|
||||
new StyleGroupView(this, "Lists", pbg.list),
|
||||
new StyleGroupView(this, "Background", pbg.background),
|
||||
new StyleGroupView(this, "Dimensions", pbg.dims),
|
||||
new StyleGroupView(this, "Positioning_and_Page_Flow", pbg.pos),
|
||||
new StyleGroupView(this, "Borders", pbg.border),
|
||||
new StyleGroupView(this, "Effects_and_Other", pbg.other),
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to give easy access to style group data from the template engine.
|
||||
*
|
||||
* @constructor
|
||||
* @param {CssHtmlTree} aTree the instance of the CssHtmlTree object that we are
|
||||
* working with.
|
||||
* @param {string} aId the style group ID.
|
||||
* @param {array} aPropertyNames the list of property names associated to this
|
||||
* style group view.
|
||||
*/
|
||||
function StyleGroupView(aTree, aId, aPropertyNames)
|
||||
{
|
||||
this.tree = aTree;
|
||||
this.id = aId;
|
||||
this.getRTLAttr = CssHtmlTree.getRTLAttr;
|
||||
this.localName = CssHtmlTree.l10n("group." + this.id);
|
||||
|
||||
this.propertyViews = [];
|
||||
aPropertyNames.forEach(function(aPropertyName) {
|
||||
if (this.isPropertySupported(aPropertyName)) {
|
||||
this.propertyViews.push(new PropertyView(this.tree, this, aPropertyName));
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.populated = false;
|
||||
|
||||
this.templateProperties = this.tree.styleDocument.getElementById("templateProperties");
|
||||
|
||||
// Populated by templater: parent element containing the open attribute
|
||||
this.element = null;
|
||||
// Destination for templateProperties.
|
||||
this.properties = null;
|
||||
}
|
||||
|
||||
StyleGroupView.prototype = {
|
||||
/**
|
||||
* The click event handler for the title of the style group view.
|
||||
*/
|
||||
click: function StyleGroupView_click()
|
||||
{
|
||||
// TODO: Animate opening/closing. See bug 587752.
|
||||
if (this.element.hasAttribute("open")) {
|
||||
this.element.removeAttribute("open");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.populated) {
|
||||
CssHtmlTree.processTemplate(this.templateProperties, this.properties, this);
|
||||
this.populated = true;
|
||||
}
|
||||
|
||||
this.element.setAttribute("open", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the style group view.
|
||||
*/
|
||||
close: function StyleGroupView_close()
|
||||
{
|
||||
if (this.element) {
|
||||
this.element.removeAttribute("open");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the style group view and its property views.
|
||||
*
|
||||
* @param {boolean} aClosePanel tells if the style panel is closing or not.
|
||||
*/
|
||||
reset: function StyleGroupView_reset(aClosePanel)
|
||||
{
|
||||
this.close();
|
||||
this.populated = false;
|
||||
for (let i = 0, numViews = this.propertyViews.length; i < numViews; i++) {
|
||||
this.propertyViews[i].reset();
|
||||
}
|
||||
|
||||
if (this.properties) {
|
||||
if (aClosePanel) {
|
||||
if (this.element) {
|
||||
this.element.removeChild(this.properties);
|
||||
}
|
||||
|
||||
this.properties = null;
|
||||
} else {
|
||||
while (this.properties.hasChildNodes()) {
|
||||
this.properties.removeChild(this.properties.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if a CSS property is supported
|
||||
*
|
||||
* @param {string} aProperty the CSS property to check for
|
||||
*
|
||||
* @return {boolean} true or false
|
||||
*/
|
||||
isPropertySupported: function(aProperty) {
|
||||
return aProperty && aProperty in CssHtmlTree.supportedPropertyLookup;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to give easy access to property data from the template engine.
|
||||
*
|
||||
* @constructor
|
||||
* @param {CssHtmlTree} aTree the CssHtmlTree instance we are working with.
|
||||
* @param {StyleGroupView} aGroup the StyleGroupView instance we are working
|
||||
* with.
|
||||
* @param {string} aName the CSS property name for which this PropertyView
|
||||
* instance will render the rules.
|
||||
*/
|
||||
function PropertyView(aTree, aGroup, aName)
|
||||
{
|
||||
this.tree = aTree;
|
||||
this.group = aGroup;
|
||||
this.name = aName;
|
||||
this.getRTLAttr = CssHtmlTree.getRTLAttr;
|
||||
|
||||
this.populated = false;
|
||||
this.showUnmatched = false;
|
||||
|
||||
this.link = "https://developer.mozilla.org/en/CSS/" + aName;
|
||||
|
||||
this.templateRules = this.tree.styleDocument.getElementById("templateRules");
|
||||
|
||||
// The parent element which contains the open attribute
|
||||
this.element = null;
|
||||
// Destination for templateRules.
|
||||
this.rules = null;
|
||||
|
||||
this.str = {};
|
||||
}
|
||||
|
||||
PropertyView.prototype = {
|
||||
/**
|
||||
* The click event handler for the property name of the property view. If
|
||||
* there are >0 rules then the rules are expanded. If there are 0 rules and
|
||||
* >0 unmatched rules then the unmatched rules are expanded instead.
|
||||
*
|
||||
* @param {Event} aEvent the DOM event
|
||||
*/
|
||||
click: function PropertyView_click(aEvent)
|
||||
{
|
||||
// Clicking on the property link itself is already handled
|
||||
if (aEvent.target.tagName.toLowerCase() == "a") {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Animate opening/closing. See bug 587752.
|
||||
if (this.element.hasAttribute("open")) {
|
||||
this.element.removeAttribute("open");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.populated) {
|
||||
let matchedRuleCount = this.propertyInfo.matchedRuleCount;
|
||||
|
||||
if (matchedRuleCount == 0 && this.showUnmatchedLink) {
|
||||
this.showUnmatchedLinkClick(aEvent);
|
||||
} else {
|
||||
CssHtmlTree.processTemplate(this.templateRules, this.rules, this);
|
||||
}
|
||||
this.populated = true;
|
||||
}
|
||||
this.element.setAttribute("open", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the computed style for the current property.
|
||||
*
|
||||
* @return {string} the computed style for the current property of the
|
||||
* currently highlighted element.
|
||||
*/
|
||||
get value()
|
||||
{
|
||||
return this.propertyInfo.value;
|
||||
},
|
||||
|
||||
/**
|
||||
* An easy way to access the CssPropertyInfo behind this PropertyView
|
||||
*/
|
||||
get propertyInfo()
|
||||
{
|
||||
return this.tree.cssLogic.getPropertyInfo(this.name);
|
||||
},
|
||||
|
||||
/**
|
||||
* Compute the title of the property view. The title includes the number of
|
||||
* rules that hold the current property.
|
||||
*
|
||||
* @param {nsIDOMElement} aElement reference to the DOM element where the rule
|
||||
* title needs to be displayed.
|
||||
* @return {string} The rule title.
|
||||
*/
|
||||
ruleTitle: function PropertyView_ruleTitle(aElement)
|
||||
{
|
||||
let result = "";
|
||||
let matchedRuleCount = this.propertyInfo.matchedRuleCount;
|
||||
|
||||
if (matchedRuleCount > 0) {
|
||||
aElement.classList.add("rule-count");
|
||||
|
||||
let str = CssHtmlTree.l10n("property.numberOfRules");
|
||||
result = PluralForm.get(matchedRuleCount, str).replace("#1", matchedRuleCount);
|
||||
} else if (this.showUnmatchedLink) {
|
||||
aElement.classList.add("rule-unmatched");
|
||||
|
||||
let unmatchedRuleCount = this.propertyInfo.unmatchedRuleCount;
|
||||
let str = CssHtmlTree.l10n("property.numberOfUnmatchedRules");
|
||||
result = PluralForm.get(unmatchedRuleCount, str).replace("#1", unmatchedRuleCount);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the property view.
|
||||
*/
|
||||
close: function PropertyView_close()
|
||||
{
|
||||
if (this.rules && this.element) {
|
||||
this.element.removeAttribute("open");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the property view.
|
||||
*/
|
||||
reset: function PropertyView_reset()
|
||||
{
|
||||
this.close();
|
||||
this.populated = false;
|
||||
this.showUnmatched = false;
|
||||
this.element = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Provide access to the SelectorViews that we are currently displaying
|
||||
*/
|
||||
get selectorViews()
|
||||
{
|
||||
var all = [];
|
||||
|
||||
function convert(aSelectorInfo) {
|
||||
all.push(new SelectorView(aSelectorInfo));
|
||||
}
|
||||
|
||||
this.propertyInfo.matchedSelectors.forEach(convert);
|
||||
if (this.showUnmatched) {
|
||||
this.propertyInfo.unmatchedSelectors.forEach(convert);
|
||||
}
|
||||
|
||||
return all;
|
||||
},
|
||||
|
||||
/**
|
||||
* Should we display a 'X unmatched rules' link?
|
||||
* @return {boolean} false if we are already showing the unmatched links or
|
||||
* if there are none to display, true otherwise.
|
||||
*/
|
||||
get showUnmatchedLink()
|
||||
{
|
||||
return !this.showUnmatched && this.propertyInfo.unmatchedRuleCount > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* The UI has a link to allow the user to display unmatched selectors.
|
||||
* This provides localized link text.
|
||||
*/
|
||||
get showUnmatchedLinkText()
|
||||
{
|
||||
let smur = CssHtmlTree.l10n("rule.showUnmatchedLink");
|
||||
let plural = PluralForm.get(this.propertyInfo.unmatchedRuleCount, smur);
|
||||
return plural.replace("#1", this.propertyInfo.unmatchedRuleCount);
|
||||
},
|
||||
|
||||
/**
|
||||
* The action when a user clicks the 'show unmatched' link.
|
||||
*/
|
||||
showUnmatchedLinkClick: function PropertyView_showUnmatchedLinkClick(aEvent)
|
||||
{
|
||||
this.showUnmatched = true;
|
||||
CssHtmlTree.processTemplate(this.templateRules, this.rules, this);
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to view us easy access to display data from a CssRule
|
||||
*/
|
||||
function SelectorView(aSelectorInfo)
|
||||
{
|
||||
this.selectorInfo = aSelectorInfo;
|
||||
this._cacheStatusNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode for cssInfo.rule.status
|
||||
* @see SelectorView.prototype._cacheStatusNames
|
||||
* @see CssLogic.STATUS
|
||||
*/
|
||||
SelectorView.STATUS_NAMES = [
|
||||
// "Unmatched", "Parent Match", "Matched", "Best Match"
|
||||
];
|
||||
|
||||
SelectorView.CLASS_NAMES = [
|
||||
"unmatched", "parentmatch", "matched", "bestmatch"
|
||||
];
|
||||
|
||||
SelectorView.prototype = {
|
||||
/**
|
||||
* Cache localized status names.
|
||||
*
|
||||
* These statuses are localized inside the styleinspector.properties string bundle.
|
||||
* @see CssLogic.jsm - the CssLogic.STATUS array.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
_cacheStatusNames: function SelectorView_cacheStatusNames()
|
||||
{
|
||||
if (SelectorView.STATUS_NAMES.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let status in CssLogic.STATUS) {
|
||||
let i = CssLogic.STATUS[status];
|
||||
if (i > -1) {
|
||||
let value = CssHtmlTree.l10n("rule.status." + status);
|
||||
// Replace normal spaces with non-breaking spaces
|
||||
SelectorView.STATUS_NAMES[i] = value.replace(/ /g, '\u00A0');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* A localized version of cssRule.status
|
||||
*/
|
||||
get statusText()
|
||||
{
|
||||
return SelectorView.STATUS_NAMES[this.selectorInfo.status];
|
||||
},
|
||||
|
||||
/**
|
||||
* Get class name for selector depending on status
|
||||
*/
|
||||
get statusClass()
|
||||
{
|
||||
return SelectorView.CLASS_NAMES[this.selectorInfo.status];
|
||||
},
|
||||
|
||||
/**
|
||||
* A localized Get localized human readable info
|
||||
*/
|
||||
humanReadableText: function SelectorView_humanReadableText(aElement)
|
||||
{
|
||||
if (CssHtmlTree.isRTL()) {
|
||||
return this.selectorInfo.value + " \u2190 " + this.text(aElement);
|
||||
} else {
|
||||
return this.text(aElement) + " \u2192 " + this.selectorInfo.value;
|
||||
}
|
||||
},
|
||||
|
||||
text: function SelectorView_text(aElement) {
|
||||
let result = this.selectorInfo.selector.text;
|
||||
if (this.selectorInfo.elementStyle) {
|
||||
if (this.selectorInfo.sourceElement == this.win.InspectorUI.selection) {
|
||||
result = "this";
|
||||
} else {
|
||||
result = CssLogic.getShortName(this.selectorInfo.sourceElement);
|
||||
aElement.parentNode.querySelector(".rule-link > a").
|
||||
addEventListener("click", function(aEvent) {
|
||||
this.win.InspectorUI.inspectNode(this.selectorInfo.sourceElement);
|
||||
aEvent.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
|
||||
result += ".style";
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is HUDService code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com> (Original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
DIRS += test
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
|
@ -0,0 +1,182 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla Inspector Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["StyleInspector"];
|
||||
|
||||
var StyleInspector = {
|
||||
/**
|
||||
* Is the Style Inspector enabled?
|
||||
* @returns {Boolean} true or false
|
||||
*/
|
||||
get isEnabled()
|
||||
{
|
||||
return Services.prefs.getBoolPref("devtools.styleinspector.enabled");
|
||||
},
|
||||
|
||||
createPanel: function SI_createPanel()
|
||||
{
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let popupSet = win.document.getElementById("mainPopupSet");
|
||||
let ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let panel = win.document.createElementNS(ns, "panel");
|
||||
|
||||
panel.setAttribute("orient", "vertical");
|
||||
panel.setAttribute("ignorekeys", "true");
|
||||
panel.setAttribute("noautofocus", "true");
|
||||
panel.setAttribute("noautohide", "true");
|
||||
panel.setAttribute("titlebar", "normal");
|
||||
panel.setAttribute("close", "true");
|
||||
panel.setAttribute("label", StyleInspector.l10n("panelTitle"));
|
||||
|
||||
// size panel to 200px wide by half browser height - 60.
|
||||
let contentWindow = win.gBrowser.selectedBrowser.contentWindow;
|
||||
panel.setAttribute("width", 200);
|
||||
panel.setAttribute("height", contentWindow.outerHeight / 2 - 60);
|
||||
|
||||
let vbox = win.document.createElement("vbox");
|
||||
vbox.setAttribute("flex", "1");
|
||||
panel.appendChild(vbox);
|
||||
|
||||
let iframe = win.document.createElementNS(ns, "iframe");
|
||||
iframe.setAttribute("flex", "1");
|
||||
iframe.setAttribute("tooltip", "aHTMLTooltip");
|
||||
iframe.setAttribute("src", "chrome://browser/content/csshtmltree.xhtml");
|
||||
vbox.appendChild(iframe);
|
||||
|
||||
let hbox = win.document.createElement("hbox");
|
||||
hbox.setAttribute("class", "resizerbox");
|
||||
vbox.appendChild(hbox);
|
||||
|
||||
let spacer = win.document.createElement("spacer");
|
||||
spacer.setAttribute("flex", "1");
|
||||
hbox.appendChild(spacer);
|
||||
|
||||
let resizer = win.document.createElement("resizer");
|
||||
resizer.setAttribute("dir", "bottomend");
|
||||
hbox.appendChild(resizer);
|
||||
popupSet.appendChild(panel);
|
||||
|
||||
panel.addEventListener("popupshown", function SI_popup_shown() {
|
||||
if (!this.cssHtmlTree) {
|
||||
this.cssLogic = new CssLogic();
|
||||
this.cssHtmlTree = new CssHtmlTree(iframe, this.cssLogic, this);
|
||||
}
|
||||
|
||||
this.cssLogic.highlight(this.selectedNode);
|
||||
this.cssHtmlTree.highlight(this.selectedNode);
|
||||
Services.obs.notifyObservers(null, "StyleInspector-opened", null);
|
||||
}, false);
|
||||
|
||||
panel.addEventListener("popuphidden", function SI_popup_hidden() {
|
||||
Services.obs.notifyObservers(null, "StyleInspector-closed", null);
|
||||
}, false);
|
||||
|
||||
/**
|
||||
* Check if the style inspector is open
|
||||
*/
|
||||
panel.isOpen = function SI_isOpen()
|
||||
{
|
||||
return this.state && this.state == "open";
|
||||
};
|
||||
|
||||
/**
|
||||
* Select a node to inspect in the Style Inspector panel
|
||||
*
|
||||
* @param aNode The node to inspect
|
||||
*/
|
||||
panel.selectNode = function SI_selectNode(aNode)
|
||||
{
|
||||
this.selectedNode = aNode;
|
||||
if (this.isOpen()) {
|
||||
this.cssLogic.highlight(aNode);
|
||||
this.cssHtmlTree.highlight(aNode);
|
||||
} else {
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
this.openPopup(win.gBrowser.selectedBrowser, "end_before", 0, 0, false, false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the Style Inspector initialized?
|
||||
* @returns {Boolean} true or false
|
||||
*/
|
||||
function isInitialized()
|
||||
{
|
||||
return panel.cssLogic && panel.cssHtmlTree;
|
||||
}
|
||||
|
||||
return panel;
|
||||
},
|
||||
|
||||
/**
|
||||
* Memonized lookup of a l10n string from a string bundle.
|
||||
* @param {string} aName The key to lookup.
|
||||
* @returns A localized version of the given key.
|
||||
*/
|
||||
l10n: function SI_l10n(aName)
|
||||
{
|
||||
try {
|
||||
return _strings.GetStringFromName(aName);
|
||||
} catch (ex) {
|
||||
Services.console.logStringMessage("Error reading '" + aName + "'");
|
||||
throw new Error("l10n error with " + aName);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_strings", function() Services.strings
|
||||
.createBundle("chrome://browser/locale/styleinspector.properties"));
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "CssLogic", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/CssLogic.jsm", tmp);
|
||||
return tmp.CssLogic;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "CssHtmlTree", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/CssHtmlTree.jsm", tmp);
|
||||
return tmp.CssHtmlTree;
|
||||
});
|
|
@ -0,0 +1,158 @@
|
|||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/styleinspector.dtd">
|
||||
%inspectorDTD;
|
||||
<!ELEMENT loop ANY>
|
||||
<!ATTLIST li foreach CDATA #IMPLIED>
|
||||
<!ATTLIST div foreach CDATA #IMPLIED>
|
||||
<!ATTLIST loop foreach CDATA #IMPLIED>
|
||||
<!ATTLIST a target CDATA #IMPLIED>
|
||||
<!ATTLIST a __pathElement CDATA #IMPLIED>
|
||||
<!ATTLIST div _id CDATA #IMPLIED>
|
||||
<!ATTLIST div save CDATA #IMPLIED>
|
||||
<!ATTLIST table save CDATA #IMPLIED>
|
||||
<!ATTLIST loop if CDATA #IMPLIED>
|
||||
<!ATTLIST tr if CDATA #IMPLIED>
|
||||
]>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is the Mozilla Inspector Module.
|
||||
-
|
||||
- The Initial Developer of the Original Code is The Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2011
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Joe Walker (jwalker@mozilla.com) (original author)
|
||||
- Mihai Șucan <mihai.sucan@gmail.com>
|
||||
- Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type"
|
||||
content="application/xhtml+xml; charset=UTF-8" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://browser/skin/devtools/csshtmltree.css" />
|
||||
</head>
|
||||
<body role="application">
|
||||
|
||||
<!-- The output from #templateRoot (below) is inserted here. -->
|
||||
<div id="root">
|
||||
</div>
|
||||
|
||||
<!--
|
||||
To visually debug the templates without running firefox, alter the display:none
|
||||
-->
|
||||
<div style="display:none;">
|
||||
<!--
|
||||
templateRoot sits at the top of the window showing what we're looking at.
|
||||
For data it needs an instance of CssHtmlTree.
|
||||
-->
|
||||
<div id="templateRoot">
|
||||
<p class="path">
|
||||
<label dir="${getRTLAttr}">&lookingAtLabel;</label>
|
||||
<ol>
|
||||
<li foreach="item in ${pathElements}" dir="${getRTLAttr}">
|
||||
<a href="#" onclick="${pathClick}" __pathElement="${item.element}">
|
||||
${__element.pathElement = item.element; item.display}
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
<div _id="groups">
|
||||
<div foreach="group in ${styleGroups}" class="group" save="${group.element}" dir="${getRTLAttr}">
|
||||
<h1 onclick="${group.click}" dir="${getRTLAttr}">
|
||||
${group.localName}
|
||||
<div class="groupexpander"></div>
|
||||
</h1>
|
||||
<div save="${group.properties}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
A templateProperties sits inside each templateGroups to show the properties
|
||||
themselves. Each needs data like this:
|
||||
{
|
||||
property: [ ..., ] // Array of PropertyViews from CssHtmlTree.jsm
|
||||
}
|
||||
-->
|
||||
<div id="templateProperties">
|
||||
<div foreach="property in ${propertyViews}" class="property-view" save="${property.element}" dir="${getRTLAttr}">
|
||||
<div class="property-header" onclick="${property.click}">
|
||||
<span class="property-name" dir="${getRTLAttr}">
|
||||
<a class="link" target="_blank" title="&helpLinkTitle;"
|
||||
href="${property.link}">${property.name}</a>
|
||||
</span>
|
||||
<span class="property-value" dir="ltr">${property.value}</span>
|
||||
<span class="link" dir="${getRTLAttr}">
|
||||
${property.ruleTitle(__element)}<div class="expander"></div>
|
||||
</span>
|
||||
</div>
|
||||
<table class="rules" save="${property.rules}" dir="${getRTLAttr}"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
A templateRules sits inside each templateProperties showing the list of rules
|
||||
that affect that property. Each needs data like this:
|
||||
{
|
||||
selectors: ..., // from cssLogic.getPropertyInfo(x).[un]matchedSelectors
|
||||
statusText: function(status) {}, // convert rule.status to readable text
|
||||
showUnmatchedRules: true / false, // show a "more unmatched rules" link
|
||||
showUnmatchedRulesClick: function() {}, // click event handler for the
|
||||
"show more unmatched rules"
|
||||
}
|
||||
This is a template so the parent does not need to be a table, except that
|
||||
using a div as the parent causes the DOM to muck with the tr elements
|
||||
-->
|
||||
<table id="templateRules">
|
||||
<loop foreach="selector in ${selectorViews}" if="${selector.selectorInfo.sheetAllowed}">
|
||||
<tr>
|
||||
<td dir="ltr" class="rule-text ${selector.statusClass}">
|
||||
${selector.humanReadableText(__element)}
|
||||
</td>
|
||||
<td class="rule-link">
|
||||
<a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
|
||||
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</loop>
|
||||
<tr if="${showUnmatchedLink}">
|
||||
<td colspan="4">
|
||||
<a href="#" onclick="${showUnmatchedLinkClick}"
|
||||
class="link">${showUnmatchedLinkText}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Style Inspector code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com> (Original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = browser
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Style Inspector code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com> (Original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = browser/devtools/styleinspector/test/browser
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_styleinspector.js \
|
||||
browser_styleinspector_webconsole.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
_BROWSER_TEST_PAGES = \
|
||||
browser_styleinspector_webconsole.htm \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
||||
libs:: $(_BROWSER_TEST_PAGES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
|
@ -0,0 +1,145 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the style inspector works properly
|
||||
|
||||
let doc;
|
||||
let stylePanel;
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
doc.body.innerHTML = '<style type="text/css"> ' +
|
||||
'span { font-variant: small-caps; color: #000000; } ' +
|
||||
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
|
||||
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
|
||||
'<h1>Some header text</h1>\n' +
|
||||
'<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
|
||||
'<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
|
||||
'solely to provide some things to <span style="color: yellow">' +
|
||||
'highlight</span> and <span style="font-weight: bold">count</span> ' +
|
||||
'style list-items in the box at right. If you are reading this, ' +
|
||||
'you should go do something else instead. Maybe read a book. Or better ' +
|
||||
'yet, write some test-cases for another bit of code. ' +
|
||||
'<span style="font-style: italic">Maybe more inspector test-cases!</span></p>\n' +
|
||||
'<p id="closing">end transmission</p>\n' +
|
||||
'<p>Inspect using inspectstyle(document.querySelectorAll("span")[0])</p>' +
|
||||
'</div>';
|
||||
doc.title = "Style Inspector Test";
|
||||
ok(window.StyleInspector, "StyleInspector exists");
|
||||
ok(StyleInspector.isEnabled, "style inspector preference is enabled");
|
||||
stylePanel = StyleInspector.createPanel();
|
||||
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
|
||||
stylePanel.openPopup(gBrowser.selectedBrowser, "end_before", 0, 0, false, false);
|
||||
}
|
||||
|
||||
function runStyleInspectorTests()
|
||||
{
|
||||
Services.obs.removeObserver(runStyleInspectorTests, "StyleInspector-opened", false);
|
||||
|
||||
ok(stylePanel.isOpen(), "style inspector is open");
|
||||
|
||||
checkForNewProperties();
|
||||
|
||||
var spans = doc.querySelectorAll("span");
|
||||
ok(spans, "captain, we have the spans");
|
||||
|
||||
let htmlTree = stylePanel.cssHtmlTree;
|
||||
|
||||
for (var i = 0, numSpans = spans.length; i < numSpans; i++) {
|
||||
stylePanel.selectNode(spans[i]);
|
||||
|
||||
is(spans[i], htmlTree.viewedElement,
|
||||
"style inspector node matches the selected node");
|
||||
is(htmlTree.viewedElement, stylePanel.cssLogic.viewedElement,
|
||||
"cssLogic node matches the cssHtmlTree node");
|
||||
|
||||
// The Fonts and Color group.
|
||||
ok(groupRuleCount(0) > 0, "we have rules for the current span");
|
||||
}
|
||||
|
||||
SI_CheckProperty();
|
||||
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
|
||||
stylePanel.hidePopup();
|
||||
}
|
||||
|
||||
function checkForNewProperties()
|
||||
{
|
||||
let htmlTree = stylePanel.cssHtmlTree;
|
||||
htmlTree.createStyleGroupViews();
|
||||
let otherProps = htmlTree._getPropertiesByGroup().other;
|
||||
let otherPlusUnknownProps = htmlTree.propertiesByGroup.other;
|
||||
|
||||
let missingProps = [];
|
||||
for each (let prop in otherPlusUnknownProps) {
|
||||
if (otherProps.indexOf(prop) == -1) {
|
||||
missingProps.push(prop);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingProps.length > 0) {
|
||||
let n = 1;
|
||||
let msg = "The following css properties need to be categorized in " +
|
||||
"CssHtmlTree.getPropertiesByGroup():\r\n";
|
||||
missingProps.forEach(function BSI_buildMissingProps(aProp) {
|
||||
msg += " " + (n++) + ". " + aProp + "\n";
|
||||
});
|
||||
ok(false, msg);
|
||||
}
|
||||
}
|
||||
|
||||
function SI_CheckProperty()
|
||||
{
|
||||
let group = stylePanel.cssHtmlTree.styleGroups[0];
|
||||
let cssLogic = stylePanel.cssLogic;
|
||||
|
||||
let propertyInfo = cssLogic.getPropertyInfo("color");
|
||||
ok(propertyInfo.matchedRuleCount > 0, "color property has matching rules");
|
||||
ok(propertyInfo.unmatchedRuleCount > 0, "color property has unmatched rules");
|
||||
}
|
||||
|
||||
function groupRuleCount(groupId)
|
||||
{
|
||||
let groupRules = 0;
|
||||
let group = stylePanel.cssHtmlTree.styleGroups[groupId];
|
||||
|
||||
ok(group, "we have a StyleGroupView");
|
||||
ok(group.tree, "we have the CssHtmlTree object");
|
||||
|
||||
let cssLogic = stylePanel.cssLogic;
|
||||
|
||||
ok(cssLogic, "we have the CssLogic object");
|
||||
|
||||
// we use the click method to populate the groups properties
|
||||
group.click();
|
||||
|
||||
ok(group.properties.childElementCount > 0, "the StyleGroupView has properties");
|
||||
|
||||
group.propertyViews.forEach(function(property) {
|
||||
groupRules += cssLogic.getPropertyInfo(property.name).matchedRuleCount;
|
||||
});
|
||||
|
||||
return groupRules;
|
||||
}
|
||||
|
||||
function finishUp()
|
||||
{
|
||||
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
|
||||
ok(!stylePanel.isOpen(), "style inspector is closed");
|
||||
doc = stylePanel = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,basic style inspector tests";
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
|
||||
<title>Style inspector test</title>
|
||||
<style>
|
||||
.text {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.container > .text {
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
.text2 {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.text3 {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.text[dir=rtl] {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.container .text {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
#container .text {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
.container > .text {
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
#container > .text {
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
#container > .dummy, #container > .dummy2 {
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
div {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
#container {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
#container > span {
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
#container .dummy {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
html + .dummy {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
span + span {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
span[id=text] {
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
span[att=glue] {
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
span::before {
|
||||
font-family: cursive;
|
||||
content: "START ";
|
||||
}
|
||||
|
||||
span::after {
|
||||
font-family: cursive;
|
||||
content: " END";
|
||||
}
|
||||
|
||||
spawn::before {
|
||||
font-family: cursive;
|
||||
content: "START ";
|
||||
}
|
||||
|
||||
spawn::after {
|
||||
font-family: cursive;
|
||||
content: " END";
|
||||
}
|
||||
|
||||
a:link {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.link:link {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.link:visited {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
a:active {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.link:active {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
font-family: sans-serif;
|
||||
outline: 5px solid #0f0;
|
||||
}
|
||||
|
||||
.link:focus {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
span::first-letter {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.text::first-letter {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
span::first-line {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.text::first-line {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
#container:first-child {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div:first-child {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
span:lang(en) {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
span:lang(it) {
|
||||
font-family: fantasy;
|
||||
}
|
||||
|
||||
html::selection {
|
||||
background-color: #f00;
|
||||
font-family: fantasy;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>font-size</h2>
|
||||
<div id="container">
|
||||
<span id="text" lang="en" class="text">Use inspectstyle($('text')) to inspect me</span><br />
|
||||
<span id="text2" class="text2">Use inspectstyle($('text2'))</span><br />
|
||||
<a class="link" href="#">Some Link</a>
|
||||
<h2>font-family has a single unmatched rule</h2>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,194 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DevTools test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Tests that inspectstyle(node) works properly
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/test/browser/browser_styleinspector_webconsole.htm";
|
||||
|
||||
let doc;
|
||||
let jsterm;
|
||||
let hudBox;
|
||||
let stylePanels = [];
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", prepConsole, false);
|
||||
}
|
||||
|
||||
function prepConsole() {
|
||||
browser.removeEventListener("DOMContentLoaded", prepConsole, false);
|
||||
doc = content.document;
|
||||
openConsole();
|
||||
|
||||
ok(window.StyleInspector, "StyleInspector exists");
|
||||
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
ok(hud, "we have a console");
|
||||
|
||||
hudBox = hud.HUDBox;
|
||||
ok(hudBox, "we have the console display");
|
||||
|
||||
jsterm = hud.jsterm;
|
||||
ok(jsterm, "we have a jsterm");
|
||||
|
||||
openStyleInspector1();
|
||||
}
|
||||
|
||||
function openStyleInspector1() {
|
||||
info("opening style inspector instance 1");
|
||||
Services.obs.addObserver(openStyleInspector2, "StyleInspector-opened", false);
|
||||
jsterm.execute("inspectstyle($('text'))");
|
||||
}
|
||||
|
||||
function openStyleInspector2() {
|
||||
Services.obs.removeObserver(openStyleInspector2, "StyleInspector-opened", false);
|
||||
info("opening style inspector instance 2");
|
||||
Services.obs.addObserver(openStyleInspector3, "StyleInspector-opened", false);
|
||||
jsterm.execute("inspectstyle($('text2'))");
|
||||
}
|
||||
|
||||
function openStyleInspector3() {
|
||||
Services.obs.removeObserver(openStyleInspector3, "StyleInspector-opened", false);
|
||||
info("opening style inspector instance 3");
|
||||
Services.obs.addObserver(teststylePanels, "StyleInspector-opened", false);
|
||||
jsterm.execute("inspectstyle($('container'))");
|
||||
}
|
||||
|
||||
function teststylePanels() {
|
||||
Services.obs.removeObserver(teststylePanels, "StyleInspector-opened", false);
|
||||
|
||||
info("adding style inspector instances to stylePanels array");
|
||||
let popupSet = document.getElementById("mainPopupSet");
|
||||
let len = popupSet.childNodes.length - 3;
|
||||
stylePanels.push(popupSet.childNodes[len++]);
|
||||
stylePanels.push(popupSet.childNodes[len++]);
|
||||
stylePanels.push(popupSet.childNodes[len++]);
|
||||
|
||||
let eltArray = [
|
||||
doc.getElementById("text"),
|
||||
doc.getElementById("text2"),
|
||||
doc.getElementById("container")
|
||||
];
|
||||
|
||||
info("looping through array to check initialization");
|
||||
for (let i = 0, max = stylePanels.length; i < max; i++) {
|
||||
ok(stylePanels[i], "style inspector instance " + i +
|
||||
" correctly initialized");
|
||||
ok(stylePanels[i].isOpen(), "style inspector " + i + " is open");
|
||||
|
||||
let htmlTree = stylePanels[i].cssHtmlTree;
|
||||
|
||||
is(eltArray[i], htmlTree.viewedElement,
|
||||
"style inspector node matches the selected node (id=" +
|
||||
eltArray[i].id + ")");
|
||||
is(htmlTree.viewedElement, stylePanels[i].cssLogic.viewedElement,
|
||||
"cssLogic node matches the cssHtmlTree node (id=" + eltArray[i].id + ")");
|
||||
|
||||
ok(groupRuleCount(0, stylePanels[i]) > 0,
|
||||
"we have rules for the current node (id=" + eltArray[i].id + ")");
|
||||
}
|
||||
|
||||
info("hiding stylePanels[1]");
|
||||
Services.obs.addObserver(styleInspectorClosedByHide,
|
||||
"StyleInspector-closed", false);
|
||||
stylePanels[1].hidePopup();
|
||||
}
|
||||
|
||||
function styleInspectorClosedByHide()
|
||||
{
|
||||
Services.obs.removeObserver(styleInspectorClosedByHide, "StyleInspector-closed", false);
|
||||
ok(stylePanels[0].isOpen(), "instance stylePanels[0] is still open");
|
||||
ok(!stylePanels[1].isOpen(), "instance stylePanels[1] is hidden");
|
||||
ok(stylePanels[2].isOpen(), "instance stylePanels[2] is still open");
|
||||
|
||||
info("closing web console");
|
||||
Services.obs.addObserver(styleInspectorClosedFromConsole1,
|
||||
"StyleInspector-closed", false);
|
||||
closeConsole();
|
||||
}
|
||||
|
||||
function styleInspectorClosedFromConsole1()
|
||||
{
|
||||
Services.obs.removeObserver(styleInspectorClosedFromConsole1,
|
||||
"StyleInspector-closed", false);
|
||||
info("Style Inspector 1 closed");
|
||||
Services.obs.addObserver(styleInspectorClosedFromConsole2,
|
||||
"StyleInspector-closed", false);
|
||||
}
|
||||
|
||||
function styleInspectorClosedFromConsole2()
|
||||
{
|
||||
Services.obs.removeObserver(styleInspectorClosedFromConsole2,
|
||||
"StyleInspector-closed", false);
|
||||
info("Style Inspector 2 closed");
|
||||
executeSoon(cleanUp);
|
||||
}
|
||||
|
||||
function cleanUp()
|
||||
{
|
||||
let popupSet = document.getElementById("mainPopupSet");
|
||||
ok(!popupSet.lastChild.hasAttribute("hudToolId"),
|
||||
"all style inspector panels are now detached and ready for garbage collection");
|
||||
|
||||
info("cleaning up");
|
||||
doc = hudBox = stylePanels = jsterm = null;
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function groupRuleCount(groupId, aStylePanel)
|
||||
{
|
||||
let groupRules = 0;
|
||||
let group = aStylePanel.cssHtmlTree.styleGroups[groupId];
|
||||
|
||||
ok(group, "we have a StyleGroupView");
|
||||
ok(group.tree, "we have the CssHtmlTree object");
|
||||
|
||||
let cssLogic = aStylePanel.cssLogic;
|
||||
|
||||
ok(cssLogic, "we have the CssLogic object");
|
||||
|
||||
// we use the click event to populate the groups properties
|
||||
group.click();
|
||||
|
||||
ok(group.properties.childElementCount > 0, "the StyleGroupView has properties");
|
||||
|
||||
group.propertyViews.forEach(function(property) {
|
||||
groupRules += cssLogic.getPropertyInfo(property.name).matchedRuleCount;
|
||||
});
|
||||
|
||||
return groupRules;
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DevTools test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Cu.import("resource:///modules/devtools/StyleInspector.jsm");
|
||||
Cu.import("resource://gre/modules/HUDService.jsm");
|
||||
|
||||
function log(aMsg)
|
||||
{
|
||||
dump("*** WebConsoleTest: " + aMsg + "\n");
|
||||
}
|
||||
|
||||
function pprint(aObj)
|
||||
{
|
||||
for (let prop in aObj) {
|
||||
if (typeof aObj[prop] == "function") {
|
||||
log("function " + prop);
|
||||
}
|
||||
else {
|
||||
log(prop + ": " + aObj[prop]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tab, browser, hudId, hud, hudBox, filterBox, outputNode, cs;
|
||||
|
||||
function addTab(aURL)
|
||||
{
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
content.location = aURL;
|
||||
tab = gBrowser.selectedTab;
|
||||
browser = gBrowser.getBrowserForTab(tab);
|
||||
}
|
||||
|
||||
function afterAllTabsLoaded(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let stillToLoad = 0;
|
||||
|
||||
function onLoad() {
|
||||
this.removeEventListener("load", onLoad, true);
|
||||
stillToLoad--;
|
||||
if (!stillToLoad)
|
||||
callback();
|
||||
}
|
||||
|
||||
for (let a = 0; a < win.gBrowser.tabs.length; a++) {
|
||||
let browser = win.gBrowser.tabs[a].linkedBrowser;
|
||||
if (browser.contentDocument.readyState != "complete") {
|
||||
stillToLoad++;
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!stillToLoad)
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a log entry exists in the HUD output node.
|
||||
*
|
||||
* @param {Element} aOutputNode
|
||||
* the HUD output node.
|
||||
* @param {string} aMatchString
|
||||
* the string you want to check if it exists in the output node.
|
||||
* @param {string} aMsg
|
||||
* the message describing the test
|
||||
* @param {boolean} [aOnlyVisible=false]
|
||||
* find only messages that are visible, not hidden by the filter.
|
||||
* @param {boolean} [aFailIfFound=false]
|
||||
* fail the test if the string is found in the output node.
|
||||
* @param {string} aClass [optional]
|
||||
* find only messages with the given CSS class.
|
||||
*/
|
||||
function testLogEntry(aOutputNode, aMatchString, aMsg, aOnlyVisible,
|
||||
aFailIfFound, aClass)
|
||||
{
|
||||
let selector = ".hud-msg-node";
|
||||
// Skip entries that are hidden by the filter.
|
||||
if (aOnlyVisible) {
|
||||
selector += ":not(.hud-filtered-by-type)";
|
||||
}
|
||||
if (aClass) {
|
||||
selector += "." + aClass;
|
||||
}
|
||||
|
||||
let msgs = aOutputNode.querySelectorAll(selector);
|
||||
let found = false;
|
||||
for (let i = 0, n = msgs.length; i < n; i++) {
|
||||
let message = msgs[i].textContent.indexOf(aMatchString);
|
||||
if (message > -1) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Search the labels too.
|
||||
let labels = msgs[i].querySelectorAll("label");
|
||||
for (let j = 0; j < labels.length; j++) {
|
||||
if (labels[j].getAttribute("value").indexOf(aMatchString) > -1) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is(found, !aFailIfFound, aMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method to call testLogEntry().
|
||||
*
|
||||
* @param string aString
|
||||
* The string to find.
|
||||
*/
|
||||
function findLogEntry(aString)
|
||||
{
|
||||
testLogEntry(outputNode, aString, "found " + aString);
|
||||
}
|
||||
|
||||
function openConsole()
|
||||
{
|
||||
HUDService.activateHUDForContext(tab);
|
||||
}
|
||||
|
||||
function closeConsole()
|
||||
{
|
||||
HUDService.deactivateHUDForContext(tab);
|
||||
}
|
||||
|
||||
function finishTest()
|
||||
{
|
||||
finish();
|
||||
}
|
||||
|
||||
function tearDown()
|
||||
{
|
||||
try {
|
||||
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
|
||||
}
|
||||
catch (ex) {
|
||||
log(ex);
|
||||
}
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
tab = browser = hudId = hud = filterBox = outputNode = cs = null;
|
||||
}
|
||||
|
||||
registerCleanupFunction(tearDown);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
* Julian Viereck <jviereck@mozilla.com>
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -71,6 +72,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
|||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/devtools/StyleInspector.jsm", obj);
|
||||
return obj.StyleInspector;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm", obj);
|
||||
|
@ -1776,6 +1783,11 @@ HUD_SERVICE.prototype =
|
|||
for (let i = 0; i < panels.length; i++) {
|
||||
panels[i].hidePopup();
|
||||
}
|
||||
panels = popupset.querySelectorAll("panel[hudToolId=" + aHUDId + "]");
|
||||
for (let i = 0; i < panels.length; i++) {
|
||||
panels[i].hidePopup();
|
||||
popupset.removeChild(panels[i]);
|
||||
}
|
||||
|
||||
let id = ConsoleUtils.supString(aHUDId);
|
||||
Services.obs.notifyObservers(id, "web-console-destroyed", null);
|
||||
|
@ -4396,6 +4408,37 @@ function JSTermHelper(aJSTerm)
|
|||
propPanel.panel.setAttribute("hudId", aJSTerm.hudId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inspects the passed aNode in the style inspector.
|
||||
*
|
||||
* @param object aNode
|
||||
* aNode to inspect.
|
||||
* @returns void
|
||||
*/
|
||||
aJSTerm.sandbox.inspectstyle = function JSTH_inspectstyle(aNode)
|
||||
{
|
||||
let errstr = null;
|
||||
aJSTerm.helperEvaluated = true;
|
||||
|
||||
if (!Services.prefs.getBoolPref("devtools.styleinspector.enabled")) {
|
||||
errstr = HUDService.getStr("inspectStyle.styleInspectorNotEnabled");
|
||||
} else if (!aNode) {
|
||||
errstr = HUDService.getStr("inspectStyle.nullObjectPassed");
|
||||
} else if (!(aNode instanceof Ci.nsIDOMNode)) {
|
||||
errstr = HUDService.getStr("inspectStyle.mustBeDomNode");
|
||||
} else if (!(aNode.style instanceof Ci.nsIDOMCSSStyleDeclaration)) {
|
||||
errstr = HUDService.getStr("inspectStyle.nodeHasNoStyleProps");
|
||||
}
|
||||
|
||||
if (!errstr) {
|
||||
let stylePanel = StyleInspector.createPanel();
|
||||
stylePanel.setAttribute("hudToolId", aJSTerm.hudId);
|
||||
stylePanel.selectNode(aNode, true);
|
||||
} else {
|
||||
aJSTerm.writeOutput(errstr + "\n", CATEGORY_OUTPUT, SEVERITY_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Prints aObject to the output.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!-- LOCALIZATION NOTE (lookingAtLabel): This is the label for the path of
|
||||
- the highlighted element in the web page. This path is based on the document
|
||||
- tree. -->
|
||||
<!ENTITY lookingAtLabel "Looking at:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (helpLinkTitle): For each style property
|
||||
- the user can hover it and get a help link button which allows one to
|
||||
- quickly jump to the documentation from the Mozilla Developer Network site.
|
||||
- This is the link title shown in the hover tooltip. -->
|
||||
<!ENTITY helpLinkTitle "Read the documentation for this property">
|
|
@ -0,0 +1,53 @@
|
|||
# LOCALIZATION NOTE These strings are used inside the Style Inspector.
|
||||
|
||||
# LOCALIZATION NOTE (panelTitle): This is the panel title
|
||||
panelTitle=Style Inspector
|
||||
|
||||
# LOCALIZATION NOTE (property.numberOfRules): For each style property the panel
|
||||
# shows the number of rules which hold that specific property, counted from all
|
||||
# of the stylesheets in the web page inspected.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
property.numberOfRules=#1 rule;#1 rules
|
||||
|
||||
# LOCALIZATION NOTE (property.numberOfUnmatchedRules): Each style property is
|
||||
# inside a rule. A rule is a selector that can match (or not) the highlighted
|
||||
# element in the web page. The property view shows no unmatched rules. If the
|
||||
# user wants to expand the property to view unmatched rules, he/she must click
|
||||
# this link displayed to the right of each property.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
property.numberOfUnmatchedRules=One unmatched rule;#1 unmatched rules
|
||||
|
||||
# LOCALIZATION NOTE (rule.status): For each style property the panel shows
|
||||
# the rules which hold that specific property. For every rule, the rule status
|
||||
# is also displayed: a rule can be the best match, a match, a parent match, or a
|
||||
# rule did not match the element the user has highlighted.
|
||||
rule.status.BEST=Best Match
|
||||
rule.status.MATCHED=Matched
|
||||
rule.status.PARENT_MATCH=Parent Match
|
||||
rule.status.UNMATCHED=Unmatched
|
||||
|
||||
# LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline): For each
|
||||
# style property the panel shows the rules which hold that specific property.
|
||||
# For every rule, the rule source is also displayed: a rule can come from a
|
||||
# file, from the same page (inline), or from the element itself (element).
|
||||
rule.sourceInline=inline
|
||||
rule.sourceElement=element
|
||||
|
||||
# LOCALIZATION NOTE (rule.showUnmatchedLink): Each style property
|
||||
# is inside a rule. A rule is a selector that can match (or not) the highlighted
|
||||
# element in the web page. The property view shows only a few of the unmatched
|
||||
# rules. If the user wants to see all of the unmatched rules, he/she must click
|
||||
# the link displayed at the bottom of the rules table. That link shows how many
|
||||
# rules are not displayed. This is the string used when the link is generated.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
rule.showUnmatchedLink=One unmatched rule...;#1 unmatched rules...
|
||||
|
||||
# LOCALIZATION NOTE (group): Style properties are displayed in categories and
|
||||
# these are the category names.
|
||||
group.Text_Fonts_and_Color=Text, Fonts & Color
|
||||
group.Background=Background
|
||||
group.Dimensions=Dimensions
|
||||
group.Positioning_and_Page_Flow=Positioning and Page Flow
|
||||
group.Borders=Borders
|
||||
group.Lists=Lists
|
||||
group.Effects_and_Other=Effects and Other
|
|
@ -14,6 +14,8 @@
|
|||
* locale/browser/browser.dtd (%chrome/browser/browser.dtd)
|
||||
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
|
||||
locale/browser/browser.properties (%chrome/browser/browser.properties)
|
||||
locale/browser/styleinspector.properties (%chrome/browser/styleinspector.properties)
|
||||
locale/browser/styleinspector.dtd (%chrome/browser/styleinspector.dtd)
|
||||
locale/browser/scratchpad.properties (%chrome/browser/scratchpad.properties)
|
||||
locale/browser/scratchpad.dtd (%chrome/browser/scratchpad.dtd)
|
||||
locale/browser/inspector.properties (%chrome/browser/inspector.properties)
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 933 B |
|
@ -0,0 +1,236 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla Inspector Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
body {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.path {
|
||||
font-size: 11px;
|
||||
word-spacing: -1px;
|
||||
}
|
||||
.path ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.path li {
|
||||
border-radius: 3px;
|
||||
padding: 2px 3px;
|
||||
text-shadow: #FFF 0 1px 0;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
background: -moz-linear-gradient(top, #F6F6FF, #E3E3FF);
|
||||
display: inline-block;
|
||||
}
|
||||
.path li:after {
|
||||
content: " > ";
|
||||
}
|
||||
.path li:last-child {
|
||||
background: -moz-linear-gradient(top, #FFC, #DD8);
|
||||
}
|
||||
.path li:last-child:after {
|
||||
color: red;
|
||||
content: "";
|
||||
}
|
||||
|
||||
#sheetList, #sheetList menuitem {
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.sheet_line input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.sheet_line label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#header, #footer {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
#sheets {
|
||||
-moz-margin-end: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 13px;
|
||||
padding: 2px 10px;
|
||||
margin: 0;
|
||||
background: -moz-linear-gradient(top, #CCC, #AAA);
|
||||
border-radius: 3px;
|
||||
text-shadow: #FFF 0 1px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.property-header {
|
||||
padding: 2px 5px;
|
||||
background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.property-name, .property-value, .rule-count, .rule-unmatched {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Take away these two :visited rules to get a core dumper */
|
||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
||||
.link { color: #55A; }
|
||||
.link:visited { color: #55A; }
|
||||
a.link { text-decoration: none; cursor: pointer }
|
||||
a.link:visited { text-decoration: none; }
|
||||
.rule-count, .rule-unmatched {
|
||||
float: right;
|
||||
}
|
||||
.rule-count[dir="rtl"], .rule-unmatched[dir="rtl"] {
|
||||
float: left;
|
||||
}
|
||||
.property-view .rule-count .expander,
|
||||
.property-view .rule-unmatched .expander {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
-moz-margin-start: 5px;
|
||||
display: inline-block;
|
||||
background: url("chrome://browser/skin/devtools/arrows.png");
|
||||
}
|
||||
|
||||
.property-view .rule-count .expander,
|
||||
.property-view .rule-unmatched .expander {
|
||||
background-position: 24px 0;
|
||||
}
|
||||
.property-view[dir="rtl"] .rule-count .expander,
|
||||
.property-view[dir="rtl"] .rule-unmatched .expander {
|
||||
background-position: 16px 0;
|
||||
}
|
||||
.property-view[open] .rule-count .expander,
|
||||
.property-view[open] .rule-unmatched .expander {
|
||||
background-position: 8px 0;
|
||||
}
|
||||
|
||||
.property-name {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
-moz-padding-end: 4px;
|
||||
color: #000;
|
||||
}
|
||||
span.property-value {
|
||||
-moz-padding-end: 5px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.group {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.group > h1 {
|
||||
color: #333;
|
||||
font-size: 11px;
|
||||
}
|
||||
.group .groupexpander {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-top: 2px;
|
||||
background: url("chrome://browser/skin/devtools/arrows.png");
|
||||
}
|
||||
.group > div {
|
||||
display: none;
|
||||
}
|
||||
.group[open] > div {
|
||||
display: block;
|
||||
}
|
||||
.group .groupexpander {
|
||||
background-position: 48px 0;
|
||||
float: right;
|
||||
}
|
||||
.group[dir="rtl"] .groupexpander {
|
||||
background-position: 40px 0;
|
||||
float: left;
|
||||
}
|
||||
.group[open] .groupexpander {
|
||||
background-position: 32px 0;
|
||||
float: right;
|
||||
}
|
||||
.group[open][dir="rtl"] .groupexpander {
|
||||
background-position: 32px 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.group, #header, #footer {
|
||||
background: #FFF;
|
||||
border: 1px solid #E1E1E1;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
}
|
||||
|
||||
.property-view > .rules {
|
||||
display: none;
|
||||
}
|
||||
.property-view[open] > .rules {
|
||||
display: table;
|
||||
}
|
||||
.rules {
|
||||
max-height: 350px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.rule-specificty, .rule-status {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rule-link {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||
.rule-text {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.resizerbox {
|
||||
background-color: window;
|
||||
}
|
||||
|
||||
.bestmatch { color: black; }
|
||||
.matched { text-decoration: line-through; }
|
||||
.parentmatch { color: #666; }
|
||||
.unmatched { color: brown; }
|
|
@ -84,6 +84,8 @@ browser.jar:
|
|||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 933 B |
|
@ -0,0 +1,236 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla Inspector Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
body {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.path {
|
||||
font-size: 11px;
|
||||
word-spacing: -1px;
|
||||
}
|
||||
.path ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.path li {
|
||||
border-radius: 3px;
|
||||
padding: 2px 3px;
|
||||
text-shadow: #FFF 0 1px 0;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
background: -moz-linear-gradient(top, #F6F6FF, #E3E3FF);
|
||||
display: inline-block;
|
||||
}
|
||||
.path li:after {
|
||||
content: " > ";
|
||||
}
|
||||
.path li:last-child {
|
||||
background: -moz-linear-gradient(top, #FFC, #DD8);
|
||||
}
|
||||
.path li:last-child:after {
|
||||
color: red;
|
||||
content: "";
|
||||
}
|
||||
|
||||
#sheetList, #sheetList menuitem {
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.sheet_line input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.sheet_line label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#header, #footer {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
#sheets {
|
||||
-moz-margin-end: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 13px;
|
||||
padding: 2px 10px;
|
||||
margin: 0;
|
||||
background: -moz-linear-gradient(top, #CCC, #AAA);
|
||||
border-radius: 3px;
|
||||
text-shadow: #FFF 0 1px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.property-header {
|
||||
padding: 2px 5px;
|
||||
background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.property-name, .property-value, .rule-count, .rule-unmatched {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Take away these two :visited rules to get a core dumper */
|
||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
||||
.link { color: #55A; }
|
||||
.link:visited { color: #55A; }
|
||||
a.link { text-decoration: none; cursor: pointer }
|
||||
a.link:visited { text-decoration: none; }
|
||||
.rule-count, .rule-unmatched {
|
||||
float: right;
|
||||
}
|
||||
.rule-count[dir="rtl"], .rule-unmatched[dir="rtl"] {
|
||||
float: left;
|
||||
}
|
||||
.property-view .rule-count .expander,
|
||||
.property-view .rule-unmatched .expander {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
-moz-margin-start: 5px;
|
||||
display: inline-block;
|
||||
background: url("chrome://browser/skin/devtools/arrows.png");
|
||||
}
|
||||
|
||||
.property-view .rule-count .expander,
|
||||
.property-view .rule-unmatched .expander {
|
||||
background-position: 24px 0;
|
||||
}
|
||||
.property-view[dir="rtl"] .rule-count .expander,
|
||||
.property-view[dir="rtl"] .rule-unmatched .expander {
|
||||
background-position: 16px 0;
|
||||
}
|
||||
.property-view[open] .rule-count .expander,
|
||||
.property-view[open] .rule-unmatched .expander {
|
||||
background-position: 8px 0;
|
||||
}
|
||||
|
||||
.property-name {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
-moz-padding-end: 4px;
|
||||
color: #000;
|
||||
}
|
||||
span.property-value {
|
||||
-moz-padding-end: 5px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.group {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.group > h1 {
|
||||
color: #333;
|
||||
font-size: 11px;
|
||||
}
|
||||
.group .groupexpander {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-top: 2px;
|
||||
background: url("chrome://browser/skin/devtools/arrows.png");
|
||||
}
|
||||
.group > div {
|
||||
display: none;
|
||||
}
|
||||
.group[open] > div {
|
||||
display: block;
|
||||
}
|
||||
.group .groupexpander {
|
||||
background-position: 48px 0;
|
||||
float: right;
|
||||
}
|
||||
.group[dir="rtl"] .groupexpander {
|
||||
background-position: 40px 0;
|
||||
float: left;
|
||||
}
|
||||
.group[open] .groupexpander {
|
||||
background-position: 32px 0;
|
||||
float: right;
|
||||
}
|
||||
.group[open][dir="rtl"] .groupexpander {
|
||||
background-position: 32px 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.group, #header, #footer {
|
||||
background: #FFF;
|
||||
border: 1px solid #E1E1E1;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
}
|
||||
|
||||
.property-view > .rules {
|
||||
display: none;
|
||||
}
|
||||
.property-view[open] > .rules {
|
||||
display: table;
|
||||
}
|
||||
.rules {
|
||||
max-height: 350px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.rule-specificty, .rule-status {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rule-link {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||
.rule-text {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.resizerbox {
|
||||
background-color: window;
|
||||
}
|
||||
|
||||
.bestmatch { color: black; }
|
||||
.matched { text-decoration: line-through; }
|
||||
.parentmatch { color: #666; }
|
||||
.unmatched { color: brown; }
|
|
@ -123,6 +123,8 @@ browser.jar:
|
|||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 933 B |
|
@ -0,0 +1,236 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla Inspector Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
body {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.path {
|
||||
font-size: 11px;
|
||||
word-spacing: -1px;
|
||||
}
|
||||
.path ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.path li {
|
||||
border-radius: 3px;
|
||||
padding: 2px 3px;
|
||||
text-shadow: #FFF 0 1px 0;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
background: -moz-linear-gradient(top, #F6F6FF, #E3E3FF);
|
||||
display: inline-block;
|
||||
}
|
||||
.path li:after {
|
||||
content: " > ";
|
||||
}
|
||||
.path li:last-child {
|
||||
background: -moz-linear-gradient(top, #FFC, #DD8);
|
||||
}
|
||||
.path li:last-child:after {
|
||||
color: red;
|
||||
content: "";
|
||||
}
|
||||
|
||||
#sheetList, #sheetList menuitem {
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.sheet_line input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.sheet_line label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#header, #footer {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
#sheets {
|
||||
-moz-margin-end: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 13px;
|
||||
padding: 2px 10px;
|
||||
margin: 0;
|
||||
background: -moz-linear-gradient(top, #CCC, #AAA);
|
||||
border-radius: 3px;
|
||||
text-shadow: #FFF 0 1px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.property-header {
|
||||
padding: 2px 5px;
|
||||
background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.property-name, .property-value, .rule-count, .rule-unmatched {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Take away these two :visited rules to get a core dumper */
|
||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
||||
.link { color: #55A; }
|
||||
.link:visited { color: #55A; }
|
||||
a.link { text-decoration: none; cursor: pointer }
|
||||
a.link:visited { text-decoration: none; }
|
||||
.rule-count, .rule-unmatched {
|
||||
float: right;
|
||||
}
|
||||
.rule-count[dir="rtl"], .rule-unmatched[dir="rtl"] {
|
||||
float: left;
|
||||
}
|
||||
.property-view .rule-count .expander,
|
||||
.property-view .rule-unmatched .expander {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
-moz-margin-start: 5px;
|
||||
display: inline-block;
|
||||
background: url("chrome://browser/skin/devtools/arrows.png");
|
||||
}
|
||||
|
||||
.property-view .rule-count .expander,
|
||||
.property-view .rule-unmatched .expander {
|
||||
background-position: 24px 0;
|
||||
}
|
||||
.property-view[dir="rtl"] .rule-count .expander,
|
||||
.property-view[dir="rtl"] .rule-unmatched .expander {
|
||||
background-position: 16px 0;
|
||||
}
|
||||
.property-view[open] .rule-count .expander,
|
||||
.property-view[open] .rule-unmatched .expander {
|
||||
background-position: 8px 0;
|
||||
}
|
||||
|
||||
.property-name {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
-moz-padding-end: 4px;
|
||||
color: #000;
|
||||
}
|
||||
span.property-value {
|
||||
-moz-padding-end: 5px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.group {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.group > h1 {
|
||||
color: #333;
|
||||
font-size: 11px;
|
||||
}
|
||||
.group .groupexpander {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-top: 2px;
|
||||
background: url("chrome://browser/skin/devtools/arrows.png");
|
||||
}
|
||||
.group > div {
|
||||
display: none;
|
||||
}
|
||||
.group[open] > div {
|
||||
display: block;
|
||||
}
|
||||
.group .groupexpander {
|
||||
background-position: 48px 0;
|
||||
float: right;
|
||||
}
|
||||
.group[dir="rtl"] .groupexpander {
|
||||
background-position: 40px 0;
|
||||
float: left;
|
||||
}
|
||||
.group[open] .groupexpander {
|
||||
background-position: 32px 0;
|
||||
float: right;
|
||||
}
|
||||
.group[open][dir="rtl"] .groupexpander {
|
||||
background-position: 32px 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.group, #header, #footer {
|
||||
background: #FFF;
|
||||
border: 1px solid #E1E1E1;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
}
|
||||
|
||||
.property-view > .rules {
|
||||
display: none;
|
||||
}
|
||||
.property-view[open] > .rules {
|
||||
display: table;
|
||||
}
|
||||
.rules {
|
||||
max-height: 350px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.rule-specificty, .rule-status {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rule-link {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||
.rule-text {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.resizerbox {
|
||||
background-color: window;
|
||||
}
|
||||
|
||||
.bestmatch { color: black; }
|
||||
.matched { text-decoration: line-through; }
|
||||
.parentmatch { color: #666; }
|
||||
.unmatched { color: brown; }
|
|
@ -106,6 +106,8 @@ browser.jar:
|
|||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
skin/classic/browser/tabview/tabview-inverted.png (tabview/tabview-inverted.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
|
|
|
@ -115,6 +115,23 @@ NetworkPanel.imageSizeDeltaDurationMS=%Sx%Spx, Δ%Sms
|
|||
NetworkPanel.responseBodyUnableToDisplay.content=Unable to display responses of type "%S"
|
||||
ConsoleAPIDisabled=The Web Console logging API (console.log, console.info, console.warn, console.error) has been disabled by a script on this page.
|
||||
|
||||
# LOCALIZATION NOTE (inspectStyle.nullObjectPassed):
|
||||
# This message is returned when a null object is passed in to inspectstyle()
|
||||
inspectStyle.nullObjectPassed=Object is null
|
||||
|
||||
# LOCALIZATION NOTE (inspectStyle.mustBeDomNode):
|
||||
# This message is returned when a non-DOM node is passed in to inspectstyle()
|
||||
inspectStyle.mustBeDomNode=Object must be a valid DOM node
|
||||
|
||||
# LOCALIZATION NOTE (inspectStyle.nodeHasNoStyleProps):
|
||||
# This message is returned when an unstyleable object is passed in to inspectstyle()
|
||||
inspectStyle.nodeHasNoStyleProps=Object cannot be styled
|
||||
|
||||
# LOCALIZATION NOTE (inspectStyle.styleInspectorNotEnabled):
|
||||
# This message is returned when devtools.styleinspector.enabled is not set to
|
||||
# true
|
||||
inspectStyle.styleInspectorNotEnabled=The style inspector is not enabled. Please set the option devtools.styleinspector.enabled to true in about:config to use this command.
|
||||
|
||||
# LOCALIZATION NOTE (webConsolePosition): The label shown for the menu which
|
||||
# allows the user to toggle between the Web Console positioning types.
|
||||
webConsolePosition=Position
|
||||
|
|
Загрузка…
Ссылка в новой задаче