[evolution/wip/mcrha/webkit-jsc-api: 212/292] Implement EvoEditor::SetAlignment()
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/mcrha/webkit-jsc-api: 212/292] Implement EvoEditor::SetAlignment()
- Date: Wed, 11 Mar 2020 16:00:39 +0000 (UTC)
commit d28eee74c24303dc50f4496c8194d44a5ad69fbe
Author: Milan Crha <mcrha redhat com>
Date: Fri Oct 25 11:38:12 2019 +0200
Implement EvoEditor::SetAlignment()
data/webkit/e-editor.js | 303 +++++++++++++++++++-
data/webkit/e-selection.js | 26 +-
data/webkit/e-undo-redo.js | 317 ++++++++-------------
src/e-util/e-util-enums.h | 6 +-
.../web-extension/e-editor-web-extension.c | 2 +
5 files changed, 443 insertions(+), 211 deletions(-)
---
diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js
index 6e9e9785e9..8378341a7a 100644
--- a/data/webkit/e-editor.js
+++ b/data/webkit/e-editor.js
@@ -21,9 +21,11 @@
public functions start with upper-case letter. */
var EvoEditor = {
+ E_CONTENT_EDITOR_ALIGNMENT_NONE : -1,
E_CONTENT_EDITOR_ALIGNMENT_LEFT : 0,
E_CONTENT_EDITOR_ALIGNMENT_CENTER : 1,
E_CONTENT_EDITOR_ALIGNMENT_RIGHT : 2,
+ E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY : 3,
E_CONTENT_EDITOR_BLOCK_FORMAT_NONE : 0,
E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH : 1,
@@ -44,6 +46,233 @@ var EvoEditor = {
storedSelection : null
};
+EvoEditor.IsBlockNode = function(node)
+{
+ if (!node || !node.tagName) {
+ return false;
+ }
+
+ return node.tagName == "BLOCKQUOTE" ||
+ node.tagName == "DIV" ||
+ node.tagName == "P" ||
+ node.tagName == "PRE" ||
+ node.tagName == "ADDRESS" ||
+ node.tagName == "H1" ||
+ node.tagName == "H2" ||
+ node.tagName == "H3" ||
+ node.tagName == "H4" ||
+ node.tagName == "H5" ||
+ node.tagName == "H6" ||
+ node.tagName == "TD" ||
+ node.tagName == "TH" ||
+ node.tagName == "UL" ||
+ node.tagName == "OL";
+}
+
+EvoEditor.foreachChildRecur = function(topParent, parent, firstChildIndex, lastChildIndex, traversar)
+{
+ if (!parent) {
+ return false;
+ }
+
+ var ii;
+
+ for (ii = firstChildIndex; ii < parent.children.length && ii <= lastChildIndex; ii++) {
+ var child = parent.children.item(ii);
+
+ if (!traversar.onlyBlockElements || EvoEditor.IsBlockNode(child)) {
+ if (!traversar.exec(topParent, child)) {
+ return false;
+ }
+ }
+
+ if (child.children.length > 0 &&
+ !traversar.flat &&
+ !EvoEditor.foreachChildRecur(topParent, child, 0, child.children.length - 1, traversar)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ Traverses children of the 'parent', between the 'firstChildIndex' and
+ the 'lastChildIndex', where both indexes are meant inclusive.
+
+ The 'traversar' is an object, which should contain at least function:
+
+ bool exec(parent, element);
+
+ which does its work in the 'element' and returns true, when the traversar
+ should continue. The 'parent' is the one with which the funcion had been
+ called with. The 'traversar' can also contain properties:
+
+ bool flat;
+ bool onlyBlockElements;
+
+ the 'flat', if set to true, traverses only direct children of the parent,
+ otherwise it dives into the hierarchy;
+
+ the 'onlyBlockElements', if set to true, calls exec() only on elements,
+ which are block elements (as of EvoEditor.IsBlockNode()), otherwise it
+ is called for each element on the way.
+*/
+EvoEditor.ForeachChild = function(parent, firstChildIndex, lastChildIndex, traversar)
+{
+ return EvoEditor.foreachChildRecur(parent, parent, firstChildIndex, lastChildIndex, traversar);
+}
+
+EvoEditor.GetCommonParent = function(firstNode, secondNode)
+{
+ if (!firstNode || !secondNode) {
+ return null;
+ }
+
+ if (firstNode.nodeType == firstNode.TEXT_NODE) {
+ firstNode = firstNode.parentElement;
+ }
+
+ if (secondNode.nodeType == secondNode.TEXT_NODE) {
+ secondNode = secondNode.parentElement;
+ }
+
+ if (!firstNode || !secondNode) {
+ return null;
+ }
+
+ var commonParent, secondParent;
+
+ if (secondParent === document.body) {
+ return document.body;
+ }
+
+ for (commonParent = firstNode.parentElement; commonParent; commonParent = commonParent.parentElement)
{
+ if (commonParent === document.body) {
+ break;
+ }
+
+ for (secondParent = secondNode.parentElement; secondNode; secondNode =
secondNode.parentElement) {
+ if (secondParent === document.body) {
+ break;
+ }
+
+ if (secondParent === commonParent) {
+ return commonParent;
+ }
+ }
+ }
+
+ return document.body;
+}
+
+EvoEditor.GetDirectChild = function(parent, child)
+{
+ if (!parent || !child || parent === child) {
+ return null;
+ }
+
+ while (child && !(child.parentElement === parent)) {
+ child = child.parentElement;
+ }
+
+ return child;
+}
+
+EvoEditor.ClaimAffectedContent = function(startNode, endNode, useParentBlockNode, withHtml)
+{
+ var commonParent, startChild, endChild;
+ var firstChildIndex = -1, html = "", ii;
+
+ if (!startNode) {
+ startNode = document.getSelection().baseNode;
+ endNode = document.getSelection().extentNode;
+
+ if (!startNode) {
+ startNode = document.body;
+ }
+ }
+
+ if (!endNode) {
+ endNode = startNode;
+ }
+
+ if (useParentBlockNode) {
+ while (startNode && !(startNode === document.body)) {
+ if (EvoEditor.IsBlockNode(startNode)) {
+ break;
+ }
+
+ startNode = startNode.parentElement;
+ }
+ }
+
+ commonParent = EvoEditor.GetCommonParent(startNode, endNode);
+ startChild = EvoEditor.GetDirectChild(commonParent, startNode);
+ endChild = EvoEditor.GetDirectChild(commonParent, endNode);
+
+ for (ii = 0 ; ii < commonParent.children.length; ii++) {
+ var child = commonParent.children.item(ii);
+
+ if (firstChildIndex == -1) {
+ /* The selection can be made both from the top to the bottom and
+ from the bottom to the top, thus cover both cases. */
+ if (child === startChild) {
+ firstChildIndex = ii;
+ } else if (child === endChild) {
+ endChild = startChild;
+ startChild = child;
+ firstChildIndex = ii;
+ }
+ }
+
+ if (firstChildIndex != -1) {
+ if (withHtml) {
+ html += child.outerHTML;
+ }
+
+ if (child === endChild) {
+ ii++;
+ break;
+ }
+ }
+ }
+
+ var affected = {};
+
+ affected.path = EvoSelection.GetChildPath(document.body, commonParent);
+ affected.firstChildIndex = firstChildIndex;
+ affected.restChildrenCount = commonParent.children.length - ii;
+
+ if (withHtml) {
+ affected.html = html;
+ }
+
+ return affected;
+}
+
+/* Calls EvoEditor.ForeachChild() on a content described by 'affected',
+ which is result of EvoEditor.ClaimAffectedContent(). */
+EvoEditor.ForeachChildInAffectedContent = function(affected, traversar)
+{
+ if (!affected || !traversar) {
+ throw "EvoEditor.ForeachChildInAffectedContent: No 'affected' or 'traversar'";
+ }
+
+ var parent, firstChildIndex, lastChildIndex;
+
+ parent = EvoSelection.FindElementByPath(document.body, affected.path);
+ if (!parent) {
+ throw "EvoEditor.ForeachChildInAffectedContent: Cannot find parent";
+ }
+
+ firstChildIndex = affected.firstChildIndex;
+ /* Cannot subtract one, when none left, because the child index is inclusive */
+ lastChildIndex = parent.children.length - affected.restChildrenCount + (affected.restChildrenCount ?
-1 : 0);
+
+ return EvoEditor.ForeachChild(parent, firstChildIndex, lastChildIndex, traversar);
+}
+
EvoEditor.StoreSelection = function()
{
EvoEditor.storedSelection = EvoSelection.Store(document);
@@ -57,11 +286,83 @@ EvoEditor.RestoreSelection = function()
}
}
+EvoEditor.applySetAlignment = function(record, isUndo)
+{
+ if (record.changes) {
+ var ii, parent, child;
+
+ parent = EvoSelection.FindElementByPath(document.body, record.path);
+ if (!parent) {
+ throw "EvoEditor.applySetAlignment: Cannot find parent at path " + record.path;
+ }
+
+ for (ii = 0; ii < record.changes.length; ii++) {
+ var change = record.changes[ii];
+
+ child = EvoSelection.FindElementByPath(parent, change.path);
+ if (!child) {
+ throw "EvoEditor.applySetAlignment: Cannot find child";
+ }
+
+ child.style.textAlign = isUndo ? change.before : record.applyValueAfter;
+ }
+ }
+}
+
EvoEditor.SetAlignment = function(alignment)
{
- EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "setAlignment");
+ var traversar = {
+ record : null,
+ toSet : null,
+
+ flat : false,
+ onlyBlockElements : true,
+
+ exec : function(parent, element) {
+ if (window.getComputedStyle(element, null).textAlign != traversar.toSet) {
+ if (traversar.record) {
+ if (!traversar.record.changes)
+ traversar.record.changes = [];
+
+ var change = {};
+
+ change.path = EvoSelection.GetChildPath(parent, element);
+ change.before = element.style.textAlign;
+
+ traversar.record.changes[traversar.record.changes.length] = change;
+ }
+
+ element.style.textAlign = traversar.toSet;
+
+ return true;
+ }
+ }
+ };
+
+ var affected = EvoEditor.ClaimAffectedContent(null, null, true, false);
+
+ if (alignment == EvoEditor.E_CONTENT_EDITOR_ALIGNMENT_NONE)
+ traversar.toSet = "";
+ else if (alignment == EvoEditor.E_CONTENT_EDITOR_ALIGNMENT_LEFT)
+ traversar.toSet = "left";
+ else if (alignment == EvoEditor.E_CONTENT_EDITOR_ALIGNMENT_CENTER)
+ traversar.toSet = "center";
+ else if (alignment == EvoEditor.E_CONTENT_EDITOR_ALIGNMENT_RIGHT)
+ traversar.toSet = "right";
+ else if (alignment == EvoEditor.E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY)
+ traversar.toSet = "justify";
+ else
+ throw "EvoEditor.SetAlignment: Unknown alignment value: '" + alignment + "'";
+
+ traversar.record = EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "setAlignment", null,
null, true, false);
try {
+ EvoEditor.ForeachChildInAffectedContent(affected, traversar);
+
+ if (traversar.record) {
+ traversar.record.applyValueAfter = traversar.toSet;
+ traversar.record.apply = EvoEditor.applySetAlignment;
+ }
} finally {
EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "setAlignment");
}
diff --git a/data/webkit/e-selection.js b/data/webkit/e-selection.js
index 0b91b33970..32574667fd 100644
--- a/data/webkit/e-selection.js
+++ b/data/webkit/e-selection.js
@@ -128,12 +128,12 @@ EvoSelection.Store = function(doc)
var selection = {}, sel = doc.getSelection();
- selection["baseElem"] = sel.baseNode ? EvoSelection.GetChildPath(doc.body, sel.baseNode) : [];
- selection["baseOffset"] = sel.baseOffset + EvoSelection.GetOverallTextOffset(sel.baseNode);
+ selection.baseElem = sel.baseNode ? EvoSelection.GetChildPath(doc.body, sel.baseNode) : [];
+ selection.baseOffset = sel.baseOffset + EvoSelection.GetOverallTextOffset(sel.baseNode);
if (!sel.isCollapsed) {
- selection["extentElem"] = EvoSelection.GetChildPath(doc.body, sel.extentNode);
- selection["extentOffset"] = sel.extentOffset +
EvoSelection.GetOverallTextOffset(sel.extentNode);
+ selection.extentElem = EvoSelection.GetChildPath(doc.body, sel.extentNode);
+ selection.extentOffset = sel.extentOffset + EvoSelection.GetOverallTextOffset(sel.extentNode);
}
return selection;
@@ -149,8 +149,8 @@ EvoSelection.Restore = function(doc, selection)
var base_node, base_offset, extent_node, extent_offset;
- base_node = EvoSelection.FindElementByPath(doc.body, selection["baseElem"]);
- base_offset = selection["baseOffset"];
+ base_node = EvoSelection.FindElementByPath(doc.body, selection.baseElem);
+ base_offset = selection.baseOffset;
if (!base_node) {
return;
@@ -163,8 +163,8 @@ EvoSelection.Restore = function(doc, selection)
base_node = EvoSelection.GetTextOffsetNode(base_node, base_offset);
base_offset -= EvoSelection.GetOverallTextOffset(base_node);
- extent_node = EvoSelection.FindElementByPath(doc.body, selection["extentElem"]);
- extent_offset = selection["extentOffset"];
+ extent_node = EvoSelection.FindElementByPath(doc.body, selection.extentElem);
+ extent_offset = selection.extentOffset;
if (extent_node) {
extent_node = EvoSelection.GetTextOffsetNode(extent_node, extent_offset);
@@ -205,10 +205,10 @@ EvoSelection.ToString = function(selection)
var str = "", base_elem, base_offset, extent_elem, extent_offset;
- base_elem = selection["baseElem"];
- base_offset = selection["baseOffset"];
- extent_elem = selection["extentElem"];
- extent_offset = selection["extentOffset"];
+ base_elem = selection.baseElem;
+ base_offset = selection.baseOffset;
+ extent_elem = selection.extentElem;
+ extent_offset = selection.extentOffset;
str += "baseElem=" + utils.arrayToString(base_elem);
str += " baseOffset=" + (base_offset ? base_offset : 0);
@@ -304,7 +304,7 @@ EvoSelection.FromString = function(str)
}
/* The "baseElem" is required, the rest is optional */
- if (!selection["baseElem"])
+ if (!selection.baseElem)
return null;
return selection;
diff --git a/data/webkit/e-undo-redo.js b/data/webkit/e-undo-redo.js
index 086701790c..0f49336cbd 100644
--- a/data/webkit/e-undo-redo.js
+++ b/data/webkit/e-undo-redo.js
@@ -25,6 +25,11 @@ var EvoUndoRedo = {
E_UNDO_REDO_STATE_CAN_UNDO : 1 << 0,
E_UNDO_REDO_STATE_CAN_REDO : 1 << 1,
+ /* Flags for StartRecord() */
+ FLAG_NONE : 0,
+ FLAG_USE_PARENT_BLOCK_NODE : 1 << 0,
+ FLAG_SAVE_HTML : 1 << 1,
+
stack : {
// to not claim changes when none being made
state : -1,
@@ -37,9 +42,9 @@ var EvoUndoRedo = {
undoRecord = EvoUndoRedo.stack.getCurrentUndoRecord();
redoRecord = EvoUndoRedo.stack.getCurrentRedoRecord();
undoAvailable = undoRecord != null;
- undoOpType = undoRecord ? undoRecord["opType"] : "";
+ undoOpType = undoRecord ? undoRecord.opType : "";
redoAvailable = redoRecord != null;
- redoOpType = redoRecord ? redoRecord["opType"] : "";
+ redoOpType = redoRecord ? redoRecord.opType : "";
var state = EvoUndoRedo.E_UNDO_REDO_STATE_NONE;
@@ -60,9 +65,9 @@ var EvoUndoRedo = {
var params = {};
- params["state"] = EvoUndoRedo.state;
- params["undoOpType"] = EvoUndoRedo.undoOpType;
- params["redoOpType"] = EvoUndoRedo.redoOpType;
+ params.state = EvoUndoRedo.state;
+ params.undoOpType = EvoUndoRedo.undoOpType;
+ params.redoOpType = EvoUndoRedo.redoOpType;
window.webkit.messageHandlers.undoRedoStateChanged.postMessage(params);
}
@@ -265,7 +270,32 @@ EvoUndoRedo.before_input_cb = function(inputEvent)
return;
}
- EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_EVENT, inputEvent.inputType, null, null);
+ var opType = inputEvent.inputType, useParentBlockNode = false;
+
+ if (opType == "" || // some WebKit-specific editing commands use this
+ opType.startsWith("format") ||
+ opType == "insertLineBreak" ||
+ opType == "insertParagraph") {
+ useParentBlockNode = true;
+ var startNode;
+
+ startNode = document.getSelection().baseNode;
+
+ if (!startNode) {
+ startNode = document.body;
+ }
+
+ while (startNode && !(startNode === document.body)) {
+ if (EvoEditor.IsBlockNode(startNode)) {
+ break;
+ }
+
+ startNode = startNode.parentElement;
+ }
+ }
+
+ EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_EVENT, opType, startNode, null,
+ EvoUndoRedo.FLAG_SAVE_HTML | (useParentBlockNode ? EvoUndoRedo.FLAG_USE_PARENT_BLOCK_NODE :
EvoUndoRedo.FLAG_NONE));
}
EvoUndoRedo.input_cb = function(inputEvent)
@@ -283,10 +313,12 @@ EvoUndoRedo.applyRecord = function(record, isUndo, withSelection)
return;
}
- if (record["kind"] == EvoUndoRedo.RECORD_KIND_GROUP) {
+ var kind = record.kind;
+
+ if (kind == EvoUndoRedo.RECORD_KIND_GROUP) {
var ii, records;
- records = record["records"];
+ records = record.records;
if (records && records.length) {
if (isUndo) {
@@ -302,9 +334,9 @@ EvoUndoRedo.applyRecord = function(record, isUndo, withSelection)
if (withSelection) {
if (isUndo) {
- EvoSelection.Restore(document, record["selectionBefore"]);
+ EvoSelection.Restore(document, record.selectionBefore);
} else {
- EvoSelection.Restore(document, record["selectionAfter"]);
+ EvoSelection.Restore(document, record.selectionAfter);
}
}
@@ -314,57 +346,67 @@ EvoUndoRedo.applyRecord = function(record, isUndo, withSelection)
EvoUndoRedo.Disable();
try {
- var commonParent, first, last, ii;
+ if (kind == EvoUndoRedo.RECORD_KIND_DOCUMENT) {
+ if (isUndo) {
+ document.documentElement.outerHTML = record.htmlBefore;
+ } else {
+ document.documentElement.outerHTML = record.htmlAfter;
+ }
+ } else if (kind == EvoUndoRedo.RECORD_KIND_CUSTOM && record.apply != null) {
+ record.apply(record, isUndo);
+ } else {
+ var commonParent, first, last, ii;
- commonParent = EvoSelection.FindElementByPath(document.body, record["path"]);
- if (!commonParent) {
- throw "EvoUndoRedo::applyRecord: Cannot find parent at path " + record["path"];
- }
+ commonParent = EvoSelection.FindElementByPath(document.body, record.path);
+ if (!commonParent) {
+ throw "EvoUndoRedo::applyRecord: Cannot find parent at path " + record.path;
+ }
- first = record["firstChildIndex"];
+ first = record.firstChildIndex;
- // it can equal to the children.length, when the node had been removed
- if (first < 0 || first > commonParent.children.length) {
- throw "EvoUndoRedo::applyRecord: firstChildIndex (" + first + ") out of bounds (" +
commonParent.children.length + ")";
- }
+ // it can equal to the children.length, when the node had been removed
+ if (first < 0 || first > commonParent.children.length) {
+ throw "EvoUndoRedo::applyRecord: firstChildIndex (" + first + ") out of
bounds (" + commonParent.children.length + ")";
+ }
- last = commonParent.children.length - record["restChildrenCount"];
- if (last < 0 || last < first) {
- throw "EvoUndoRedo::applyRecord: restChildrenCount (" + record["restChildrenCount"] +
") out of bounds (length:" +
- commonParent.children.length + " first:" + first + " last:" + last + ")";
- }
+ last = commonParent.children.length - record.restChildrenCount;
+ if (last < 0 || last < first) {
+ throw "EvoUndoRedo::applyRecord: restChildrenCount (" +
record.restChildrenCount + ") out of bounds (length:" +
+ commonParent.children.length + " first:" + first + " last:" + last +
")";
+ }
- for (ii = last - 1; ii >= first; ii--) {
- if (ii >= 0 && ii < commonParent.children.length) {
- commonParent.removeChild(commonParent.children.item(ii));
+ for (ii = last - 1; ii >= first; ii--) {
+ if (ii >= 0 && ii < commonParent.children.length) {
+ commonParent.removeChild(commonParent.children.item(ii));
+ }
}
- }
- var tmpNode = document.createElement("evo-tmp");
+ var tmpNode = document.createElement("evo-tmp");
- if (isUndo) {
- tmpNode.innerHTML = record["htmlBefore"];
- } else {
- tmpNode.innerHTML = record["htmlAfter"];
- }
+ if (isUndo) {
+ tmpNode.innerHTML = record.htmlBefore;
+ } else {
+ tmpNode.innerHTML = record.htmlAfter;
+ }
- if (first + 1 < commonParent.children.length) {
- first = commonParent.children.item(first + 1);
+ if (first + 1 < commonParent.children.length) {
+ first = commonParent.children.item(first + 1);
- for (ii = tmpNode.children.length - 1; ii >= 0; ii--) {
- commonParent.insertBefore(tmpNode.children.item(ii), first);
- }
- } else {
- while(tmpNode.children.length) {
- commonParent.appendChild(tmpNode.children.item(0));
+ for (ii = tmpNode.children.length - 1; ii >= 0; ii--) {
+ commonParent.insertBefore(tmpNode.children.item(ii), first);
+ }
+ } else {
+ while(tmpNode.children.length) {
+ commonParent.appendChild(tmpNode.children.item(0));
+ }
}
}
if (withSelection) {
if (isUndo) {
- EvoSelection.Restore(document, record["selectionBefore"]);
+ EvoSelection.Restore(document, record.selectionBefore);
} else {
- EvoSelection.Restore(document, record["selectionAfter"]);
+ EvoSelection.Restore(document, record.selectionAfter);
}
}
} finally {
@@ -372,157 +414,38 @@ EvoUndoRedo.applyRecord = function(record, isUndo, withSelection)
}
}
-EvoUndoRedo.getCommonParent = function(firstNode, secondNode)
-{
- if (!firstNode || !secondNode) {
- return null;
- }
-
- if (firstNode.nodeType == firstNode.TEXT_NODE) {
- firstNode = firstNode.parentElement;
- }
-
- if (secondNode.nodeType == secondNode.TEXT_NODE) {
- secondNode = secondNode.parentElement;
- }
-
- if (!firstNode || !secondNode) {
- return null;
- }
-
- var commonParent, secondParent;
-
- if (secondParent === document.body) {
- return document.body;
- }
-
- for (commonParent = firstNode.parentElement; commonParent; commonParent = commonParent.parentElement)
{
- if (commonParent === document.body) {
- break;
- }
-
- for (secondParent = secondNode.parentElement; secondNode; secondNode =
secondNode.parentElement) {
- if (secondParent === document.body) {
- break;
- }
-
- if (secondParent === commonParent) {
- return commonParent;
- }
- }
- }
-
- return document.body;
-}
-
-EvoUndoRedo.getDirectChild = function(parent, child)
-{
- if (!parent || !child || parent === child) {
- return null;
- }
-
- while (child && !(child.parentElement === parent)) {
- child = child.parentElement;
- }
-
- return child;
-}
-
-EvoUndoRedo.StartRecord = function(kind, opType, startNode, endNode)
+EvoUndoRedo.StartRecord = function(kind, opType, startNode, endNode, flags)
{
if (EvoUndoRedo.disabled) {
- return;
+ return null;
}
- var record = {};
+ var record = {}, saveHTML;
- record["kind"] = kind;
- record["opType"] = opType;
- record["selectionBefore"] = EvoSelection.Store(document);
+ saveHTML = (flags & EvoUndoRedo.FLAG_SAVE_HTML) != 0;
- if (kind != EvoUndoRedo.RECORD_KIND_GROUP) {
- var commonParent, startChild, endChild;
- var firstChildIndex = -1, html = "", ii;
+ record.kind = kind;
+ record.opType = opType;
+ record.selectionBefore = EvoSelection.Store(document);
- if (!startNode) {
- startNode = document.getSelection().baseNode;
- endNode = document.getSelection().extentNode;
+ if (kind == EvoUndoRedo.RECORD_KIND_DOCUMENT) {
+ record.htmlBefore = document.documentElement.outerHTML;
+ } else if (kind != EvoUndoRedo.RECORD_KIND_GROUP) {
+ var affected;
- if (!startNode) {
- startNode = document.body;
- }
- }
+ affected = EvoEditor.ClaimAffectedContent(startNode, endNode, (flags &
EvoUndoRedo.FLAG_USE_PARENT_BLOCK_NODE) != 0, saveHTML);
- if (!endNode) {
- endNode = startNode;
- }
+ record.path = affected.path;
+ record.firstChildIndex = affected.firstChildIndex;
+ record.restChildrenCount = affected.restChildrenCount;
- /* Tweak what to save, because some events do not modify only selection, but also its parent
elements */
- if (kind == EvoUndoRedo.RECORD_KIND_EVENT) {
- if (opType == "" || // some WebKit-specific editing commands use this
- opType.startsWith("format") ||
- opType == "insertLineBreak" ||
- opType == "insertParagraph") {
- while (startNode && !(startNode === document.body)) {
- if (startNode.tagName == "P" ||
- startNode.tagName == "DIV" ||
- startNode.tagName == "BLOCKQUOTE" ||
- startNode.tagName == "UL" ||
- startNode.tagName == "OL" ||
- startNode.tagName == "PRE" ||
- startNode.tagName == "H1" ||
- startNode.tagName == "H2" ||
- startNode.tagName == "H3" ||
- startNode.tagName == "H4" ||
- startNode.tagName == "H5" ||
- startNode.tagName == "H6" ||
- startNode.tagName == "ADDRESS" ||
- startNode.tagName == "TD" ||
- startNode.tagName == "TH") {
- break;
- }
-
- startNode = startNode.parentElement;
- }
- }
- }
-
- commonParent = EvoUndoRedo.getCommonParent(startNode, endNode);
- startChild = EvoUndoRedo.getDirectChild(commonParent, startNode);
- endChild = EvoUndoRedo.getDirectChild(commonParent, endNode);
-
- for (ii = 0 ; ii < commonParent.children.length; ii++) {
- var child = commonParent.children.item(ii);
-
- if (firstChildIndex == -1) {
- /* The selection can be made both from the top to the bottom and
- from the bottom to the top, thus cover both cases. */
- if (child === startChild) {
- firstChildIndex = ii;
- } else if (child === endChild) {
- endChild = startChild;
- startChild = child;
- firstChildIndex = ii;
- }
- }
-
- if (firstChildIndex != -1) {
- html += child.outerHTML;
-
- if (child === endChild) {
- ii++;
- break;
- }
- }
- }
-
- record["path"] = EvoSelection.GetChildPath(document.body, commonParent);
- record["firstChildIndex"] = firstChildIndex;
- record["restChildrenCount"] = commonParent.children.length - ii;
- record["htmlBefore"] = html;
+ if (saveHTML)
+ record.htmlBefore = affected.html;
}
EvoUndoRedo.ongoingRecordings[EvoUndoRedo.ongoingRecordings.length] = record;
+
+ return record;
}
EvoUndoRedo.StopRecord = function(kind, opType)
@@ -537,37 +460,39 @@ EvoUndoRedo.StopRecord = function(kind, opType)
var record = EvoUndoRedo.ongoingRecordings[EvoUndoRedo.ongoingRecordings.length - 1];
- if (record["kind"] != kind) {
- throw "EvoUndoRedo:StopRecord: Mismatch in record kind, expected " + record["kind"] + ", but
received " + kind;
+ if (record.kind != kind) {
+ throw "EvoUndoRedo:StopRecord: Mismatch in record kind, expected " + record.kind + ", but
received " + kind;
}
- if (record["opType"] != opType) {
- throw "EvoUndoRedo:StopRecord: Mismatch in record opType, expected '" + record["opType"] +
"', but received '" + opType + "'";
+ if (record.opType != opType) {
+ throw "EvoUndoRedo:StopRecord: Mismatch in record opType, expected '" + record.opType + "',
but received '" + opType + "'";
}
EvoUndoRedo.ongoingRecordings.length = EvoUndoRedo.ongoingRecordings.length - 1;
- record["selectionAfter"] = EvoSelection.Store(document);
+ record.selectionAfter = EvoSelection.Store(document);
- if (kind != EvoUndoRedo.RECORD_KIND_GROUP) {
+ if (kind == EvoUndoRedo.RECORD_KIND_DOCUMENT) {
+ record.htmlAfter = document.documentElement.outerHTML;
+ } else if (record.htmlBefore != window.undefined) {
var commonParent, first, last, ii, html = "";
- commonParent = EvoSelection.FindElementByPath(document.body, record["path"]);
+ commonParent = EvoSelection.FindElementByPath(document.body, record.path);
if (!commonParent) {
throw "EvoUndoRedo.StopRecord:: Failed to stop '" + opType + "', cannot find common
parent";
}
- first = record["firstChildIndex"];
+ first = record.firstChildIndex;
// it can equal to the children.length, when the node had been removed
if (first < 0 || first > commonParent.children.length) {
throw "EvoUndoRedo::StopRecord: firstChildIndex (" + first + ") out of bounds (" +
commonParent.children.length + ")";
}
- last = commonParent.children.length - record["restChildrenCount"];
+ last = commonParent.children.length - record.restChildrenCount;
if (last < 0 || last < first) {
- throw "EvoUndoRedo::StopRecord: restChildrenCount (" + record["restChildrenCount"] +
") out of bounds (length:" +
+ throw "EvoUndoRedo::StopRecord: restChildrenCount (" + record.restChildrenCount + ")
out of bounds (length:" +
commonParent.children.length + " first:" + first + " last:" + last + ")";
}
@@ -577,17 +502,17 @@ EvoUndoRedo.StopRecord = function(kind, opType)
}
}
- record["htmlAfter"] = html;
+ record.htmlAfter = html;
}
if (EvoUndoRedo.ongoingRecordings.length) {
var parentRecord = EvoUndoRedo.ongoingRecordings[EvoUndoRedo.ongoingRecordings.length - 1];
- var records = parentRecord["records"];
+ var records = parentRecord.records;
if (!records) {
records = [];
}
records[records.length] = record;
- parentRecord["records"] = records;
+ parentRecord.records = records;
} else {
EvoUndoRedo.stack.push(record);
}
diff --git a/src/e-util/e-util-enums.h b/src/e-util/e-util-enums.h
index 9bdb26d3af..4ea7165872 100644
--- a/src/e-util/e-util-enums.h
+++ b/src/e-util/e-util-enums.h
@@ -292,16 +292,20 @@ typedef enum {
/**
* EContentEditorAlignment:
+ * @E_CONTENT_EDITOR_ALIGNMENT_NONE:
* @E_CONTENT_EDITOR_ALIGNMENT_LEFT:
* @E_CONTENT_EDITOR_ALIGNMENT_CENTER:
* @E_CONTENT_EDITOR_ALIGNMENT_RIGHT:
+ * @E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY:
*
* Since: 3.22
**/
typedef enum {
+ E_CONTENT_EDITOR_ALIGNMENT_NONE = -1,
E_CONTENT_EDITOR_ALIGNMENT_LEFT = 0,
E_CONTENT_EDITOR_ALIGNMENT_CENTER,
- E_CONTENT_EDITOR_ALIGNMENT_RIGHT
+ E_CONTENT_EDITOR_ALIGNMENT_RIGHT,
+ E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY
} EContentEditorAlignment;
/**
diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
index de431baffd..7b02093190 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
@@ -2497,6 +2497,8 @@ load_javascript_file (JSCContext *jsc_context,
jsc_exception_get_line_number (exception),
jsc_exception_get_column_number (exception),
jsc_exception_get_message (exception));
+
+ jsc_context_clear_exception (jsc_context);
}
g_clear_object (&result);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]