mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 00:05:36 +00:00
Bug 1269226 - Explicitly handle node deletion in inspector breadcrumbs. r=pbro
This commit is contained in:
parent
970e9b8288
commit
32fa6f3a81
@ -584,6 +584,22 @@ HTMLBreadcrumbs.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this was an interesting deletion; then trim the breadcrumb trail
|
||||
if (reason === "markupmutation") {
|
||||
for (let {type, removed} of mutations) {
|
||||
if (type !== "childList") {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let node of removed) {
|
||||
let removedIndex = this.indexOf(node);
|
||||
if (removedIndex > -1) {
|
||||
this.cutAfter(removedIndex - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.selection.isElementNode()) {
|
||||
// no selection
|
||||
this.setCursor(-1);
|
||||
|
@ -857,12 +857,26 @@ MarkupView.prototype = {
|
||||
this.undo.do(() => {
|
||||
this.walker.removeNode(node).then(siblings => {
|
||||
nextSibling = siblings.nextSibling;
|
||||
let focusNode = moveBackward ? siblings.previousSibling : nextSibling;
|
||||
let prevSibling = siblings.previousSibling;
|
||||
let focusNode = moveBackward ? prevSibling : nextSibling;
|
||||
|
||||
// If we can't move as the user wants, we move to the other direction.
|
||||
// If there is no sibling elements anymore, move to the parent node.
|
||||
if (!focusNode) {
|
||||
focusNode = nextSibling || siblings.previousSibling || parent;
|
||||
focusNode = nextSibling || prevSibling || parent;
|
||||
}
|
||||
|
||||
let isNextSiblingText = nextSibling ?
|
||||
nextSibling.nodeType === Ci.nsIDOMNode.TEXT_NODE : false;
|
||||
let isPrevSiblingText = prevSibling ?
|
||||
prevSibling.nodeType === Ci.nsIDOMNode.TEXT_NODE : false;
|
||||
|
||||
// If the parent had two children and the next or previous sibling
|
||||
// is a text node, then it now has only a single text node, is about
|
||||
// to be in-lined; and focus should move to the parent.
|
||||
if (parent.numChildren === 2
|
||||
&& (isNextSiblingText || isPrevSiblingText)) {
|
||||
focusNode = parent;
|
||||
}
|
||||
|
||||
if (container.selected) {
|
||||
|
@ -18,31 +18,15 @@ add_task(function* () {
|
||||
yield testManuallyDeleteSelectedNode();
|
||||
yield testAutomaticallyDeleteSelectedNode();
|
||||
yield testDeleteSelectedNodeContainerFrame();
|
||||
yield testDeleteWithNonElementNode();
|
||||
|
||||
function* testManuallyDeleteSelectedNode() {
|
||||
info("Selecting a node, deleting it via context menu and checking that " +
|
||||
"its parent node is selected and breadcrumbs are updated.");
|
||||
"its parent node is selected and breadcrumbs are updated.");
|
||||
|
||||
yield selectNode("#deleteManually", inspector);
|
||||
yield deleteNodeWithContextMenu("#deleteManually");
|
||||
|
||||
info("Getting the node container in the markup view.");
|
||||
let container = yield getContainerForSelector("#deleteManually", inspector);
|
||||
|
||||
info("Simulating right-click on the markup view container.");
|
||||
EventUtils.synthesizeMouse(container.tagLine, 2, 2,
|
||||
{type: "contextmenu", button: 2}, inspector.panelWin);
|
||||
|
||||
info("Waiting for the context menu to open.");
|
||||
yield once(inspector.panelDoc.getElementById("inspectorPopupSet"),
|
||||
"popupshown");
|
||||
|
||||
info("Clicking 'Delete Node' in the context menu.");
|
||||
inspector.panelDoc.getElementById("node-menu-delete").click();
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
info("Inspector updated, performing checks.");
|
||||
info("Performing checks.");
|
||||
yield assertNodeSelectedAndPanelsUpdated("#selectedAfterDelete",
|
||||
"li#selectedAfterDelete");
|
||||
}
|
||||
@ -85,12 +69,80 @@ add_task(function* () {
|
||||
yield assertNodeSelectedAndPanelsUpdated("body", "body");
|
||||
}
|
||||
|
||||
function* testDeleteWithNonElementNode() {
|
||||
info("Selecting a node, deleting it via context menu and checking that " +
|
||||
"its parent node is selected and breadcrumbs are updated " +
|
||||
"when the node is followed by a non-element node");
|
||||
|
||||
yield deleteNodeWithContextMenu("#deleteWithNonElement");
|
||||
|
||||
let expectedCrumbs = ["html", "body", "div#deleteToMakeSingleTextNode"];
|
||||
yield assertNodeSelectedAndCrumbsUpdated(expectedCrumbs,
|
||||
Node.TEXT_NODE);
|
||||
|
||||
let div = yield getNodeFront("#deleteToMakeSingleTextNode", inspector);
|
||||
let {nodes} = yield inspector.walker.children(div);
|
||||
let secondTextNode = nodes[1];
|
||||
yield deleteNodeWithKey(secondTextNode);
|
||||
expectedCrumbs = ["html", "body", "div#deleteToMakeSingleTextNode"];
|
||||
yield assertNodeSelectedAndCrumbsUpdated(expectedCrumbs,
|
||||
Node.ELEMENT_NODE);
|
||||
}
|
||||
|
||||
function* deleteNodeWithKey(selector) {
|
||||
yield selectNode(selector, inspector);
|
||||
|
||||
info("Simulating delete keypress on the markup view container.");
|
||||
EventUtils.synthesizeKey("VK_DELETE", {}, inspector.panelWin);
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
}
|
||||
|
||||
function* deleteNodeWithContextMenu(selector) {
|
||||
yield selectNode(selector, inspector);
|
||||
|
||||
info("Getting the node container in the markup view.");
|
||||
let container = yield getContainerForSelector(selector, inspector);
|
||||
|
||||
info("Simulating right-click on the markup view container.");
|
||||
EventUtils.synthesizeMouse(container.tagLine, 2, 2,
|
||||
{type: "contextmenu", button: 2}, inspector.panelWin);
|
||||
|
||||
info("Waiting for the context menu to open.");
|
||||
let popupSet = inspector.panelDoc.getElementById("inspectorPopupSet");
|
||||
yield once(popupSet, "popupshown");
|
||||
|
||||
info("Clicking 'Delete Node' in the context menu.");
|
||||
inspector.panelDoc.getElementById("node-menu-delete").click();
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
}
|
||||
|
||||
function* assertNodeSelectedAndCrumbsUpdated(expectedCrumbs,
|
||||
expectedNodeType) {
|
||||
info("Performing checks");
|
||||
let actualNodeType = inspector.selection.nodeFront.nodeType;
|
||||
is(actualNodeType, expectedNodeType, "The node has the right type");
|
||||
|
||||
let breadcrumbs = inspector.panelDoc
|
||||
.getElementById("inspector-breadcrumbs")
|
||||
.childNodes;
|
||||
is(breadcrumbs.length, expectedCrumbs.length,
|
||||
"Have the correct number of breadcrumbs");
|
||||
for (let i = 0; i < breadcrumbs.length; i++) {
|
||||
is(breadcrumbs[i].textContent, expectedCrumbs[i],
|
||||
"Text content for button " + i + " is correct");
|
||||
}
|
||||
}
|
||||
|
||||
function* assertNodeSelectedAndPanelsUpdated(selector, crumbLabel) {
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
is(inspector.selection.nodeFront, nodeFront, "The right node is selected");
|
||||
|
||||
let breadcrumbs = inspector.panelDoc.getElementById(
|
||||
"inspector-breadcrumbs");
|
||||
let breadcrumbs = inspector.panelDoc
|
||||
.getElementById("inspector-breadcrumbs");
|
||||
is(breadcrumbs.querySelector("button[checked=true]").textContent,
|
||||
crumbLabel,
|
||||
"The right breadcrumb is selected");
|
||||
|
@ -11,5 +11,10 @@
|
||||
<li id="deleteAutomatically">Delete me via javascript</li>
|
||||
</ul>
|
||||
<iframe id="deleteIframe" src="data:text/html,%3C!DOCTYPE%20html%3E%3Chtml%20lang%3D%22en%22%3E%3Cbody%3E%3Cp%20id%3D%22deleteInIframe%22%3EDelete my container iframe%3C%2Fp%3E%3C%2Fbody%3E%3C%2Fhtml%3E"></iframe>
|
||||
<div id="deleteToMakeSingleTextNode">
|
||||
1
|
||||
<b id="deleteWithNonElement">Delete me and select the non-element node</b>
|
||||
2
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user