Bug 911148 - Tabbing when editing an attribute stays in edit mode. r=pbrosset

This commit is contained in:
Athena
2015-01-14 19:46:00 -05:00
parent cca15db3e7
commit 57ebfa1877
6 changed files with 315 additions and 12 deletions

View File

@@ -2129,7 +2129,7 @@ function ElementEditor(aContainer, aNode) {
}
// Make the new attribute space editable.
editableField({
this.newAttr.editMode = editableField({
element: this.newAttr,
trigger: "dblclick",
stopOnReturn: true,
@@ -2235,7 +2235,7 @@ ElementEditor.prototype = {
}
// Make the attribute editable.
editableField({
attr.editMode = editableField({
element: inner,
trigger: "dblclick",
stopOnReturn: true,
@@ -2257,7 +2257,7 @@ ElementEditor.prototype = {
aEditor.input.select();
}
},
done: (aVal, aCommit) => {
done: (aVal, aCommit, direction) => {
if (!aCommit || aVal === initial) {
return;
}
@@ -2269,6 +2269,7 @@ ElementEditor.prototype = {
// parsed out of the input element. Restore original attribute if
// parsing fails.
try {
this.refocusOnEdit(aAttr.name, attr, direction);
this._saveAttribute(aAttr.name, undoMods);
doMods.removeAttribute(aAttr.name);
this._applyAttributes(aVal, attr, doMods, undoMods);
@@ -2347,6 +2348,97 @@ ElementEditor.prototype = {
}
},
/**
* Listen to mutations, and when the attribute list is regenerated
* try to focus on the attribute after the one that's being edited now.
* If the attribute order changes, go to the beginning of the attribute list.
*/
refocusOnEdit: function(attrName, attrNode, direction) {
// Only allow one refocus on attribute change at a time, so when there's
// more than 1 request in parallel, the last one wins.
if (this._editedAttributeObserver) {
this.markup._inspector.off("markupmutation", this._editedAttributeObserver);
this._editedAttributeObserver = null;
}
let container = this.markup.getContainer(this.node);
let activeAttrs = [...this.attrList.childNodes].filter(el => el.style.display != "none");
let attributeIndex = activeAttrs.indexOf(attrNode);
let onMutations = this._editedAttributeObserver = (e, mutations) => {
let isDeletedAttribute = false;
let isNewAttribute = false;
for (let mutation of mutations) {
let inContainer = this.markup.getContainer(mutation.target) === container;
if (!inContainer) {
continue;
}
let isOriginalAttribute = mutation.attributeName === attrName;
isDeletedAttribute = isDeletedAttribute || isOriginalAttribute && mutation.newValue === null;
isNewAttribute = isNewAttribute || mutation.attributeName !== attrName;
}
let isModifiedOrder = isDeletedAttribute && isNewAttribute;
this._editedAttributeObserver = null;
// "Deleted" attributes are merely hidden, so filter them out.
let visibleAttrs = [...this.attrList.childNodes].filter(el => el.style.display != "none");
let activeEditor;
if (visibleAttrs.length > 0) {
if (!direction) {
// No direction was given; stay on current attribute.
activeEditor = visibleAttrs[attributeIndex];
} else if (isModifiedOrder) {
// The attribute was renamed, reordering the existing attributes.
// So let's go to the beginning of the attribute list for consistency.
activeEditor = visibleAttrs[0];
} else {
let newAttributeIndex;
if (isDeletedAttribute) {
newAttributeIndex = attributeIndex;
} else {
if (direction == Ci.nsIFocusManager.MOVEFOCUS_FORWARD) {
newAttributeIndex = attributeIndex + 1;
} else if (direction == Ci.nsIFocusManager.MOVEFOCUS_BACKWARD) {
newAttributeIndex = attributeIndex - 1;
}
}
// The number of attributes changed (deleted), or we moved through the array
// so check we're still within bounds.
if (newAttributeIndex >= 0 && newAttributeIndex <= visibleAttrs.length - 1) {
activeEditor = visibleAttrs[newAttributeIndex];
}
}
}
// Either we have no attributes left,
// or we just edited the last attribute and want to move on.
if (!activeEditor) {
activeEditor = this.newAttr;
}
// Refocus was triggered by tab or shift-tab.
// Continue in edit mode.
if (direction) {
activeEditor.editMode();
} else {
// Refocus was triggered by enter.
// Exit edit mode (but restore focus).
let editable = activeEditor === this.newAttr ? activeEditor : activeEditor.querySelector(".editable");
editable.focus();
}
this.markup.emit("refocusedonedit");
};
// Start listening for mutations until we find an attributes change
// that modifies this attribute.
this.markup._inspector.once("markupmutation", onMutations);
},
/**
* Called when the tag name editor has is done editing.
*/