From e44a7e37b6c7b5961adaffc62b9042b8d442938e Mon Sep 17 00:00:00 2001 From: mensonge Date: Thu, 13 Nov 2008 09:49:11 +0000 Subject: New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f --- includes/js/dijit/_editor/range.js | 570 +++++++++++++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 includes/js/dijit/_editor/range.js (limited to 'includes/js/dijit/_editor/range.js') diff --git a/includes/js/dijit/_editor/range.js b/includes/js/dijit/_editor/range.js new file mode 100644 index 0000000..cd84b60 --- /dev/null +++ b/includes/js/dijit/_editor/range.js @@ -0,0 +1,570 @@ +if(!dojo._hasResource["dijit._editor.range"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.range"] = true; +dojo.provide("dijit._editor.range"); + +dijit.range={}; + +dijit.range.getIndex=function(/*DomNode*/node, /*DomNode*/parent){ +// dojo.profile.start("dijit.range.getIndex"); + var ret=[], retR=[]; + var stop = parent; + var onode = node; + + var pnode, n; + while(node != stop){ + var i = 0; + pnode = node.parentNode; + while((n=pnode.childNodes[i++])){ + if(n===node){ + --i; + break; + } + } + if(i>=pnode.childNodes.length){ + dojo.debug("Error finding index of a node in dijit.range.getIndex"); + } + ret.unshift(i); + retR.unshift(i-pnode.childNodes.length); + node = pnode; + } + + //normalized() can not be called so often to prevent + //invalidating selection/range, so we have to detect + //here that any text nodes in a row + if(ret.length>0 && onode.nodeType==3){ + n = onode.previousSibling; + while(n && n.nodeType==3){ + ret[ret.length-1]--; + n = n.previousSibling; + } + n = onode.nextSibling; + while(n && n.nodeType==3){ + retR[retR.length-1]++; + n = n.nextSibling; + } + } +// dojo.profile.end("dijit.range.getIndex"); + return {o: ret, r:retR}; +} + +dijit.range.getNode = function(/*Array*/index, /*DomNode*/parent){ + if(!dojo.isArray(index) || index.length==0){ + return parent; + } + var node = parent; +// if(!node)debugger + dojo.every(index, function(i){ + if(i>=0&&i< node.childNodes.length){ + node = node.childNodes[i]; + }else{ + node = null; + console.debug('Error: can not find node with index',index,'under parent node',parent ); + return false; //terminate dojo.every + } + return true; //carry on the every loop + }); + + return node; +} + +dijit.range.getCommonAncestor = function(n1,n2,root){ + var getAncestors = function(n,root){ + var as=[]; + while(n){ + as.unshift(n); + if(n!=root && n.tagName!='BODY'){ + n = n.parentNode; + }else{ + break; + } + } + return as; + }; + var n1as = getAncestors(n1,root); + var n2as = getAncestors(n2,root); + + var m = Math.min(n1as.length,n2as.length); + var com = n1as[0]; //at least, one element should be in the array: the root (BODY by default) + for(var i=1;i0){ + dojo.every(parentNode.childNodes, function(node,i){ + var calOffset; + if(node.nodeType != 3){ + atmrange.moveToElementText(node); + + if(atmrange.compareEndPoints(cmpstr,range) > 0){ + startnode = node.previousSibling; + if(lastNode && lastNode.nodeType == 3){ + //where share we put the start? in the text node or after? + startnode = lastNode; + calOffset = true; + }else{ + startnode = parentNode; + startOffset = i; + return false; + } + }else{ + if(i==parentNode.childNodes.length-1){ + startnode = parentNode; + startOffset = parentNode.childNodes.length; + return false; + } + } + }else{ + if(i==parentNode.childNodes.length-1){//at the end of this node + startnode = node; + calOffset = true; + } + } + // try{ + if(calOffset && startnode){ + var prevnode = dijit.range.adjacentNoneTextNode(startnode)[0]; + if(prevnode){ + startnode = prevnode.nextSibling; + }else{ + startnode = parentNode.firstChild; //firstChild must be a text node + } + var prevnodeobj = dijit.range.adjacentNoneTextNode(startnode); + prevnode = prevnodeobj[0]; + var lenoffset = prevnodeobj[1]; + if(prevnode){ + atmrange.moveToElementText(prevnode); + atmrange.collapse(false); + }else{ + atmrange.moveToElementText(parentNode); + } + atmrange.setEndPoint(cmpstr, range); + startOffset = atmrange.text.length-lenoffset; + + return false; + } + // }catch(e){ debugger } + lastNode = node; + return true; + }); + }else{ + startnode = parentNode; + startOffset = 0; + } + + //if at the end of startnode and we are dealing with start container, then + //move the startnode to nextSibling if it is a text node + //TODO: do this for end container? + if(!end && startnode.nodeType!=3 && startOffset == startnode.childNodes.length){ + if(startnode.nextSibling && startnode.nextSibling.nodeType==3){ + startnode = startnode.nextSibling; + startOffset = 0; + } + } + return [startnode, startOffset]; + }, + setEndPoint: function(range, container, offset){ + //text node + var atmrange = range.duplicate(), node, len; + if(container.nodeType!=3){ //normal node + atmrange.moveToElementText(container); + atmrange.collapse(true); + if(offset == container.childNodes.length){ + if(offset > 0){ + //a simple atmrange.collapse(false); won't work here: + //although moveToElementText(node) is supposed to encompass the content of the node, + //but when collapse to end, it is in fact after the ending tag of node (collapse to start + //is after the begining tag of node as expected) + node = container.lastChild; + len = 0; + while(node && node.nodeType == 3){ + len += node.length; + container = node; //pass through + node = node.previousSibling; + } + if(node){ + atmrange.moveToElementText(node); + } + atmrange.collapse(false); + offset = len; //pass through + }else{ //no childNodes + atmrange.moveToElementText(container); + atmrange.collapse(true); + } + }else{ + if(offset > 0){ + node = container.childNodes[offset-1]; + if(node.nodeType==3){ + container = node; + offset = node.length; + //pass through + }else{ + atmrange.moveToElementText(node); + atmrange.collapse(false); + } + } + } + } + if(container.nodeType==3){ + var prevnodeobj = dijit.range.adjacentNoneTextNode(container); + var prevnode = prevnodeobj[0]; + len = prevnodeobj[1]; + if(prevnode){ + atmrange.moveToElementText(prevnode); + atmrange.collapse(false); + //if contentEditable is not inherit, the above collapse won't make the end point + //in the correctly position: it always has a -1 offset, so compensate it + if(prevnode.contentEditable!='inherit'){ + len++; + } + }else{ + atmrange.moveToElementText(container.parentNode); + atmrange.collapse(true); + } + + offset += len; + if(offset>0){ + if(atmrange.moveEnd('character',offset) != offset){ + alert('Error when moving!'); + } + atmrange.collapse(false); + } + } + + return atmrange; + }, + decomposeTextRange: function(range){ + var tmpary = dijit.range.ie.getEndPoint(range); + var startContainter = tmpary[0], startOffset = tmpary[1]; + var endContainter = tmpary[0], endOffset = tmpary[1]; + + if(range.htmlText.length){ + if(range.htmlText == range.text){ //in the same text node + endOffset = startOffset+range.text.length; + }else{ + tmpary = dijit.range.ie.getEndPoint(range,true); + endContainter = tmpary[0], endOffset = tmpary[1]; + } + } + return [[startContainter, startOffset],[endContainter, endOffset], range.parentElement()]; + }, + setRange: function(range, startContainter, + startOffset, endContainter, endOffset, check){ + var startrange = dijit.range.ie.setEndPoint(range, startContainter, startOffset); + range.setEndPoint('StartToStart', startrange); + if(!this.collapsed){ + var endrange = dijit.range.ie.setEndPoint(range, endContainter, endOffset); + range.setEndPoint('EndToEnd', endrange); + } + + return range; + } + } + +dojo.declare("dijit.range.W3CRange",null, { + constructor: function(){ + if(arguments.length>0){ + this.setStart(arguments[0][0][0],arguments[0][0][1]); + this.setEnd(arguments[0][1][0],arguments[0][1][1],arguments[0][2]); + }else{ + this.commonAncestorContainer = null; + this.startContainer = null; + this.startOffset = 0; + this.endContainer = null; + this.endOffset = 0; + this.collapsed = true; + } + }, + _simpleSetEndPoint: function(node, range, end){ + var r = (this._body||node.ownerDocument.body).createTextRange(); + if(node.nodeType!=1){ + r.moveToElementText(node.parentNode); + }else{ + r.moveToElementText(node); + } + r.collapse(true); + range.setEndPoint(end?'EndToEnd':'StartToStart',r); + }, + _updateInternal: function(__internal_common){ + if(this.startContainer !== this.endContainer){ + if(!__internal_common){ + var r = (this._body||this.startContainer.ownerDocument.body).createTextRange(); + this._simpleSetEndPoint(this.startContainer,r); + this._simpleSetEndPoint(this.endContainer,r,true); + __internal_common = r.parentElement(); + } + this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer, __internal_common); + }else{ + this.commonAncestorContainer = this.startContainer; + } + this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset); + }, + setStart: function(node, offset, __internal_common){ + offset=parseInt(offset); + if(this.startContainer === node && this.startOffset == offset){ + return; + } + delete this._cachedBookmark; + + this.startContainer = node; + this.startOffset = offset; + if(!this.endContainer){ + this.setEnd(node, offset, __internal_common); + }else{ + this._updateInternal(__internal_common); + } + }, + setEnd: function(node, offset, __internal_common){ + offset=parseInt(offset); + if(this.endContainer === node && this.endOffset == offset){ + return; + } + delete this._cachedBookmark; + + this.endContainer = node; + this.endOffset = offset; + if(!this.startContainer){ + this.setStart(node, offset, __internal_common); + }else{ + this._updateInternal(__internal_common); + } + }, + setStartAfter: function(node, offset){ + this._setPoint('setStart', node, offset, 1); + }, + setStartBefore: function(node, offset){ + this._setPoint('setStart', node, offset, 0); + }, + setEndAfter: function(node, offset){ + this._setPoint('setEnd', node, offset, 1); + }, + setEndBefore: function(node, offset){ + this._setPoint('setEnd', node, offset, 0); + }, + _setPoint: function(what, node, offset, ext){ + var index = dijit.range.getIndex(node, node.parentNode).o; + this[what](node.parentNode, index.pop()+ext); + }, + _getIERange: function(){ + var r=(this._body||this.endContainer.ownerDocument.body).createTextRange(); + dijit.range.ie.setRange(r, this.startContainer, this.startOffset, this.endContainer, this.endOffset); + return r; + }, + getBookmark: function(body){ + this._getIERange(); + return this._cachedBookmark; + }, + _select: function(){ + var r = this._getIERange(); + r.select(); + }, + deleteContents: function(){ + var r = this._getIERange(); + r.pasteHTML(''); + this.endContainer = this.startContainer; + this.endOffset = this.startOffset; + this.collapsed = true; + }, + cloneRange: function(){ + var r = new dijit.range.W3CRange([[this.startContainer,this.startOffset], + [this.endContainer,this.endOffset]]); + r._body = this._body; + return r; + }, + detach: function(){ + this._body = null; + this.commonAncestorContainer = null; + this.startContainer = null; + this.startOffset = 0; + this.endContainer = null; + this.endOffset = 0; + this.collapsed = true; +} +}); +} //if(!dijit.range._w3c) + +} -- cgit v1.2.3