Make bold etc. work in editor
More of the same: we have to deal with both the active range itself, and
the selection's range(s).
--- a/editing.html Fri Aug 12 15:16:08 2011 -0600
+++ b/editing.html Fri Aug 12 15:34:18 2011 -0600
@@ -65,7 +65,7 @@
<body class=draft>
<div class=head id=head>
<h1>HTML Editing APIs</h1>
-<h2 class="no-num no-toc" id=work-in-progress-—-last-update-11-august-2011>Work in Progress — Last Update 11 August 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-12-august-2011>Work in Progress — Last Update 12 August 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <<a href=mailto:ayg@aryeh.name>ayg@aryeh.name</a>>
--- a/implementation.js Fri Aug 12 15:16:08 2011 -0600
+++ b/implementation.js Fri Aug 12 15:34:18 2011 -0600
@@ -1060,62 +1060,67 @@
var oldParent = node.parentNode;
var oldIndex = getNodeIndex(node);
- // We only even attempt to preserve the global range object, not every
- // range out there (the latter is probably impossible).
- var start = [globalRange.startContainer, globalRange.startOffset];
- var end = [globalRange.endContainer, globalRange.endOffset];
-
- // "If a boundary point's node is the same as or a descendant of node,
- // leave it unchanged, so it moves to the new location."
- //
- // No modifications necessary.
-
- // "If a boundary point's node is new parent and its offset is greater than
- // new index, add one to its offset."
- if (globalRange.startContainer == newParent
- && globalRange.startOffset > newIndex) {
- start[1]++;
- }
- if (globalRange.endContainer == newParent
- && globalRange.endOffset > newIndex) {
- end[1]++;
- }
-
- // "If a boundary point's node is old parent and its offset is old index or
- // old index + 1, set its node to new parent and add new index − old index
- // to its offset."
- if (globalRange.startContainer == oldParent
- && (globalRange.startOffset == oldIndex
- || globalRange.startOffset == oldIndex + 1)) {
- start[0] = newParent;
- start[1] += newIndex - oldIndex;
- }
- if (globalRange.endContainer == oldParent
- && (globalRange.endOffset == oldIndex
- || globalRange.endOffset == oldIndex + 1)) {
- end[0] = newParent;
- end[1] += newIndex - oldIndex;
- }
-
- // "If a boundary point's node is old parent and its offset is greater than
- // old index + 1, subtract one from its offset."
- if (globalRange.startContainer == oldParent
- && globalRange.startOffset > oldIndex + 1) {
- start[1]--;
- }
- if (globalRange.endContainer == oldParent
- && globalRange.endOffset > oldIndex + 1) {
- end[1]--;
- }
-
- // Now actually move it and preserve the range.
+ // We only even attempt to preserve the global range object and the ranges
+ // in the selection, not every range out there (the latter is probably
+ // impossible).
+ var ranges = [globalRange];
+ for (var i = 0; i < getSelection().rangeCount; i++) {
+ ranges.push(getSelection().getRangeAt(i));
+ }
+ var boundaryPoints = [];
+ ranges.forEach(function(range) {
+ boundaryPoints.push([range.startContainer, range.startOffset]);
+ boundaryPoints.push([range.endContainer, range.endOffset]);
+ });
+
+ boundaryPoints.forEach(function(boundaryPoint) {
+ // "If a boundary point's node is the same as or a descendant of node,
+ // leave it unchanged, so it moves to the new location."
+ //
+ // No modifications necessary.
+
+ // "If a boundary point's node is new parent and its offset is greater
+ // than new index, add one to its offset."
+ if (boundaryPoint[0] == newParent
+ && boundaryPoint[1] > newIndex) {
+ boundaryPoint[1]++;
+ }
+
+ // "If a boundary point's node is old parent and its offset is old index or
+ // old index + 1, set its node to new parent and add new index − old index
+ // to its offset."
+ if (boundaryPoint[0] == oldParent
+ && (boundaryPoint[1] == oldIndex
+ || boundaryPoint[1] == oldIndex + 1)) {
+ boundaryPoint[0] = newParent;
+ boundaryPoint[1] += newIndex - oldIndex;
+ }
+
+ // "If a boundary point's node is old parent and its offset is greater than
+ // old index + 1, subtract one from its offset."
+ if (boundaryPoint[0] == oldParent
+ && boundaryPoint[1] > oldIndex + 1) {
+ boundaryPoint[1]--;
+ }
+ });
+
+ // Now actually move it and preserve the ranges.
if (newParent.childNodes.length == newIndex) {
newParent.appendChild(node);
} else {
newParent.insertBefore(node, newParent.childNodes[newIndex]);
}
- globalRange.setStart(start[0], start[1]);
- globalRange.setEnd(end[0], end[1]);
+
+ globalRange.setStart(boundaryPoints[0][0], boundaryPoints[0][1]);
+ globalRange.setEnd(boundaryPoints[1][0], boundaryPoints[1][1]);
+
+ getSelection().removeAllRanges();
+ for (var i = 1; i < ranges.length; i++) {
+ var newRange = document.createRange();
+ newRange.setStart(boundaryPoints[2*i][0], boundaryPoints[2*i][1]);
+ newRange.setEnd(boundaryPoints[2*i + 1][0], boundaryPoints[2*i + 1][1]);
+ getSelection().addRange(newRange);
+ }
}
function setTagName(element, newName) {
@@ -2825,14 +2830,18 @@
&& getActiveRange().startOffset != 0
&& getActiveRange().startOffset != getNodeLength(getActiveRange().startContainer)) {
// Account for browsers not following range mutation rules
+ var newNode = getActiveRange().startContainer.splitText(getActiveRange().startOffset);
+ var newActiveRange = document.createRange();
if (getActiveRange().startContainer == getActiveRange().endContainer) {
- var newEnd = getActiveRange().endOffset - getActiveRange().startOffset;
- var newNode = getActiveRange().startContainer.splitText(getActiveRange().startOffset);
- getActiveRange().setStart(newNode, 0);
- getActiveRange().setEnd(newNode, newEnd);
- } else {
- getActiveRange().setStart(getActiveRange().startContainer.splitText(getActiveRange().startOffset), 0);
- }
+ var newEndOffset = getActiveRange().endOffset - getActiveRange().startOffset;
+ newActiveRange.setEnd(newNode, newEndOffset);
+ getActiveRange().setEnd(newNode, newEndOffset);
+ }
+ newActiveRange.setStart(newNode, 0);
+ getSelection().removeAllRanges();
+ getSelection().addRange(newActiveRange);
+
+ getActiveRange().setStart(newNode, 0);
}
// "If the active range's end node is an editable Text node, and its end
@@ -2853,6 +2862,9 @@
activeRange.endContainer.splitText(activeRange.endOffset);
activeRange.setStart(newStart[0], newStart[1]);
activeRange.setEnd(newEnd[0], newEnd[1]);
+
+ getSelection().removeAllRanges();
+ getSelection().addRange(activeRange);
}
// "Let element list be all editable Elements effectively contained in the