InsertionPoint.js
Summary
Tools for editing operations.
Version: 0.8
$Id: overview-summary-InsertionPoint.js.html,v 1.10 2008/02/20 18:47:09 jameso Exp $
Author: James A. Overton
mozile.require("mozile.dom");
mozile.require("mozile.edit");
mozile.provide("mozile.edit.InsertionPoint");
mozile.edit.InsertionPoint = function(node, offset) {
this._node = node;
this._offset = offset;
}
mozile.edit.InsertionPoint.prototype._matchLeadingWS = /^(\s*)/;
mozile.edit.InsertionPoint.prototype._matchTrailingWS = /(\s*)$/;
mozile.edit.InsertionPoint.prototype._matchNonWS = /\S/;
mozile.edit.InsertionPoint.prototype.getNode = function() { return this._node; }
mozile.edit.InsertionPoint.prototype.getOffset = function() {
if(this._offset < 0) this._offset = 0;
return this._offset;
}
mozile.edit.InsertionPoint.prototype.toString = function() {
return "Insertion Point: "+ mozile.xpath.getXPath(this._node) +" "+ this._offset;
}
mozile.edit.InsertionPoint.prototype.charAt = function() {
var node = this.getNode();
if(node && node.nodeType != mozile.dom.TEXT_NODE) return "";
if(node.data.length <= this.getOffset()) return "";
return node.data.charAt(this.getOffset());
}
mozile.edit.InsertionPoint.prototype.select = function() {
try {
var selection = mozile.dom.selection.get();
selection.collapse(this.getNode(), this.getOffset());
} catch(e) {
mozile.debug.debug("mozile.edit.InsertionPoint.prototype.select", "Bad collapse for IP "+ mozile.xpath.getXPath(this.getNode()) +" "+ this.getOffset() +"\n"+ mozile.dumpError(e));
}
}
mozile.edit.InsertionPoint.prototype.extend = function() {
try {
var selection = mozile.dom.selection.get();
selection.extend(this.getNode(), this.getOffset());
} catch(e) {
mozile.debug.debug("mozile.edit.InsertionPoint.prototype.extend", "Bad extend for IP "+ mozile.xpath.getXPath(this.getNode()) +" "+ this.getOffset() +"\n"+ mozile.dumpError(e));
}
}
mozile.edit.InsertionPoint.prototype.next = function(extraStep, container) {
return this.seek(mozile.edit.NEXT, extraStep, container);
}
mozile.edit.InsertionPoint.prototype.previous = function(extraStep, container) {
return this.seek(mozile.edit.PREVIOUS, extraStep, container);
}
mozile.edit.InsertionPoint.prototype.seek = function(direction, extraStep, container) {
var node = this.getNode();
var offset = this.getOffset();
if(!node || typeof(offset) == "undefined") return false;
if(node.nodeType != mozile.dom.TEXT_NODE ||
(!mozile.edit.mayContainText(node) && mozile.edit.isEmpty(node)) ||
(direction == mozile.edit.PREVIOUS && offset == 0) ||
(direction == mozile.edit.NEXT && offset == node.data.length) ||
(direction == mozile.edit.NEXT && mozile.edit.isEmptyToken(node)) ) {
return this.seekNode(direction, extraStep, container);
}
else offset = offset + direction;
if(!node || typeof(offset) == "undefined") return false;
if(mozile.edit.isEmptyToken(node)) {
this._offset = 0;
return true;
}
var content = node.data;
var substring, result, altSpaceIndex;
if(direction == mozile.edit.NEXT) {
substring = content.substring(this.getOffset());
result = substring.match(this._matchLeadingWS);
if(mozile.alternateSpace)
altSpaceIndex = substring.indexOf(mozile.alternateSpace);
}
else {
substring = content.substring(0, this.getOffset());
result = substring.match(this._matchTrailingWS);
if(mozile.alternateSpace) {
altSpaceIndex = substring.length;
altSpaceIndex -= substring.lastIndexOf(mozile.alternateSpace) + 1;
}
}
var wsLength = result[0].length;
if(Number(altSpaceIndex) != NaN && altSpaceIndex > -1 &&
altSpaceIndex < wsLength) {
wsLength = altSpaceIndex;
}
var moveBy = 0;
if(wsLength < 2) moveBy = direction;
else if(mozile.dom.getStyle(node.parentNode, "white-space").toLowerCase() == "pre") moveBy = direction;
else if(wsLength < substring.length) moveBy = wsLength * direction;
else if(wsLength == substring.length)
return this.seekNode(direction, extraStep, container);
else throw Error("Unhandled case in InsertionPoint.seek()");
this._node = node;
this._offset = this.getOffset() + moveBy;
return true;
}
mozile.edit.InsertionPoint.prototype.seekNode = function(direction, extraStep, container) {
if(extraStep !== false) extraStep = true;
var node = this.getNode();
if(!node) return false;
var offset = this.getOffset();
if(direction == mozile.edit.NEXT && offset > 0) offset--;
if(node.nodeType == mozile.dom.ELEMENT_NODE &&
node.childNodes[offset])
node = node.childNodes[offset];
if(!container) mozile.edit.getContainer(node);
if(!container) container = mozile.document.documentElement;
var treeWalker = document.createTreeWalker(container, mozile.dom.NodeFilter.SHOW_ALL, null, false);
treeWalker.currentNode = node;
var startNode = node;
var IP, tempNode, lastNode, nextNode;
while(node) {
lastNode = node;
if(direction == mozile.edit.NEXT) node = treeWalker.nextNode();
else {
tempNode = node;
node = treeWalker.previousNode();
while(node && node.firstChild == tempNode) {
tempNode = node;
node = treeWalker.previousNode();
}
}
if(!node) break;
IP = mozile.edit.getInsertionPoint(node, direction);
if(IP) {
this._node = IP.getNode();
this._offset = IP.getOffset();
if(mozile.edit.isEmptyToken(this._node)) this._offset = 0;
else if(extraStep && mozile.edit.mayContainText(lastNode) &&
mozile.edit.getParentBlock(node) ==
mozile.edit.getParentBlock(startNode))
this._offset = this._offset + direction;
else if(extraStep && lastNode.nodeType == mozile.dom.COMMENT_NODE &&
node == IP.getNode())
this._offset = this._offset + direction;
return true;
}
nextNode = node;
while(nextNode) {
if(direction == mozile.edit.NEXT) nextNode = nextNode.nextSibling;
else nextNode = nextNode.previousSibling;
if(nextNode && nextNode.nodeType == mozile.dom.COMMENT_NODE) continue;
else break;
}
if(nextNode) {
IP = mozile.edit.getInsertionPoint(nextNode, direction);
if(IP) continue;
}
if(node.nodeType == mozile.dom.ELEMENT_NODE &&
mozile.edit.mayContainText(node.parentNode)) {
this._node = node.parentNode;
this._offset = mozile.dom.getIndex(node);
if(direction == mozile.edit.NEXT &&
this._offset < this._node.childNodes.length)
this._offset++;
while(this._node.childNodes[this._offset-1] &&
this._node.childNodes[this._offset-1].nodeType ==
mozile.dom.COMMENT_NODE)
this._offset--;
return true;
}
}
return false;
}
mozile.dom.Selection.prototype.getInsertionPoint = function(force) {
if(!this.focusNode || this.focusOffset == null) return null;
else return new mozile.edit.InsertionPoint(this.focusNode, this.focusOffset, force);
}
if(mozile.dom.InternetExplorerSelection) {
mozile.dom.InternetExplorerSelection.prototype.getInsertionPoint = mozile.dom.Selection.prototype.getInsertionPoint;
}
mozile.edit.getInsertionPoint = function(node, direction, force) {
if(!node) return false;
var offset, IP;
if(!mozile.edit.isEmpty(node) || mozile.edit.mayContainText(node) || force) {
if(node.nodeType == mozile.dom.TEXT_NODE) {
if(direction == mozile.edit.NEXT) offset = 0;
else if(mozile.edit.isEmptyToken(node)) offset = 0;
else offset = node.data.length;
return new mozile.edit.InsertionPoint(node, offset);
}
if(direction == mozile.edit.NEXT) IP = mozile.edit.getInsertionPoint(node.firstChild, direction, force);
else IP = mozile.edit.getInsertionPoint(node.lastChild, direction, force);
if(IP) return IP;
if(direction == mozile.edit.NEXT) offset = 0;
else offset = node.childNodes.length;
return new mozile.edit.InsertionPoint(node, offset);
}
return null;
}
Documentation generated by
JSDoc on Wed Feb 20 13:25:28 2008