<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
 * Full Terms at http://mozile.mozdev.org/license.html
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Playsophy code.
 *
 * The Initial Developer of the Original Code is Playsophy
 * Portions created by the Initial Developer are Copyright (C) 2002-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

// $Id$

/* 
 * mozCE V0.5
 * 
 * Mozilla Inline text editing that relies on eDOM, extensions to the standard w3c DOM.
 *
 * This file implements contenteditable/user modify in Mozilla by leverging
 * Mozilla's proprietary Selection object as well as eDOM, a set of browser independent
 * extensions to the w3c DOM for building editors. 
 *
 * POST05:
 * - refactor userModify code as part of "EditableElement" 
 * - IE's "ContentEditable" means that an element is editable whenever its "ContentEditable"
 * setting is true. However, we may change this so that you have to set editing on for a
 * document as a whole before its individual editable sections become editable. This would
 * allow a user to browse an editable document and explicitly choose to edit it or not.
 * - see if can move to using DOM events and away from Window.getSelection() if possible 
 * (effects how generic it can be!)
 * - selection model: word, line etc. Write custom handlers of clicks and use new Range
 * expansion methods
 */

/****************************************************************************************
 *
 * MozUserModify and ContentEditable: allow precise designation of editing scope. This
 * file implements user-modify/contentEditable. The following utilities let the implementation
 * determine scope.
 *
 * - http://www.w3.org/TR/1999/WD-css3-userint-19990916#user-modify
 *
 * POST04
 * - rename to be "mozSelection.js"
 * - remove need to spec ContentEditable as equivalent to mozUserModify: do mapping in
 * style sheet: *[contentEditable="true"] 
 * - to change as part of "editableElement": may also move Selection methods into EditableElement
 * - support for tracking whether changes were made to elements or not ie/ does a user
 * need to save? Should MozCE warn a user to save before exiting the browser? Some of
 * this may go into eDOM itself in enhancements to document or to all elements ie/ changed?
 *
 ****************************************************************************************/

/**
 * Start of "EditableElement": this will move into eDOM once it is fleshed out.
 *
 * POST04: set user-input and user-select properly as a side effect of setting user-modify. 
 * Need to chase to explicit parent of the editable area and check if true
 * Also for contentEditable - make sure set moz user modify and other properties!
 */
Element.prototype.__defineGetter__(
	"mozUserModify",
	function()
	{
		return document.defaultView.getComputedStyle(this, null).MozUserModify;
	}
);

/**
 * Does MozUserModify set this element modifiable
 */
Element.prototype.__defineGetter__(
		"mozUserModifiable",
		function()
		{
			// first check user modify!
			if (!this._mozUserModify) {
				var mozUserModify = this.mozUserModify;
				if(mozUserModify == "read-write")
				{	
					this._mozUserModify = true;
					return true;
				}
				
				return false;
			}
			return true;
		}
);

/**
 * mozUserModify and contentEditable both count
 */
Element.prototype.__defineGetter__(
	"userModify",
	function()
	{
		if (!this._userModify) {
		// special case: allow MS attribute to set modify level
			if(this.isContentEditable)
				return("read-write");
			var mozUserModify = this.mozUserModify;
			this._userModify = mozUserModify;
			return mozUserModify;
		}
		return this._userModify;
	}
);

/**
 * If either contentEditable is true or userModify is not read-only then return true. This makes
 * it easy to support a single approach to user modification of elements in a page using either
 * the W3c or Microsoft approaches.
 * 
 * POST04:
 * - consider not supporting contentEditable here
 */
Element.prototype.__defineGetter__(
		"userModifiable",
		function()
		{
			// first check user modify!
			if (this._userModify) {
				return true;
			} else {
				if(this.userModify == "read-write")
				{
					this._userModify = true;
					return true;
				}
			}
			return false;
		}
);

/*
 * UserModifiableContext means a parent element that is explicitly set to userModifiable. Note that this accounts for
 * different degrees of userModify. If say "writetext" is inside a "write" then context will stop at the writetext
 * element. That is the context for that level of usermodify. 
 */ 
Element.prototype.__defineGetter__(
	"userModifiableContext",
	function()
	{
		// Moz route (userModify) 
		if(this.mozUserModifiable)
		{
			var context = this;
			contextUserModify = this.mozUserModify;
			while(context.parentNode)
			{
				var contextParentUserModify = context.parentNode.mozUserModify;
				if(contextParentUserModify != contextUserModify)
					break;
				context = context.parentNode;
				contextUserModify = contextParentUserModify;
			}
			return context;
		}

		// try IE route
		return this.contentEditableContext;
	}
);

/***************************************************************************************************************
 * New Selection methods to support styling the current selection
 *
 * POST05:
 * - move alot of the content here (the XHTML specific stuff) to eDOMXHTML leaving these methods as just Selection
 * wrappers for Range methods.
 ***************************************************************************************************************/

/**
 * "Delete" for selected XHTML represents three behaviors:
 * - if range isn't collapsed then delete contents of the range - treat table contents properly (see code for behavior)
 * - if range is collapsed
 *   - if at start of line then merge line with previous line if there is one and this is appropriate
 *   - otherwise delete character or element before the selected point in the line
 *
 * Note: this is an XHTML compliant deletion. It is driven solely by CSS settings. This works for XHTML selections but
 * it is unlikely to work for semantically rich and restrictive XML. Deletion of an XML document would have to pay 
 * attention to that document's semantics.
 */
Selection.prototype.deleteSelection = function(backspace, makeDefault)
{
	var cssr = this.getEditableRange();
	var doTransform = false;
	if(!cssr)
		return;
	var _posPlus = null;
	if(cssr.collapsed) {
		if (cssr.startContainer.nodeValue.strip().length == 1) {
			try {
			var sel = window.getSelection();
			cssr = this.getEditableRange();
			var par = cssr.startContainer.parentNode.XMLNode._node;
			par.normalize();
			if (par.childNodes.length <= 1) {
				// if attributenode
				if (par.nodeType == 2) {
					var parpar = par.ownerElement;
					parpar.removeAttributeNode(par);
				} else {
					var parpar = par.parentNode;
					var nextSibling = par.nextSibling;
					bxe_checkEmpty(par.XMLNode,makeDefault);
				}
				if (!parpar.XMLNode.isNodeValid(true,2,true)) {
					var _new = parpar.insertBefore(parpar.ownerDocument.createElementNS(par.namespaceURI,par.localName),nextSibling);
					_new.XMLNode = _new.getXMLNode();
					bxe_checkEmpty(_new.XMLNode,makeDefault);
				}
				parpar.normalize();
				var _h = par.XMLNode._htmlnode;
				if (!makeDefault) {
					var _pref = bxe_goToNextNode(cssr,true);
					if (_pref && _pref.nodeType == 1) { _pref = _pref.lastChild;}
					if (_pref && _pref.nodeValue) { 
						sel.collapse(_pref,_pref.nodeValue.length);
					} else {
						//alert(_pref);
					}
				}
				sel.collapseToStart();
				
				bxe_Transform();
				return;
				
			}
			sel.collapse(cssr.startContainer,0);
			
			sel.extend(cssr.startContainer,cssr.startContainer.length);
			sel.deleteSelection(backspace);
			
			return;
			} catch (e) { bxe_catch_alert(e);}
		}
		
		var ip = documentCreateInsertionPoint(cssr.top, cssr.startContainer, cssr.startOffset);
		var par = cssr.startContainer.parentNode;
		if (!backspace && cssr.startOffset == 0  ) {
			if ( !cssr.startContainer.previousSibling) {
				var prev = par.previousSibling;
				while (prev && prev.nodeType != 1) {
					prev = prev.previousSibling;
				}
				if (prev) {
					var sel = window.getSelection();
					sel.collapse(prev.lastChild,prev.lastChild.length);
					sel.extend(cssr.startContainer,0);
					cssr = this.getEditableRange();
					sel.deleteSelection();
					
				}
				return;
			} else {
				
				var sel = window.getSelection();
				this.collapse(cssr.startContainer.previousSibling.lastChild,cssr.startContainer.previousSibling.lastChild.length);
				var cssr = this.getEditableRange();
				ip = documentCreateInsertionPoint(cssr.top, cssr.startContainer, cssr.startOffset);
			}
			
		} else if (backspace && cssr.startContainer.length == cssr.startOffset ) {
			if ( !cssr.startContainer.nextSibling) {
				var prev = par.nextSibling;
				while (prev && prev.nodeType != 1) {
					prev = prev.nextSibling;
				}
				if (prev) {
					var sel = window.getSelection();
					sel.collapse(cssr.startContainer,cssr.startContainer.length);
					sel.extend(prev.firstChild,0);
					cssr = this.getEditableRange();
					sel.deleteSelection();
					
				}
				return;
			}  else {
				
				var sel = window.getSelection();
				this.collapse(cssr.startContainer.nextSibling.firstChild,0);
				var cssr = this.getEditableRange();
				ip = documentCreateInsertionPoint(cssr.top, cssr.startContainer, cssr.startOffset);
			}
		}
		if (backspace) {
			ip.forwardOne();
		}
		
		var result = ip.deletePreviousInLine();
		
		if (result) {
			//cssr.selectInsertionPoint(ip);
			
			var startC =   cssr.startContainer;
			var par = startC.parentNode
			
			
			var lala = par.XMLNode._node; 
			par.edited = true ;
			if (lala.nodeType == 2) {
				lala.value =  par.getContent();
			} else {
				
				var _position = bxe_getChildPosition(startC);
				lala.replaceChild(bxe_config.xmldoc.importNode( startC,true),lala.childNodes[_position]);
			}
		} 
		
	
	} else {
		//TESTME
		this.fixFocus();
		
		var xmlnode = bxe_getXMLNodeByHTMLNodeRecursive(this.anchorNode.parentNode);
		if (xmlnode.betterNormalize) {
			xmlnode.betterNormalize();
		}
		
		
		if (xmlnode.nodeType == 2) {
			//FIXME 2.0
			//xmlnode._node.value =  xmlnode._node.ownerElement.getContent();
			cssr.extractContentsByCSS();
			xmlnode.nodeValue =  this.anchorNode.nodeValue;
		} else {
			if (xmlnode.XMLNode.vdom && xmlnode.XMLNode.vdom.bxeTabletype == "table-cell") {
				if (xmlnode.XMLNode._node != this.focusNode.parentNode.XMLNode._node ) {
					this.collapse(this.anchorNode,1);
					this.extend(this.anchorNode,this.anchorNode.length);
				}
			}
			var _position = bxe_getChildPosition(this.anchorNode);
			
			var textNode = xmlnode.childNodes[_position];
			
			// first delete all subnodes, if we have
			if (this.anchorNode != this.focusNode) {
				
				var endxmlnode = bxe_getXMLNodeByHTMLNodeRecursive(this.focusNode.parentNode);
				endxmlnode.betterNormalize();
				var _endposition = bxe_getChildPosition(this.focusNode);
				var endtextNode = endxmlnode.childNodes[_endposition ];
				if(endtextNode.splitText) {
					endtextNode.splitText(this.focusOffset);
				} else {
					var _next = endtextNode.childNodes[this.focusOffset];
					if (_next && _next.nodeType == 3) {
						endtextNode = _next;
						endtextNode.splitText(0);
						endxmlnode = endtextNode.parentNode;
					}
				}
					
				var walker = document.createTreeWalker(
				textNode.ownerDocument.documentElement, NodeFilter.SHOW_ALL,
				null, 
				true);
				walker.currentNode = textNode;
				var oldnode;
				node = walker.nextNode();
				do {
					if (node == endtextNode) {
						break;
					}
					oldnode = node;
					if (!(oldnode.compareDocumentPosition(endtextNode) & Node.DOCUMENT_POSITION_CONTAINED_BY)) {
						// if children, delete all of them first
						if (oldnode.hasChildNodes()) {
							while (oldnode.firstChild) {
								oldnode.removeChild(oldnode.firstChild);
							}
						}
						node =   walker.nextNode();
						oldnode.parentNode.removeChild(oldnode);
					} else {
						node =   walker.nextNode();
					}
					
					
				} while(node);
				// merge nodes
				
			} else {
				
				textNode.splitText(this.focusOffset);
			}
			textNode = textNode.splitText(this.anchorOffset);
						// delete last node
			if (this.anchorNode != this.focusNode) {
				//endxmlnode.betterNormalize();
				endxmlnode.removeChild(endtextNode);
				var blockparent = xmlnode.getBlockParent();
				var endblockparent = endxmlnode.getBlockParent();
				
				if (blockparent.nextSibling.nextSibling == endblockparent || blockparent.nextSibling == endblockparent ) {
					//merge nodes
					 blockparent.mergeWith(endblockparent);
				}
				doTransform = true;
				
			} else {
				cssr.extractContentsByCSS();
				this.anchorNode.parentNode.removeAttribute("__bxe_defaultcontent");
				if (this.anchorNode.parentNode.XMLNode) {
					this.anchorNode.parentNode.XMLNode._node.removeAttribute("__bxe_defaultcontent");
				}
			}
			if (textNode.parentNode == xmlnode) {
				var _prev = textNode.previousSibling;
				xmlnode.removeChild(textNode);
				bxe_checkEmptyParent(xmlnode.XMLNode);
				
			} else {
				delete textNode;
			}
			if (blockparent) {
				blockparent.betterNormalize(); 
			}
		}
	}
	
	//this.selectEditableRange(cssr);
	var _posAnchor = null;
	if ( this.focusNode.nodeValue.substr(this.focusOffset,1) == " ") {
		 _posPlus = this.anchorOffset;
		 _posAnchor = this.anchorNode;
	} else if (this.focusOffset >= this.focusNode.length && this.focusNode.nodeValue.substr(this.focusNode.length -1 ,1) == " ") {
		_posPlus = this.focusNode.length;
	} else if (this.anchorOffset == 0) {
		_posPlus = 0;	
	}
	this.removeAllRanges();<commit_msg>fix BXEB-58 error while onemptycheck<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
 * Full Terms at http://mozile.mozdev.org/license.html
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Playsophy code.
 *
 * The Initial Developer of the Original Code is Playsophy
 * Portions created by the Initial Developer are Copyright (C) 2002-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

// $Id$

/* 
 * mozCE V0.5
 * 
 * Mozilla Inline text editing that relies on eDOM, extensions to the standard w3c DOM.
 *
 * This file implements contenteditable/user modify in Mozilla by leverging
 * Mozilla's proprietary Selection object as well as eDOM, a set of browser independent
 * extensions to the w3c DOM for building editors. 
 *
 * POST05:
 * - refactor userModify code as part of "EditableElement" 
 * - IE's "ContentEditable" means that an element is editable whenever its "ContentEditable"
 * setting is true. However, we may change this so that you have to set editing on for a
 * document as a whole before its individual editable sections become editable. This would
 * allow a user to browse an editable document and explicitly choose to edit it or not.
 * - see if can move to using DOM events and away from Window.getSelection() if possible 
 * (effects how generic it can be!)
 * - selection model: word, line etc. Write custom handlers of clicks and use new Range
 * expansion methods
 */

/****************************************************************************************
 *
 * MozUserModify and ContentEditable: allow precise designation of editing scope. This
 * file implements user-modify/contentEditable. The following utilities let the implementation
 * determine scope.
 *
 * - http://www.w3.org/TR/1999/WD-css3-userint-19990916#user-modify
 *
 * POST04
 * - rename to be "mozSelection.js"
 * - remove need to spec ContentEditable as equivalent to mozUserModify: do mapping in
 * style sheet: *[contentEditable="true"] 
 * - to change as part of "editableElement": may also move Selection methods into EditableElement
 * - support for tracking whether changes were made to elements or not ie/ does a user
 * need to save? Should MozCE warn a user to save before exiting the browser? Some of
 * this may go into eDOM itself in enhancements to document or to all elements ie/ changed?
 *
 ****************************************************************************************/

/**
 * Start of "EditableElement": this will move into eDOM once it is fleshed out.
 *
 * POST04: set user-input and user-select properly as a side effect of setting user-modify. 
 * Need to chase to explicit parent of the editable area and check if true
 * Also for contentEditable - make sure set moz user modify and other properties!
 */
Element.prototype.__defineGetter__(
	"mozUserModify",
	function()
	{
		return document.defaultView.getComputedStyle(this, null).MozUserModify;
	}
);

/**
 * Does MozUserModify set this element modifiable
 */
Element.prototype.__defineGetter__(
		"mozUserModifiable",
		function()
		{
			// first check user modify!
			if (!this._mozUserModify) {
				var mozUserModify = this.mozUserModify;
				if(mozUserModify == "read-write")
				{	
					this._mozUserModify = true;
					return true;
				}
				
				return false;
			}
			return true;
		}
);

/**
 * mozUserModify and contentEditable both count
 */
Element.prototype.__defineGetter__(
	"userModify",
	function()
	{
		if (!this._userModify) {
		// special case: allow MS attribute to set modify level
			if(this.isContentEditable)
				return("read-write");
			var mozUserModify = this.mozUserModify;
			this._userModify = mozUserModify;
			return mozUserModify;
		}
		return this._userModify;
	}
);

/**
 * If either contentEditable is true or userModify is not read-only then return true. This makes
 * it easy to support a single approach to user modification of elements in a page using either
 * the W3c or Microsoft approaches.
 * 
 * POST04:
 * - consider not supporting contentEditable here
 */
Element.prototype.__defineGetter__(
		"userModifiable",
		function()
		{
			// first check user modify!
			if (this._userModify) {
				return true;
			} else {
				if(this.userModify == "read-write")
				{
					this._userModify = true;
					return true;
				}
			}
			return false;
		}
);

/*
 * UserModifiableContext means a parent element that is explicitly set to userModifiable. Note that this accounts for
 * different degrees of userModify. If say "writetext" is inside a "write" then context will stop at the writetext
 * element. That is the context for that level of usermodify. 
 */ 
Element.prototype.__defineGetter__(
	"userModifiableContext",
	function()
	{
		// Moz route (userModify) 
		if(this.mozUserModifiable)
		{
			var context = this;
			contextUserModify = this.mozUserModify;
			while(context.parentNode)
			{
				var contextParentUserModify = context.parentNode.mozUserModify;
				if(contextParentUserModify != contextUserModify)
					break;
				context = context.parentNode;
				contextUserModify = contextParentUserModify;
			}
			return context;
		}

		// try IE route
		return this.contentEditableContext;
	}
);

/***************************************************************************************************************
 * New Selection methods to support styling the current selection
 *
 * POST05:
 * - move alot of the content here (the XHTML specific stuff) to eDOMXHTML leaving these methods as just Selection
 * wrappers for Range methods.
 ***************************************************************************************************************/

/**
 * "Delete" for selected XHTML represents three behaviors:
 * - if range isn't collapsed then delete contents of the range - treat table contents properly (see code for behavior)
 * - if range is collapsed
 *   - if at start of line then merge line with previous line if there is one and this is appropriate
 *   - otherwise delete character or element before the selected point in the line
 *
 * Note: this is an XHTML compliant deletion. It is driven solely by CSS settings. This works for XHTML selections but
 * it is unlikely to work for semantically rich and restrictive XML. Deletion of an XML document would have to pay 
 * attention to that document's semantics.
 */
Selection.prototype.deleteSelection = function(backspace, makeDefault)
{
	var cssr = this.getEditableRange();
	var doTransform = false;
	if(!cssr)
		return;
	var _posPlus = null;
	if(cssr.collapsed) {
		if (cssr.startContainer.nodeValue.strip().length == 1) {
			try {
			var sel = window.getSelection();
			cssr = this.getEditableRange();
			var par = cssr.startContainer.parentNode.XMLNode._node;
			par.normalize();
			if (par.childNodes.length <= 1) {
				// if attributenode
				if (par.nodeType == 2) {
					var parpar = par.ownerElement;
					parpar.removeAttributeNode(par);
				} else {
					var parpar = par.parentNode;
					var nextSibling = par.nextSibling;
					bxe_checkEmpty(par.XMLNode,makeDefault);
				}
				if (!parpar.XMLNode.isNodeValid(true,2,true)) {
					var _new = parpar.insertBefore(parpar.ownerDocument.createElementNS(par.namespaceURI,par.localName),nextSibling);
					_new.XMLNode = _new.getXMLNode();
					bxe_checkEmpty(_new.XMLNode,makeDefault);
				}
				parpar.normalize();
				var _h = par.XMLNode._htmlnode;
				if (!makeDefault) {
					var _pref = bxe_goToNextNode(cssr,true);
					if (_pref && _pref.nodeType == 1) { _pref = _pref.lastChild;}
					if (_pref && _pref.nodeValue) { 
						sel.collapse(_pref,_pref.nodeValue.length);
					} else {
						//alert(_pref);
					}
				}
				sel.collapseToStart();
				
				bxe_Transform();
				return;
				
			}
			sel.collapse(cssr.startContainer,0);
			
			sel.extend(cssr.startContainer,cssr.startContainer.length);
			sel.deleteSelection(backspace);
			
			return;
			} catch (e) { bxe_catch_alert(e);}
		}
		
		var ip = documentCreateInsertionPoint(cssr.top, cssr.startContainer, cssr.startOffset);
		var par = cssr.startContainer.parentNode;
		if (!backspace && cssr.startOffset == 0  ) {
			if ( !cssr.startContainer.previousSibling) {
				var prev = par.previousSibling;
				while (prev && prev.nodeType != 1) {
					prev = prev.previousSibling;
				}
				if (prev) {
					var sel = window.getSelection();
					sel.collapse(prev.lastChild,prev.lastChild.length);
					sel.extend(cssr.startContainer,0);
					cssr = this.getEditableRange();
					sel.deleteSelection();
					
				}
				return;
			} else {
				
				var sel = window.getSelection();
				this.collapse(cssr.startContainer.previousSibling.lastChild,cssr.startContainer.previousSibling.lastChild.length);
				var cssr = this.getEditableRange();
				ip = documentCreateInsertionPoint(cssr.top, cssr.startContainer, cssr.startOffset);
			}
			
		} else if (backspace && cssr.startContainer.length == cssr.startOffset ) {
			if ( !cssr.startContainer.nextSibling) {
				var prev = par.nextSibling;
				while (prev && prev.nodeType != 1) {
					prev = prev.nextSibling;
				}
				if (prev) {
					var sel = window.getSelection();
					sel.collapse(cssr.startContainer,cssr.startContainer.length);
					sel.extend(prev.firstChild,0);
					cssr = this.getEditableRange();
					sel.deleteSelection();
					
				}
				return;
			}  else {
				
				var sel = window.getSelection();
				this.collapse(cssr.startContainer.nextSibling.firstChild,0);
				var cssr = this.getEditableRange();
				ip = documentCreateInsertionPoint(cssr.top, cssr.startContainer, cssr.startOffset);
			}
		}
		if (backspace) {
			ip.forwardOne();
		}
		
		var result = ip.deletePreviousInLine();
		
		if (result) {
			//cssr.selectInsertionPoint(ip);
			
			var startC =   cssr.startContainer;
			var par = startC.parentNode
			
			
			var lala = par.XMLNode._node; 
			par.edited = true ;
			if (lala.nodeType == 2) {
				lala.value =  par.getContent();
			} else {
				
				var _position = bxe_getChildPosition(startC);
				lala.replaceChild(bxe_config.xmldoc.importNode( startC,true),lala.childNodes[_position]);
			}
		} 
		
	
	} else {
		//TESTME
		this.fixFocus();
		
		var xmlnode = bxe_getXMLNodeByHTMLNodeRecursive(this.anchorNode.parentNode);
		if (xmlnode.betterNormalize) {
			xmlnode.betterNormalize();
		}
		
		
		if (xmlnode.nodeType == 2) {
			//FIXME 2.0
			//xmlnode._node.value =  xmlnode._node.ownerElement.getContent();
			cssr.extractContentsByCSS();
			xmlnode.nodeValue =  this.anchorNode.nodeValue;
		} else {
			if (xmlnode.XMLNode.vdom && xmlnode.XMLNode.vdom.bxeTabletype == "table-cell") {
				if (xmlnode.XMLNode._node != this.focusNode.parentNode.XMLNode._node ) {
					this.collapse(this.anchorNode,1);
					this.extend(this.anchorNode,this.anchorNode.length);
				}
			}
			var _position = bxe_getChildPosition(this.anchorNode);
			
			var textNode = xmlnode.childNodes[_position];
			
			// first delete all subnodes, if we have
			if (this.anchorNode != this.focusNode) {
				
				var endxmlnode = bxe_getXMLNodeByHTMLNodeRecursive(this.focusNode.parentNode);
				endxmlnode.betterNormalize();
				var _endposition = bxe_getChildPosition(this.focusNode);
				var endtextNode = endxmlnode.childNodes[_endposition ];
				if(endtextNode.splitText) {
					endtextNode.splitText(this.focusOffset);
				} else {
					var _next = endtextNode.childNodes[this.focusOffset];
					if (_next && _next.nodeType == 3) {
						endtextNode = _next;
						endtextNode.splitText(0);
						endxmlnode = endtextNode.parentNode;
					}
				}
					
				var walker = document.createTreeWalker(
				textNode.ownerDocument.documentElement, NodeFilter.SHOW_ALL,
				null, 
				true);
				walker.currentNode = textNode;
				var oldnode;
				node = walker.nextNode();
				do {
					if (node == endtextNode) {
						break;
					}
					oldnode = node;
					if (!(oldnode.compareDocumentPosition(endtextNode) & Node.DOCUMENT_POSITION_CONTAINED_BY)) {
						// if children, delete all of them first
						if (oldnode.hasChildNodes()) {
							while (oldnode.firstChild) {
								oldnode.removeChild(oldnode.firstChild);
							}
						}
						node =   walker.nextNode();
						oldnode.parentNode.removeChild(oldnode);
					} else {
						node =   walker.nextNode();
					}
					
					
				} while(node);
				// merge nodes
				
			} else {
				
				textNode.splitText(this.focusOffset);
			}
			textNode = textNode.splitText(this.anchorOffset);
						// delete last node
			if (this.anchorNode != this.focusNode) {
				//endxmlnode.betterNormalize();
				endxmlnode.removeChild(endtextNode);
				var blockparent = xmlnode.getBlockParent();
				var endblockparent = endxmlnode.getBlockParent();
				
				if (blockparent.nextSibling.nextSibling == endblockparent || blockparent.nextSibling == endblockparent ) {
					//merge nodes
					 blockparent.mergeWith(endblockparent);
				}
				doTransform = true;
				
			} else {
				cssr.extractContentsByCSS();
				this.anchorNode.parentNode.removeAttribute("__bxe_defaultcontent");
				if (this.anchorNode.parentNode.XMLNode) {
					this.anchorNode.parentNode.XMLNode._node.removeAttribute("__bxe_defaultcontent");
				}
			}
			if (textNode.parentNode == xmlnode) {
				var _prev = textNode.previousSibling;
				xmlnode.removeChild(textNode);
				bxe_checkEmptyParent(xmlnode.XMLNode);
				
			} else {
				delete textNode;
			}
			if (blockparent) {
				blockparent.betterNormalize(); 
			}
		}
	}
	
	//this.selectEditableRange(cssr);
	var _posAnchor = null;
	if ( this.focusNode.nodeValue && this.focusNode.nodeValue.substr(this.focusOffset,1) == " ") {
		 _posPlus = this.anchorOffset;
		 _posAnchor = this.anchorNode;
	} else if (this.focusOffset >= this.focusNode.length && this.focusNode.nodeValue.substr(this.focusNode.length -1 ,1) == " ") {
		_posPlus = this.focusNode.length;
	} else if (this.anchorOffset == 0) {
		_posPlus = 0;	
	}
	this.removeAllRanges();
{'fraction_non_alphanumeric': 0.12935341009743134, 'fraction_numerical': 0.004818423383525243, 'mean_word_length': 3.411691153485464, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 46}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7412342', 'n_tokens_mistral': 10288, 'n_tokens_neox': 8471, 'n_words': 2238}