зеркало из https://github.com/mozilla/gecko-dev.git
Bug 755388 - "hud is null" when using the edit gcli command; r=dcamp
This commit is contained in:
Родитель
48d6fb6894
Коммит
b6f52dbe1b
|
@ -135,9 +135,8 @@ gcli.addCommand({
|
|||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||
let StyleEditor = hud.gcliterm.document.defaultView.StyleEditor;
|
||||
StyleEditor.openChrome(args.resource.element, args.line);
|
||||
let win = HUDService.currentContext();
|
||||
win.StyleEditor.openChrome(args.resource.element, args.line);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -4157,7 +4157,7 @@ var ResourceCache = {
|
|||
* Drop all cache entries. Helpful to prevent memory leaks
|
||||
*/
|
||||
clear: function() {
|
||||
ResourceCache._cached = {};
|
||||
ResourceCache._cached = [];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
_BROWSER_TEST_FILES = \
|
||||
browser_gcli_break.js \
|
||||
browser_gcli_commands.js \
|
||||
browser_gcli_edit.js \
|
||||
browser_gcli_inspect.js \
|
||||
browser_gcli_integrate.js \
|
||||
browser_gcli_pref.js \
|
||||
|
@ -26,6 +27,10 @@ _BROWSER_TEST_FILES = \
|
|||
_BROWSER_TEST_PAGES = \
|
||||
browser_gcli_break.html \
|
||||
browser_gcli_inspect.html \
|
||||
resources_inpage.js \
|
||||
resources_inpage1.css \
|
||||
resources_inpage2.css \
|
||||
resources.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the edit command works
|
||||
|
||||
const TEST_URI = TEST_BASE_HTTP + "resources.html";
|
||||
|
||||
function test() {
|
||||
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
|
||||
testEditStatus(browser, tab);
|
||||
// Bug 759853
|
||||
// testEditExec(browser, tab); // calls finish()
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function testEditStatus(browser, tab) {
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit",
|
||||
markup: "VVVV",
|
||||
status: "ERROR",
|
||||
emptyParameters: [ " <resource>", " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit i",
|
||||
markup: "VVVVVI",
|
||||
status: "ERROR",
|
||||
directTabText: "nline-css",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit c",
|
||||
markup: "VVVVVI",
|
||||
status: "ERROR",
|
||||
directTabText: "ss#style2",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit http",
|
||||
markup: "VVVVVIIII",
|
||||
status: "ERROR",
|
||||
directTabText: "://example.com/browser/browser/devtools/commandline/test/resources_inpage1.css",
|
||||
arrowTabText: "",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit page1",
|
||||
markup: "VVVVVIIIII",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
arrowTabText: "http://example.com/browser/browser/devtools/commandline/test/resources_inpage1.css",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit page2",
|
||||
markup: "VVVVVIIIII",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
arrowTabText: "http://example.com/browser/browser/devtools/commandline/test/resources_inpage2.css",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit stylez",
|
||||
markup: "VVVVVEEEEEE",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
arrowTabText: "",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2",
|
||||
markup: "VVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
directTabText: "",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2 5",
|
||||
markup: "VVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
directTabText: "",
|
||||
emptyParameters: [ ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2 0",
|
||||
markup: "VVVVVVVVVVVVVVVVE",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
emptyParameters: [ ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2 -1",
|
||||
markup: "VVVVVVVVVVVVVVVVEE",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
emptyParameters: [ ],
|
||||
});
|
||||
}
|
||||
|
||||
var windowListener = {
|
||||
onOpenWindow: function(win) {
|
||||
// Wait for the window to finish loading
|
||||
let win = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
win.close();
|
||||
}, false);
|
||||
win.addEventListener("unload", function onUnload() {
|
||||
win.removeEventListener("unload", onUnload, false);
|
||||
Services.wm.removeListener(windowListener);
|
||||
finish();
|
||||
}, false);
|
||||
},
|
||||
onCloseWindow: function(win) { },
|
||||
onWindowTitleChange: function(win, title) { }
|
||||
};
|
||||
|
||||
function testEditExec(browser, tab) {
|
||||
|
||||
Services.wm.addListener(windowListener);
|
||||
|
||||
var style2 = browser.contentDocument.getElementById("style2");
|
||||
DeveloperToolbarTest.exec({
|
||||
typed: "edit css#style2",
|
||||
args: {
|
||||
resource: function(resource) {
|
||||
return resource.element.ownerNode == style2;
|
||||
},
|
||||
line: 1
|
||||
},
|
||||
completed: true,
|
||||
blankOutput: true,
|
||||
});
|
||||
}
|
|
@ -95,7 +95,7 @@ function testPrefStatus() {
|
|||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "pref show devtools.toolbar.ena",
|
||||
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||
markup: "VVVVVVVVVVIIIIIIIIIIIIIIIIIIII",
|
||||
directTabText: "bled",
|
||||
status: "ERROR",
|
||||
emptyParameters: [ ]
|
||||
|
@ -103,7 +103,7 @@ function testPrefStatus() {
|
|||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "pref show hideIntro",
|
||||
markup: "VVVVVVVVVVVVVVVVVVV",
|
||||
markup: "VVVVVVVVVVIIIIIIIII",
|
||||
directTabText: "",
|
||||
arrowTabText: "devtools.gcli.hideIntro",
|
||||
status: "ERROR",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/commandline/test/";
|
||||
const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/commandline/test/";
|
||||
|
||||
let console = (function() {
|
||||
let tempScope = {};
|
||||
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
|
||||
|
@ -83,57 +86,69 @@ let DeveloperToolbarTest = {
|
|||
* emptyParameters: [ "<message>" ], // Still to type
|
||||
* directTabText: "o", // Simple completion text
|
||||
* arrowTabText: "", // When the completion is not an extension
|
||||
* markup: "VVVIIIEEE", // What state should the error markup be in
|
||||
* });
|
||||
*/
|
||||
checkInputStatus: function DTT_checkInputStatus(test) {
|
||||
if (test.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(test.typed);
|
||||
checkInputStatus: function DTT_checkInputStatus(tests) {
|
||||
let display = DeveloperToolbar.display;
|
||||
|
||||
if (tests.typed) {
|
||||
display.inputter.setInput(tests.typed);
|
||||
}
|
||||
else {
|
||||
ok(false, "Missing typed for " + JSON.stringify(test));
|
||||
ok(false, "Missing typed for " + JSON.stringify(tests));
|
||||
return;
|
||||
}
|
||||
|
||||
if (test.cursor) {
|
||||
DeveloperToolbar.display.inputter.setCursor(test.cursor)
|
||||
if (tests.cursor) {
|
||||
display.inputter.setCursor(tests.cursor)
|
||||
}
|
||||
|
||||
if (test.status) {
|
||||
is(DeveloperToolbar.display.requisition.getStatus().toString(),
|
||||
test.status,
|
||||
"status for " + test.typed);
|
||||
if (tests.status) {
|
||||
is(display.requisition.getStatus().toString(),
|
||||
tests.status, "status for " + tests.typed);
|
||||
}
|
||||
|
||||
if (test.emptyParameters == null) {
|
||||
test.emptyParameters = [];
|
||||
if (tests.emptyParameters == null) {
|
||||
tests.emptyParameters = [];
|
||||
}
|
||||
|
||||
let completer = DeveloperToolbar.display.completer;
|
||||
let realParams = completer.emptyParameters;
|
||||
is(realParams.length, test.emptyParameters.length,
|
||||
'emptyParameters.length for \'' + test.typed + '\'');
|
||||
let realParams = display.completer.emptyParameters;
|
||||
is(realParams.length, tests.emptyParameters.length,
|
||||
'emptyParameters.length for \'' + tests.typed + '\'');
|
||||
|
||||
if (realParams.length === test.emptyParameters.length) {
|
||||
if (realParams.length === tests.emptyParameters.length) {
|
||||
for (let i = 0; i < realParams.length; i++) {
|
||||
is(realParams[i].replace(/\u00a0/g, ' '), test.emptyParameters[i],
|
||||
'emptyParameters[' + i + '] for \'' + test.typed + '\'');
|
||||
is(realParams[i].replace(/\u00a0/g, ' '), tests.emptyParameters[i],
|
||||
'emptyParameters[' + i + '] for \'' + tests.typed + '\'');
|
||||
}
|
||||
}
|
||||
|
||||
if (test.directTabText) {
|
||||
is(completer.directTabText, test.directTabText,
|
||||
'directTabText for \'' + test.typed + '\'');
|
||||
if (tests.directTabText) {
|
||||
is(display.completer.directTabText, tests.directTabText,
|
||||
'directTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
else {
|
||||
is(completer.directTabText, '', 'directTabText for \'' + test.typed + '\'');
|
||||
is(display.completer.directTabText, '',
|
||||
'directTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
|
||||
if (test.arrowTabText) {
|
||||
is(completer.arrowTabText, ' \u00a0\u21E5 ' + test.arrowTabText,
|
||||
'arrowTabText for \'' + test.typed + '\'');
|
||||
if (tests.arrowTabText) {
|
||||
is(display.completer.arrowTabText, ' \u00a0\u21E5 ' + tests.arrowTabText,
|
||||
'arrowTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
else {
|
||||
is(completer.arrowTabText, '', 'arrowTabText for \'' + test.typed + '\'');
|
||||
is(display.completer.arrowTabText, '',
|
||||
'arrowTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
|
||||
if (tests.markup) {
|
||||
let cursor = tests.cursor ? tests.cursor.start : tests.typed.length;
|
||||
let statusMarkup = display.requisition.getInputStatusMarkup(cursor);
|
||||
let actualMarkup = statusMarkup.map(function(s) {
|
||||
return Array(s.string.length + 1).join(s.status.toString()[0]);
|
||||
}).join('');
|
||||
is(tests.markup, actualMarkup, 'markup for ' + tests.typed);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -151,11 +166,11 @@ let DeveloperToolbarTest = {
|
|||
* blankOutput: true, // Special checks when there is no output
|
||||
* });
|
||||
*/
|
||||
exec: function DTT_exec(test) {
|
||||
test = test || {};
|
||||
exec: function DTT_exec(tests) {
|
||||
tests = tests || {};
|
||||
|
||||
if (test.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(test.typed);
|
||||
if (tests.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(tests.typed);
|
||||
}
|
||||
|
||||
let typed = DeveloperToolbar.display.inputter.getInputState().typed;
|
||||
|
@ -163,7 +178,7 @@ let DeveloperToolbarTest = {
|
|||
|
||||
is(typed, output.typed, 'output.command for: ' + typed);
|
||||
|
||||
if (test.completed !== false) {
|
||||
if (tests.completed !== false) {
|
||||
ok(output.completed, 'output.completed false for: ' + typed);
|
||||
}
|
||||
else {
|
||||
|
@ -172,14 +187,18 @@ let DeveloperToolbarTest = {
|
|||
// ok(!output.completed, 'output.completed true for: ' + typed);
|
||||
}
|
||||
|
||||
if (test.args != null) {
|
||||
is(Object.keys(test.args).length, Object.keys(output.args).length,
|
||||
if (tests.args != null) {
|
||||
is(Object.keys(tests.args).length, Object.keys(output.args).length,
|
||||
'arg count for ' + typed);
|
||||
|
||||
Object.keys(output.args).forEach(function(arg) {
|
||||
let expectedArg = test.args[arg];
|
||||
let expectedArg = tests.args[arg];
|
||||
let actualArg = output.args[arg];
|
||||
|
||||
if (typeof expectedArg === 'function') {
|
||||
ok(expectedArg(actualArg), 'failed test func. ' + typed + '/' + arg);
|
||||
}
|
||||
else {
|
||||
if (Array.isArray(expectedArg)) {
|
||||
if (!Array.isArray(actualArg)) {
|
||||
ok(false, 'actual is not an array. ' + typed + '/' + arg);
|
||||
|
@ -196,12 +215,13 @@ let DeveloperToolbarTest = {
|
|||
else {
|
||||
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let displayed = DeveloperToolbar.outputPanel._div.textContent;
|
||||
|
||||
if (test.outputMatch) {
|
||||
if (tests.outputMatch) {
|
||||
function doTest(match, against) {
|
||||
if (!match.test(against)) {
|
||||
ok(false, "html output for " + typed + " against " + match.source +
|
||||
|
@ -210,17 +230,17 @@ let DeveloperToolbarTest = {
|
|||
info(against);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(test.outputMatch)) {
|
||||
test.outputMatch.forEach(function(match) {
|
||||
if (Array.isArray(tests.outputMatch)) {
|
||||
tests.outputMatch.forEach(function(match) {
|
||||
doTest(match, displayed);
|
||||
});
|
||||
}
|
||||
else {
|
||||
doTest(test.outputMatch, displayed);
|
||||
doTest(tests.outputMatch, displayed);
|
||||
}
|
||||
}
|
||||
|
||||
if (test.blankOutput != null) {
|
||||
if (tests.blankOutput != null) {
|
||||
if (!/^$/.test(displayed)) {
|
||||
ok(false, "html output for " + typed + " (textContent sent to info)");
|
||||
info("Actual textContent");
|
||||
|
@ -260,6 +280,8 @@ let DeveloperToolbarTest = {
|
|||
if (appMenuItem) {
|
||||
appMenuItem.hidden = true;
|
||||
}
|
||||
|
||||
// leakHunt({ DeveloperToolbar: DeveloperToolbar });
|
||||
});
|
||||
|
||||
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
|
||||
|
@ -289,3 +311,158 @@ let DeveloperToolbarTest = {
|
|||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Memory leak hunter. Walks a tree of objects looking for DOM nodes.
|
||||
* Usage:
|
||||
* leakHunt({
|
||||
* thing: thing,
|
||||
* otherthing: otherthing
|
||||
* });
|
||||
*/
|
||||
|
||||
var noRecurse = [
|
||||
/^string$/, /^number$/, /^boolean$/, /^null/, /^undefined/,
|
||||
/^Window$/, /^Document$/,
|
||||
/^XULDocument$/, /^XULElement$/,
|
||||
/^DOMWindow$/, /^HTMLDocument$/, /^HTML.*Element$/
|
||||
];
|
||||
|
||||
var hide = [ /^string$/, /^number$/, /^boolean$/, /^null/, /^undefined/ ];
|
||||
|
||||
function leakHunt(root, path, seen) {
|
||||
path = path || [];
|
||||
seen = seen || [];
|
||||
|
||||
try {
|
||||
var output = leakHuntInner(root, path, seen);
|
||||
output.forEach(function(line) {
|
||||
dump(line + '\n');
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
dump(ex + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
function leakHuntInner(root, path, seen) {
|
||||
var prefix = new Array(path.length).join(' ');
|
||||
|
||||
var reply = [];
|
||||
function log(msg) {
|
||||
reply.push(msg);
|
||||
}
|
||||
|
||||
var direct
|
||||
try {
|
||||
direct = Object.keys(root);
|
||||
}
|
||||
catch (ex) {
|
||||
log(prefix + ' Error enumerating: ' + ex);
|
||||
return reply;
|
||||
}
|
||||
|
||||
for (var prop in root) {
|
||||
var newPath = path.slice();
|
||||
newPath.push(prop);
|
||||
prefix = new Array(newPath.length).join(' ');
|
||||
|
||||
var data;
|
||||
try {
|
||||
data = root[prop];
|
||||
}
|
||||
catch (ex) {
|
||||
log(prefix + prop + ' Error reading: ' + ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
var recurse = true;
|
||||
var message = getType(data);
|
||||
|
||||
if (matchesAnyPattern(message, hide)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message === 'function' && direct.indexOf(prop) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message === 'string') {
|
||||
var extra = data.length > 10 ? data.substring(0, 9) + '_' : data;
|
||||
message += ' "' + extra.replace(/\n/g, "|") + '"';
|
||||
recurse = false;
|
||||
}
|
||||
else if (matchesAnyPattern(message, noRecurse)) {
|
||||
message += ' (no recurse)'
|
||||
recurse = false;
|
||||
}
|
||||
else if (seen.indexOf(data) !== -1) {
|
||||
message += ' (already seen)';
|
||||
recurse = false;
|
||||
}
|
||||
|
||||
if (recurse) {
|
||||
seen.push(data);
|
||||
var lines = leakHuntInner(data, newPath, seen);
|
||||
if (lines.length == 0) {
|
||||
if (message !== 'function') {
|
||||
log(prefix + prop + ' = ' + message + ' { }');
|
||||
}
|
||||
}
|
||||
else {
|
||||
log(prefix + prop + ' = ' + message + ' {');
|
||||
lines.forEach(function(line) {
|
||||
reply.push(line);
|
||||
});
|
||||
log(prefix + '}');
|
||||
}
|
||||
}
|
||||
else {
|
||||
log(prefix + prop + ' = ' + message);
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
function matchesAnyPattern(str, patterns) {
|
||||
var match = false;
|
||||
patterns.forEach(function(pattern) {
|
||||
if (str.match(pattern)) {
|
||||
match = true;
|
||||
}
|
||||
});
|
||||
return match;
|
||||
}
|
||||
|
||||
function getType(data) {
|
||||
if (data === null) {
|
||||
return 'null';
|
||||
}
|
||||
if (data === undefined) {
|
||||
return 'undefined';
|
||||
}
|
||||
|
||||
var type = typeof data;
|
||||
if (type === 'object' || type === 'Object') {
|
||||
type = getCtorName(data);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
function getCtorName(aObj) {
|
||||
try {
|
||||
if (aObj.constructor && aObj.constructor.name) {
|
||||
return aObj.constructor.name;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
return 'UnknownObject';
|
||||
}
|
||||
|
||||
// If that fails, use Objects toString which sometimes gives something
|
||||
// better than 'Object', and at least defaults to Object if nothing better
|
||||
return Object.prototype.toString.call(aObj).slice(8, -1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Resources</title>
|
||||
<script type="text/javascript" id="script1">
|
||||
window.addEventListener('load', function() {
|
||||
var pid = document.getElementById('pid');
|
||||
var div = document.createElement('div');
|
||||
div.id = 'divid';
|
||||
div.classList.add('divclass');
|
||||
div.appendChild(document.createTextNode('div'));
|
||||
div.setAttribute('data-a1', 'div');
|
||||
pid.parentNode.appendChild(div);
|
||||
});
|
||||
</script>
|
||||
<script src="resources_inpage.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage1.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage2.css"/>
|
||||
<style type="text/css">
|
||||
p { color: #800; }
|
||||
div { color: #008; }
|
||||
h4 { color: #080; }
|
||||
h3 { color: #880; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<style type="text/css" id=style2>
|
||||
.pclass { background-color: #FEE; }
|
||||
.divclass { background-color: #EEF; }
|
||||
.h4class { background-color: #EFE; }
|
||||
.h3class { background-color: #FFE; }
|
||||
</style>
|
||||
|
||||
<p class="pclass" id="pid" data-a1="p">paragraph</p>
|
||||
|
||||
<script>
|
||||
var pid = document.getElementById('pid');
|
||||
var h4 = document.createElement('h4');
|
||||
h4.id = 'h4id';
|
||||
h4.classList.add('h4class');
|
||||
h4.appendChild(document.createTextNode('h4'));
|
||||
h4.setAttribute('data-a1', 'h4');
|
||||
pid.parentNode.appendChild(h4);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
// This script is used from within browser_gcli_edit.html
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var pid = document.getElementById('pid');
|
||||
var h3 = document.createElement('h3');
|
||||
h3.id = 'h3id';
|
||||
h3.classList.add('h3class');
|
||||
h3.appendChild(document.createTextNode('h3'));
|
||||
h3.setAttribute('data-a1', 'h3');
|
||||
pid.parentNode.appendChild(h3);
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
@charset "utf-8";
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#pid { border-top: 2px dotted #F00; }
|
||||
#divid { border-top: 2px dotted #00F; }
|
||||
#h4id { border-top: 2px dotted #0F0; }
|
||||
#h3id { border-top: 2px dotted #FF0; }
|
|
@ -0,0 +1,11 @@
|
|||
@charset "utf-8";
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
*[data-a1=p] { border-left: 4px solid #F00; }
|
||||
*[data-a1=div] { border-left: 4px solid #00F; }
|
||||
*[data-a1=h4] { border-left: 4px solid #0F0; }
|
||||
*[data-a1=h3] { border-left: 4px solid #FF0; }
|
Загрузка…
Ссылка в новой задаче