Return-Path: X-Original-To: apmail-corinthia-commits-archive@minotaur.apache.org Delivered-To: apmail-corinthia-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0CCB31818F for ; Mon, 17 Aug 2015 08:50:24 +0000 (UTC) Received: (qmail 65916 invoked by uid 500); 17 Aug 2015 08:50:17 -0000 Delivered-To: apmail-corinthia-commits-archive@corinthia.apache.org Received: (qmail 65885 invoked by uid 500); 17 Aug 2015 08:50:17 -0000 Mailing-List: contact commits-help@corinthia.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@corinthia.incubator.apache.org Delivered-To: mailing list commits@corinthia.incubator.apache.org Received: (qmail 65876 invoked by uid 99); 17 Aug 2015 08:50:17 -0000 Received: from Unknown (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 17 Aug 2015 08:50:17 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 27E68DE6F0 for ; Mon, 17 Aug 2015 08:50:17 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.204 X-Spam-Level: * X-Spam-Status: No, score=1.204 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.577, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-west.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id LOxUWrjGAPYC for ; Mon, 17 Aug 2015 08:50:07 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-west.apache.org (ASF Mail Server at mx1-us-west.apache.org) with SMTP id 8289E2119F for ; Mon, 17 Aug 2015 08:49:54 +0000 (UTC) Received: (qmail 64777 invoked by uid 99); 17 Aug 2015 08:49:54 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 17 Aug 2015 08:49:54 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 17577E00D6; Mon, 17 Aug 2015 08:49:54 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jani@apache.org To: commits@corinthia.incubator.apache.org Date: Mon, 17 Aug 2015 08:50:04 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [12/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/Layer0_Javascript/Formatting.js ---------------------------------------------------------------------- diff --git a/experiments/editorFramework/src/Layer0_Javascript/Formatting.js b/experiments/editorFramework/src/Layer0_Javascript/Formatting.js deleted file mode 100644 index 51bc5d3..0000000 --- a/experiments/editorFramework/src/Layer0_Javascript/Formatting.js +++ /dev/null @@ -1,1281 +0,0 @@ -// 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 Formatting_splitTextBefore; -var Formatting_splitTextAfter; -var Formatting_movePreceding; -var Formatting_moveFollowing; -var Formatting_splitAroundSelection; -var Formatting_mergeUpwards; -var Formatting_mergeWithNeighbours; -var Formatting_paragraphTextUpToPosition; -var Formatting_getAllNodeProperties; -var Formatting_getFormatting; -var Formatting_pushDownInlineProperties; -var Formatting_applyFormattingChanges; -var Formatting_formatInlineNode; - -var Formatting_MERGEABLE_INLINE; -var Formatting_MERGEABLE_BLOCK; -var Formatting_MERGEABLE_BLOCK_AND_INLINE; - -(function() { - - // Some properties in CSS, such as 'margin', 'border', and 'padding', are shorthands which - // set multiple, more fine-grained properties. The CSS spec outlines what these are - e.g. - // an assignment to the 'margin' property is considered a simultaneous assignment to - // 'margin-left', 'margin-right', 'margin-top', and 'margin-bottom' properties. - - // However, Firefox contains a bug (https://bugzilla.mozilla.org/show_bug.cgi?id=241234), - // which has gone unfixed for more than six years, whereby it actually sets different - // properties for *-left and *-right, which are reflected when examining the style property - // of an element. Additionally, it also gives an error if you try to set these, so if you simply - // get all the style properties and try to set them again it won't work. - - // To get around this problem, we record the following set of replacements. When getting the - // style properties of an element, we replace any properties with the names given below with - // their corresponding spec name. A null entry means that property should be ignored altogether. - - // You should always use getStyleProperties() instead of accessing element.style directly. - - var CSS_PROPERTY_REPLACEMENTS = { - "margin-left-value": "margin-left", - "margin-left-ltr-source": null, - "margin-left-rtl-source": null, - "margin-right-value": "margin-right", - "margin-right-ltr-source": null, - "margin-right-rtl-source": null, - "padding-left-value": "padding-left", - "padding-left-ltr-source": null, - "padding-left-rtl-source": null, - "padding-right-value": "padding-right", - "padding-right-ltr-source": null, - "padding-right-rtl-source": null, - "border-right-width-value": "border-right-width", - "border-right-width-ltr-source": null, - "border-right-width-rtl-source": null, - "border-left-width-value": "border-left-width", - "border-left-width-ltr-source": null, - "border-left-width-rtl-source": null, - "border-right-color-value": "border-right-color", - "border-right-color-ltr-source": null, - "border-right-color-rtl-source": null, - "border-left-color-value": "border-left-color", - "border-left-color-ltr-source": null, - "border-left-color-rtl-source": null, - "border-right-style-value": "border-right-style", - "border-right-style-ltr-source": null, - "border-right-style-rtl-source": null, - "border-left-style-value": "border-left-style", - "border-left-style-ltr-source": null, - "border-left-style-rtl-source": null, - }; - - // private - function getStyleProperties(element,dontReplace) - { - var properties = new Object(); - - for (var i = 0; i < element.style.length; i++) { - var name = element.style[i]; - var value = element.style.getPropertyValue(name); - - var replacement; - if (dontReplace) { - replacement = name; - } - else { - replacement = CSS_PROPERTY_REPLACEMENTS[name]; - if (typeof(replacement) == "undefined") - replacement = name; - } - - if (replacement != null) - properties[replacement] = value; - } - return properties; - } - - // public (for testing purposes only) - Formatting_splitAroundSelection = function(range,allowDirectInline) - { - Range_trackWhileExecuting(range,function() { - if (!allowDirectInline) - Range_ensureInlineNodesInParagraph(range); - Range_ensureValidHierarchy(range); - - if ((range.start.node.nodeType == Node.TEXT_NODE) && - (range.start.offset > 0)) { - Formatting_splitTextBefore(range.start); - if (range.end.node == range.start.node) - range.end.offset -= range.start.offset; - range.start.offset = 0; - } - else if (range.start.node.nodeType == Node.ELEMENT_NODE) { - Formatting_movePreceding(range.start,isBlockOrNoteNode); - } - else { - Formatting_movePreceding(new Position(range.start.node.parentNode, - DOM_nodeOffset(range.start.node)), - isBlockOrNoteNode); - } - - // Save the start and end position of the range. The mutation listeners will move it - // when the following node is moved, which we don't actually want in this case. - var startNode = range.start.node; - var startOffset = range.start.offset; - var endNode = range.end.node; - var endOffset = range.end.offset; - - if ((range.end.node.nodeType == Node.TEXT_NODE) && - (range.end.offset < range.end.node.nodeValue.length)) { - Formatting_splitTextAfter(range.end); - } - else if (range.end.node.nodeType == Node.ELEMENT_NODE) { - Formatting_moveFollowing(range.end,isBlockOrNoteNode); - } - else { - Formatting_moveFollowing(new Position(range.end.node.parentNode, - DOM_nodeOffset(range.end.node)+1), - isBlockOrNoteNode); - } - - range.start.node = startNode; - range.start.offset = startOffset; - range.end.node = endNode; - range.end.offset = endOffset; - }); - } - - // public - Formatting_mergeUpwards = function(node,whiteList) - { - while ((node != null) && whiteList[node._type]) { - var parent = node.parentNode; - Formatting_mergeWithNeighbours(node,whiteList,true); - node = parent; - } - } - - function isDiscardable(node) - { - if (node.nodeType != Node.ELEMENT_NODE) - return false; - - if (!isInlineNode(node)) - return false; - - if (isOpaqueNode(node)) - return false; - - for (var child = node.firstChild; child != null; child = child.nextSibling) { - if (!isDiscardable(child)) - return false; - } - - return true; - } - - // public (for use by tests) - Formatting_mergeWithNeighbours = function(node,whiteList,trim) - { - var parent = node.parentNode; - if (parent == null) - return; - - var start = node; - var end = node; - - while ((start.previousSibling != null) && - DOM_nodesMergeable(start.previousSibling,start,whiteList)) - start = start.previousSibling; - - while ((end.nextSibling != null) && - DOM_nodesMergeable(end,end.nextSibling,whiteList)) - end = end.nextSibling; - - if (trim) { - while ((start.previousSibling != null) && isDiscardable(start.previousSibling)) - DOM_deleteNode(start.previousSibling); - while ((end.nextSibling != null) && isDiscardable(end.nextSibling)) - DOM_deleteNode(end.nextSibling); - } - - if (start != end) { - var lastMerge; - do { - lastMerge = (start.nextSibling == end); - - var lastChild = null; - if (start.nodeType == Node.ELEMENT_NODE) - lastChild = start.lastChild; - - DOM_mergeWithNextSibling(start,whiteList); - - if (lastChild != null) - Formatting_mergeWithNeighbours(lastChild,whiteList); - } while (!lastMerge); - } - } - - // private - function mergeRange(range,whiteList) - { - var nodes = Range_getAllNodes(range); - for (var i = 0; i < nodes.length; i++) { - var next; - for (var p = nodes[i]; p != null; p = next) { - next = p.parentNode; - Formatting_mergeWithNeighbours(p,whiteList); - } - } - } - - // public (called from cursor.js) - Formatting_splitTextBefore = function(pos,parentCheckFn,force) - { - var node = pos.node; - var offset = pos.offset; - if (parentCheckFn == null) - parentCheckFn = isBlockNode; - - if (force || (offset > 0)) { - var before = DOM_createTextNode(document,""); - DOM_insertBefore(node.parentNode,before,node); - DOM_moveCharacters(node,0,offset,before,0,false,true); - Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)), - parentCheckFn,force); - return new Position(before,before.nodeValue.length); - } - else { - Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)), - parentCheckFn,force); - return pos; - } - } - - // public - Formatting_splitTextAfter = function(pos,parentCheckFn,force) - { - var node = pos.node; - var offset = pos.offset; - if (parentCheckFn == null) - parentCheckFn = isBlockNode; - - if (force || (offset < pos.node.nodeValue.length)) { - var after = DOM_createTextNode(document,""); - DOM_insertBefore(node.parentNode,after,node.nextSibling); - DOM_moveCharacters(node,offset,node.nodeValue.length,after,0,true,false); - Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1), - parentCheckFn,force); - return new Position(after,0); - } - else { - Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1), - parentCheckFn,force); - return pos; - } - } - - // FIXME: movePreceding and moveNext could possibly be optimised by passing in a (parent,child) - // pair instead of (node,offset), i.e. parent is the same as node, but rather than passing the - // index of a child, we pass the child itself (or null if the offset is equal to - // childNodes.length) - // public - Formatting_movePreceding = function(pos,parentCheckFn,force) - { - var node = pos.node; - var offset = pos.offset; - if (parentCheckFn(node) || (node == document.body)) - return new Position(node,offset); - - var toMove = new Array(); - var justWhitespace = true; - var result = new Position(node,offset); - for (var i = 0; i < offset; i++) { - if (!isWhitespaceTextNode(node.childNodes[i])) - justWhitespace = false; - toMove.push(node.childNodes[i]); - } - - if ((toMove.length > 0) || force) { - if (justWhitespace && !force) { - for (var i = 0; i < toMove.length; i++) - DOM_insertBefore(node.parentNode,toMove[i],node); - } - else { - var copy = DOM_shallowCopyElement(node); - DOM_insertBefore(node.parentNode,copy,node); - - for (var i = 0; i < toMove.length; i++) - DOM_insertBefore(copy,toMove[i],null); - result = new Position(copy,copy.childNodes.length); - } - } - - Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)), - parentCheckFn,force); - return result; - } - - // public - Formatting_moveFollowing = function(pos,parentCheckFn,force) - { - var node = pos.node; - var offset = pos.offset; - if (parentCheckFn(node) || (node == document.body)) - return new Position(node,offset); - - var toMove = new Array(); - var justWhitespace = true; - var result = new Position(node,offset); - for (var i = offset; i < node.childNodes.length; i++) { - if (!isWhitespaceTextNode(node.childNodes[i])) - justWhitespace = false; - toMove.push(node.childNodes[i]); - } - - if ((toMove.length > 0) || force) { - if (justWhitespace && !force) { - for (var i = 0; i < toMove.length; i++) - DOM_insertBefore(node.parentNode,toMove[i],node.nextSibling); - } - else { - var copy = DOM_shallowCopyElement(node); - DOM_insertBefore(node.parentNode,copy,node.nextSibling); - - for (var i = 0; i < toMove.length; i++) - DOM_insertBefore(copy,toMove[i],null); - result = new Position(copy,0); - } - } - - Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1), - parentCheckFn,force); - return result; - } - - // public - Formatting_paragraphTextUpToPosition = function(pos) - { - if (pos.node.nodeType == Node.TEXT_NODE) { - return stringToStartOfParagraph(pos.node,pos.offset); - } - else { - return stringToStartOfParagraph(Position_closestActualNode(pos),0); - } - - function stringToStartOfParagraph(node,offset) - { - var start = node; - var components = new Array(); - while (isInlineNode(node)) { - if (node.nodeType == Node.TEXT_NODE) { - if (node == start) - components.push(node.nodeValue.slice(0,offset)); - else - components.push(node.nodeValue); - } - - if (node.previousSibling != null) { - node = node.previousSibling; - while (isInlineNode(node) && (node.lastChild != null)) - node = node.lastChild; - } - else { - node = node.parentNode; - } - } - return components.reverse().join(""); - } - } - - // public - Formatting_getFormatting = function() - { - // FIXME: implement a more efficient version of this algorithm which avoids duplicate checks - - var range = Selection_get(); - if (range == null) - return {}; - - Range_assertValid(range,"Selection"); - - var outermost = Range_getOutermostNodes(range,true); - - var leafNodes = new Array(); - for (var i = 0; i < outermost.length; i++) { - findLeafNodes(outermost[i],leafNodes); - } - var empty = Range_isEmpty(range); - - var commonProperties = null; - for (var i = 0; i < leafNodes.length; i++) { - if (!isWhitespaceTextNode(leafNodes[i]) || empty) { - var leafNodeProperties = Formatting_getAllNodeProperties(leafNodes[i]); - if (leafNodeProperties["-uxwrite-paragraph-style"] == null) - leafNodeProperties["-uxwrite-paragraph-style"] = Keys.NONE_STYLE; - if (commonProperties == null) - commonProperties = leafNodeProperties; - else - commonProperties = intersection(commonProperties,leafNodeProperties); - } - } - - if (commonProperties == null) - commonProperties = {"-uxwrite-paragraph-style": Keys.NONE_STYLE}; - - for (var i = 0; i < leafNodes.length; i++) { - var leaf = leafNodes[i]; - if (leaf._type == HTML_LI) { - switch (leaf.parentNode._type) { - case HTML_UL: - commonProperties["-uxwrite-in-ul"] = "true"; - break; - case HTML_OL: - commonProperties["-uxwrite-in-ol"] = "true"; - break; - } - } - else { - for (var ancestor = leaf; - ancestor.parentNode != null; - ancestor = ancestor.parentNode) { - - if (ancestor.parentNode._type == HTML_LI) { - var havePrev = false; - for (var c = ancestor.previousSibling; c != null; c = c.previousSibling) { - if (!isWhitespaceTextNode(c)) { - havePrev = true; - break; - } - } - if (!havePrev) { - var listNode = ancestor.parentNode.parentNode; - switch (listNode._type) { - case HTML_UL: - commonProperties["-uxwrite-in-ul"] = "true"; - break; - case HTML_OL: - commonProperties["-uxwrite-in-ol"] = "true"; - break; - } - } - } - } - } - } - - getFlags(range.start,commonProperties); - - return commonProperties; - - function getFlags(pos,commonProperties) - { - var strBeforeCursor = Formatting_paragraphTextUpToPosition(pos); - - if (isWhitespaceString(strBeforeCursor)) { - var firstInParagraph = true; - for (var p = pos.node; isInlineNode(p); p = p.parentNode) { - if (p.previousSibling != null) - firstInParagraph = false; - } - if (firstInParagraph) - commonProperties["-uxwrite-shift"] = "true"; - } - if (strBeforeCursor.match(/\.\s*$/)) - commonProperties["-uxwrite-shift"] = "true"; - if (strBeforeCursor.match(/\([^\)]*$/)) - commonProperties["-uxwrite-in-brackets"] = "true"; - if (strBeforeCursor.match(/\u201c[^\u201d]*$/)) - commonProperties["-uxwrite-in-quotes"] = "true"; - } - - function intersection(a,b) - { - var result = new Object(); - for (var name in a) { - if (a[name] == b[name]) - result[name] = a[name]; - } - return result; - } - - function findLeafNodes(node,result) - { - if (node.firstChild == null) { - result.push(node); - } - else { - for (var child = node.firstChild; child != null; child = child.nextSibling) - findLeafNodes(child,result); - } - } - } - - // public - Formatting_getAllNodeProperties = function(node) - { - if (node == null) - throw new Error("Node is not in tree"); - - if (node == node.ownerDocument.body) - return new Object(); - - var properties = Formatting_getAllNodeProperties(node.parentNode); - - if (node.nodeType == Node.ELEMENT_NODE) { - // Note: Style names corresponding to element names must be in lowercase, because - // canonicaliseSelector() in Styles.js always converts selectors to lowercase. - if (node.hasAttribute("STYLE")) { - var nodeProperties = getStyleProperties(node); - for (var name in nodeProperties) - properties[name] = nodeProperties[name]; - } - - var type = node._type; - switch (type) { - case HTML_B: - properties["font-weight"] = "bold"; - break; - case HTML_I: - properties["font-style"] = "italic"; - break; - case HTML_U: { - var components = []; - if (properties["text-decoration"] != null) { - var components = properties["text-decoration"].toLowerCase().split(/\s+/); - if (components.indexOf("underline") == -1) - properties["text-decoration"] += " underline"; - } - else { - properties["text-decoration"] = "underline"; - } - break; - } -// case HTML_TT: -// properties["-uxwrite-in-tt"] = "true"; -// break; - case HTML_IMG: - properties["-uxwrite-in-image"] = "true"; - break; - case HTML_FIGURE: - properties["-uxwrite-in-figure"] = "true"; - break; - case HTML_TABLE: - properties["-uxwrite-in-table"] = "true"; - break; - case HTML_A: - if (node.hasAttribute("href")) { - var href = node.getAttribute("href"); - if (href.charAt(0) == "#") - properties["-uxwrite-in-reference"] = "true"; - else - properties["-uxwrite-in-link"] = "true"; - } - break; - case HTML_NAV: { - var className = DOM_getAttribute(node,"class"); - if ((className == Keys.SECTION_TOC) || - (className == Keys.FIGURE_TOC) || - (className == Keys.TABLE_TOC)) - properties["-uxwrite-in-toc"] = "true"; - break; - } - default: - if (PARAGRAPH_ELEMENTS[type]) { - var name = node.nodeName.toLowerCase(); - var selector; - if (node.hasAttribute("class")) - selector = name + "." + node.getAttribute("class"); - else - selector = name; - properties["-uxwrite-paragraph-style"] = selector; - } - break; - } - - if (OUTLINE_TITLE_ELEMENTS[type] && node.hasAttribute("id")) - properties["-uxwrite-in-item-title"] = node.getAttribute("id"); - } - - return properties; - } - - var PARAGRAPH_PROPERTIES = { - "margin-left": true, - "margin-right": true, - "margin-top": true, - "margin-bottom": true, - - "padding-left": true, - "padding-right": true, - "padding-top": true, - "padding-bottom": true, - - "border-left-width": true, - "border-right-width": true, - "border-top-width": true, - "border-bottom-width": true, - - "border-left-style": true, - "border-right-style": true, - "border-top-style": true, - "border-bottom-style": true, - - "border-left-color": true, - "border-right-color": true, - "border-top-color": true, - "border-bottom-color": true, - - "border-top-left-radius": true, - "border-top-right-radius": true, - "border-bottom-left-radius": true, - "border-bottom-right-radius": true, - - "text-align": true, - "text-indent": true, - "line-height": true, - "display": true, - - "width": true, - "height": true, - }; - - var SPECIAL_PROPERTIES = { - "-webkit-text-size-adjust": true, // set on HTML element for text scaling purposes - }; - - function isParagraphProperty(name) - { - return PARAGRAPH_PROPERTIES[name]; - } - - function isInlineProperty(name) - { - return !PARAGRAPH_PROPERTIES[name] && !SPECIAL_PROPERTIES[name]; - } - - // private - function putDirectInlineChildrenInParagraphs(parent) - { - var inlineChildren = new Array(); - for (var child = parent.firstChild; child != null; child = child.nextSibling) - if (isInlineNode(child)) - inlineChildren.push(child); - for (var i = 0; i < inlineChildren.length; i++) { - if (inlineChildren[i].parentNode == parent) { // may already have been moved - if (!isWhitespaceTextNode(inlineChildren[i])) - Hierarchy_wrapInlineNodesInParagraph(inlineChildren[i]); - } - } - } - - // private - function getParagraphs(nodes) - { - var array = new Array(); - var set = new NodeSet(); - for (var i = 0; i < nodes.length; i++) { - for (var anc = nodes[i].parentNode; anc != null; anc = anc.parentNode) { - if (anc._type == HTML_LI) - putDirectInlineChildrenInParagraphs(anc); - } - recurse(nodes[i]); - } - - var remove = new NodeSet(); - for (var i = 0; i < array.length; i++) { - for (var anc = array[i].parentNode; anc != null; anc = anc.parentNode) - remove.add(anc); - } - - var modified = new Array(); - for (var i = 0; i < array.length; i++) { - if (!remove.contains(array[i])) - modified.push(array[i]); - } - - return modified; - - function recurse(node) - { - if (node._type == HTML_LI) - putDirectInlineChildrenInParagraphs(node); - if (node.firstChild == null) { - // Leaf node - for (var anc = node; anc != null; anc = anc.parentNode) - if (isParagraphNode(anc)) { - add(anc); - } - } - else { - for (var child = node.firstChild; child != null; child = child.nextSibling) - recurse(child); - } - } - - function add(node) - { - if (!set.contains(node)) { - array.push(node); - set.add(node); - } - } - } - - // private - function setParagraphStyle(paragraph,selector) - { - var wasHeading = isHeadingNode(paragraph); - DOM_removeAttribute(paragraph,"class"); - if (selector == "") { - if (paragraph._type != HTML_P) - paragraph = DOM_replaceElement(paragraph,"P"); - } - else { - var elementClassRegex = /^([a-zA-Z0-9]+)?(\.(.+))?$/; - var result = elementClassRegex.exec(selector); - if ((result != null) && (result.length == 4)) { - var elementName = result[1]; - var className = result[3]; - - if (elementName == null) - elementName = "P"; - else - elementName = elementName.toUpperCase(); - - var elementType = ElementTypes[elementName]; - - if (!PARAGRAPH_ELEMENTS[elementType]) - return; // better than throwing an exception - - if (paragraph._type != elementType) - paragraph = DOM_replaceElement(paragraph,elementName); - - if (className != null) - DOM_setAttribute(paragraph,"class",className); - else - DOM_removeAttribute(paragraph,"class"); - } - } - - // FIXME: this will need to change when we add Word/ODF support, because the ids serve - // a purpose other than simply being targets for references - var isHeading = isHeadingNode(paragraph); - if (wasHeading && !isHeading) - DOM_removeAttribute(paragraph,"id"); - } - - // public - Formatting_pushDownInlineProperties = function(outermost) - { - for (var i = 0; i < outermost.length; i++) - outermost[i] = pushDownInlinePropertiesSingle(outermost[i]); - } - - // private - function pushDownInlinePropertiesSingle(target) - { - recurse(target.parentNode); - return target; - - function recurse(node) - { - if (node.nodeType == Node.DOCUMENT_NODE) - return; - - if (node.parentNode != null) - recurse(node.parentNode); - - var inlineProperties = new Object(); - var nodeProperties = getStyleProperties(node); - for (var name in nodeProperties) { - if (isInlineProperty(name)) { - inlineProperties[name] = nodeProperties[name]; - } - } - - var remove = new Object(); - for (var name in inlineProperties) - remove[name] = null; - DOM_setStyleProperties(node,remove); - - var type = node._type; - switch (type) { - case HTML_B: - inlineProperties["font-weight"] = "bold"; - break; - case HTML_I: - inlineProperties["font-style"] = "italic"; - break; - case HTML_U: - if (inlineProperties["text-decoration"] != null) - inlineProperties["text-decoration"] += " underline"; - else - inlineProperties["text-decoration"] = "underline"; - break; - } - - var special = extractSpecial(inlineProperties); - var count = Object.getOwnPropertyNames(inlineProperties).length; - - if ((count > 0) || special.bold || special.italic || special.underline) { - - var next; - for (var child = node.firstChild; child != null; child = next) { - next = child.nextSibling; - - if (isWhitespaceTextNode(child)) - continue; - - var replacement = applyInlineFormatting(child,inlineProperties,special); - if (target == child) - target = replacement; - } - } - - if (node.hasAttribute("style") && (node.style.length == 0)) - DOM_removeAttribute(node,"style"); - - switch (type) { - case HTML_B: - case HTML_I: - case HTML_U: - DOM_removeNodeButKeepChildren(node); - break; - } - } - } - - // private - function wrapInline(node,elementName) - { - if (!isInlineNode(node) || isAbstractSpan(node)) { - var next; - for (var child = node.firstChild; child != null; child = next) { - next = child.nextSibling; - wrapInline(child,elementName); - } - return node; - } - else { - return DOM_wrapNode(node,elementName); - } - } - - // private - function applyInlineFormatting(target,inlineProperties,special,applyToWhitespace) - { - if (!applyToWhitespace && isWhitespaceTextNode(target)) - return; - - if (special.underline) - target = wrapInline(target,"U"); - if (special.italic) - target = wrapInline(target,"I"); - if (special.bold) - target = wrapInline(target,"B"); - - var isbiu = false; - switch (target._type) { - case HTML_B: - case HTML_I: - case HTML_U: - isbiu = true; - break; - } - - if ((Object.getOwnPropertyNames(inlineProperties).length > 0) && - ((target.nodeType != Node.ELEMENT_NODE) || - isbiu || isSpecialSpan(target))) { - target = wrapInline(target,"SPAN"); - } - - - var propertiesToSet = new Object(); - for (var name in inlineProperties) { - var existing = target.style.getPropertyValue(name); - if ((existing == null) || (existing == "")) - propertiesToSet[name] = inlineProperties[name]; - } - DOM_setStyleProperties(target,propertiesToSet); - - return target; - } - - // private - function extractSpecial(properties) - { - var special = { bold: null, italic: null, underline: null }; - var fontWeight = properties["font-weight"]; - var fontStyle = properties["font-style"]; - var textDecoration = properties["text-decoration"]; - - if (typeof(fontWeight) != "undefined") { - special.bold = false; - if ((fontWeight != null) && - (fontWeight.toLowerCase() == "bold")) { - special.bold = true; - delete properties["font-weight"]; - } - } - - if (typeof(fontStyle) != "undefined") { - special.italic = false; - if ((fontStyle != null) && - (fontStyle.toLowerCase() == "italic")) { - special.italic = true; - delete properties["font-style"]; - } - } - - if (typeof(textDecoration) != "undefined") { - special.underline = false; - if (textDecoration != null) { - var values = textDecoration.toLowerCase().split(/\s+/); - var index; - while ((index = values.indexOf("underline")) >= 0) { - values.splice(index,1); - special.underline = true; - } - if (values.length == 0) - delete properties["text-decoration"]; - else - properties["text-decoration"] = values.join(" "); - } - } - return special; - } - - // private - function removeProperties(outermost,properties) - { - properties = clone(properties); - var special = extractSpecial(properties); - var remaining = new Array(); - for (var i = 0; i < outermost.length; i++) { - removePropertiesSingle(outermost[i],properties,special,remaining); - } - return remaining; - } - - // private - function getOutermostParagraphs(paragraphs) - { - var all = new NodeSet(); - for (var i = 0; i < paragraphs.length; i++) - all.add(paragraphs[i]); - - var result = new Array(); - for (var i = 0; i < paragraphs.length; i++) { - var haveAncestor = false; - for (var p = paragraphs[i].parentNode; p != null; p = p.parentNode) { - if (all.contains(p)) { - haveAncestor = true; - break; - } - } - if (!haveAncestor) - result.push(paragraphs[i]); - } - return result; - } - - // private - function removePropertiesSingle(node,properties,special,remaining) - { - if ((node.nodeType == Node.ELEMENT_NODE) && (node.hasAttribute("style"))) { - var remove = new Object(); - for (var name in properties) - remove[name] = null; - DOM_setStyleProperties(node,remove); - } - - var willRemove = false; - switch (node._type) { - case HTML_B: - willRemove = (special.bold != null); - break; - case HTML_I: - willRemove = (special.italic != null); - break; - case HTML_U: - willRemove = (special.underline != null); - break; - case HTML_SPAN: - willRemove = (!node.hasAttribute("style") && !isSpecialSpan(node)); - break; - } - - var childRemaining = willRemove ? remaining : null; - - var next; - for (var child = node.firstChild; child != null; child = next) { - next = child.nextSibling; - removePropertiesSingle(child,properties,special,childRemaining); - } - - if (willRemove) - DOM_removeNodeButKeepChildren(node); - else if (remaining != null) - remaining.push(node); - } - - function isSpecialSpan(span) - { - if (span._type == HTML_SPAN) { - if (span.hasAttribute(Keys.ABSTRACT_ELEMENT)) - return true; - var className = DOM_getStringAttribute(span,"class"); - if (className.indexOf(Keys.UXWRITE_PREFIX) == 0) - return true; - if ((className == "footnote") || (className == "endnote")) - return true; - } - return false; - } - - // private - function containsOnlyWhitespace(ancestor) - { - for (child = ancestor.firstChild; child != null; child = child.nextSibling) { - if (!isWhitespaceTextNode(child)) - return false; - } - return true; - } - - // public - Formatting_applyFormattingChanges = function(style,properties) - { - debug("JS: applyFormattingChanges: style = "+JSON.stringify(style)); - if (properties != null) { - var names = Object.getOwnPropertyNames(properties).sort(); - for (var i = 0; i < names.length; i++) { - debug(" "+names[i]+" = "+properties[names[i]]); - } - } - UndoManager_newGroup("Apply formatting changes"); - - if (properties == null) - properties = new Object(); - - if (style == Keys.NONE_STYLE) - style = null; - - var paragraphProperties = new Object(); - var inlineProperties = new Object(); - - for (var name in properties) { - if (isParagraphProperty(name)) - paragraphProperties[name] = properties[name]; - else if (isInlineProperty(name)) - inlineProperties[name] = properties[name]; - } - - var selectionRange = Selection_get(); - if (selectionRange == null) - return; - - // If we're applying formatting properties to an empty selection, and the node of the - // selection start & end is an element, add an empty text node so that we have something - // to apply the formatting to. - if (Range_isEmpty(selectionRange) && - (selectionRange.start.node.nodeType == Node.ELEMENT_NODE)) { - var node = selectionRange.start.node; - var offset = selectionRange.start.offset; - var text = DOM_createTextNode(document,""); - DOM_insertBefore(node,text,node.childNodes[offset]); - Selection_set(text,0,text,0); - selectionRange = Selection_get(); - } - - // If the cursor is in a container (such as BODY OR FIGCAPTION), and not inside a paragraph, - // put it in one so we can set a paragraph style - - if ((style != null) && Range_isEmpty(selectionRange)) { - var node = Range_singleNode(selectionRange); - while (isInlineNode(node)) - node = node.parentNode; - if (isContainerNode(node) && containsOnlyInlineChildren(node)) { - var p = DOM_createElement(document,"P"); - DOM_appendChild(node,p); - while (node.firstChild != p) - DOM_appendChild(p,node.firstChild); - Cursor_updateBRAtEndOfParagraph(p); - } - } - - - var range = new Range(selectionRange.start.node,selectionRange.start.offset, - selectionRange.end.node,selectionRange.end.offset); - var positions = [selectionRange.start,selectionRange.end, - range.start,range.end]; - - var allowDirectInline = (style == null); - Position_trackWhileExecuting(positions,function() { - Formatting_splitAroundSelection(range,allowDirectInline); - Range_expand(range); - if (!allowDirectInline) - Range_ensureInlineNodesInParagraph(range); - Range_ensureValidHierarchy(range); - Range_expand(range); - var outermost = Range_getOutermostNodes(range); - var target = null; - - var paragraphs; - if (outermost.length > 0) - paragraphs = getParagraphs(outermost); - else - paragraphs = getParagraphs([Range_singleNode(range)]); - - // Push down inline properties - Formatting_pushDownInlineProperties(outermost); - - outermost = removeProperties(outermost,inlineProperties); - - // Set properties on inline nodes - for (var i = 0; i < outermost.length; i++) { - var existing = Formatting_getAllNodeProperties(outermost[i]); - var toSet = new Object(); - for (var name in inlineProperties) { - if ((inlineProperties[name] != null) && - (existing[name] != inlineProperties[name])) { - toSet[name] = inlineProperties[name]; - } - } - - var special = extractSpecial(toSet); - var applyToWhitespace = (outermost.length == 1); - applyInlineFormatting(outermost[i],toSet,special,applyToWhitespace); - } - - // Remove properties from paragraph nodes - paragraphs = removeProperties(paragraphs,paragraphProperties,{}); - - // Set properties on paragraph nodes - var paragraphPropertiesToSet = new Object(); - for (var name in paragraphProperties) { - if (paragraphProperties[name] != null) - paragraphPropertiesToSet[name] = paragraphProperties[name]; - } - - var outermostParagraphs = getOutermostParagraphs(paragraphs); - for (var i = 0; i < outermostParagraphs.length; i++) - DOM_setStyleProperties(outermostParagraphs[i],paragraphPropertiesToSet); - - // Set style on paragraph nodes - if (style != null) { - for (var i = 0; i < paragraphs.length; i++) { - setParagraphStyle(paragraphs[i],style); - } - } - - mergeRange(range,Formatting_MERGEABLE_INLINE); - - if (target != null) { - for (var p = target; p != null; p = next) { - next = p.parentNode; - Formatting_mergeWithNeighbours(p,Formatting_MERGEABLE_INLINE); - } - } - }); - - // The current cursor position may no longer be valid, e.g. if a heading span was inserted - // and the cursor is at a position that is now immediately before the span. - var start = Position_closestMatchForwards(selectionRange.start,Position_okForInsertion); - var end = Position_closestMatchBackwards(selectionRange.end,Position_okForInsertion); - var tempRange = new Range(start.node,start.offset,end.node,end.offset); - tempRange = Range_forwards(tempRange); - Range_ensureValidHierarchy(tempRange); - start = tempRange.start; - end = tempRange.end; - Selection_set(start.node,start.offset,end.node,end.offset); - - function containsOnlyInlineChildren(node) - { - for (var child = node.firstChild; child != null; child = child.nextSibling) { - if (!isInlineNode(child)) - return false; - } - return true; - } - } - - Formatting_formatInlineNode = function(node,properties) - { - properties = clone(properties); - var special = extractSpecial(properties); - return applyInlineFormatting(node,properties,special,true); - } - - Formatting_MERGEABLE_INLINE = new Array(HTML_COUNT); - - Formatting_MERGEABLE_INLINE[HTML_TEXT] = true; - - Formatting_MERGEABLE_INLINE[HTML_SPAN] = true; - Formatting_MERGEABLE_INLINE[HTML_A] = true; - Formatting_MERGEABLE_INLINE[HTML_Q] = true; - - // HTML 4.01 Section 9.2.1: Phrase elements - Formatting_MERGEABLE_INLINE[HTML_EM] = true; - Formatting_MERGEABLE_INLINE[HTML_STRONG] = true; - Formatting_MERGEABLE_INLINE[HTML_DFN] = true; - Formatting_MERGEABLE_INLINE[HTML_CODE] = true; - Formatting_MERGEABLE_INLINE[HTML_SAMP] = true; - Formatting_MERGEABLE_INLINE[HTML_KBD] = true; - Formatting_MERGEABLE_INLINE[HTML_VAR] = true; - Formatting_MERGEABLE_INLINE[HTML_CITE] = true; - Formatting_MERGEABLE_INLINE[HTML_ABBR] = true; - - // HTML 4.01 Section 9.2.3: Subscripts and superscripts - Formatting_MERGEABLE_INLINE[HTML_SUB] = true; - Formatting_MERGEABLE_INLINE[HTML_SUP] = true; - - // HTML 4.01 Section 15.2.1: Font style elements - Formatting_MERGEABLE_INLINE[HTML_I] = true; - Formatting_MERGEABLE_INLINE[HTML_B] = true; - Formatting_MERGEABLE_INLINE[HTML_SMALL] = true; - Formatting_MERGEABLE_INLINE[HTML_S] = true; - Formatting_MERGEABLE_INLINE[HTML_U] = true; - - Formatting_MERGEABLE_BLOCK = new Array(HTML_COUNT); - - Formatting_MERGEABLE_BLOCK[HTML_P] = true; - Formatting_MERGEABLE_BLOCK[HTML_H1] = true; - Formatting_MERGEABLE_BLOCK[HTML_H2] = true; - Formatting_MERGEABLE_BLOCK[HTML_H3] = true; - Formatting_MERGEABLE_BLOCK[HTML_H4] = true; - Formatting_MERGEABLE_BLOCK[HTML_H5] = true; - Formatting_MERGEABLE_BLOCK[HTML_H6] = true; - Formatting_MERGEABLE_BLOCK[HTML_DIV] = true; - Formatting_MERGEABLE_BLOCK[HTML_PRE] = true; - Formatting_MERGEABLE_BLOCK[HTML_BLOCKQUOTE] = true; - - Formatting_MERGEABLE_BLOCK[HTML_UL] = true; - Formatting_MERGEABLE_BLOCK[HTML_OL] = true; - Formatting_MERGEABLE_BLOCK[HTML_LI] = true; - - Formatting_MERGEABLE_BLOCK_AND_INLINE = new Array(HTML_COUNT); - for (var i = 0; i < HTML_COUNT; i++) { - if (Formatting_MERGEABLE_INLINE[i] || Formatting_MERGEABLE_BLOCK[i]) - Formatting_MERGEABLE_BLOCK_AND_INLINE[i] = true; - Formatting_MERGEABLE_BLOCK_AND_INLINE["force"] = true; - } - -})(); http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js ---------------------------------------------------------------------- diff --git a/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js b/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js deleted file mode 100644 index 07c0526..0000000 --- a/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js +++ /dev/null @@ -1,284 +0,0 @@ -// 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 Hierarchy_ensureValidHierarchy; -var Hierarchy_ensureInlineNodesInParagraph; -var Hierarchy_wrapInlineNodesInParagraph; -var Hierarchy_avoidInlineChildren; - -(function() { - - // private - function wrapInlineChildren(first,last,ancestors) - { - var haveNonWhitespace = false; - for (var node = first; node != last.nextSibling; node = node.nextSibling) { - if (!isWhitespaceTextNode(node)) - haveNonWhitespace = true; - } - if (!haveNonWhitespace) - return false; - - var parentNode = first.parentNode; - var nextSibling = first; - for (var i = ancestors.length-1; i >= 0; i--) { - var ancestorCopy = DOM_shallowCopyElement(ancestors[i]); - DOM_insertBefore(parentNode,ancestorCopy,nextSibling); - parentNode = ancestorCopy; - nextSibling = null; - - var node = first; - while (true) { - var next = node.nextSibling; - DOM_insertBefore(parentNode,node,null); - if (node == last) - break; - node = next; - } - } - } - - // private - function wrapInlineChildrenInAncestors(node,ancestors) - { - var firstInline = null; - var lastInline = null; - - var child = node.firstChild; - while (true) { - var next = (child != null) ? child.nextSibling : null; - if ((child == null) || !isInlineNode(child)) { - - if ((firstInline != null) && (lastInline != null)) { - wrapInlineChildren(firstInline,lastInline,ancestors); - } - firstInline = null; - lastInline = null; - if (child != null) - wrapInlineChildrenInAncestors(child,ancestors); - } - else { - if (firstInline == null) - firstInline = child; - lastInline = child; - } - if (child == null) - break; - child = next; - } - } - - function checkInvalidNesting(node) - { - var parent = node.parentNode; - if ((parent._type == HTML_DIV) && - (DOM_getAttribute(parent,"class") == Keys.SELECTION_CLASS)) { - parent = parent.parentNode; - } - - var invalidNesting = !isContainerNode(parent); - switch (parent._type) { - case HTML_DIV: - if (isParagraphNode(node) || isListNode(node)) - invalidNesting = false; // this case is ok - break; - case HTML_CAPTION: - case HTML_FIGCAPTION: - case HTML_TABLE: - case HTML_FIGURE: - switch (node._type) { - case HTML_FIGURE: - case HTML_TABLE: - case HTML_H1: - case HTML_H2: - case HTML_H3: - case HTML_H4: - case HTML_H5: - case HTML_H6: - return true; - } - break; - } - - return invalidNesting; - } - - function checkInvalidHeadingNesting(node) - { - switch (node._type) { - case HTML_H1: - case HTML_H2: - case HTML_H3: - case HTML_H4: - case HTML_H5: - case HTML_H6: - switch (node.parentNode._type) { - case HTML_BODY: - case HTML_NAV: - case HTML_DIV: - return false; - default: - return true; - } - break; - default: - return false; - } - } - - function nodeHasSignificantChildren(node) - { - for (var child = node.firstChild; child != null; child = child.nextSibling) { - if (!isWhitespaceTextNode(child)) - return true; - } - return false; - } - - // Enforce the restriction that any path from the root to a given node must be of the form - // container+ paragraph inline - // or container+ paragraph - // or container+ - // public - Hierarchy_ensureValidHierarchy = function(node,recursive,allowDirectInline) - { - var count = 0; - while ((node != null) && (node.parentNode != null) && (node != document.body)) { - count++; - if (count > 200) - throw new Error("too many iterations"); - - if (checkInvalidHeadingNesting(node)) { - var offset = DOM_nodeOffset(node); - var parent = node.parentNode; - Formatting_moveFollowing(new Position(node.parentNode,offset+1), - function() { return false; }); - DOM_insertBefore(node.parentNode.parentNode, - node, - node.parentNode.nextSibling); - - while ((parent != document.body) && !nodeHasSignificantChildren(parent)) { - var grandParent = parent.parentNode; - DOM_deleteNode(parent); - parent = grandParent; - } - - continue; - } - else if (isContainerNode(node) || isParagraphNode(node)) { - var invalidNesting = checkInvalidNesting(node); - if (invalidNesting) { - var ancestors = new Array(); - var child = node; - while (!isContainerNode(child.parentNode)) { - if (isInlineNode(child.parentNode)) { - var keep = false; - if (child.parentNode._type == HTML_SPAN) { - for (var i = 0; i < child.attributes.length; i++) { - var attr = child.attributes[i]; - if (attr.nodeName.toUpperCase() != "ID") - keep = true; - } - if (keep) - ancestors.push(child.parentNode); - } - else { - ancestors.push(child.parentNode); - } - } - child = child.parentNode; - } - - while (checkInvalidNesting(node)) { - var offset = DOM_nodeOffset(node); - var parent = node.parentNode; - Formatting_moveFollowing(new Position(node.parentNode,offset+1), - isContainerNode); - DOM_insertBefore(node.parentNode.parentNode, - node, - node.parentNode.nextSibling); - if (!nodeHasSignificantChildren(parent)) - DOM_deleteNode(parent); - - } - wrapInlineChildrenInAncestors(node,ancestors); - } - } - - node = node.parentNode; - } - } - - Hierarchy_ensureInlineNodesInParagraph = function(node,weak) - { - var count = 0; - while ((node != null) && (node.parentNode != null) && (node != document.body)) { - count++; - if (count > 200) - throw new Error("too many iterations"); - if (isInlineNode(node) && - isContainerNode(node.parentNode) && (node.parentNode._type != HTML_LI) && - (!weak || !isTableCell(node.parentNode)) && - !isWhitespaceTextNode(node)) { - Hierarchy_wrapInlineNodesInParagraph(node); - return; - } - node = node.parentNode; - } - } - - // public - Hierarchy_wrapInlineNodesInParagraph = function(node) - { - var start = node; - var end = node; - - while ((start.previousSibling != null) && isInlineNode(start.previousSibling)) - start = start.previousSibling; - while ((end.nextSibling != null) && isInlineNode(end.nextSibling)) - end = end.nextSibling; - - return DOM_wrapSiblings(start,end,"P"); - } - - Hierarchy_avoidInlineChildren = function(parent) - { - var child = parent.firstChild; - - while (child != null) { - if (isInlineNode(child)) { - var start = child; - var end = child; - var haveContent = nodeHasContent(end); - while ((end.nextSibling != null) && isInlineNode(end.nextSibling)) { - end = end.nextSibling; - if (nodeHasContent(end)) - haveContent = true; - } - child = DOM_wrapSiblings(start,end,"P"); - var next = child.nextSibling; - if (!nodeHasContent(child)) - DOM_deleteNode(child); - child = next; - } - else { - child = child.nextSibling; - } - } - } - -})(); http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Input.js ---------------------------------------------------------------------- diff --git a/experiments/editorFramework/src/Layer0_Javascript/Input.js b/experiments/editorFramework/src/Layer0_Javascript/Input.js deleted file mode 100644 index db8cb99..0000000 --- a/experiments/editorFramework/src/Layer0_Javascript/Input.js +++ /dev/null @@ -1,746 +0,0 @@ -// 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 Input_removePosition; -var Input_addPosition; -var Input_getPosition; -var Input_textInRange; -var Input_replaceRange; -var Input_selectedTextRange; -var Input_setSelectedTextRange; -var Input_markedTextRange; -var Input_setMarkedText; -var Input_unmarkText; -var Input_forwardSelectionAffinity; -var Input_setForwardSelectionAffinity; -var Input_positionFromPositionOffset; -var Input_positionFromPositionInDirectionOffset; -var Input_comparePositionToPosition; -var Input_offsetFromPositionToPosition; -var Input_positionWithinRangeFarthestInDirection; -var Input_characterRangeByExtendingPositionInDirection; -var Input_firstRectForRange; -var Input_caretRectForPosition; -var Input_closestPositionToPoint; -var Input_closestPositionToPointWithinRange; -var Input_characterRangeAtPoint; -var Input_positionWithinRangeAtCharacterOffset; -var Input_characterOffsetOfPositionWithinRange; - -var Input_isAtWordBoundary; -var Input_isAtParagraphBoundary; -var Input_isPositionAtBoundaryGranularityInDirection; -var Input_isPositionWithinTextUnitInDirection; -var Input_toWordBoundary; -var Input_toParagraphBoundary; -var Input_toLineBoundary; -var Input_positionFromPositionToBoundaryInDirection; -var Input_rangeEnclosingPositionWithGranularityInDirection; - -// FIXME: ensure updateFormatting() is called after any cursor/selection changes -// FIXME: test capitalisation of on-screen keyboard at start of sentence - -(function() { - - //function idebug(str) - //{ - // debug(str); - //} - - var forwardSelection = true; - var positions = new Object(); - var BaseIdNull = 0; - var BaseIdDocumentStart = 1; - var BaseIdDocumentEnd = 2; - var BaseIdSelectionStart = 3; - var BaseIdSelectionEnd = 4; - var firstDynamicPosId = 5; - var nextPosId = firstDynamicPosId; - - function addPosition(pos) - { - if (pos == null) - return 0; - var copy = new Position(pos.node,pos.offset); - copy.targetX = pos.targetX; - pos = copy; - pos.posId = nextPosId++; - positions[pos.posId] = pos; - Position_track(pos); - return pos.posId; - } - - Input_addPosition = addPosition; - - function getPosition(posId) - { - if (posId instanceof Position) // for tests - return posId; - if (posId < firstDynamicPosId) { - switch (posId) { - case BaseIdNull: { - return null; - } - case BaseIdDocumentStart: { - var pos = new Position(document.body,0); - pos = Position_closestMatchForwards(pos,Position_okForMovement); - return pos; - } - case BaseIdDocumentEnd: { - var pos = new Position(document.body,document.body.childNodes.length); - pos = Position_closestMatchBackwards(pos,Position_okForMovement); - return pos; - } - case BaseIdSelectionStart: { - var range = Selection_get(); - return (range != null) ? range.start : null; - } - case BaseIdSelectionEnd: { - var range = Selection_get(); - return (range != null) ? range.end : null; - } - default: - return null; - } - } - if (positions[posId] == null) - throw new Error("No position for pos id "+posId); - return positions[posId]; - } - - Input_getPosition = getPosition; - - // void - Input_removePosition = function(posId) - { - //idebug("Input_removePosition("+posId+")"); - var pos = positions[posId]; - if (pos == null) { - throw new Error("no position for id "+posId); - } - Position_untrack(pos); - delete positions[posId]; - } - - // string - Input_textInRange = function(startId,startAdjust,endId,endAdjust) - { - var start = getPosition(startId); - var end = getPosition(endId); - start = positionRight(start,startAdjust); - end = positionRight(end,endAdjust); - if ((start == null) || (end == null)) - return ""; - - var range = new Range(start.node,start.offset,end.node,end.offset); - var result = Range_getText(range); - //idebug("Input_textInRange("+startId+","+startAdjust+","+endId+","+endAdjust+") = "+ - // JSON.stringify(result)); - return result; - } - - // void - Input_replaceRange = function(startId,endId,text) - { - //idebug("Input_replaceRange("+startId+","+endId+","+JSON.stringify(text)+")"); - var start = getPosition(startId); - var end = getPosition(endId); - if (start == null) - throw new Error("start is null"); - if (end == null) - throw new Error("end is null"); - - var range = new Range(start.node,start.offset,end.node,end.offset); - Range_trackWhileExecuting(range,function() { - Selection_deleteRangeContents(range,true); - }); - range.start = Position_preferTextPosition(range.start); - var node = range.start.node; - var offset = range.start.offset; - - if (node.nodeType == Node.TEXT_NODE) { - DOM_insertCharacters(node,offset,text); - Cursor_set(node,offset+text.length); - } - else if (node.nodeType == Node.ELEMENT_NODE) { - var textNode = DOM_createTextNode(document,text); - DOM_insertBefore(node,textNode,node.childNodes[offset]); - Cursor_set(node,offset+1); - } - } - - // { startId, endId } - Input_selectedTextRange = function() - { - var range = Selection_get(); - if (range == null) { - //idebug("Input_selectedTextRange = null"); - return null; - } - else { - var startId = addPosition(range.start); - var endId = addPosition(range.end); - //idebug("Input_selectedTextRange = "+startId+", "+endId); - return { startId: startId, - endId: endId }; - } - } - - // void - Input_setSelectedTextRange = function(startId,endId) - { - //idebug("Input_setSelectedTextRange("+startId+","+endId+")"); - var start = getPosition(startId); - var end = getPosition(endId); - - var oldSelection = Selection_get(); - var oldStart = (oldSelection != null) ? oldSelection.start : null; - var oldEnd = (oldSelection != null) ? oldSelection.end : null; - - Selection_set(start.node,start.offset,end.node,end.offset); - - // The positions may have changed as a result of spans being added/removed - var newRange = Selection_get(); - start = newRange.start; - end = newRange.end; - - if (Position_equal(start,end)) - Cursor_ensurePositionVisible(end); - else if (Position_equal(oldStart,start) && !Position_equal(oldEnd,end)) - Cursor_ensurePositionVisible(end); - else if (Position_equal(oldEnd,end) && !Position_equal(oldStart,start)) - Cursor_ensurePositionVisible(start); - } - - // { startId, endId } - Input_markedTextRange = function() - { - //idebug("Input_markedTextRange"); - return null; - } - - // void - Input_setMarkedText = function(text,startOffset,endOffset) - { - Selection_deleteContents(true); - var oldSel = Selection_get(); - Range_trackWhileExecuting(oldSel,function() { - Cursor_insertCharacter(text,false,false,true); - }); - var newSel = Selection_get(); - - Selection_set(oldSel.start.node,oldSel.start.offset, - newSel.end.node,newSel.end.offset,false,true); - } - - // void - Input_unmarkText = function() - { - var range = Selection_get(); - Cursor_set(range.end.node,range.end.offset); - //idebug("Input_unmarkText"); - } - - // boolean - Input_forwardSelectionAffinity = function() - { - //idebug("Input_forwardSelectionAffinity"); - return forwardSelection; - } - - // void - Input_setForwardSelectionAffinity = function(value) - { - //idebug("Input_setForwardSelectionAffinity"); - forwardSelection = value; - } - - function positionRight(pos,offset) - { - if (offset > 0) { - for (; offset > 0; offset--) { - var next = Position_nextMatch(pos,Position_okForMovement); - if (next == null) - return pos; - pos = next; - } - } - else { - for (; offset < 0; offset++) { - var prev = Position_prevMatch(pos,Position_okForMovement); - if (prev == null) - return pos; - pos = prev; - } - } - return pos; - } - - function positionDown(pos,offset) - { - if (offset > 0) { - for (; offset > 0; offset--) { - var below = Text_posBelow(pos); - if (below == null) - return pos; - pos = below; - } - } - else { - for (; offset < 0; offset++) { - var above = Text_posAbove(pos); - if (above == null) - return pos; - pos = above; - } - } - return pos; - } - - // posId - Input_positionFromPositionOffset = function(posId,offset) - { - var pos = getPosition(posId); - var res = addPosition(positionRight(pos,offset)); - //idebug("Input_positionFromPositionOffset("+posId+","+offset+") = "+res); - return res; - } - - // posId - Input_positionFromPositionInDirectionOffset = function(posId,direction,offset) - { - //idebug("Input_positionFromPositionInDirectionOffset("+posId+","+direction+","+offset+")"); - var pos = getPosition(posId); - if (direction == "left") - return addPosition(positionRight(pos,-offset)); - else if (direction == "right") - return addPosition(positionRight(pos,offset)); - else if (direction == "up") - return addPosition(positionDown(pos,-offset)); - else if (direction == "down") - return addPosition(positionDown(pos,offset)); - else - throw new Error("unknown direction: "+direction); - } - - // int - Input_comparePositionToPosition = function(posId1,posId2) - { - //idebug("Input_comparePositionToPosition("+posId1+","+posId2+")"); - var pos1 = getPosition(posId1); - var pos2 = getPosition(posId2); - if (pos1 == null) - throw new Error("pos1 is null"); - if (pos2 == null) - throw new Error("pos2 is null"); - return Position_compare(pos1,pos2); - } - - // int - Input_offsetFromPositionToPosition = function(fromId,toId) - { - //idebug("Input_offsetFromPositionToPosition("+fromId+","+toId+")"); - throw new Error("offsetFromPositionToPosition: not implemented"); - } - - Input_positionWithinRangeFarthestInDirection = function(startId,endId,direction) - { - //idebug("Input_positionWithinRangeFarthestInDirection("+startId+","+endId+","+direction); - throw new Error("positionWithinRangeFarthestInDirection: not implemented"); - } - - // { startId, endId } - Input_characterRangeByExtendingPositionInDirection = function(posId,direction) - { - //idebug("Input_characterRangeByExtendingPositionInDirection("+posId+","+direction); - throw new Error("characterRangeByExtendingPositionInDirection: not implemented"); - } - - Input_firstRectForRange = function(startId,endId) - { - //idebug("Input_firstRectForRange("+startId+","+endId+")"); - var start = getPosition(startId); - var end = getPosition(endId); - var range = new Range(start.node,start.offset,end.node,end.offset); - var rects = Range_getClientRects(range); - if (rects.length == 0) - return { x: 0, y: 0, width: 0, height: 0 }; - else - return { x: rects[0].left, y: rects[0].top, - width: rects[0].width, height: rects[0].height }; - } - - Input_caretRectForPosition = function(posId) - { - //idebug("Input_caretRectForPosition("+posId+")"); - var pos = getPosition(posId); - var rect = Position_rectAtPos(pos); - if (rect == null) - return { x: 0, y: 0, width: 0, height: 0 }; - else - return { x: rect.left, y: rect.top, width: rect.width, height: rect.height }; - } - - // posId - Input_closestPositionToPoint = function(x,y) - { - //idebug("Input_closestPositionToPoint("+x+","+y+")"); - throw new Error("closestPositionToPoint: not implemented"); - } - - // posId - Input_closestPositionToPointWithinRange = function(x,y,startId,endId) - { - //idebug("Input_closestPositionToPointWithinRange("+x+","+y+")"); - throw new Error("closestPositionToPointWithinRange: not implemented"); - } - - // { startId, endId } - Input_characterRangeAtPoint = function(x,y) - { - //idebug("Input_characterRangeAtPoint("+x+","+y+")"); - throw new Error("characterRangeAtPoint: not implemented"); - } - - // posId - Input_positionWithinRangeAtCharacterOffset = function(startId,endId,offset) - { - //idebug("Input_positionWithinRangeAtCharacterOffset("+startId+","+endId+","+offset+")"); - throw new Error("positionWithinRangeAtCharacterOffset: not implemented"); - } - - // int - Input_characterOffsetOfPositionWithinRange = function(posId,startId,endId) - { - //idebug("Input_characterOffsetOfPositionWithinRange("+posId+","+startId+","+endId+")"); - throw new Error("characterOffsetOfPositionWithinRange: not implemented"); - } - - // UITextInputTokenizer methods - - var punctuation = "!\"#%&',-/:;<=>@`~\\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|"; - var letterRE = new RegExp("[^\\s"+punctuation+"]"); - var wordAtStartRE = new RegExp("^[^\\s"+punctuation+"]+"); - var nonWordAtStartRE = new RegExp("^[\\s"+punctuation+"]+"); - var wordAtEndRE = new RegExp("[^\\s"+punctuation+"]+$"); - var nonWordAtEndRE = new RegExp("[\\s"+punctuation+"]+$"); - - function isForward(direction) - { - return ((direction == "forward") || - (direction == "right") || - (direction == "down")); - } - - Input_isAtWordBoundary = function(pos,direction) - { - if (pos.node.nodeType != Node.TEXT_NODE) - return false; - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return false; - var offset = Paragraph_offsetAtPosition(paragraph,pos); - var before = paragraph.text.substring(0,offset); - var after = paragraph.text.substring(offset); - var text = paragraph.text; - - var afterMatch = (offset < text.length) && (text.charAt(offset).match(letterRE)); - var beforeMatch = (offset > 0) && (text.charAt(offset-1).match(letterRE)); - - // coerce to boolean - afterMatch = !!afterMatch; - beforeMatch = !!beforeMatch; - - if (isForward(direction)) - return beforeMatch && !afterMatch; - else - return !beforeMatch; - } - - Input_isAtParagraphBoundary = function(pos,direction) - { - } - - Input_isPositionAtBoundaryGranularityInDirection = function(posId,granularity,direction) - { - //idebug("Input_isPositionAtBoundaryGranularityInDirection("+ - // posId+","+granularity+","+direction+")"); - var pos = getPosition(posId); - if (pos == null) - return false; - - // FIXME: Temporary hack to avoid exceptions when running under iOS 8 - if ((granularity == "sentence") || (granularity == "document")) - return false; - - if (granularity == "character") { - return true; - } - else if (granularity == "word") { - return Input_isAtWordBoundary(pos,direction); - } - else if ((granularity == "paragraph") || (granularity == "line")) { - if (isForward(direction)) - return Position_equal(pos,Text_toEndOfBoundary(pos,granularity)); - else - return Position_equal(pos,Text_toStartOfBoundary(pos,granularity)); - } - else if (granularity == "sentence") { - } - else if (granularity == "document") { - } - throw new Error("unsupported granularity: "+granularity); - } - - Input_isPositionWithinTextUnitInDirection = function(posId,granularity,direction) - { - //idebug("Input_isPositionWithinTextUnitInDirection("+ - // posId+","+granularity+","+direction+")"); - var pos = getPosition(posId); - if (pos == null) - return false; - - // FIXME: Temporary hack to avoid exceptions when running under iOS 8 - if ((granularity == "sentence") || (granularity == "document")) - return true; - - if (granularity == "character") { - return true; - } - else if (granularity == "word") { - pos = Text_closestPosInDirection(pos,direction); - if (pos == null) - return false; - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return false; - if ((pos != null) && (pos.node.nodeType == Node.TEXT_NODE)) { - var offset = Paragraph_offsetAtPosition(paragraph,pos); - var text = paragraph.text; - if (isForward(direction)) - return !!((offset < text.length) && (text.charAt(offset).match(letterRE))); - else - return !!((offset > 0) && (text.charAt(offset-1).match(letterRE))); - } - else { - return false; - } - } - else if (granularity == "sentence") { - } - else if ((granularity == "paragraph") || (granularity == "line")) { - var start = Text_toStartOfBoundary(pos,granularity); - var end = Text_toEndOfBoundary(pos,granularity); - start = start ? start : pos; - end = end ? end : pos; - if (isForward(direction)) { - return ((Position_compare(start,pos) <= 0) && - (Position_compare(pos,end) < 0)); - } - else { - return ((Position_compare(start,pos) < 0) && - (Position_compare(pos,end) <= 0)); - } - } - else if (granularity == "document") { - } - throw new Error("unsupported granularity: "+granularity); - } - - Input_toWordBoundary = function(pos,direction) - { - pos = Text_closestPosInDirection(pos,direction); - if (pos == null) - return null; - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return null; - var run = Paragraph_runFromNode(paragraph,pos.node); - var offset = pos.offset + run.start; - - if (isForward(direction)) { - var remaining = paragraph.text.substring(offset); - var afterWord = remaining.replace(wordAtStartRE,""); - var afterNonWord = remaining.replace(nonWordAtStartRE,""); - - if (remaining.length == 0) { - return pos; - } - else if (afterWord.length < remaining.length) { - var newOffset = offset + (remaining.length - afterWord.length); - return Paragraph_positionAtOffset(paragraph,newOffset); - } - else { - var newOffset = offset + (remaining.length - afterNonWord.length); - return Paragraph_positionAtOffset(paragraph,newOffset); - } - } - else { - var remaining = paragraph.text.substring(0,offset); - var beforeWord = remaining.replace(wordAtEndRE,""); - var beforeNonWord = remaining.replace(nonWordAtEndRE,""); - - if (remaining.length == 0) { - return pos; - } - else if (beforeWord.length < remaining.length) { - var newOffset = offset - (remaining.length - beforeWord.length); - return Paragraph_positionAtOffset(paragraph,newOffset); - } - else { - var newOffset = offset - (remaining.length - beforeNonWord.length); - return Paragraph_positionAtOffset(paragraph,newOffset); - } - } - } - - Input_toParagraphBoundary = function(pos,direction) - { - if (isForward(direction)) { - var end = Text_toEndOfBoundary(pos,"paragraph"); - if (Position_equal(pos,end)) { - end = Position_nextMatch(end,Position_okForMovement); - end = Text_toEndOfBoundary(end,"paragraph"); - end = Text_toStartOfBoundary(end,"paragraph"); - } - return end ? end : pos; - } - else { - var start = Text_toStartOfBoundary(pos,"paragraph"); - if (Position_equal(pos,start)) { - start = Position_prevMatch(start,Position_okForMovement); - start = Text_toStartOfBoundary(start,"paragraph"); - start = Text_toEndOfBoundary(start,"paragraph"); - } - return start ? start : pos; - } - } - - Input_toLineBoundary = function(pos,direction) - { - if (isForward(direction)) { - var end = Text_toEndOfBoundary(pos,"line"); - return end ? end : pos; - } - else { - var start = Text_toStartOfBoundary(pos,"line"); - return start ? start : pos; - } - } - - Input_positionFromPositionToBoundaryInDirection = function(posId,granularity,direction) - { - //idebug("Input_positionFromPositionToBoundaryInDirection("+ - // posId+","+granularity+","+direction+")"); - var pos = getPosition(posId); - if (pos == null) - return null; - - // FIXME: Temporary hack to avoid exceptions when running under iOS 8 - if (granularity == "sentence") - granularity = "paragraph"; - - if (granularity == "word") - return addPosition(Input_toWordBoundary(pos,direction)); - else if (granularity == "paragraph") - return addPosition(Input_toParagraphBoundary(pos,direction)); - else if (granularity == "line") - return addPosition(Input_toLineBoundary(pos,direction)); - else if (granularity == "character") - return Input_positionFromPositionInDirectionOffset(posId,direction,1); - else if (granularity == "document") - return isForward(direction) ? BaseIdDocumentEnd : BaseIdDocumentStart; - else - throw new Error("unsupported granularity: "+granularity); - } - - Input_rangeEnclosingPositionWithGranularityInDirection = function(posId,granularity,direction) - { - //idebug("Input_rangeEnclosingPositionWithGranularityInDirection("+ - // posId+","+granularity+","+direction); - var pos = getPosition(posId); - if (pos == null) - return null; - - // FIXME: Temporary hack to avoid exceptions when running under iOS 8 - if (granularity == "sentence") - granularity = "paragraph"; - - if (granularity == "word") { - pos = Text_closestPosInDirection(pos,direction); - if (pos == null) - return null; - var paragraph = Text_analyseParagraph(pos); - if (pos == null) - return addPosition(null); - if (paragraph == null) - return addPosition(null); - var run = Paragraph_runFromNode(paragraph,pos.node); - var offset = pos.offset + run.start; - - var before = paragraph.text.substring(0,offset); - var after = paragraph.text.substring(offset); - var beforeWord = before.replace(wordAtEndRE,""); - var afterWord = after.replace(wordAtStartRE,""); - - var ok; - - if (isForward(direction)) - ok = (afterWord.length < after.length); - else - ok = (beforeWord.length < before.length); - - if (ok) { - var charsBefore = (before.length - beforeWord.length); - var charsAfter = (after.length - afterWord.length); - var startOffset = offset - charsBefore; - var endOffset = offset + charsAfter; - - var startPos = Paragraph_positionAtOffset(paragraph,startOffset); - var endPos = Paragraph_positionAtOffset(paragraph,endOffset); - return { startId: addPosition(startPos), - endId: addPosition(endPos) }; - } - else { - return null; - } - } - else if ((granularity == "paragraph") || (granularity == "line")) { - var start = Text_toStartOfBoundary(pos,granularity); - var end = Text_toEndOfBoundary(pos,granularity); - start = start ? start : pos; - end = end ? end : pos; - - if ((granularity == "paragraph") || !isForward(direction)) { - if (isForward(direction)) { - if (Position_equal(pos,Text_toEndOfBoundary(pos,granularity))) - return null; - } - else { - if (Position_equal(pos,Text_toStartOfBoundary(pos,granularity))) - return null; - } - } - return { startId: addPosition(start), - endId: addPosition(end) }; - } - else { - throw new Error("unsupported granularity: "+granularity); - } - } - -})();