/* * Copyright(c) 2011 * OJC Technologies * all rights reserved * @author: Jake Smith */ function LogicalCursor() { this.lCurs = new RealCursor('left'); this.rCurs = new RealCursor('right'); this.isVirtual = false; this.isPlaced = false; printer = new Printer(); this.isTarget = function(clickTargetElement) { return (this.lCurs.isTarget(clickTargetElement) || this.rCurs.isTarget(clickTargetElement)); } this.placeAt = function(location) { var relation, node, offset, proxHelp; proxHelp = new ProximityHelper(-1,-1); relation = location[0]; node = location[1]; offset = location[2]; switch (relation) { case proxHelp.WITHIN: this.placeWithin(node, offset); break; case proxHelp.ABOVE: this.placeAtStart(node); break; case proxHelp.LEFT: this.placeAtStart(node); break; case proxHelp.BELOW: this.placeAtEnd(node); break; case proxHelp.RIGHT: this.placeAtEnd(node); break; default: throw new Error("\'" + relation + "\'" + " is an invalid location relation"); break; } this.isPlaced = true; } this.remove = function() { if (!this.isPlaced) { return; } this.rCurs.remove(); this.lCurs.remove(); this.isPlaced = false; } this.insert = function(text) { this.rCurs.insert(text); this.lCurs.moveRight(); } this.inputSpace = function() { var whiteChar, space, nbsp; space = "\u0020"; nbsp = "\u00A0"; if (this.rCurs.overBreakingWS()) { this.rCursToNBSP(); whiteChar = space; } else if (this.bothOverChars()) { whiteChar = space; } else if (this.rCurs.overNonBreakWS() && this.lCurs.overChar()) { whiteChar = space; }else { whiteChar = nbsp; } this.insert(whiteChar); } this.doDelete = function() { this.rCurs.del(); if (this.bothOverBreakWS()) { this.rCursToNBSP(); } } this.backspace = function() { this.lCurs.bksps(); if (this.bothOverBreakWS()) { this.rCursToNBSP(); } } this.moveLeft = function() { if (this.lCurs.atStartOfPage) return; this.lCurs.moveLeft(); this.rCurs.moveLeft(); } this.moveRight = function() { if (this.rCurs.atEndOfPage) return; this.rCurs.moveRight(); this.lCurs.moveRight(); } //-----------------------// // "Private" functions // //-----------------------// this.placeWithin = function(node, offset) { var text, startIndex, endIndex, valueWhitespace, functor, rightHalfNode, leftHalfNode; text = node.nodeValue; if (offset == 0) { this.placeAtStart(node); return; } if (text.length < 2) { throw new Error("stand-in error; not sure what to do about" + " degenerate nodes (with length less than 2)"); } functor = new CursorFunctor(); valueWhitespace = functor.isToPreserveWhitespace(node.parentNode); if (valueWhitespace) { startIndex = offset; } else { startIndex = functor.getStartOffset(text, offset); } leftHalfNode = document.createTextNode(text.substring(0, startIndex)); rightHalfNode = document.createTextNode(text.substring(startIndex)); node.parentNode.insertBefore(leftHalfNode, node); node.parentNode.replaceChild(rightHalfNode, node); if (valueWhitespace) { endIndex = 1; } else { endIndex = functor.getEndOffset(rightHalfNode.nodeValue, 0); } this.rCurs.placeAt(rightHalfNode, 0, endIndex); endIndex = leftHalfNode.nodeValue.length; startIndex = endIndex - 1; if (!valueWhitespace) { startIndex = functor.getStartOffset(leftHalfNode.nodeValue, startIndex); } this.lCurs.placeAt(leftHalfNode, startIndex, endIndex); } this.placeAtStart = function(node) { var functor, text, valueWhitespace, endIndex, prevNode, startI; functor = new CursorFunctor(); text = node.nodeValue; valueWhitespace = functor.isToPreserveWhitespace(node.parentNode); if (valueWhitespace) { endIndex = 1; } else { endIndex = functor.getEndOffset(text, 0); } this.rCurs.placeAt(node, 0, endIndex); prevNode = functor.getNodePreceding(this.rCurs.cursor.element); if (prevNode == null) { throw new Error("place@start: prevNode == null"); } else if (prevNode.nodeType != Node.TEXT_NODE) { this.lCurs.placeOverNonTextNode(prevNode); } else { text = prevNode.nodeValue; endIndex = text.length; startI = endIndex - 1; if (functor.isToPreserveWhitespace(prevNode)) { startI = functor.getStartOffset(text, startI); } this.lCurs.placeAt(prevNode, startI, endIndex); // } } this.placeAtEnd = function(node) { var functor, text, valueWhitespace, startIndex, endIndex, nextNode; functor = new CursorFunctor(); text = node.nodeValue; valueWhitespace = functor.isToPreserveWhitespace(node.parentNode); endIndex = text.length; startIndex = endIndex - 1; if (!valueWhitespace) { startIndex = functor.getStartOffset(text, startIndex); } this.lCurs.placeAt(node, startIndex, endIndex); nextNode = functor.getNodeFollowing(this.lCurs.cursor.element); if (nextNode == null) { throw new Error("place@end: nextNode == null"); } else if (nextNode.nodeType != Node.TEXT_NODE) { this.rCurs.placeOverNonTextNode(nextNode); } else { text = nextNode.nodeValue; startIndex = 0; if (functor.isToPreserveWhitespace(nextNode)) { endIndex = 1; } else { endIndex = functor.getEndOffset(text, startIndex); } this.rCurs.placeAt(nextNode, startIndex, endIndex); } } this.bothOverChars = function() { var rightOver, leftOver; rightOver = this.rCurs.overChar(); leftOver = this.lCurs.overChar(); return rightOver && leftOver; return false; } this.bothOverBreakWS = function() { var rightOver, leftOver; rightOver = this.rCurs.overBreakingWS(); leftOver = this.lCurs.overBreakingWS(); return rightOver && leftOver; } this.rCursToNBSP = function() { this.rCurs.del(); this.rCurs.insert("\u00A0"); this.rCurs.moveLeft(); } } // LogicalCursor()