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 739BC17D28 for ; Sun, 16 Aug 2015 10:58:22 +0000 (UTC) Received: (qmail 96301 invoked by uid 500); 16 Aug 2015 10:58:22 -0000 Delivered-To: apmail-corinthia-commits-archive@corinthia.apache.org Received: (qmail 96280 invoked by uid 500); 16 Aug 2015 10:58:22 -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 96271 invoked by uid 99); 16 Aug 2015 10:58:22 -0000 Received: from Unknown (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 16 Aug 2015 10:58:22 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id C0074C0861 for ; Sun, 16 Aug 2015 10:58:21 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.775 X-Spam-Level: * X-Spam-Status: No, score=1.775 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.006, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-eu-west.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id HCYIhwNMCQt7 for ; Sun, 16 Aug 2015 10:58:10 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-eu-west.apache.org (ASF Mail Server at mx1-eu-west.apache.org) with SMTP id DCF3424CEB for ; Sun, 16 Aug 2015 10:57:41 +0000 (UTC) Received: (qmail 94128 invoked by uid 99); 16 Aug 2015 10:57:37 -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; Sun, 16 Aug 2015 10:57:37 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id C8713E0441; Sun, 16 Aug 2015 10:57:37 +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: Sun, 16 Aug 2015 10:58:18 -0000 Message-Id: <88761dea3a504f74934e191394e10239@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [43/51] [partial] incubator-corinthia git commit: Added editorFramework in experiments. http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/26f461e7/experiments/Editor/src/Tables.js ---------------------------------------------------------------------- diff --git a/experiments/Editor/src/Tables.js b/experiments/Editor/src/Tables.js deleted file mode 100644 index f1f27be..0000000 --- a/experiments/Editor/src/Tables.js +++ /dev/null @@ -1,1362 +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 Tables_insertTable; -var Tables_addAdjacentRow; -var Tables_addAdjacentColumn; -var Tables_removeAdjacentRow; -var Tables_removeAdjacentColumn; -var Tables_deleteRegion; -var Tables_clearCells; -var Tables_mergeCells; -var Tables_splitSelection; -var Tables_cloneRegion; -var Tables_analyseStructure; -var Tables_findContainingCell; -var Tables_findContainingTable; -var Tables_regionFromRange; -var Tables_getSelectedTableId; -var Tables_getProperties; -var Tables_setProperties; -var Tables_getColWidths; -var Tables_setColWidths; -var Tables_getGeometry; - -var Table_get; -var Table_set; -var Table_setRegion; -var Table_fix; -var Table_fixColumnWidths; -var TableRegion_splitCells; - -(function() { - - function Cell(element,row,col) - { - this.element = element; - this.row = row; - this.col = col; - - if (element.hasAttribute("colspan")) - this.colspan = parseInt(element.getAttribute("colspan")); - else - this.colspan = 1; - if (element.hasAttribute("rowspan")) - this.rowspan = parseInt(element.getAttribute("rowspan")); - else - this.rowspan = 1; - - if (this.colspan < 1) - this.colspan = 1; - if (this.rowspan < 1) - this.rowspan = 1; - - this.top = this.row; - this.bottom = this.top + this.rowspan - 1; - this.left = this.col; - this.right = this.left + this.colspan - 1; - } - - function Cell_setRowspan(cell,rowspan) - { - if (rowspan < 1) - rowspan = 1; - cell.rowspan = rowspan; - cell.bottom = cell.top + cell.rowspan - 1; - if (rowspan == 1) - DOM_removeAttribute(cell.element,"rowspan"); - else - DOM_setAttribute(cell.element,"rowspan",rowspan); - } - - function Cell_setColspan(cell,colspan) - { - if (colspan < 1) - colspan = 1; - cell.colspan = colspan; - cell.right = cell.left + cell.colspan - 1; - if (colspan == 1) - DOM_removeAttribute(cell.element,"colspan"); - else - DOM_setAttribute(cell.element,"colspan",colspan); - } - - function Table(element) - { - this.element = element; - this.row = 0; - this.col = 0; - this.cells = new Array(); - this.numRows = 0; - this.numCols = 0; - this.translated = false; - this.cellsByElement = new NodeMap(); - Table_processTable(this,element); - } - - // public - Table_get = function(table,row,col) - { - if (table.cells[row] == null) - return null; - return table.cells[row][col]; - } - - // public - Table_set = function(table,row,col,cell) - { - if (table.numRows < row+1) - table.numRows = row+1; - if (table.numCols < col+1) - table.numCols = col+1; - if (table.cells[row] == null) - table.cells[row] = new Array(); - table.cells[row][col] = cell; - } - - // public - Table_setRegion = function(table,top,left,bottom,right,cell) - { - for (var row = top; row <= bottom; row++) { - for (var col = left; col <= right; col++) { - var destCell = Table_get(table,row,col); - DOM_deleteNode(destCell.element); - Table_set(table,row,col,cell); - } - } - } - - function Table_processTable(table,node) - { - var type = node._type; - switch (node._type) { - case HTML_TD: - case HTML_TH: { - while (Table_get(table,table.row,table.col) != null) - table.col++; - - var cell = new Cell(node,table.row,table.col); - table.cellsByElement.put(node,cell); - - for (var r = 0; r < cell.rowspan; r++) { - for (var c = 0; c < cell.colspan; c++) { - Table_set(table,table.row+r,table.col+c,cell); - } - } - table.col += cell.colspan; - break; - } - case HTML_TR: - for (var child = node.firstChild; child != null; child = child.nextSibling) - Table_processTable(table,child); - table.row++; - table.col = 0; - break; - default: - for (var child = node.firstChild; child != null; child = child.nextSibling) - Table_processTable(table,child); - break; - } - } - - // public - Tables_insertTable = function(rows,cols,width,numbered,caption,className) - { - UndoManager_newGroup("Insert table"); - - if (rows < 1) - rows = 1; - if (cols < 1) - cols = 1; - - var haveCaption = (caption != null) && (caption != ""); - var table = DOM_createElement(document,"TABLE"); - - if (width != null) - DOM_setStyleProperties(table,{"width": width}); - - if (className != null) - DOM_setAttribute(table,"class",className); - - // Caption comes first - if (haveCaption) { - var tableCaption = DOM_createElement(document,"CAPTION"); - DOM_appendChild(tableCaption,DOM_createTextNode(document,caption)); - DOM_appendChild(table,tableCaption); - } - - // Set equal column widths - var colWidth = Math.round(100/cols)+"%"; - for (var c = 0; c < cols; c++) { - var col = DOM_createElement(document,"COL"); - DOM_setAttribute(col,"width",colWidth); - DOM_appendChild(table,col); - } - - var firstTD = null; - - // Then the rows and columns - var tbody = DOM_createElement(document,"TBODY"); - DOM_appendChild(table,tbody); - for (var r = 0; r < rows; r++) { - var tr = DOM_createElement(document,"TR"); - DOM_appendChild(tbody,tr); - for (var c = 0; c < cols; c++) { - var td = DOM_createElement(document,"TD"); - var p = DOM_createElement(document,"P"); - var br = DOM_createElement(document,"BR"); - DOM_appendChild(tr,td); - DOM_appendChild(td,p); - DOM_appendChild(p,br); - - if (firstTD == null) - firstTD = td; - } - } - - Clipboard_pasteNodes([table]); - - // Now that the table 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(table.getAttribute("id"),numbered); - - // Place the cursor at the start of the first cell on the first row - var pos = new Position(firstTD,0); - pos = Position_closestMatchForwards(pos,Position_okForMovement); - Selection_set(pos.node,pos.offset,pos.node,pos.offset); - - PostponedActions_add(UndoManager_newGroup); - } - - // private - function createEmptyTableCell(elementName) - { - var br = DOM_createElement(document,"BR"); - var p = DOM_createElement(document,"P"); - var td = DOM_createElement(document,elementName); - DOM_appendChild(p,br); - DOM_appendChild(td,p); - return td; - } - - // private - function addEmptyTableCell(newTR,elementName) - { - var td = createEmptyTableCell(elementName); - DOM_appendChild(newTR,td); - return td; - } - - // private - function populateNewRow(structure,newTR,newRow,oldRow) - { - var col = 0; - while (col < structure.numCols) { - var existingCell = Table_get(structure,oldRow,col); - if (((newRow > oldRow) && (newRow < existingCell.row + existingCell.rowspan)) || - ((newRow < oldRow) && (newRow >= existingCell.row))) { - Cell_setRowspan(existingCell,existingCell.rowspan+1); - } - else { - var td = addEmptyTableCell(newTR,existingCell.element.nodeName); // check-ok - if (existingCell.colspan != 1) - DOM_setAttribute(td,"colspan",existingCell.colspan); - } - col += existingCell.colspan; - } - } - - function tableAtRightOfRange(range) - { - if (!Range_isEmpty(range)) - return null; - - var pos = Position_preferElementPosition(range.start); - if ((pos.node.nodeType == Node.ELEMENT_NODE) && - (pos.offset < pos.node.childNodes.length) && - (pos.node.childNodes[pos.offset]._type == HTML_TABLE)) { - var element = pos.node.childNodes[pos.offset]; - var table = Tables_analyseStructure(element); - return table; - } - return null; - } - - function tableAtLeftOfRange(range) - { - if (!Range_isEmpty(range)) - return null; - - var pos = Position_preferElementPosition(range.start); - if ((pos.node.nodeType == Node.ELEMENT_NODE) && - (pos.offset > 0) && - (pos.node.childNodes[pos.offset-1]._type == HTML_TABLE)) { - var element = pos.node.childNodes[pos.offset-1]; - var table = Tables_analyseStructure(element); - return table; - } - return null; - } - - function insertRowAbove(table,row) - { - var cell = Table_get(table,row,0); - var oldTR = cell.element.parentNode; - var newTR = DOM_createElement(document,"TR"); - DOM_insertBefore(oldTR.parentNode,newTR,oldTR); - populateNewRow(table,newTR,row-1,row); - } - - function insertRowBelow(table,row) - { - var cell = Table_get(table,row,0); - var oldTR = cell.element.parentNode; - var newTR = DOM_createElement(document,"TR"); - DOM_insertBefore(oldTR.parentNode,newTR,oldTR.nextSibling); - populateNewRow(table,newTR,row+1,row); - } - - function insertRowAdjacentToRange(range) - { - var table; - - table = tableAtLeftOfRange(range); - if (table != null) { - insertRowBelow(table,table.numRows-1); - return; - } - - table = tableAtRightOfRange(range); - if (table != null) { - insertRowAbove(table,0); - return; - } - } - - // public - Tables_addAdjacentRow = function() - { - UndoManager_newGroup("Insert row below"); - Selection_preserveWhileExecuting(function() { - var range = Selection_get(); - var region = Tables_regionFromRange(range,true); - if (region != null) - insertRowBelow(region.structure,region.bottom); - else - insertRowAdjacentToRange(range); - }); - UndoManager_newGroup(); - } - - // private - function getColElements(table) - { - var cols = new Array(); - for (child = table.firstChild; child != null; child = child.nextSibling) { - switch (child._type) { - case HTML_COLGROUP: - for (var gc = child.firstChild; gc != null; gc = gc.nextSibling) { - if (gc._type == HTML_COL) - cols.push(gc); - } - break; - case HTML_COL: - cols.push(child); - break; - } - } - return cols; - } - - // private - function getColWidths(colElements,expectedCount) - { - // FIXME: also handle the case where the width has been set as a CSS property in the - // style attribute. There's probably not much we can do if the width comes from a style - // rule elsewhere in the document though. - var colWidths = new Array(); - for (var i = 0; i < colElements.length; i++) { - if (colElements[i].hasAttribute("width")) - colWidths.push(colElements[i].getAttribute("width")); - else - colWidths.push(""); - } - return colWidths; - } - - // private - function addMissingColElements(structure,colElements) - { - // If there are fewer COL elements than there are colums, add extra ones, copying the - // width value from the last one - // FIXME: handle col elements with colspan > 1, as well as colgroups with width set - // FIXME: What if there are 0 col elements? - while (colElements.length < structure.numCols) { - var newColElement = DOM_createElement(document,"COL"); - var lastColElement = colElements[colElements.length-1]; - DOM_insertBefore(lastColElement.parentNode,newColElement,lastColElement.nextSibling); - colElements.push(newColElement); - DOM_setAttribute(newColElement,"width",lastColElement.getAttribute("width")); - } - } - - // private - function fixColPercentages(structure,colElements) - { - var colWidths = getColWidths(colElements,structure.numCols); - - var percentages = colWidths.map(getPercentage); - if (percentages.every(notNull)) { - var colWidthTotal = 0; - for (var i = 0; i < percentages.length; i++) - colWidthTotal += percentages[i]; - - for (var i = 0; i < colElements.length; i++) { - var pct = 100*percentages[i]/colWidthTotal; - // Store value using at most two decimal places - pct = Math.round(100*pct)/100; - DOM_setAttribute(colElements[i],"width",pct+"%"); - } - } - - function notNull(arg) - { - return (arg != null); - } - - function getPercentage(str) - { - if (str.match(/^\s*\d+(\.\d+)?\s*%\s*$/)) - return parseInt(str.replace(/\s*%\s*$/,"")); - else - return null; - } - } - - // private - function addColElement(structure,oldIndex,right) - { - var table = structure.element; - - var colElements = getColElements(table); - if (colElements.length == 0) { - // The table doesn't have any COL elements; don't add any - return; - } - - addMissingColElements(structure,colElements); - - var prevColElement = colElements[oldIndex]; - var newColElement = DOM_createElement(document,"COL"); - DOM_setAttribute(newColElement,"width",prevColElement.getAttribute("width")); - if (right) - DOM_insertBefore(prevColElement.parentNode,newColElement,prevColElement.nextSibling); - else - DOM_insertBefore(prevColElement.parentNode,newColElement,prevColElement); - - if (right) { - colElements.splice(oldIndex+1,0,newColElement); - } - else { - colElements.splice(oldIndex+1,0,newColElement); - } - - fixColPercentages(structure,colElements); - } - - // private - function deleteColElements(structure,left,right) - { - var table = structure.element; - - var colElements = getColElements(table); - if (colElements.length == 0) { - // The table doesn't have any COL elements - return; - } - - addMissingColElements(structure,colElements); - - for (var col = left; col <= right; col++) - DOM_deleteNode(colElements[col]); - colElements.splice(left,right-left+1); - - fixColPercentages(structure,colElements); - } - - // private - function addColumnCells(structure,oldIndex,right) - { - for (var row = 0; row < structure.numRows; row++) { - var cell = Table_get(structure,row,oldIndex); - var oldTD = cell.element; - if (cell.row == row) { - - if (((right && (oldIndex+1 < cell.col + cell.colspan)) || - (!right && (oldIndex-1 >= cell.col))) && - (cell.colspan > 1)) { - Cell_setColspan(cell,cell.colspan+1); - } - else { - var newTD = createEmptyTableCell(oldTD.nodeName); // check-ok - if (right) - DOM_insertBefore(cell.element.parentNode,newTD,oldTD.nextSibling); - else - DOM_insertBefore(cell.element.parentNode,newTD,oldTD); - if (cell.rowspan != 1) - DOM_setAttribute(newTD,"rowspan",cell.rowspan); - } - } - } - } - - function insertColumnAdjacentToRange(range) - { - var table; - - table = tableAtLeftOfRange(range); - if (table != null) { - var right = table.numCols-1; - addColElement(table,right,right+1); - addColumnCells(table,right,true); - return; - } - - table = tableAtRightOfRange(range); - if (table != null) { - var left = 0; - addColElement(table,left,left-1); - addColumnCells(table,left,false); - return; - } - } - - // public - Tables_addAdjacentColumn = function() - { - UndoManager_newGroup("Insert column at right"); - Selection_preserveWhileExecuting(function() { - var range = Selection_get(); - var region = Tables_regionFromRange(range,true); - if (region != null) { - addColElement(region.structure,region.right,region.right+1); - addColumnCells(region.structure,region.right,true); - } - else { - insertColumnAdjacentToRange(range); - } - }); - UndoManager_newGroup(); - } - - function columnHasContent(table,col) - { - for (var row = 0; row < table.numRows; row++) { - var cell = Table_get(table,row,col); - if ((cell != null) && (cell.col == col) && nodeHasContent(cell.element)) - return true; - } - return false; - } - - function rowHasContent(table,row) - { - for (var col = 0; col < table.numCols; col++) { - var cell = Table_get(table,row,col); - if ((cell != null) && (cell.row == row) && nodeHasContent(cell.element)) - return true; - } - return false; - } - - function selectRegion(table,top,bottom,left,right) - { - left = clampCol(table,left); - right = clampCol(table,right); - top = clampRow(table,top); - bottom = clampRow(table,bottom); - - var tlCell = Table_get(table,top,left); - var brCell = Table_get(table,bottom,right); - if ((tlCell != null) && (brCell != null)) { - var tlPos = new Position(tlCell.element,0); - tlPos = Position_closestMatchForwards(tlPos,Position_okForMovement); - - var brPos = new Position(brCell.element,brCell.element.childNodes.length); - brPos = Position_closestMatchBackwards(brPos,Position_okForMovement); - - Selection_set(tlPos.node,tlPos.offset,brPos.node,brPos.offset); - } - } - - function clampCol(table,col) - { - if (col > table.numCols-1) - col = table.numCols-1; - if (col < 0) - col = 0; - return col; - } - - function clampRow(table,row) - { - if (row > table.numRows-1) - row = table.numRows-1; - if (row < 0) - row = 0; - return row; - } - - function removeRowAdjacentToRange(range) - { - var table; - - table = tableAtLeftOfRange(range); - if ((table != null) && (table.numRows >= 2)) { - UndoManager_newGroup("Delete one row"); - var row = table.numRows-1; - Tables_deleteRegion(new TableRegion(table,row,row,0,table.numCols-1)); - UndoManager_newGroup(); - return; - } - - table = tableAtRightOfRange(range); - if ((table != null) && (table.numRows >= 2)) { - UndoManager_newGroup("Delete one row"); - Tables_deleteRegion(new TableRegion(table,0,0,0,table.numCols-1)); - UndoManager_newGroup(); - return; - } - } - - Tables_removeAdjacentRow = function() - { - var range = Selection_get(); - var region = Tables_regionFromRange(range,true); - - if (region == null) { - removeRowAdjacentToRange(range); - return; - } - - if (region.structure.numRows <= 1) - return; - - UndoManager_newGroup("Delete one row"); - - var table = region.structure; - var left = region.left; - var right = region.right; - var top = region.top; - var bottom = region.bottom; - - // Is there an empty row below the selection? If so, delete it - if ((bottom+1 < table.numRows) && !rowHasContent(table,bottom+1)) { - Selection_preserveWhileExecuting(function() { - Tables_deleteRegion(new TableRegion(table,bottom+1,bottom+1,0,table.numCols-1)); - }); - } - - // Is there an empty row above the selection? If so, delete it - else if ((top-1 >= 0) && !rowHasContent(table,top-1)) { - Selection_preserveWhileExecuting(function() { - Tables_deleteRegion(new TableRegion(table,top-1,top-1,0,table.numCols-1)); - }); - } - - - // There are no empty rows adjacent to the selection. Delete the right-most row - // of the selection (which may be the only one) - else { - Selection_preserveWhileExecuting(function() { - Tables_deleteRegion(new TableRegion(table,bottom,bottom,0,table.numCols-1)); - }); - - table = Tables_analyseStructure(table.element); - var multiple = (top != bottom); - - if (multiple) { - selectRegion(table,top,bottom-1,left,right); - } - else { - var newRow = clampRow(table,bottom); - var newCell = Table_get(table,newRow,left); - if (newCell != null) { - var pos = new Position(newCell.element,0); - pos = Position_closestMatchForwards(pos,Position_okForMovement); - Selection_set(pos.node,pos.offset,pos.node,pos.offset); - } - } - } - - UndoManager_newGroup(); - } - - function removeColumnAdjacentToRange(range) - { - var table; - - table = tableAtLeftOfRange(range); - if ((table != null) && (table.numCols >= 2)) { - UndoManager_newGroup("Delete one column"); - var col = table.numCols-1; - Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,col,col)); - UndoManager_newGroup(); - return; - } - - table = tableAtRightOfRange(range); - if ((table != null) && (table.numCols >= 2)) { - UndoManager_newGroup("Delete one column"); - Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,0,0)); - UndoManager_newGroup(); - return; - } - } - - Tables_removeAdjacentColumn = function() - { - var range = Selection_get(); - var region = Tables_regionFromRange(range,true); - - if (region == null) { - removeColumnAdjacentToRange(range); - return; - } - - if (region.structure.numCols <= 1) - return; - - UndoManager_newGroup("Delete one column"); - - var table = region.structure; - var left = region.left; - var right = region.right; - var top = region.top; - var bottom = region.bottom; - - // Is there an empty column to the right of the selection? If so, delete it - if ((right+1 < table.numCols) && !columnHasContent(table,right+1)) { - Selection_preserveWhileExecuting(function() { - Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,right+1,right+1)); - }); - } - - // Is there an empty column to the left of the selection? If so, delete it - else if ((left-1 >= 0) && !columnHasContent(table,left-1)) { - Selection_preserveWhileExecuting(function() { - Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,left-1,left-1)); - }); - } - - // There are no empty columns adjacent to the selection. Delete the right-most column - // of the selection (which may be the only one) - else { - Selection_preserveWhileExecuting(function() { - Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,right,right)); - }); - - table = Tables_analyseStructure(table.element); - var multiple = (left != right); - - if (multiple) { - selectRegion(table,top,bottom,left,right-1); - } - else { - var newCol = clampCol(table,right); - var newCell = Table_get(table,top,newCol); - if (newCell != null) { - var pos = new Position(newCell.element,0); - pos = Position_closestMatchForwards(pos,Position_okForMovement); - Selection_set(pos.node,pos.offset,pos.node,pos.offset); - } - } - } - - UndoManager_newGroup(); - } - - // private - function deleteTable(structure) - { - DOM_deleteNode(structure.element); - } - - // private - function deleteRows(structure,top,bottom) - { - var trElements = new Array(); - getTRs(structure.element,trElements); - - for (var row = top; row <= bottom; row++) - DOM_deleteNode(trElements[row]); - } - - // private - function getTRs(node,result) - { - if (node._type == HTML_TR) { - result.push(node); - } - else { - for (var child = node.firstChild; child != null; child = child.nextSibling) - getTRs(child,result); - } - } - - // private - function deleteColumns(structure,left,right) - { - var nodesToDelete = new NodeSet(); - for (var row = 0; row < structure.numRows; row++) { - for (var col = left; col <= right; col++) { - var cell = Table_get(structure,row,col); - nodesToDelete.add(cell.element); - } - } - nodesToDelete.forEach(DOM_deleteNode); - deleteColElements(structure,left,right); - } - - // private - function deleteCellContents(region) - { - var structure = region.structure; - for (var row = region.top; row <= region.bottom; row++) { - for (var col = region.left; col <= region.right; col++) { - var cell = Table_get(structure,row,col); - DOM_deleteAllChildren(cell.element); - } - } - } - - // public - Tables_deleteRegion = function(region) - { - var structure = region.structure; - - var coversEntireWidth = (region.left == 0) && (region.right == structure.numCols-1); - var coversEntireHeight = (region.top == 0) && (region.bottom == structure.numRows-1); - - if (coversEntireWidth && coversEntireHeight) - deleteTable(region.structure); - else if (coversEntireWidth) - deleteRows(structure,region.top,region.bottom); - else if (coversEntireHeight) - deleteColumns(structure,region.left,region.right); - else - deleteCellContents(region); - } - - // public - Tables_clearCells = function() - { - } - - // public - Tables_mergeCells = function() - { - Selection_preserveWhileExecuting(function() { - var region = Tables_regionFromRange(Selection_get()); - if (region == null) - return; - - var structure = region.structure; - - // FIXME: handle the case of missing cells - // (or even better, add cells where there are some missing) - - for (var row = region.top; row <= region.bottom; row++) { - for (var col = region.left; col <= region.right; col++) { - var cell = Table_get(structure,row,col); - var cellFirstRow = cell.row; - var cellLastRow = cell.row + cell.rowspan - 1; - var cellFirstCol = cell.col; - var cellLastCol = cell.col + cell.colspan - 1; - - if ((cellFirstRow < region.top) || (cellLastRow > region.bottom) || - (cellFirstCol < region.left) || (cellLastCol > region.right)) { - debug("Can't merge this table: cell at "+row+","+col+ - " goes outside bounds of selection"); - return; - } - } - } - - var mergedCell = Table_get(structure,region.top,region.left); - - for (var row = region.top; row <= region.bottom; row++) { - for (var col = region.left; col <= region.right; col++) { - var cell = Table_get(structure,row,col); - // parentNode will be null if we've already done this cell - if ((cell != mergedCell) && (cell.element.parentNode != null)) { - while (cell.element.firstChild != null) - DOM_appendChild(mergedCell.element,cell.element.firstChild); - DOM_deleteNode(cell.element); - } - } - } - - var totalRows = region.bottom - region.top + 1; - var totalCols = region.right - region.left + 1; - if (totalRows == 1) - DOM_removeAttribute(mergedCell.element,"rowspan"); - else - DOM_setAttribute(mergedCell.element,"rowspan",totalRows); - if (totalCols == 1) - DOM_removeAttribute(mergedCell.element,"colspan"); - else - DOM_setAttribute(mergedCell.element,"colspan",totalCols); - }); - } - - // public - Tables_splitSelection = function() - { - Selection_preserveWhileExecuting(function() { - var range = Selection_get(); - Range_trackWhileExecuting(range,function() { - var region = Tables_regionFromRange(range,true); - if (region != null) - TableRegion_splitCells(region); - }); - }); - } - - // public - TableRegion_splitCells = function(region) - { - var structure = region.structure; - var trElements = new Array(); - getTRs(structure.element,trElements); - - for (var row = region.top; row <= region.bottom; row++) { - for (var col = region.left; col <= region.right; col++) { - var cell = Table_get(structure,row,col); - if ((cell.rowspan > 1) || (cell.colspan > 1)) { - - var original = cell.element; - - for (var r = cell.top; r <= cell.bottom; r++) { - for (var c = cell.left; c <= cell.right; c++) { - if ((r == cell.top) && (c == cell.left)) - continue; - var newTD = createEmptyTableCell(original.nodeName); // check-ok - var nextElement = null; - - var nextCol = cell.right+1; - while (nextCol < structure.numCols) { - var nextCell = Table_get(structure,r,nextCol); - if ((nextCell != null) && (nextCell.row == r)) { - nextElement = nextCell.element; - break; - } - nextCol++; - } - - DOM_insertBefore(trElements[r],newTD,nextElement); - Table_set(structure,r,c,new Cell(newTD,r,c)); - } - } - DOM_removeAttribute(original,"rowspan"); - DOM_removeAttribute(original,"colspan"); - } - } - } - } - - // public - Tables_cloneRegion = function(region) - { - var cellNodesDone = new NodeSet(); - var table = DOM_shallowCopyElement(region.structure.element); - for (var row = region.top; row <= region.bottom; row++) { - var tr = DOM_createElement(document,"TR"); - DOM_appendChild(table,tr); - for (var col = region.left; col <= region.right; col++) { - var cell = Table_get(region.structure,row,col); - if (!cellNodesDone.contains(cell.element)) { - DOM_appendChild(tr,DOM_cloneNode(cell.element,true)); - cellNodesDone.add(cell.element); - } - } - } - return table; - } - - // private - function pasteCells(fromTableElement,toRegion) - { - // FIXME - var fromStructure = Tables_analyseStructure(fromTableElement); - } - - // public - Table_fix = function(table) - { - var changed = false; - - var tbody = null; - for (var child = table.element.firstChild; child != null; child = child.nextSibling) { - if (child._type == HTML_TBODY) - tbody = child; - } - - if (tbody == null) - return table; // FIXME: handle presence of THEAD and TFOOT, and also a missing TBODY - - var trs = new Array(); - for (var child = tbody.firstChild; child != null; child = child.nextSibling) { - if (child._type == HTML_TR) - trs.push(child); - } - - while (trs.length < table.numRows) { - var tr = DOM_createElement(document,"TR"); - DOM_appendChild(tbody,tr); - trs.push(tr); - } - - for (var row = 0; row < table.numRows; row++) { - for (var col = 0; col < table.numCols; col++) { - var cell = Table_get(table,row,col); - if (cell == null) { - var td = createEmptyTableCell("TD"); - DOM_appendChild(trs[row],td); - changed = true; - } - } - } - - if (changed) - return new Table(table.element); - else - return table; - } - - // public - Table_fixColumnWidths = function(structure) - { - var colElements = getColElements(structure.element); - if (colElements.length == 0) - return; - addMissingColElements(structure,colElements); - - var widths = Tables_getColWidths(structure); - fixWidths(widths,structure.numCols); - colElements = getColElements(structure.element); - for (var i = 0; i < widths.length; i++) - DOM_setAttribute(colElements[i],"width",widths[i]+"%"); - } - - // public - Tables_analyseStructure = function(element) - { - // FIXME: we should probably be preserving the selection here, since we are modifying - // the DOM (though I think it's unlikely it would cause problems, becausing the fixup - // logic only adds elements). However this method is called (indirectly) from within - // Selection_update(), which causes unbounded recursion due to the subsequent Selecton_set() - // that occurs. - var initial = new Table(element); - var fixed = Table_fix(initial); - return fixed; - } - - // public - Tables_findContainingCell = function(node) - { - for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) { - if (isTableCell(ancestor)) - return ancestor; - } - return null; - } - - // public - Tables_findContainingTable = function(node) - { - for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) { - if (ancestor._type == HTML_TABLE) - return ancestor; - } - return null; - } - - function TableRegion(structure,top,bottom,left,right) - { - this.structure = structure; - this.top = top; - this.bottom = bottom; - this.left = left; - this.right = right; - } - - TableRegion.prototype.toString = function() - { - return "("+this.top+","+this.left+") - ("+this.bottom+","+this.right+")"; - } - - // public - Tables_regionFromRange = function(range,allowSameCell) - { - var region = null; - - if (range == null) - return null; - - var start = Position_closestActualNode(range.start,true); - var end = Position_closestActualNode(range.end,true); - - var startTD = Tables_findContainingCell(start); - var endTD = Tables_findContainingCell(end); - - if (!isTableCell(start) || !isTableCell(end)) { - if (!allowSameCell) { - if (startTD == endTD) // not in cell, or both in same cell - return null; - } - } - - if ((startTD == null) || (endTD == null)) - return null; - - var startTable = Tables_findContainingTable(startTD); - var endTable = Tables_findContainingTable(endTD); - - if (startTable != endTable) - return null; - - var structure = Tables_analyseStructure(startTable); - - var startInfo = structure.cellsByElement.get(startTD); - var endInfo = structure.cellsByElement.get(endTD); - - var startTopRow = startInfo.row; - var startBottomRow = startInfo.row + startInfo.rowspan - 1; - var startLeftCol = startInfo.col; - var startRightCol = startInfo.col + startInfo.colspan - 1; - - var endTopRow = endInfo.row; - var endBottomRow = endInfo.row + endInfo.rowspan - 1; - var endLeftCol = endInfo.col; - var endRightCol = endInfo.col + endInfo.colspan - 1; - - var top = (startTopRow < endTopRow) ? startTopRow : endTopRow; - var bottom = (startBottomRow > endBottomRow) ? startBottomRow : endBottomRow; - var left = (startLeftCol < endLeftCol) ? startLeftCol : endLeftCol; - var right = (startRightCol > endRightCol) ? startRightCol : endRightCol; - - var region = new TableRegion(structure,top,bottom,left,right); - adjustRegionForSpannedCells(region); - return region; - } - - // private - function adjustRegionForSpannedCells(region) - { - var structure = region.structure; - var boundariesOk; - var columnsOk; - do { - boundariesOk = true; - for (var row = region.top; row <= region.bottom; row++) { - var cell = Table_get(structure,row,region.left); - if (region.left > cell.left) { - region.left = cell.left; - boundariesOk = false; - } - cell = Table_get(structure,row,region.right); - if (region.right < cell.right) { - region.right = cell.right; - boundariesOk = false; - } - } - - for (var col = region.left; col <= region.right; col++) { - var cell = Table_get(structure,region.top,col); - if (region.top > cell.top) { - region.top = cell.top; - boundariesOk = false; - } - cell = Table_get(structure,region.bottom,col); - if (region.bottom < cell.bottom) { - region.bottom = cell.bottom; - boundariesOk = false; - } - } - } while (!boundariesOk); - } - - Tables_getSelectedTableId = function() - { - var element = Cursor_getAdjacentNodeWithType(HTML_TABLE); - return element ? element.getAttribute("id") : null; - } - - Tables_getProperties = function(itemId) - { - var element = document.getElementById(itemId); - if ((element == null) || (element._type != HTML_TABLE)) - return null; - var structure = Tables_analyseStructure(element); - var width = element.style.width; - return { width: width, rows: structure.numRows, cols: structure.numCols }; - } - - Tables_setProperties = function(itemId,width) - { - var table = document.getElementById(itemId); - if (table == null) - return null; - DOM_setStyleProperties(table,{ width: width }); - Selection_update(); // ensure cursor/selection drawn in correct pos - } - - // Returns an array of numbers representing the percentage widths (0 - 100) of each - // column. This works on the assumption that all tables are supposed to have all of - // their column widths specified, and in all cases as percentages. Any which do not - // are considered invalid, and have any non-percentage values filled in based on the - // average values of all valid percentage-based columns. - Tables_getColWidths = function(structure) - { - var colElements = getColElements(structure.element); - var colWidths = new Array(); - - for (var i = 0; i < structure.numCols; i++) { - var value = null; - - if (i < colElements.length) { - var widthStr = DOM_getAttribute(colElements[i],"width"); - if (widthStr != null) { - value = parsePercentage(widthStr); - } - } - - if ((value != null) && (value >= 1.0)) { - colWidths[i] = value; - } - else { - colWidths[i] = null; - } - } - - fixWidths(colWidths,structure.numCols); - - return colWidths; - - function parsePercentage(str) - { - if (str.match(/^\s*\d+(\.\d+)?\s*%\s*$/)) - return parseFloat(str.replace(/\s*%\s*$/,"")); - else - return null; - } - } - - function fixWidths(colWidths,numCols) - { - var totalWidth = 0; - var numValidCols = 0; - for (var i = 0; i < numCols; i++) { - if (colWidths[i] != null) { - totalWidth += colWidths[i]; - numValidCols++; - } - } - - var averageWidth = (numValidCols > 0) ? totalWidth/numValidCols : 1.0; - for (var i = 0; i < numCols; i++) { - if (colWidths[i] == null) { - colWidths[i] = averageWidth; - totalWidth += averageWidth; - } - } - - // To cater for the case where the column widths do not all add up to 100%, - // recalculate all of them based on their value relative to the total width - // of all columns. For example, if there are three columns of 33%, 33%, and 33%, - // these will get rounded up to 33.33333.....%. - // If there are no column widths defined, each will have 100/numCols%. - if (totalWidth > 0) { - for (var i = 0; i < numCols; i++) { - colWidths[i] = 100.0*colWidths[i]/totalWidth; - } - } - } - - // public - Tables_setColWidths = function(itemId,widths) - { - var element = document.getElementById(itemId); - if (element == null) - return null; - - var structure = Tables_analyseStructure(element); - - fixWidths(widths,structure.numCols); - - var colElements = getColElements(element); - for (var i = 0; i < widths.length; i++) - DOM_setAttribute(colElements[i],"width",widths[i]+"%"); - - Selection_update(); - } - - // public - Tables_getGeometry = function(itemId) - { - var element = document.getElementById(itemId); - if ((element == null) || (element.parentNode == null)) - return null; - - var structure = Tables_analyseStructure(element); - - var result = new Object(); - - // Calculate the rect based on the cells, not the whole table element; - // we want to ignore the caption - var topLeftCell = Table_get(structure,0,0); - var bottomRightCell = Table_get(structure,structure.numRows-1,structure.numCols-1); - - if (topLeftCell == null) - throw new Error("No top left cell"); - if (bottomRightCell == null) - throw new Error("No bottom right cell"); - - var topLeftRect = topLeftCell.element.getBoundingClientRect(); - var bottomRightRect = bottomRightCell.element.getBoundingClientRect(); - - var left = topLeftRect.left + window.scrollX; - var right = bottomRightRect.right + window.scrollX; - var top = topLeftRect.top + window.scrollY; - var bottom = bottomRightRect.bottom + window.scrollY; - - result.contentRect = { x: left, y: top, width: right - left, height: bottom - top }; - result.fullRect = xywhAbsElementRect(element); - result.parentRect = xywhAbsElementRect(element.parentNode); - - result.columnWidths = Tables_getColWidths(structure); - - var caption = firstChildOfType(element,HTML_CAPTION); - result.hasCaption = (caption != null); - - return result; - - } - -})(); http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/26f461e7/experiments/Editor/src/Text.js ---------------------------------------------------------------------- diff --git a/experiments/Editor/src/Text.js b/experiments/Editor/src/Text.js deleted file mode 100644 index 5a69feb..0000000 --- a/experiments/Editor/src/Text.js +++ /dev/null @@ -1,543 +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 Text_findParagraphBoundaries; -var Text_analyseParagraph; -var Text_posAbove; -var Text_posBelow; -var Text_closestPosBackwards; -var Text_closestPosForwards; -var Text_closestPosInDirection; - -var Paragraph_runFromOffset; -var Paragraph_runFromNode; -var Paragraph_positionAtOffset; -var Paragraph_offsetAtPosition; -var Paragraph_getRunRects; -var Paragraph_getRunOrFallbackRects; - -var Text_toStartOfBoundary; -var Text_toEndOfBoundary; - -(function() { - - function Paragraph(node,startOffset,endOffset,runs,text) - { - this.node = node; - this.startOffset = startOffset; - this.endOffset = endOffset; - this.runs = runs; - this.text = text; - - Object.defineProperty(this,"first",{ - get: function() { throw new Error("Attempt to access first property of Position") }, - set: function() {}, - enumerable: true }); - Object.defineProperty(this,"last",{ - get: function() { throw new Error("Attempt to access last property of Position") }, - set: function() {}, - enumerable: true }); - } - - function Run(node,start,end) - { - this.node = node; - this.start = start; - this.end = end; - } - - // In this code, we represent a paragraph by its first and last node. Normally, this will be - // the first and last child of a paragraph-level element (e.g. p or h1), but this scheme also - // represent a sequence of inline nodes between two paragraph or container nodes, e.g. - // - //

...

Some inline nodes

...

- - Text_findParagraphBoundaries = function(pos) - { - Position_assertValid(pos); - var startOffset = pos.offset; - var endOffset = pos.offset; - var node = pos.node; - - while (isInlineNode(node)) { - startOffset = DOM_nodeOffset(node); - endOffset = DOM_nodeOffset(node)+1; - node = node.parentNode; - } - - if (node.nodeType != Node.ELEMENT_NODE) - throw new Error("Not an element node: "+nodeString(node)); - - while ((startOffset > 0) && isInlineNode(node.childNodes[startOffset-1])) - startOffset--; - while ((endOffset < node.childNodes.length) && isInlineNode(node.childNodes[endOffset])) - endOffset++; - - return { node: node, startOffset: startOffset, endOffset: endOffset }; - } - - Text_analyseParagraph = function(pos) - { - var initial = pos.node; - var strings = new Array(); - var runs = new Array(); - var offset = 0; - - var boundaries = Text_findParagraphBoundaries(pos); - if (boundaries == null) - return null; - - for (var off = boundaries.startOffset; off < boundaries.endOffset; off++) - recurse(boundaries.node.childNodes[off]); - - var text = strings.join(""); - - return new Paragraph(boundaries.node,boundaries.startOffset,boundaries.endOffset,runs,text); - - function recurse(node) - { - if (node.nodeType == Node.TEXT_NODE) { - strings.push(node.nodeValue); - var start = offset; - var end = offset + node.nodeValue.length; - runs.push(new Run(node,start,end)); - offset += node.nodeValue.length; - } - for (var child = node.firstChild; child != null; child = child.nextSibling) - recurse(child); - } - } - - Text_posAbove = function(pos,cursorRect,cursorX) - { - if (cursorX == null) - cursorX = pos.targetX; - pos = Position_closestMatchBackwards(pos,Position_okForMovement); - if (cursorRect == null) { - cursorRect = Position_rectAtPos(pos); - if (cursorRect == null) - return null; - } - - if (cursorX == null) { - cursorX = cursorRect.left; - } - - while (true) { - pos = Position_closestMatchBackwards(pos,Position_okForMovement); - if (pos == null) - return null; - - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return null; - - var rects = Paragraph_getRunOrFallbackRects(paragraph,pos); - - rects = rects.filter(function (rect) { - return (rect.bottom <= cursorRect.top); - }); - - - - var bottom = findLowestBottom(rects); - - rects = rects.filter(function (rect) { return (rect.bottom == bottom); }); - - // Scroll previous line into view, if necessary - var top = findHighestTop(rects); - if (top < 0) { - var offset = -top; - window.scrollBy(0,-offset); - rects = offsetRects(rects,0,offset); - } - - for (var i = 0; i < rects.length; i++) { - if ((cursorX >= rects[i].left) && (cursorX <= rects[i].right)) { - var newPos = Position_atPoint(cursorX,rects[i].top + rects[i].height/2); - if (newPos != null) { - newPos = Position_closestMatchBackwards(newPos,Position_okForInsertion); - newPos.targetX = cursorX; - return newPos; - } - } - } - - var rightMost = findRightMostRect(rects); - if (rightMost != null) { - var newPos = Position_atPoint(rightMost.right,rightMost.top + rightMost.height/2); - if (newPos != null) { - newPos = Position_closestMatchBackwards(newPos,Position_okForInsertion); - newPos.targetX = cursorX; - return newPos; - } - } - - - pos = new Position(paragraph.node,paragraph.startOffset); - pos = Position_prevMatch(pos,Position_okForMovement); - } - } - - var findHighestTop = function(rects) - { - var top = null; - for (var i = 0; i < rects.length; i++) { - if ((top == null) || (top > rects[i].top)) - top = rects[i].top; - } - return top; - } - - var findLowestBottom = function(rects) - { - var bottom = null; - for (var i = 0; i < rects.length; i++) { - if ((bottom == null) || (bottom < rects[i].bottom)) - bottom = rects[i].bottom; - } - return bottom; - } - - var findRightMostRect = function(rects) - { - var rightMost = null; - for (var i = 0; i < rects.length; i++) { - if ((rightMost == null) || (rightMost.right < rects[i].right)) - rightMost = rects[i]; - } - return rightMost; - } - - var offsetRects = function(rects,offsetX,offsetY) - { - var result = new Array(); - for (var i = 0; i < rects.length; i++) { - result.push({ top: rects[i].top + offsetY, - bottom: rects[i].bottom + offsetY, - left: rects[i].left + offsetX, - right: rects[i].right + offsetX, - width: rects[i].width, - height: rects[i].height }); - } - return result; - } - - Text_posBelow = function(pos,cursorRect,cursorX) - { - if (cursorX == null) - cursorX = pos.targetX; - pos = Position_closestMatchForwards(pos,Position_okForMovement); - if (cursorRect == null) { - cursorRect = Position_rectAtPos(pos); - if (cursorRect == null) - return null; - } - - if (cursorX == null) { - cursorX = cursorRect.left; - } - - - while (true) { - pos = Position_closestMatchForwards(pos,Position_okForMovement); - if (pos == null) - return null; - - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return null; - - var rects = Paragraph_getRunOrFallbackRects(paragraph,pos); - - rects = rects.filter(function (rect) { - return (rect.top >= cursorRect.bottom); - }); - - var top = findHighestTop(rects); - - rects = rects.filter(function (rect) { return (rect.top == top); }); - - // Scroll next line into view, if necessary - var bottom = findLowestBottom(rects); - if (bottom > window.innerHeight) { - var offset = window.innerHeight - bottom; - window.scrollBy(0,-offset); - rects = offsetRects(rects,0,offset); - } - - for (var i = 0; i < rects.length; i++) { - if ((cursorX >= rects[i].left) && (cursorX <= rects[i].right)) { - var newPos = Position_atPoint(cursorX,rects[i].top + rects[i].height/2); - if (newPos != null) { - newPos = Position_closestMatchForwards(newPos,Position_okForInsertion); - newPos.targetX = cursorX; - return newPos; - } - } - } - - var rightMost = findRightMostRect(rects); - if (rightMost != null) { - var newPos = Position_atPoint(rightMost.right,rightMost.top + rightMost.height/2); - if (newPos != null) { - newPos = Position_closestMatchForwards(newPos,Position_okForInsertion); - newPos.targetX = cursorX; - return newPos; - } - } - - pos = new Position(paragraph.node,paragraph.endOffset); - pos = Position_nextMatch(pos,Position_okForMovement); - } - } - - Text_closestPosBackwards = function(pos) - { - if (isNonWhitespaceTextNode(pos.node)) - return pos; - var node; - if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset > 0)) { - node = pos.node.childNodes[pos.offset-1]; - while (node.lastChild != null) - node = node.lastChild; - } - else { - node = pos.node; - } - while ((node != null) && (node != document.body) && !isNonWhitespaceTextNode(node)) - node = prevNode(node); - - if ((node == null) || (node == document.body)) - return null; - else - return new Position(node,node.nodeValue.length); - } - - Text_closestPosForwards = function(pos) - { - if (isNonWhitespaceTextNode(pos.node)) - return pos; - var node; - if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset < pos.node.childNodes.length)) { - node = pos.node.childNodes[pos.offset]; - while (node.firstChild != null) - node = node.firstChild; - } - else { - node = nextNodeAfter(pos.node); - } - while ((node != null) && !isNonWhitespaceTextNode(node)) { - var old = nodeString(node); - node = nextNode(node); - } - - if (node == null) - return null; - else - return new Position(node,0); - } - - Text_closestPosInDirection = function(pos,direction) - { - if ((direction == "forward") || - (direction == "right") || - (direction == "down")) { - return Text_closestPosForwards(pos); - } - else { - return Text_closestPosBackwards(pos); - } - } - - Paragraph_runFromOffset = function(paragraph,offset,end) - { - if (paragraph.runs.length == 0) - throw new Error("Paragraph has no runs"); - if (!end) { - - for (var i = 0; i < paragraph.runs.length; i++) { - var run = paragraph.runs[i]; - if ((offset >= run.start) && (offset < run.end)) - return run; - if ((i == paragraph.runs.length-1) && (offset == run.end)) - return run; - } - - } - else { - - for (var i = 0; i < paragraph.runs.length; i++) { - var run = paragraph.runs[i]; - if ((offset > run.start) && (offset <= run.end)) - return run; - if ((i == 0) && (offset == 0)) - return run; - } - - } - } - - Paragraph_runFromNode = function(paragraph,node) - { - for (var i = 0; i < paragraph.runs.length; i++) { - if (paragraph.runs[i].node == node) - return paragraph.runs[i]; - } - throw new Error("Run for text node not found"); - } - - Paragraph_positionAtOffset = function(paragraph,offset,end) - { - var run = Paragraph_runFromOffset(paragraph,offset,end); - if (run == null) - throw new Error("Run at offset "+offset+" not found"); - return new Position(run.node,offset-run.start); - } - - Paragraph_offsetAtPosition = function(paragraph,pos) - { - var run = Paragraph_runFromNode(paragraph,pos.node); - return run.start + pos.offset; - } - - Paragraph_getRunRects = function(paragraph) - { - var rects = new Array(); - for (var i = 0; i < paragraph.runs.length; i++) { - var run = paragraph.runs[i]; - var runRange = new Range(run.node,0,run.node,run.node.nodeValue.length); - var runRects = Range_getClientRects(runRange); - Array.prototype.push.apply(rects,runRects); - } - return rects; - } - - Paragraph_getRunOrFallbackRects = function(paragraph,pos) - { - var rects = Paragraph_getRunRects(paragraph); - if ((rects.length == 0) && (paragraph.node.nodeType == Node.ELEMENT_NODE)) { - if (isBlockNode(paragraph.node) && - (paragraph.startOffset == 0) && - (paragraph.endOffset == paragraph.node.childNodes.length)) { - rects = [paragraph.node.getBoundingClientRect()]; - } - else { - var beforeNode = paragraph.node.childNodes[paragraph.startOffset-1]; - var afterNode = paragraph.node.childNodes[paragraph.endOffset]; - if ((afterNode != null) && isBlockNode(afterNode)) { - rects = [afterNode.getBoundingClientRect()]; - } - else if ((beforeNode != null) && isBlockNode(beforeNode)) { - rects = [beforeNode.getBoundingClientRect()]; - } - } - } - return rects; - } - - function toStartOfParagraph(pos) - { - pos = Position_closestMatchBackwards(pos,Position_okForMovement); - if (pos == null) - return null; - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return null; - - var newPos = new Position(paragraph.node,paragraph.startOffset); - return Position_closestMatchForwards(newPos,Position_okForMovement); - } - - function toEndOfParagraph(pos) - { - pos = Position_closestMatchForwards(pos,Position_okForMovement); - if (pos == null) - return null; - var paragraph = Text_analyseParagraph(pos); - if (paragraph == null) - return null; - - var newPos = new Position(paragraph.node,paragraph.endOffset); - return Position_closestMatchBackwards(newPos,Position_okForMovement); - } - - function toStartOfLine(pos) - { - var posRect = Position_rectAtPos(pos); - if (posRect == null) { - pos = Text_closestPosBackwards(pos); - posRect = Position_rectAtPos(pos); - if (posRect == null) { - return null; - } - } - - while (true) { - var check = Position_prevMatch(pos,Position_okForMovement); - var checkRect = Position_rectAtPos(check); // handles check == null case - if (checkRect == null) - return pos; - if ((checkRect.bottom <= posRect.top) || (checkRect.top >= posRect.bottom)) - return pos; - pos = check; - } - } - - function toEndOfLine(pos) - { - var posRect = Position_rectAtPos(pos); - if (posRect == null) { - pos = Text_closestPosForwards(pos); - posRect = Position_rectAtPos(pos); - if (posRect == null) { - return null; - } - } - - while (true) { - var check = Position_nextMatch(pos,Position_okForMovement); - var checkRect = Position_rectAtPos(check); // handles check == null case - if (checkRect == null) - return pos; - if ((checkRect.bottom <= posRect.top) || (checkRect.top >= posRect.bottom)) - return pos; - pos = check; - } - } - - Text_toStartOfBoundary = function(pos,boundary) - { - if (boundary == "paragraph") - return toStartOfParagraph(pos); - else if (boundary == "line") - return toStartOfLine(pos); - else - throw new Error("Unsupported boundary: "+boundary); - } - - Text_toEndOfBoundary = function(pos,boundary) - { - if (boundary == "paragraph") - return toEndOfParagraph(pos); - else if (boundary == "line") - return toEndOfLine(pos); - else - throw new Error("Unsupported boundary: "+boundary); - } - -})(); http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/26f461e7/experiments/Editor/src/UndoManager.js ---------------------------------------------------------------------- diff --git a/experiments/Editor/src/UndoManager.js b/experiments/Editor/src/UndoManager.js deleted file mode 100644 index 9f63c43..0000000 --- a/experiments/Editor/src/UndoManager.js +++ /dev/null @@ -1,270 +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. - -// FIXME: place a limit on the number of undo steps recorded - say, 30-50? - -var UndoManager_getLength; -var UndoManager_getIndex; -var UndoManager_setIndex; -var UndoManager_print; -var UndoManager_undo; -var UndoManager_redo; -var UndoManager_addAction; -var UndoManager_newGroup; -var UndoManager_groupType; -var UndoManager_disableWhileExecuting; -var UndoManager_isActive; -var UndoManager_isDisabled; -var UndoManager_clear; -var UndoManager_setProperty; -var UndoManager_deleteProperty; - -(function() { - - var UNDO_LIMIT = 50; - - function UndoGroup(type,onClose) - { - this.type = type; - this.onClose = onClose; - this.actions = new Array(); - } - - function UndoAction(fun,args) - { - this.fun = fun; - this.args = args; - } - - UndoAction.prototype.toString = function() - { - var name; - if (this.fun.wrappedName != null) - name = this.fun.wrappedName; - else - name = this.fun.name; - - var argStrings = new Array(); - for (var i = 0; i < this.args.length; i++) { - if (this.args[i] instanceof Node) - argStrings.push(nodeString(this.args[i])); - else if (this.args[i] == null) - argStrings.push("null"); - else - argStrings.push(this.args[i].toString()); - } - - return name + "(" + argStrings.join(",") + ")"; - } - - var undoStack = new Array(); - var redoStack = new Array(); - var inUndo = false; - var inRedo = false; - var currentGroup = null; - var disabled = 0; - - // public - UndoManager_getLength = function() - { - return undoStack.length + redoStack.length; - } - - // public - UndoManager_getIndex = function() - { - return undoStack.length; - } - - // public - UndoManager_setIndex = function(index) - { - while (undoStack.length > index) - UndoManager_undo(); - while (undoStack.length < index) - UndoManager_redo(); - } - - // public - UndoManager_print = function() - { - debug(""); - debug("--------------------------------------------------------------------"); - debug("Undo stack:"); - for (var groupIndex = 0; groupIndex < undoStack.length; groupIndex++) { - var group = undoStack[groupIndex]; - debug(" "+group.type); - for (var actionIndex = 0; actionIndex < group.actions.length; actionIndex++) { - var action = group.actions[actionIndex]; - debug(" "+action); - } - } - debug("Redo stack:"); - for (var groupIndex = 0; groupIndex < redoStack.length; groupIndex++) { - var group = redoStack[groupIndex]; - debug(" "+group.type); - for (var actionIndex = 0; actionIndex < group.actions.length; actionIndex++) { - var action = group.actions[actionIndex]; - debug(" "+action); - } - } - debug("Current group = "+currentGroup); - debug("--------------------------------------------------------------------"); - debug(""); - } - - function closeCurrentGroup() - { - if ((currentGroup != null) && (currentGroup.onClose != null)) - currentGroup.onClose(); - currentGroup = null; - } - - // public - UndoManager_undo = function() - { - closeCurrentGroup(); - if (undoStack.length > 0) { - var group = undoStack.pop(); - inUndo = true; - for (var i = group.actions.length-1; i >= 0; i--) - group.actions[i].fun.apply(null,group.actions[i].args); - inUndo = false; - } - closeCurrentGroup(); - } - - // public - UndoManager_redo = function() - { - closeCurrentGroup(); - if (redoStack.length > 0) { - var group = redoStack.pop(); - inRedo = true; - for (var i = group.actions.length-1; i >= 0; i--) - group.actions[i].fun.apply(null,group.actions[i].args); - inRedo = false; - } - closeCurrentGroup(); - } - - // public - UndoManager_addAction = function(fun) - { - if (disabled > 0) - return; - - // remaining parameters after fun are arguments to be supplied to fun - var args = new Array(); - for (var i = 1; i < arguments.length; i++) - args.push(arguments[i]); - - if (!inUndo && !inRedo && (redoStack.length > 0)) - redoStack.length = 0; - - var stack = inUndo ? redoStack : undoStack; - if (currentGroup == null) - UndoManager_newGroup(null); - - // Only add a group to the undo stack one it has at least one action, to avoid having - // empty groups present. - if (currentGroup.actions.length == 0) { - if (!inUndo && !inRedo && (stack.length == UNDO_LIMIT)) - stack.shift(); - stack.push(currentGroup); - } - - currentGroup.actions.push(new UndoAction(fun,args)); - } - - // public - UndoManager_newGroup = function(type,onClose) - { - if (disabled > 0) - return; - - closeCurrentGroup(); - - // We don't actually add the group to the undo stack until the first request to add an - // action to it. This way we don't end up with empty groups in the undo stack, which - // simplifies logic for moving back and forward through the undo history. - - if ((type == null) || (type == "")) - type = "Anonymous"; - currentGroup = new UndoGroup(type,onClose); - } - - // public - UndoManager_groupType = function() - { - if (undoStack.length > 0) - return undoStack[undoStack.length-1].type; - else - return null; - } - - UndoManager_disableWhileExecuting = function(fun) { - disabled++; - try { - return fun(); - } - finally { - disabled--; - } - } - - UndoManager_isActive = function() - { - return (inUndo || inRedo); - } - - UndoManager_isDisabled = function() { - return (disabled > 0); - } - - UndoManager_clear = function() { - undoStack.length = 0; - redoStack.length = 0; - } - - function saveProperty(obj,name) - { - if (obj.hasOwnProperty(name)) - UndoManager_addAction(UndoManager_setProperty,obj,name,obj[name]); - else - UndoManager_addAction(UndoManager_deleteProperty,obj,name); - } - - UndoManager_setProperty = function(obj,name,value) - { - if (obj.hasOwnProperty(name) && (obj[name] == value)) - return; // no point in adding an undo action - saveProperty(obj,name); - obj[name] = value; - } - - UndoManager_deleteProperty = function(obj,name) - { - if (!obj.hasOwnProperty(name)) - return; // no point in adding an undo action - saveProperty(obj,name); - delete obj[name]; - } - -})(); - -window.undoSupported = true; http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/26f461e7/experiments/Editor/src/Viewport.js ---------------------------------------------------------------------- diff --git a/experiments/Editor/src/Viewport.js b/experiments/Editor/src/Viewport.js deleted file mode 100644 index 47fbdfd..0000000 --- a/experiments/Editor/src/Viewport.js +++ /dev/null @@ -1,80 +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 Viewport_init; -var Viewport_setViewportWidth; -var Viewport_setTextScale; - -(function() { - - var viewportMetaElement = null; - - // public - Viewport_init = function(width,textScale) - { - var head = DOM_documentHead(document); - for (var child = head.firstChild; child != null; child = child.nextSibling) { - if ((child._type == HTML_META) && (child.getAttribute("name") == "viewport")) { - viewportMetaElement = child; - break; - } - } - - if (viewportMetaElement == null) { - viewportMetaElement = DOM_createElement(document,"META"); - DOM_setAttribute(viewportMetaElement,"name","viewport"); - DOM_appendChild(head,viewportMetaElement); - } - - if (width != 0) { - // Only set the width and text scale if they are not already set, to avoid triggering - // an extra layout at load time - var contentValue = "width = "+width+", user-scalable = no"; - if (viewportMetaElement.getAttribute("content") != contentValue) - DOM_setAttribute(viewportMetaElement,"content",contentValue); - } - - if (textScale != 0) { - var pct = textScale+"%"; - if (document.documentElement.style.getPropertyValue("-webkit-text-size-adjust") != pct) - DOM_setStyleProperties(document.documentElement,{"-webkit-text-size-adjust": pct}); - } - } - - // public - Viewport_setViewportWidth = function(width) - { - var contentValue = "width = "+width+", user-scalable = no"; - if (viewportMetaElement.getAttribute("content") != contentValue) - DOM_setAttribute(viewportMetaElement,"content",contentValue); - - Selection_update(); - Cursor_ensureCursorVisible(); - } - - // public - Viewport_setTextScale = function(textScale) - { - var pct = textScale+"%"; - if (document.documentElement.style.getPropertyValue("-webkit-text-size-adjust") != pct) - DOM_setStyleProperties(document.documentElement,{"-webkit-text-size-adjust": pct}); - - Selection_update(); - Cursor_ensureCursorVisible(); - } - -})(); http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/26f461e7/experiments/Editor/src/check-dom-methods.sh ---------------------------------------------------------------------- diff --git a/experiments/Editor/src/check-dom-methods.sh b/experiments/Editor/src/check-dom-methods.sh deleted file mode 100755 index 6e17a4e..0000000 --- a/experiments/Editor/src/check-dom-methods.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -jsgrep -F '.createElement' | grep -vF '// check-ok' -jsgrep -F '.createTextNode' | grep -vF '// check-ok' -jsgrep -F '.createComment' | grep -vF '// check-ok' -jsgrep -F '.appendChild' | grep -vF '// check-ok' -jsgrep -F '.insertBefore' | grep -vF '// check-ok' -jsgrep -F '.removeChild' | grep -vF '// check-ok' -jsgrep -F '.cloneNode' | grep -vF '// check-ok' -jsgrep -F '.nodeName' | grep -vE '(dtdsource/|tests/|treevis/)' | grep -vF '// check-ok' -jsgrep -F '.setAttribute' | grep -vE '(dtdsource/|treevis/|docx/)' | grep -vF '// check-ok' -jsgrep -F '.removeAttribute' | grep -vE '(dtdsource/|treevis/|docx/)' | grep -vF '// check-ok' -jsgrep -F '.setProperty' | grep -vE '(dtdsource/|treevis/)' | grep -vF '// check-ok' -jsgrep -F '.removeProperty' | grep -vE '(dtdsource/|treevis/)' | grep -vF '// check-ok' -jsgrep -E '\.style\[.* = ' | grep -vE '(treevis/|docx/)' | grep -vF '// check-ok' -jsgrep -E '\.style\..* = ' | grep -vE '(treevis/|docx/)' | grep -vF '// check-ok'