function getRange() {
			var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail;

			// If selection is outside the current document just return an empty range
			element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
			if (element.ownerDocument != dom.doc)
				return domRange;

			collapsed = selection.isCollapsed();

			// Handle control selection
			if (ieRange.item) {
				domRange.setStart(element.parentNode, dom.nodeIndex(element));
				domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);

				return domRange;
			}

			function findEndPoint(start) {
				var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue;

				container = endPoint.node;
				offset = endPoint.offset;

				if (endPoint.inside && !container.hasChildNodes()) {
					domRange[start ? 'setStart' : 'setEnd'](container, 0);
					return;
				}

				if (offset === undef) {
					domRange[start ? 'setStartBefore' : 'setEndAfter'](container);
					return;
				}

				if (endPoint.position < 0) {
					sibling = endPoint.inside ? container.firstChild : container.nextSibling;

					if (!sibling) {
						domRange[start ? 'setStartAfter' : 'setEndAfter'](container);
						return;
					}

					if (!offset) {
						if (sibling.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, 0);
						else
							domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling);

						return;
					}

					// Find the text node and offset
					while (sibling) {
						nodeValue = sibling.nodeValue;
						textNodeOffset += nodeValue.length;

						// We are at or passed the position we where looking for
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							textNodeOffset = nodeValue.length - textNodeOffset;
							break;
						}

						sibling = sibling.nextSibling;
					}
				} else {
					// Find the text node and offset
					sibling = container.previousSibling;

					if (!sibling)
						return domRange[start ? 'setStartBefore' : 'setEndBefore'](container);

					// If there isn't any text to loop then use the first position
					if (!offset) {
						if (container.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length);
						else
							domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling);

						return;
					}

					while (sibling) {
						textNodeOffset += sibling.nodeValue.length;

						// We are at or passed the position we where looking for
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							break;
						}

						sibling = sibling.previousSibling;
					}
				}

				domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset);
			};

			try {
				// Find start point
				findEndPoint(true);

				// Find end point if needed
				if (!collapsed)
					findEndPoint();
			} catch (ex) {
				// IE has a nasty bug where text nodes might throw "invalid argument" when you
				// access the nodeValue or other properties of text nodes. This seems to happend when
				// text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it.
				if (ex.number == -2147024809) {
					// Get the current selection
					bookmark = self.getBookmark(2);

					// Get start element
					tmpRange = ieRange.duplicate();
					tmpRange.collapse(true);
					element = tmpRange.parentElement();

					// Get end element
					if (!collapsed) {
						tmpRange = ieRange.duplicate();
						tmpRange.collapse(false);
						element2 = tmpRange.parentElement();
						element2.innerHTML = element2.innerHTML;
					}

					// Remove the broken elements
					element.innerHTML = element.innerHTML;

					// Restore the selection
					self.moveToBookmark(bookmark);

					// Since the range has moved we need to re-get it
					ieRange = selection.getRng();

					// Find start point
					findEndPoint(true);

					// Find end point if needed
					if (!collapsed)
						findEndPoint();
				} else
					throw ex; // Throw other errors
			}

			return domRange;
		}
function getRange() {
			var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail;

			
			element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
			if (element.ownerDocument != dom.doc)
				return domRange;

			collapsed = selection.isCollapsed();

			
			if (ieRange.item) {
				domRange.setStart(element.parentNode, dom.nodeIndex(element));
				domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);

				return domRange;
			}

			function findEndPoint(start) {
				var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue;

				container = endPoint.node;
				offset = endPoint.offset;

				if (endPoint.inside && !container.hasChildNodes()) {
					domRange[start ? 'setStart' : 'setEnd'](container, 0);
					return;
				}

				if (offset === undef) {
					domRange[start ? 'setStartBefore' : 'setEndAfter'](container);
					return;
				}

				if (endPoint.position < 0) {
					sibling = endPoint.inside ? container.firstChild : container.nextSibling;

					if (!sibling) {
						domRange[start ? 'setStartAfter' : 'setEndAfter'](container);
						return;
					}

					if (!offset) {
						if (sibling.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, 0);
						else
							domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling);

						return;
					}

					
					while (sibling) {
						nodeValue = sibling.nodeValue;
						textNodeOffset += nodeValue.length;

						
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							textNodeOffset = nodeValue.length - textNodeOffset;
							break;
						}

						sibling = sibling.nextSibling;
					}
				} else {
					
					sibling = container.previousSibling;

					if (!sibling)
						return domRange[start ? 'setStartBefore' : 'setEndBefore'](container);

					
					if (!offset) {
						if (container.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length);
						else
							domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling);

						return;
					}

					while (sibling) {
						textNodeOffset += sibling.nodeValue.length;

						
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							break;
						}

						sibling = sibling.previousSibling;
					}
				}

				domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset);
			};

			try {
				
				findEndPoint(true);

				
				if (!collapsed)
					findEndPoint();
			} catch (ex) {
				
				
				
				if (ex.number == -2147024809) {
					
					bookmark = self.getBookmark(2);

					
					tmpRange = ieRange.duplicate();
					tmpRange.collapse(true);
					element = tmpRange.parentElement();

					
					if (!collapsed) {
						tmpRange = ieRange.duplicate();
						tmpRange.collapse(false);
						element2 = tmpRange.parentElement();
						element2.innerHTML = element2.innerHTML;
					}

					
					element.innerHTML = element.innerHTML;

					
					self.moveToBookmark(bookmark);

					
					ieRange = selection.getRng();

					
					findEndPoint(true);

					
					if (!collapsed)
						findEndPoint();
				} else
					throw ex; 
			}

			return domRange;
		}
function getRange ( ) { var ieRange = selection . getRng ( ) , domRange = dom . createRng ( ) , element , collapsed , tmpRange , element2 , bookmark , fail ; // If selection is outside the current document just return an empty range
 element = ieRange . item ? ieRange . item ( 0 ) : ieRange . parentElement ( ) ; if ( element . ownerDocument != dom . doc ) return domRange ; collapsed = selection . isCollapsed ( ) ; // Handle control selection
 if ( ieRange . item ) { domRange . setStart ( element . parentNode , dom . nodeIndex ( element ) ) ; domRange . setEnd ( domRange . startContainer , domRange . startOffset + 1 ) ; return domRange ; } function findEndPoint ( start ) { var endPoint = getPosition ( ieRange , start ) , container , offset , textNodeOffset = 0 , sibling , undef , nodeValue ; container = endPoint . node ; offset = endPoint . offset ; if ( endPoint . inside && ! container . hasChildNodes ( ) ) { domRange [ start ? 'setStart' : 'setEnd' ] ( container , 0 ) ; return ; } if ( offset === undef ) { domRange [ start ? 'setStartBefore' : 'setEndAfter' ] ( container ) ; return ; } if ( endPoint . position < 0 ) { sibling = endPoint . inside ? container . firstChild : container . nextSibling ; if ( ! sibling ) { domRange [ start ? 'setStartAfter' : 'setEndAfter' ] ( container ) ; return ; } if ( ! offset ) { if ( sibling . nodeType == 3 ) domRange [ start ? 'setStart' : 'setEnd' ] ( sibling , 0 ) ; else domRange [ start ? 'setStartBefore' : 'setEndBefore' ] ( sibling ) ; return ; } // Find the text node and offset
 while ( sibling ) { nodeValue = sibling . nodeValue ; textNodeOffset += nodeValue . length ; // We are at or passed the position we where looking for
 if ( textNodeOffset >= offset ) { container = sibling ; textNodeOffset -= offset ; textNodeOffset = nodeValue . length - textNodeOffset ; break ; } sibling = sibling . nextSibling ; } } else { // Find the text node and offset
 sibling = container . previousSibling ; if ( ! sibling ) return domRange [ start ? 'setStartBefore' : 'setEndBefore' ] ( container ) ; // If there isn't any text to loop then use the first position
 if ( ! offset ) { if ( container . nodeType == 3 ) domRange [ start ? 'setStart' : 'setEnd' ] ( sibling , container . nodeValue . length ) ; else domRange [ start ? 'setStartAfter' : 'setEndAfter' ] ( sibling ) ; return ; } while ( sibling ) { textNodeOffset += sibling . nodeValue . length ; // We are at or passed the position we where looking for
 if ( textNodeOffset >= offset ) { container = sibling ; textNodeOffset -= offset ; break ; } sibling = sibling . previousSibling ; } } domRange [ start ? 'setStart' : 'setEnd' ] ( container , textNodeOffset ) ; } ; try { // Find start point
 findEndPoint ( true ) ; // Find end point if needed
 if ( ! collapsed ) findEndPoint ( ) ; } catch ( ex ) { // IE has a nasty bug where text nodes might throw "invalid argument" when you
 // access the nodeValue or other properties of text nodes. This seems to happend when
 // text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it.
 if ( ex . number == - 2147024809 ) { // Get the current selection
 bookmark = self . getBookmark ( 2 ) ; // Get start element
 tmpRange = ieRange . duplicate ( ) ; tmpRange . collapse ( true ) ; element = tmpRange . parentElement ( ) ; // Get end element
 if ( ! collapsed ) { tmpRange = ieRange . duplicate ( ) ; tmpRange . collapse ( false ) ; element2 = tmpRange . parentElement ( ) ; element2 . innerHTML = element2 . innerHTML ; } // Remove the broken elements
 element . innerHTML = element . innerHTML ; // Restore the selection
 self . moveToBookmark ( bookmark ) ; // Since the range has moved we need to re-get it
 ieRange = selection . getRng ( ) ; // Find start point
 findEndPoint ( true ) ; // Find end point if needed
 if ( ! collapsed ) findEndPoint ( ) ; } else throw ex ; // Throw other errors
 } return domRange ; }
Returns a W3C DOM compatible range object by using the IE Range API
Returns a W3C DOM compatible range object by using the IE Range API