Bug 895561 - 'Edit As HTML' option in the markup view - toolkit changes, r=fitzgen

This commit is contained in:
Brian Grinstead 2013-10-23 11:53:39 -05:00
parent f95f28628d
commit a89ef93583
5 changed files with 94 additions and 7 deletions

View File

@ -241,6 +241,7 @@ this.DebuggerClient = function DebuggerClient(aTransport)
this.compat = new ProtocolCompatibility(this, [
new SourcesShim(),
]);
this.traits = {};
this.request = this.request.bind(this);
this.localTransport = this._transport.onOutputStreamReady === undefined;
@ -360,11 +361,12 @@ DebuggerClient.prototype = {
* received from the debugging server.
*/
connect: function DC_connect(aOnConnected) {
if (aOnConnected) {
this.addOneTimeListener("connected", function(aName, aApplicationType, aTraits) {
this.addOneTimeListener("connected", (aName, aApplicationType, aTraits) => {
this.traits = aTraits;
if (aOnConnected) {
aOnConnected(aApplicationType, aTraits);
});
}
}
});
this._transport.ready();
},

View File

@ -76,6 +76,10 @@ HELPER_SHEET += ":-moz-devtools-highlighted { outline: 2px dashed #F06!important
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
loader.lazyGetter(this, "DOMParser", function() {
return Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
});
exports.register = function(handle) {
handle.addTabActor(InspectorActor, "inspectorActor");
};
@ -143,6 +147,11 @@ var NodeActor = protocol.ActorClass({
*/
get conn() this.walker.conn,
isDocumentElement: function() {
return this.rawNode.ownerDocument &&
this.rawNode.ownerDocument.documentElement === this.rawNode;
},
// Returns the JSON representation of this object over the wire.
form: function(detail) {
if (detail === "actorid") {
@ -177,8 +186,7 @@ var NodeActor = protocol.ActorClass({
pseudoClassLocks: this.writePseudoClassLocks(),
};
if (this.rawNode.ownerDocument &&
this.rawNode.ownerDocument.documentElement === this.rawNode) {
if (this.isDocumentElement()) {
form.isDocumentElement = true;
}
@ -1547,6 +1555,62 @@ var WalkerActor = protocol.ActorClass({
}
}),
/**
* Set a node's outerHTML property.
*/
setOuterHTML: method(function(node, value) {
let parsedDOM = DOMParser.parseFromString(value, "text/html");
let rawNode = node.rawNode;
let parentNode = rawNode.parentNode;
// Special case for head and body. Setting document.body.outerHTML
// creates an extra <head> tag, and document.head.outerHTML creates
// an extra <body>. So instead we will call replaceChild with the
// parsed DOM, assuming that they aren't trying to set both tags at once.
if (rawNode.tagName === "BODY") {
if (parsedDOM.head.innerHTML === "") {
parentNode.replaceChild(parsedDOM.body, rawNode);
} else {
rawNode.outerHTML = value;
}
} else if (rawNode.tagName === "HEAD") {
if (parsedDOM.body.innerHTML === "") {
parentNode.replaceChild(parsedDOM.head, rawNode);
} else {
rawNode.outerHTML = value;
}
} else if (node.isDocumentElement()) {
// Unable to set outerHTML on the document element. Fall back by
// setting attributes manually, then replace the body and head elements.
let finalAttributeModifications = [];
let attributeModifications = {};
for (let attribute of rawNode.attributes) {
attributeModifications[attribute.name] = null;
}
for (let attribute of parsedDOM.documentElement.attributes) {
attributeModifications[attribute.name] = attribute.value;
}
for (let key in attributeModifications) {
finalAttributeModifications.push({
attributeName: key,
newValue: attributeModifications[key]
});
}
node.modifyAttributes(finalAttributeModifications);
rawNode.replaceChild(parsedDOM.head, rawNode.querySelector("head"));
rawNode.replaceChild(parsedDOM.body, rawNode.querySelector("body"));
} else {
rawNode.outerHTML = value;
}
}, {
request: {
node: Arg(0, "domnode"),
value: Arg(1),
},
response: {
}
}),
/**
* Removes a node from its parent node.
*

View File

@ -175,7 +175,8 @@ RootActor.prototype = {
/* This is not in the spec, but it's used by tests. */
testConnectionPrefix: this.conn.prefix,
traits: {
sources: true
sources: true,
editOuterHTML: true
}
};
},

View File

@ -50,5 +50,6 @@
<div id="longlist-sibling">
<div id="longlist-sibling-firstchild"></div>
</div>
<p id="edit-html"></p>
</body>
</html>

View File

@ -73,6 +73,25 @@ addTest(function testOuterHTML() {
}).then(runNextTest));
});
addTest(function testSetOuterHTMLNode() {
let newHTML = "<p id=\"edit-html-done\">after edit</p>";
promiseDone(gWalker.querySelector(gWalker.rootNode, "#edit-html").then(node => {
return gWalker.setOuterHTML(node, newHTML);
}).then(() => {
return gWalker.querySelector(gWalker.rootNode, "#edit-html-done");
}).then(node => {
return gWalker.outerHTML(node);
}).then(longstring => {
return longstring.string();
}).then(outerHTML => {
is(outerHTML, newHTML, "outerHTML has been updated");
}).then(() => {
return gWalker.querySelector(gWalker.rootNode, "#edit-html");
}).then(node => {
ok(!node, "The node with the old ID cannot be selected anymore");
}).then(runNextTest));
});
addTest(function testQuerySelector() {
promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(node => {
is(node.getAttribute("data-test"), "exists", "should have found the right node");