You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@corinthia.apache.org by ja...@apache.org on 2015/08/17 10:50:17 UTC
[25/28] incubator-corinthia git commit: included MOC compiler for Qt
implementation
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/DOM.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/DOM.js b/experiments/editorFramework/src/Javascript_Layer_0/DOM.js
new file mode 100644
index 0000000..b2371bc
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/DOM.js
@@ -0,0 +1,966 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Helper functions
+var DOM_assignNodeIds;
+
+// Primitive node creation operations
+var DOM_createElement;
+var DOM_createElementNS;
+var DOM_createTextNode;
+var DOM_createComment;
+var DOM_cloneNode;
+
+// Primitive and high-level node mutation operations
+var DOM_appendChild;
+var DOM_insertBefore;
+var DOM_deleteNode;
+var DOM_setAttribute;
+var DOM_setAttributeNS;
+var DOM_removeAttribute;
+var DOM_removeAttributeNS;
+var DOM_setStyleProperties;
+var DOM_insertCharacters;
+var DOM_moveCharacters;
+var DOM_deleteCharacters;
+var DOM_setNodeValue;
+
+// High-level DOM operations
+var DOM_getAttribute;
+var DOM_getAttributeNS;
+var DOM_getStringAttribute;
+var DOM_getStringAttributeNS;
+var DOM_getStyleProperties;
+var DOM_deleteAllChildren;
+var DOM_shallowCopyElement;
+var DOM_replaceElement;
+var DOM_wrapNode;
+var DOM_wrapSiblings;
+var DOM_mergeWithNextSibling;
+var DOM_nodesMergeable;
+var DOM_replaceCharacters;
+var DOM_addTrackedPosition;
+var DOM_removeTrackedPosition;
+var DOM_removeAdjacentWhitespace;
+var DOM_documentHead;
+var DOM_ensureUniqueIds;
+var DOM_nodeOffset;
+var DOM_maxChildOffset;
+var DOM_ignoreMutationsWhileExecuting;
+var DOM_getIgnoreMutations;
+var DOM_addListener;
+var DOM_removeListener;
+var DOM_Listener;
+
+(function() {
+
+ var nextNodeId = 0;
+ var nodeData = new Object();
+ var ignoreMutations = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // //
+ // DOM Helper Functions //
+ // //
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+
+ function addUndoAction()
+ {
+ if (window.undoSupported)
+ UndoManager_addAction.apply(null,arrayCopy(arguments));
+ }
+
+ function assignNodeId(node)
+ {
+ if (node._nodeId != null)
+ throw new Error(node+" already has id");
+ node._nodeId = nextNodeId++;
+ node._type = ElementTypes[node.nodeName];
+ return node;
+ }
+
+ function checkNodeId(node)
+ {
+ if (node._nodeId == null)
+ throw new Error(node.nodeName+" lacks _nodeId");
+ }
+
+ // public
+ DOM_assignNodeIds = function(root)
+ {
+ if (root._nodeId != null)
+ throw new Error(root+" already has id");
+ recurse(root);
+ return;
+
+ function recurse(node) {
+ node._nodeId = nextNodeId++;
+ node._type = ElementTypes[node.nodeName];
+ for (var child = node.firstChild; child != null; child = child.nextSibling)
+ recurse(child);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // //
+ // Primitive DOM Operations //
+ // //
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+
+ The following functions are considered "primitive", in that they are the core functions
+ through which all manipulation of the DOM ultimately occurs. All other DOM functions call
+ these, either directly or indirectly, instead of making direct method calls on node objects.
+ These functions are divided into two categories: node creation and mode mutation.
+
+ The creation functions are as follows:
+
+ * createElement(document,elementName)
+ * createElementNS(document,namespaceURI,qualifiedName)
+ * createTextNode(document,data)
+ * createComment(document,data)
+ * cloneNode(original,deep,noIdAttr)
+
+ The purpose of these is to ensure that a unique _nodeId value is assigned to each node object,
+ which is needed for using the NodeSet and NodeMap classes. All nodes in a document must have
+ this set; we use our own functions for this because DOM provides no other way of uniquely
+ identifying nodes in a way that allows them to be stored in a hash table.
+
+ The mutation functions are as follows:
+
+ * insertBeforeInternal(parent,newChild,refChild)
+ * deleteNodeInternal(node,deleteDescendantData)
+ * setAttribute(element,name,value)
+ * setAttributeNS(element,namespaceURI,qualifiedName,value)
+ * setStyleProperties(element,properties)
+ * insertCharacters(textNode,offset,characters)
+ * deleteCharacters(textNode,startOffset,endOffset)
+ * moveCharacters(srcTextNode,srcStartOffset,srcEndOffset,destTextNode,destOffset)
+ * setNodeValue(textNode,value)
+
+ These functions exist to allow us to record undo information. We can't use DOM mutation events
+ for this purpose they're not fully supported in WebKit.
+
+ Every time a mutation operation is performed on a node, we add an action to the undo stack
+ corresponding to the inverse of that operaton, i.e. an action that undoes the operaton. It
+ is absolutely critical that all changes to a DOM node go through these functions, regardless
+ of whether or not the node currently resides in the tree. This ensures that the undo history
+ is able to correctly revert the tree to the same state that it was in at the relevant point
+ in time.
+
+ By routing all DOM modifications through these few functions, virtually all of the other
+ javascript code can be ignorant of the undo manager, provided the only state they change is
+ in the DOM. Parts of the code which maintain their own state about the document, such as the
+ style manager, must implement their own undo-compliant state manipulation logic.
+
+ *** IMPORTANT ***
+
+ Just in case it isn't already clear, you must *never* make direct calls to methods like
+ appendChild() and createElement() on the node objects themselves. Doing so will result in
+ subtle and probably hard-to-find bugs. As far as all javascript code for UX Write is
+ concerned, consider the public functions defined in this file to be the DOM API. You can use
+ check-dom-methods.sh to search for any cases where this rule has been violated.
+
+ */
+
+ // public
+ DOM_createElement = function(document,elementName)
+ {
+ return assignNodeId(document.createElement(elementName)); // check-ok
+ }
+
+ // public
+ DOM_createElementNS = function(document,namespaceURI,qualifiedName)
+ {
+ return assignNodeId(document.createElementNS(namespaceURI,qualifiedName)); // check-ok
+ }
+
+ // public
+ DOM_createTextNode = function(document,data)
+ {
+ return assignNodeId(document.createTextNode(data)); // check-ok
+ }
+
+ // public
+ DOM_createComment = function(document,data)
+ {
+ return assignNodeId(document.createComment(data)); // check-ok
+ }
+
+ // public
+ DOM_cloneNode = function(original,deep,noIdAttr)
+ {
+ var clone = original.cloneNode(deep); // check-ok
+ DOM_assignNodeIds(clone);
+ if (noIdAttr)
+ clone.removeAttribute("id"); // check-ok
+ return clone;
+ }
+
+ function insertBeforeInternal(parent,newChild,refChild)
+ {
+ if (newChild.parentNode == null) {
+ addUndoAction(deleteNodeInternal,newChild)
+ }
+ else {
+ var oldParent = newChild.parentNode;
+ var oldNext = newChild.nextSibling;
+ addUndoAction(insertBeforeInternal,oldParent,newChild,oldNext);
+ }
+
+ parent.insertBefore(newChild,refChild); // check-ok
+ }
+
+ function deleteNodeInternal(node,deleteDescendantData)
+ {
+ checkNodeId(node);
+
+ addUndoAction(insertBeforeInternal,node.parentNode,node,node.nextSibling);
+
+ if (node.parentNode == null)
+ throw new Error("Undo delete "+nodeString(node)+": parent is null");
+ node.parentNode.removeChild(node); // check-ok
+
+ // Delete all data associated with the node. This is not preserved across undo/redo;
+ // currently the only thing we are using this data for is tracked positions, and we
+ // are going to be recording undo information for the selection separately, so this is
+ // not a problem.
+ if (deleteDescendantData)
+ deleteNodeDataRecursive(node);
+ else
+ deleteNodeData(node);
+
+ return;
+
+ function deleteNodeData(current)
+ {
+ delete nodeData[current._nodeId];
+ }
+
+ function deleteNodeDataRecursive(current)
+ {
+ deleteNodeData(current);
+ for (var child = current.firstChild; child != null; child = child.nextSibling)
+ deleteNodeDataRecursive(child);
+ }
+ }
+
+ // public
+ DOM_setAttribute = function(element,name,value)
+ {
+ if (element.hasAttribute(name))
+ addUndoAction(DOM_setAttribute,element,name,element.getAttribute(name));
+ else
+ addUndoAction(DOM_setAttribute,element,name,null);
+
+ if (value == null)
+ element.removeAttribute(name); // check-ok
+ else
+ element.setAttribute(name,value); // check-ok
+ }
+
+ // public
+ DOM_setAttributeNS = function(element,namespaceURI,qualifiedName,value)
+ {
+ var localName = qualifiedName.replace(/^.*:/,"");
+ if (element.hasAttributeNS(namespaceURI,localName)) {
+ var oldValue = element.getAttributeNS(namespaceURI,localName);
+ var oldQName = element.getAttributeNodeNS(namespaceURI,localName).nodeName; // check-ok
+ addUndoAction(DOM_setAttributeNS,element,namespaceURI,oldQName,oldValue)
+ }
+ else {
+ addUndoAction(DOM_setAttributeNS,element,namespaceURI,localName,null);
+ }
+
+ if (value == null)
+ element.removeAttributeNS(namespaceURI,localName); // check-ok
+ else
+ element.setAttributeNS(namespaceURI,qualifiedName,value); // check-ok
+ }
+
+ // public
+ DOM_setStyleProperties = function(element,properties)
+ {
+ if (Object.getOwnPropertyNames(properties).length == 0)
+ return;
+
+ if (element.hasAttribute("style"))
+ addUndoAction(DOM_setAttribute,element,"style",element.getAttribute("style"));
+ else
+ addUndoAction(DOM_setAttribute,element,"style",null);
+
+ for (var name in properties)
+ element.style.setProperty(name,properties[name]); // check-ok
+
+ if (element.getAttribute("style") == "")
+ element.removeAttribute("style"); // check-ok
+ }
+
+ // public
+ DOM_insertCharacters = function(textNode,offset,characters)
+ {
+ if (textNode.nodeType != Node.TEXT_NODE)
+ throw new Error("DOM_insertCharacters called on non-text node");
+ if ((offset < 0) || (offset > textNode.nodeValue.length))
+ throw new Error("DOM_insertCharacters called with invalid offset");
+ trackedPositionsForNode(textNode).forEach(function (position) {
+ if (position.offset > offset)
+ position.offset += characters.length;
+ });
+ textNode.nodeValue = textNode.nodeValue.slice(0,offset) +
+ characters +
+ textNode.nodeValue.slice(offset);
+ var startOffset = offset;
+ var endOffset = offset + characters.length;
+ addUndoAction(DOM_deleteCharacters,textNode,startOffset,endOffset);
+ }
+
+ // public
+ DOM_deleteCharacters = function(textNode,startOffset,endOffset)
+ {
+ if (textNode.nodeType != Node.TEXT_NODE)
+ throw new Error("DOM_deleteCharacters called on non-text node "+nodeString(textNode));
+ if (endOffset == null)
+ endOffset = textNode.nodeValue.length;
+ if (endOffset < startOffset)
+ throw new Error("DOM_deleteCharacters called with invalid start/end offset");
+ trackedPositionsForNode(textNode).forEach(function (position) {
+ var deleteCount = endOffset - startOffset;
+ if ((position.offset > startOffset) && (position.offset < endOffset))
+ position.offset = startOffset;
+ else if (position.offset >= endOffset)
+ position.offset -= deleteCount;
+ });
+
+ var removed = textNode.nodeValue.slice(startOffset,endOffset);
+ addUndoAction(DOM_insertCharacters,textNode,startOffset,removed);
+
+ textNode.nodeValue = textNode.nodeValue.slice(0,startOffset) +
+ textNode.nodeValue.slice(endOffset);
+ }
+
+ // public
+ DOM_moveCharacters = function(srcTextNode,srcStartOffset,srcEndOffset,destTextNode,destOffset,
+ excludeStartPos,excludeEndPos)
+ {
+ if (srcTextNode == destTextNode)
+ throw new Error("src and dest text nodes cannot be the same");
+ if (srcStartOffset > srcEndOffset)
+ throw new Error("Invalid src range "+srcStartOffset+" - "+srcEndOffset);
+ if (srcStartOffset < 0)
+ throw new Error("srcStartOffset < 0");
+ if (srcEndOffset > srcTextNode.nodeValue.length)
+ throw new Error("srcEndOffset beyond end of src length");
+ if (destOffset < 0)
+ throw new Error("destOffset < 0");
+ if (destOffset > destTextNode.nodeValue.length)
+ throw new Error("destOffset beyond end of dest length");
+
+ var length = srcEndOffset - srcStartOffset;
+
+ addUndoAction(DOM_moveCharacters,destTextNode,destOffset,destOffset+length,
+ srcTextNode,srcStartOffset,excludeStartPos,excludeEndPos);
+
+ trackedPositionsForNode(destTextNode).forEach(function (pos) {
+ var startMatch = excludeStartPos ? (pos.offset > destOffset)
+ : (pos.offset >= destOffset);
+ if (startMatch)
+ pos.offset += length;
+ });
+ trackedPositionsForNode(srcTextNode).forEach(function (pos) {
+
+ var startMatch = excludeStartPos ? (pos.offset > srcStartOffset)
+ : (pos.offset >= srcStartOffset);
+ var endMatch = excludeEndPos ? (pos.offset < srcEndOffset)
+ : (pos.offset <= srcEndOffset);
+
+ if (startMatch && endMatch) {
+ pos.node = destTextNode;
+ pos.offset = destOffset + (pos.offset - srcStartOffset);
+ }
+ else if (pos.offset >= srcEndOffset) {
+ pos.offset -= length;
+ }
+ });
+ var extract = srcTextNode.nodeValue.substring(srcStartOffset,srcEndOffset);
+ srcTextNode.nodeValue = srcTextNode.nodeValue.slice(0,srcStartOffset) +
+ srcTextNode.nodeValue.slice(srcEndOffset);
+ destTextNode.nodeValue = destTextNode.nodeValue.slice(0,destOffset) +
+ extract +
+ destTextNode.nodeValue.slice(destOffset);
+ }
+
+ // public
+ DOM_setNodeValue = function(textNode,value)
+ {
+ if (textNode.nodeType != Node.TEXT_NODE)
+ throw new Error("DOM_setNodeValue called on non-text node");
+ trackedPositionsForNode(textNode).forEach(function (position) {
+ position.offset = 0;
+ });
+ var oldValue = textNode.nodeValue;
+ addUndoAction(DOM_setNodeValue,textNode,oldValue);
+ textNode.nodeValue = value;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // //
+ // High-level DOM Operations //
+ // //
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+
+ function appendChildInternal(parent,newChild)
+ {
+ insertBeforeInternal(parent,newChild,null);
+ }
+
+ // public
+ DOM_appendChild = function(node,child)
+ {
+ return DOM_insertBefore(node,child,null);
+ }
+
+ // public
+ DOM_insertBefore = function(parent,child,nextSibling)
+ {
+ var newOffset;
+ if (nextSibling != null)
+ newOffset = DOM_nodeOffset(nextSibling);
+ else
+ newOffset = parent.childNodes.length;
+
+ var oldParent = child.parentNode;
+ if (oldParent != null) { // already in tree
+ var oldOffset = DOM_nodeOffset(child);
+
+ if ((oldParent == parent) && (newOffset > oldOffset))
+ newOffset--;
+
+ trackedPositionsForNode(oldParent).forEach(function (position) {
+ if (position.offset > oldOffset) {
+ position.offset--;
+ }
+ else if (position.offset == oldOffset) {
+ position.node = parent;
+ position.offset = newOffset;
+ }
+ });
+ }
+
+ var result = insertBeforeInternal(parent,child,nextSibling);
+ trackedPositionsForNode(parent).forEach(function (position) {
+ if (position.offset > newOffset)
+ position.offset++;
+ });
+ return result;
+ }
+
+ // public
+ DOM_deleteNode = function(node)
+ {
+ if (node.parentNode == null) // already deleted
+ return;
+ adjustPositionsRecursive(node);
+ deleteNodeInternal(node,true);
+
+ function adjustPositionsRecursive(current)
+ {
+ for (var child = current.firstChild; child != null; child = child.nextSibling)
+ adjustPositionsRecursive(child);
+
+ trackedPositionsForNode(current.parentNode).forEach(function (position) {
+ var offset = DOM_nodeOffset(current);
+ if (offset < position.offset) {
+ position.offset--;
+ }
+ });
+ trackedPositionsForNode(current).forEach(function (position) {
+ var offset = DOM_nodeOffset(current);
+ position.node = current.parentNode;
+ position.offset = offset;
+ });
+ }
+ }
+
+ // public
+ DOM_removeAttribute = function(element,name,value)
+ {
+ DOM_setAttribute(element,name,null);
+ }
+
+ // public
+ DOM_removeAttributeNS = function(element,namespaceURI,localName)
+ {
+ DOM_setAttributeNS(element,namespaceURI,localName,null)
+ }
+
+ // public
+ DOM_getAttribute = function(element,name)
+ {
+ if (element.hasAttribute(name))
+ return element.getAttribute(name);
+ else
+ return null;
+ }
+
+ // public
+ DOM_getAttributeNS = function(element,namespaceURI,localName)
+ {
+ if (element.hasAttributeNS(namespaceURI,localName))
+ return element.getAttributeNS(namespaceURI,localName);
+ else
+ return null;
+ }
+
+ // public
+ DOM_getStringAttribute = function(element,name)
+ {
+ var value = element.getAttribute(name);
+ return (value == null) ? "" : value;
+ }
+
+ // public
+ DOM_getStringAttributeNS = function(element,namespaceURI,localName)
+ {
+ var value = element.getAttributeNS(namespaceURI,localName);
+ return (value == null) ? "" : value;
+ }
+
+ // public
+ DOM_getStyleProperties = function(node)
+ {
+ var properties = new Object();
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ for (var i = 0; i < node.style.length; i++) {
+ var name = node.style[i];
+ var value = node.style.getPropertyValue(name);
+ properties[name] = value;
+ }
+ }
+ return properties;
+ }
+
+ // public
+ DOM_deleteAllChildren = function(parent)
+ {
+ while (parent.firstChild != null)
+ DOM_deleteNode(parent.firstChild);
+ }
+
+ // public
+ DOM_shallowCopyElement = function(element)
+ {
+ return DOM_cloneNode(element,false,true);
+ }
+
+ // public
+ DOM_removeNodeButKeepChildren = function(node)
+ {
+ if (node.parentNode == null)
+ throw new Error("Node "+nodeString(node)+" has no parent");
+ var offset = DOM_nodeOffset(node);
+ var childCount = node.childNodes.length;
+
+ trackedPositionsForNode(node.parentNode).forEach(function (position) {
+ if (position.offset > offset)
+ position.offset += childCount-1;
+ });
+
+ trackedPositionsForNode(node).forEach(function (position) {
+ position.node = node.parentNode;
+ position.offset += offset;
+ });
+
+ var parent = node.parentNode;
+ var nextSibling = node.nextSibling;
+ deleteNodeInternal(node,false);
+
+ while (node.firstChild != null) {
+ var child = node.firstChild;
+ insertBeforeInternal(parent,child,nextSibling);
+ }
+ }
+
+ // public
+ DOM_replaceElement = function(oldElement,newName)
+ {
+ var listeners = listenersForNode(oldElement);
+ var newElement = DOM_createElement(document,newName);
+ for (var i = 0; i < oldElement.attributes.length; i++) {
+ var name = oldElement.attributes[i].nodeName; // check-ok
+ var value = oldElement.getAttribute(name);
+ DOM_setAttribute(newElement,name,value);
+ }
+
+ var positions = arrayCopy(trackedPositionsForNode(oldElement));
+ if (positions != null) {
+ for (var i = 0; i < positions.length; i++) {
+ if (positions[i].node != oldElement)
+ throw new Error("replaceElement: position with wrong node");
+ positions[i].node = newElement;
+ }
+ }
+
+ var parent = oldElement.parentNode;
+ var nextSibling = oldElement.nextSibling;
+ while (oldElement.firstChild != null)
+ appendChildInternal(newElement,oldElement.firstChild);
+ // Deletion must be done first so if it's a heading, the outline code picks up the change
+ // correctly. Otherwise, there could be two elements in the document with the same id at
+ // the same time.
+ deleteNodeInternal(oldElement,false);
+ insertBeforeInternal(parent,newElement,nextSibling);
+
+ for (var i = 0; i < listeners.length; i++)
+ listeners[i].afterReplaceElement(oldElement,newElement);
+
+ return newElement;
+ }
+
+ // public
+ DOM_wrapNode = function(node,elementName)
+ {
+ return DOM_wrapSiblings(node,node,elementName);
+ }
+
+ DOM_wrapSiblings = function(first,last,elementName)
+ {
+ var parent = first.parentNode;
+ var wrapper = DOM_createElement(document,elementName);
+
+ if (first.parentNode != last.parentNode)
+ throw new Error("first and last are not siblings");
+
+ if (parent != null) {
+ var firstOffset = DOM_nodeOffset(first);
+ var lastOffset = DOM_nodeOffset(last);
+ var nodeCount = lastOffset - firstOffset + 1;
+ trackedPositionsForNode(parent).forEach(function (position) {
+ if ((position.offset >= firstOffset) && (position.offset <= lastOffset+1)) {
+ position.node = wrapper;
+ position.offset -= firstOffset;
+ }
+ else if (position.offset > lastOffset+1) {
+ position.offset -= (nodeCount-1);
+ }
+ });
+
+ insertBeforeInternal(parent,wrapper,first);
+ }
+
+ var end = last.nextSibling;
+ var current = first;
+ while (current != end) {
+ var next = current.nextSibling;
+ appendChildInternal(wrapper,current);
+ current = next;
+ }
+ return wrapper;
+ }
+
+ // public
+ DOM_mergeWithNextSibling = function(current,whiteList)
+ {
+ var parent = current.parentNode;
+ var next = current.nextSibling;
+
+ if ((next == null) || !DOM_nodesMergeable(current,next,whiteList))
+ return;
+
+ var currentLength = DOM_maxChildOffset(current);
+ var nextOffset = DOM_nodeOffset(next);
+
+ var lastChild = null;
+
+ if (current.nodeType == Node.ELEMENT_NODE) {
+ lastChild = current.lastChild;
+ DOM_insertBefore(current,next,null);
+ DOM_removeNodeButKeepChildren(next);
+ }
+ else {
+ DOM_insertCharacters(current,current.nodeValue.length,next.nodeValue);
+
+ trackedPositionsForNode(next).forEach(function (position) {
+ position.node = current;
+ position.offset = position.offset+currentLength;
+ });
+
+ trackedPositionsForNode(current.parentNode).forEach(function (position) {
+ if (position.offset == nextOffset) {
+ position.node = current;
+ position.offset = currentLength;
+ }
+ });
+
+ DOM_deleteNode(next);
+ }
+
+ if (lastChild != null)
+ DOM_mergeWithNextSibling(lastChild,whiteList);
+ }
+
+ // public
+ DOM_nodesMergeable = function(a,b,whiteList)
+ {
+ if ((a.nodeType == Node.TEXT_NODE) && (b.nodeType == Node.TEXT_NODE))
+ return true;
+ else if ((a.nodeType == Node.ELEMENT_NODE) && (b.nodeType == Node.ELEMENT_NODE))
+ return elementsMergableTypes(a,b);
+ else
+ return false;
+
+ function elementsMergableTypes(a,b)
+ {
+ if (whiteList["force"] && isParagraphNode(a) && isParagraphNode(b))
+ return true;
+ if ((a._type == b._type) &&
+ whiteList[a._type] &&
+ (a.attributes.length == b.attributes.length)) {
+ for (var i = 0; i < a.attributes.length; i++) {
+ var attrName = a.attributes[i].nodeName; // check-ok
+ if (a.getAttribute(attrName) != b.getAttribute(attrName))
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ function getDataForNode(node,create)
+ {
+ if (node._nodeId == null)
+ throw new Error("getDataForNode: node "+node.nodeName+" has no _nodeId property");
+ if ((nodeData[node._nodeId] == null) && create)
+ nodeData[node._nodeId] = new Object();
+ return nodeData[node._nodeId];
+ }
+
+ function trackedPositionsForNode(node)
+ {
+ var data = getDataForNode(node,false);
+ if ((data != null) && (data.trackedPositions != null)) {
+ // Sanity check
+ for (var i = 0; i < data.trackedPositions.length; i++) {
+ if (data.trackedPositions[i].node != node)
+ throw new Error("Position "+data.trackedPositions[i]+" has wrong node");
+ }
+ return arrayCopy(data.trackedPositions);
+ }
+ else {
+ return [];
+ }
+ }
+
+ function listenersForNode(node)
+ {
+ var data = getDataForNode(node,false);
+ if ((data != null) && (data.listeners != null))
+ return data.listeners;
+ else
+ return [];
+ }
+
+ // public
+ DOM_replaceCharacters = function(textNode,startOffset,endOffset,replacement)
+ {
+ // Note that we do the insertion *before* the deletion so that the position is properly
+ // maintained, and ends up at the end of the replacement (unless it was previously at
+ // startOffset, in which case it will stay the same)
+ DOM_insertCharacters(textNode,startOffset,replacement);
+ DOM_deleteCharacters(textNode,startOffset+replacement.length,endOffset+replacement.length);
+ }
+
+ // public
+ DOM_addTrackedPosition = function(position)
+ {
+ var data = getDataForNode(position.node,true);
+ if (data.trackedPositions == null)
+ data.trackedPositions = new Array();
+ data.trackedPositions.push(position);
+ }
+
+ // public
+ DOM_removeTrackedPosition = function(position)
+ {
+ var data = getDataForNode(position.node,false);
+ if ((data == null) || (data.trackedPositions == null))
+ throw new Error("DOM_removeTrackedPosition: no registered positions for this node "+
+ "("+position.node.nodeName+")");
+ for (var i = 0; i < data.trackedPositions.length; i++) {
+ if (data.trackedPositions[i] == position) {
+ data.trackedPositions.splice(i,1);
+ return;
+ }
+ }
+ throw new Error("DOM_removeTrackedPosition: position is not registered ("+
+ data.trackedPositions.length+" others)");
+ }
+
+ // public
+ DOM_removeAdjacentWhitespace = function(node)
+ {
+ while ((node.previousSibling != null) && (isWhitespaceTextNode(node.previousSibling)))
+ DOM_deleteNode(node.previousSibling);
+ while ((node.nextSibling != null) && (isWhitespaceTextNode(node.nextSibling)))
+ DOM_deleteNode(node.nextSibling);
+ }
+
+ // public
+ DOM_documentHead = function(document)
+ {
+ var html = document.documentElement;
+ for (var child = html.firstChild; child != null; child = child.nextSibling) {
+ if (child._type == HTML_HEAD)
+ return child;
+ }
+ throw new Error("Document contains no HEAD element");
+ }
+
+ // public
+ DOM_ensureUniqueIds = function(root)
+ {
+ var ids = new Object();
+ var duplicates = new Array();
+
+ discoverDuplicates(root);
+ renameDuplicates();
+
+ return;
+
+ function discoverDuplicates(node)
+ {
+ if (node.nodeType != Node.ELEMENT_NODE)
+ return;
+
+ var id = node.getAttribute("id");
+ if ((id != null) && (id != "")) {
+ if (ids[id])
+ duplicates.push(node);
+ else
+ ids[id] = true;
+ }
+ for (var child = node.firstChild; child != null; child = child.nextSibling)
+ discoverDuplicates(child);
+ }
+
+ function renameDuplicates()
+ {
+ var nextNumberForPrefix = new Object();
+ for (var i = 0; i < duplicates.length; i++) {
+ var id = duplicates[i].getAttribute("id");
+ var prefix = id.replace(/[0-9]+$/,"");
+ var num = nextNumberForPrefix[prefix] ? nextNumberForPrefix[prefix] : 1;
+
+ var candidate;
+ do {
+ candidate = prefix + num;
+ num++;
+ } while (ids[candidate]);
+
+ DOM_setAttribute(duplicates[i],"id",candidate);
+ ids[candidate] = true;
+ nextNumberForPrefix[prefix] = num;
+ }
+ }
+ }
+
+ // public
+ DOM_nodeOffset = function(node,parent)
+ {
+ if ((node == null) && (parent != null))
+ return DOM_maxChildOffset(parent);
+ var offset = 0;
+ for (var n = node.parentNode.firstChild; n != node; n = n.nextSibling)
+ offset++;
+ return offset;
+ }
+
+ // public
+ DOM_maxChildOffset = function(node)
+ {
+ if (node.nodeType == Node.TEXT_NODE)
+ return node.nodeValue.length;
+ else if (node.nodeType == Node.ELEMENT_NODE)
+ return node.childNodes.length;
+ else
+ throw new Error("maxOffset: invalid node type ("+node.nodeType+")");
+ }
+
+ function incIgnoreMutations()
+ {
+ UndoManager_addAction(decIgnoreMutations);
+ ignoreMutations++;
+ }
+
+ function decIgnoreMutations()
+ {
+ UndoManager_addAction(incIgnoreMutations);
+ ignoreMutations--;
+ if (ignoreMutations < 0)
+ throw new Error("ignoreMutations is now negative");
+ }
+
+ // public
+ DOM_ignoreMutationsWhileExecuting = function(fun)
+ {
+ incIgnoreMutations();
+ try {
+ return fun();
+ }
+ finally {
+ decIgnoreMutations();
+ }
+ }
+
+ // public
+ DOM_getIgnoreMutations = function()
+ {
+ return ignoreMutations;
+ }
+
+ // public
+ DOM_addListener = function(node,listener)
+ {
+ var data = getDataForNode(node,true);
+ if (data.listeners == null)
+ data.listeners = [listener];
+ else
+ data.listeners.push(listener);
+ }
+
+ // public
+ DOM_removeListener = function(node,listener)
+ {
+ var list = listenersForNode(node);
+ var index = list.indexOf(listener);
+ if (index >= 0)
+ list.splice(index,1);
+ }
+
+ // public
+ function Listener()
+ {
+ }
+
+ Listener.prototype.afterReplaceElement = function(oldElement,newElement) {}
+
+ DOM_Listener = Listener;
+
+})();
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Editor.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Editor.js b/experiments/editorFramework/src/Javascript_Layer_0/Editor.js
new file mode 100644
index 0000000..50f0d21
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Editor.js
@@ -0,0 +1,113 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+var Editor_getBackMessages;
+var Editor_debug;
+var Editor_addOutlineItem;
+var Editor_updateOutlineItem;
+var Editor_removeOutlineItem;
+var Editor_outlineUpdated;
+var Editor_setCursor;
+var Editor_setSelectionHandles;
+var Editor_clearSelectionHandlesAndCursor;
+var Editor_setSelectionBounds;
+var Editor_updateAutoCorrect;
+var Editor_error;
+var debug;
+
+(function(){
+
+ var backMessages = new Array();
+
+ function addBackMessage()
+ {
+ backMessages.push(arrayCopy(arguments));
+ return null;
+ }
+
+ Editor_getBackMessages = function()
+ {
+ var result = JSON.stringify(backMessages);
+ backMessages = new Array();
+ return result;
+ };
+
+ Editor_debug = function(str)
+ {
+ addBackMessage("debug",str);
+ };
+
+ Editor_error = function(error,type)
+ {
+ if (type == null)
+ type = "";
+ addBackMessage("error",error.toString(),type);
+ };
+
+ Editor_addOutlineItem = function(itemId,type,title)
+ {
+ addBackMessage("addOutlineItem",itemId,type,title);
+ };
+
+ Editor_updateOutlineItem = function(itemId,title)
+ {
+ addBackMessage("updateOutlineItem",itemId,title);
+ };
+
+ Editor_removeOutlineItem = function(itemId)
+ {
+ addBackMessage("removeOutlineItem",itemId);
+ };
+
+ Editor_outlineUpdated = function()
+ {
+ addBackMessage("outlineUpdated");
+ };
+
+ Editor_setCursor = function(x,y,width,height)
+ {
+ addBackMessage("setCursor",x,y,width,height);
+ };
+
+ Editor_setSelectionHandles = function(x1,y1,height1,x2,y2,height2)
+ {
+ addBackMessage("setSelectionHandles",x1,y1,height1,x2,y2,height2);
+ };
+
+ Editor_setTableSelection = function(x,y,width,height)
+ {
+ addBackMessage("setTableSelection",x,y,width,height);
+ };
+
+ Editor_setSelectionBounds = function(left,top,right,bottom)
+ {
+ addBackMessage("setSelectionBounds",left,top,right,bottom);
+ };
+
+ Editor_clearSelectionHandlesAndCursor = function()
+ {
+ addBackMessage("clearSelectionHandlesAndCursor");
+ };
+
+ Editor_updateAutoCorrect = function()
+ {
+ addBackMessage("updateAutoCorrect");
+ };
+
+ debug = Editor_debug;
+
+})();
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js b/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js
new file mode 100644
index 0000000..06702a2
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js
@@ -0,0 +1,344 @@
+// Automatically generated from elements.txt
+ElementTypes = {
+ "#DOCUMENT": 1,
+ "#document": 1,
+ "#TEXT": 2,
+ "#text": 2,
+ "#COMMENT": 3,
+ "#comment": 3,
+ "A": 4,
+ "a": 4,
+ "ABBR": 5,
+ "abbr": 5,
+ "ADDRESS": 6,
+ "address": 6,
+ "AREA": 7,
+ "area": 7,
+ "ARTICLE": 8,
+ "article": 8,
+ "ASIDE": 9,
+ "aside": 9,
+ "AUDIO": 10,
+ "audio": 10,
+ "B": 11,
+ "b": 11,
+ "BASE": 12,
+ "base": 12,
+ "BDI": 13,
+ "bdi": 13,
+ "BDO": 14,
+ "bdo": 14,
+ "BLOCKQUOTE": 15,
+ "blockquote": 15,
+ "BODY": 16,
+ "body": 16,
+ "BR": 17,
+ "br": 17,
+ "BUTTON": 18,
+ "button": 18,
+ "CANVAS": 19,
+ "canvas": 19,
+ "CAPTION": 20,
+ "caption": 20,
+ "CITE": 21,
+ "cite": 21,
+ "CODE": 22,
+ "code": 22,
+ "COL": 23,
+ "col": 23,
+ "COLGROUP": 24,
+ "colgroup": 24,
+ "COMMAND": 25,
+ "command": 25,
+ "DATA": 26,
+ "data": 26,
+ "DATALIST": 27,
+ "datalist": 27,
+ "DD": 28,
+ "dd": 28,
+ "DEL": 29,
+ "del": 29,
+ "DETAILS": 30,
+ "details": 30,
+ "DFN": 31,
+ "dfn": 31,
+ "DIALOG": 32,
+ "dialog": 32,
+ "DIV": 33,
+ "div": 33,
+ "DL": 34,
+ "dl": 34,
+ "DT": 35,
+ "dt": 35,
+ "EM": 36,
+ "em": 36,
+ "EMBED": 37,
+ "embed": 37,
+ "FIELDSET": 38,
+ "fieldset": 38,
+ "FIGCAPTION": 39,
+ "figcaption": 39,
+ "FIGURE": 40,
+ "figure": 40,
+ "FOOTER": 41,
+ "footer": 41,
+ "FORM": 42,
+ "form": 42,
+ "H1": 43,
+ "h1": 43,
+ "H2": 44,
+ "h2": 44,
+ "H3": 45,
+ "h3": 45,
+ "H4": 46,
+ "h4": 46,
+ "H5": 47,
+ "h5": 47,
+ "H6": 48,
+ "h6": 48,
+ "HEAD": 49,
+ "head": 49,
+ "HEADER": 50,
+ "header": 50,
+ "HGROUP": 51,
+ "hgroup": 51,
+ "HR": 52,
+ "hr": 52,
+ "HTML": 53,
+ "html": 53,
+ "I": 54,
+ "i": 54,
+ "IFRAME": 55,
+ "iframe": 55,
+ "IMG": 56,
+ "img": 56,
+ "INPUT": 57,
+ "input": 57,
+ "INS": 58,
+ "ins": 58,
+ "KBD": 59,
+ "kbd": 59,
+ "KEYGEN": 60,
+ "keygen": 60,
+ "LABEL": 61,
+ "label": 61,
+ "LEGEND": 62,
+ "legend": 62,
+ "LI": 63,
+ "li": 63,
+ "LINK": 64,
+ "link": 64,
+ "MAP": 65,
+ "map": 65,
+ "MARK": 66,
+ "mark": 66,
+ "MENU": 67,
+ "menu": 67,
+ "META": 68,
+ "meta": 68,
+ "METER": 69,
+ "meter": 69,
+ "NAV": 70,
+ "nav": 70,
+ "NOSCRIPT": 71,
+ "noscript": 71,
+ "OBJECT": 72,
+ "object": 72,
+ "OL": 73,
+ "ol": 73,
+ "OPTGROUP": 74,
+ "optgroup": 74,
+ "OPTION": 75,
+ "option": 75,
+ "OUTPUT": 76,
+ "output": 76,
+ "P": 77,
+ "p": 77,
+ "PARAM": 78,
+ "param": 78,
+ "PRE": 79,
+ "pre": 79,
+ "PROGRESS": 80,
+ "progress": 80,
+ "Q": 81,
+ "q": 81,
+ "RP": 82,
+ "rp": 82,
+ "RT": 83,
+ "rt": 83,
+ "RUBY": 84,
+ "ruby": 84,
+ "S": 85,
+ "s": 85,
+ "SAMP": 86,
+ "samp": 86,
+ "SCRIPT": 87,
+ "script": 87,
+ "SECTION": 88,
+ "section": 88,
+ "SELECT": 89,
+ "select": 89,
+ "SMALL": 90,
+ "small": 90,
+ "SOURCE": 91,
+ "source": 91,
+ "SPAN": 92,
+ "span": 92,
+ "STRONG": 93,
+ "strong": 93,
+ "STYLE": 94,
+ "style": 94,
+ "SUB": 95,
+ "sub": 95,
+ "SUMMARY": 96,
+ "summary": 96,
+ "SUP": 97,
+ "sup": 97,
+ "TABLE": 98,
+ "table": 98,
+ "TBODY": 99,
+ "tbody": 99,
+ "TD": 100,
+ "td": 100,
+ "TEXTAREA": 101,
+ "textarea": 101,
+ "TFOOT": 102,
+ "tfoot": 102,
+ "TH": 103,
+ "th": 103,
+ "THEAD": 104,
+ "thead": 104,
+ "TIME": 105,
+ "time": 105,
+ "TITLE": 106,
+ "title": 106,
+ "TR": 107,
+ "tr": 107,
+ "TRACK": 108,
+ "track": 108,
+ "U": 109,
+ "u": 109,
+ "UL": 110,
+ "ul": 110,
+ "VAR": 111,
+ "var": 111,
+ "VIDEO": 112,
+ "video": 112,
+ "WBR": 113,
+ "wbr": 113,
+};
+
+HTML_DOCUMENT = 1;
+HTML_TEXT = 2;
+HTML_COMMENT = 3;
+HTML_A = 4;
+HTML_ABBR = 5;
+HTML_ADDRESS = 6;
+HTML_AREA = 7;
+HTML_ARTICLE = 8;
+HTML_ASIDE = 9;
+HTML_AUDIO = 10;
+HTML_B = 11;
+HTML_BASE = 12;
+HTML_BDI = 13;
+HTML_BDO = 14;
+HTML_BLOCKQUOTE = 15;
+HTML_BODY = 16;
+HTML_BR = 17;
+HTML_BUTTON = 18;
+HTML_CANVAS = 19;
+HTML_CAPTION = 20;
+HTML_CITE = 21;
+HTML_CODE = 22;
+HTML_COL = 23;
+HTML_COLGROUP = 24;
+HTML_COMMAND = 25;
+HTML_DATA = 26;
+HTML_DATALIST = 27;
+HTML_DD = 28;
+HTML_DEL = 29;
+HTML_DETAILS = 30;
+HTML_DFN = 31;
+HTML_DIALOG = 32;
+HTML_DIV = 33;
+HTML_DL = 34;
+HTML_DT = 35;
+HTML_EM = 36;
+HTML_EMBED = 37;
+HTML_FIELDSET = 38;
+HTML_FIGCAPTION = 39;
+HTML_FIGURE = 40;
+HTML_FOOTER = 41;
+HTML_FORM = 42;
+HTML_H1 = 43;
+HTML_H2 = 44;
+HTML_H3 = 45;
+HTML_H4 = 46;
+HTML_H5 = 47;
+HTML_H6 = 48;
+HTML_HEAD = 49;
+HTML_HEADER = 50;
+HTML_HGROUP = 51;
+HTML_HR = 52;
+HTML_HTML = 53;
+HTML_I = 54;
+HTML_IFRAME = 55;
+HTML_IMG = 56;
+HTML_INPUT = 57;
+HTML_INS = 58;
+HTML_KBD = 59;
+HTML_KEYGEN = 60;
+HTML_LABEL = 61;
+HTML_LEGEND = 62;
+HTML_LI = 63;
+HTML_LINK = 64;
+HTML_MAP = 65;
+HTML_MARK = 66;
+HTML_MENU = 67;
+HTML_META = 68;
+HTML_METER = 69;
+HTML_NAV = 70;
+HTML_NOSCRIPT = 71;
+HTML_OBJECT = 72;
+HTML_OL = 73;
+HTML_OPTGROUP = 74;
+HTML_OPTION = 75;
+HTML_OUTPUT = 76;
+HTML_P = 77;
+HTML_PARAM = 78;
+HTML_PRE = 79;
+HTML_PROGRESS = 80;
+HTML_Q = 81;
+HTML_RP = 82;
+HTML_RT = 83;
+HTML_RUBY = 84;
+HTML_S = 85;
+HTML_SAMP = 86;
+HTML_SCRIPT = 87;
+HTML_SECTION = 88;
+HTML_SELECT = 89;
+HTML_SMALL = 90;
+HTML_SOURCE = 91;
+HTML_SPAN = 92;
+HTML_STRONG = 93;
+HTML_STYLE = 94;
+HTML_SUB = 95;
+HTML_SUMMARY = 96;
+HTML_SUP = 97;
+HTML_TABLE = 98;
+HTML_TBODY = 99;
+HTML_TD = 100;
+HTML_TEXTAREA = 101;
+HTML_TFOOT = 102;
+HTML_TH = 103;
+HTML_THEAD = 104;
+HTML_TIME = 105;
+HTML_TITLE = 106;
+HTML_TR = 107;
+HTML_TRACK = 108;
+HTML_U = 109;
+HTML_UL = 110;
+HTML_VAR = 111;
+HTML_VIDEO = 112;
+HTML_WBR = 113;
+HTML_COUNT = 114;
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Equations.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Equations.js b/experiments/editorFramework/src/Javascript_Layer_0/Equations.js
new file mode 100644
index 0000000..46bace8
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Equations.js
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+var Equations_insertEquation;
+
+(function() {
+
+ Equations_insertEquation = function()
+ {
+ var math = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","math");
+ var mrow = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
+ var msup = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","msup");
+ var mi = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
+ var mn = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mn");
+ var mfrac = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mfrac");
+ var mrow1 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
+ var mrow2 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
+ var mi1 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
+ var mi2 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
+ var mo = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mo");
+
+ DOM_appendChild(mi,DOM_createTextNode(document,"x"));
+ DOM_appendChild(mn,DOM_createTextNode(document,"2"));
+ DOM_appendChild(mo,DOM_createTextNode(document,"+"));
+ DOM_appendChild(mi1,DOM_createTextNode(document,"a"));
+ DOM_appendChild(mi2,DOM_createTextNode(document,"b"));
+ DOM_appendChild(mrow1,mi1);
+ DOM_appendChild(mrow2,mi2);
+ DOM_appendChild(mfrac,mrow1);
+ DOM_appendChild(mfrac,mrow2);
+ DOM_appendChild(msup,mi);
+ DOM_appendChild(msup,mn);
+ DOM_appendChild(mrow,msup);
+ DOM_appendChild(mrow,mo);
+ DOM_appendChild(mrow,mfrac);
+ DOM_appendChild(math,mrow);
+
+ Clipboard_pasteNodes([math]);
+ }
+
+})();
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Figures.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Figures.js b/experiments/editorFramework/src/Javascript_Layer_0/Figures.js
new file mode 100644
index 0000000..dcda1fc
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Figures.js
@@ -0,0 +1,125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+var Figures_insertFigure;
+var Figures_getSelectedFigureId;
+var Figures_getProperties;
+var Figures_setProperties;
+var Figures_getGeometry;
+
+(function() {
+
+ // public
+ Figures_insertFigure = function(filename,width,numbered,caption)
+ {
+ UndoManager_newGroup("Insert figure");
+
+ var figure = DOM_createElement(document,"FIGURE");
+ var img = DOM_createElement(document,"IMG");
+ DOM_setAttribute(img,"src",encodeURI(filename));
+ DOM_setStyleProperties(img,{"width": width});
+ DOM_appendChild(figure,img);
+
+ if ((caption != null) && (caption != "")) {
+ var figcaption = DOM_createElement(document,"FIGCAPTION");
+ DOM_appendChild(figcaption,DOM_createTextNode(document,caption));
+ DOM_appendChild(figure,figcaption);
+ }
+
+ Clipboard_pasteNodes([figure]);
+
+ // Now that the figure has been inserted into the DOM tree, the outline code will
+ // have noticed it and added an id attribute, as well as a caption giving the
+ // table number.
+ Outline_setNumbered(figure.getAttribute("id"),numbered);
+
+ // Place the cursor directly after the figure
+ var offset = DOM_nodeOffset(figure);
+ var pos = new Position(figure.parentNode,offset);
+ pos = Position_closestMatchForwards(pos,Position_okForMovement);
+ Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+
+ PostponedActions_add(UndoManager_newGroup);
+ }
+
+ Figures_getSelectedFigureId = function()
+ {
+ var element = Cursor_getAdjacentNodeWithType(HTML_FIGURE);
+ return element ? element.getAttribute("id") : null;
+ }
+
+ // public
+ Figures_getProperties = function(itemId)
+ {
+ var figure = document.getElementById(itemId);
+ if (figure == null)
+ return null;
+ var rect = figure.getBoundingClientRect();
+ var result = { width: null, src: null };
+
+ var img = firstDescendantOfType(figure,HTML_IMG);
+ if (img != null) {
+ result.src = decodeURI(img.getAttribute("src"));
+ result.width = img.style.width;
+
+ if ((result.width == null) || (result.width == ""))
+ result.width = DOM_getAttribute(img,"width");
+ }
+ return result;
+ }
+
+ // public
+ Figures_setProperties = function(itemId,width,src)
+ {
+ var figure = document.getElementById(itemId);
+ if (figure == null)
+ return null;
+ var img = firstDescendantOfType(figure,HTML_IMG);
+ if (img != null) {
+ if (src == null)
+ DOM_removeAttribute(img,"src");
+ else
+ DOM_setAttribute(img,"src",encodeURI(src));
+
+ DOM_setStyleProperties(img,{"width": width});
+ if (img.getAttribute("style") == "")
+ DOM_removeAttribute(img,"style");
+ Selection_update();
+ }
+ }
+
+ // public
+ Figures_getGeometry = function(itemId)
+ {
+ var figure = document.getElementById(itemId);
+ if ((figure == null) || (figure.parentNode == null))
+ return null;
+ var img = firstDescendantOfType(figure,HTML_IMG);
+ if (img == null)
+ return null;
+
+ var figcaption = firstChildOfType(figure,HTML_FIGCAPTION);
+
+ var result = new Object();
+ result.contentRect = xywhAbsElementRect(img);
+ result.fullRect = xywhAbsElementRect(figure);
+ result.parentRect = xywhAbsElementRect(figure.parentNode);
+ result.hasCaption = (figcaption != null);
+ return result;
+ }
+
+})();