TEST
Simple Implementation of DOM Range in JavaScript
最終更新:
eriax
-
view
制限
- なし。無理矢理 1200 行内に収める。
ソースコード
/*@cc_on@*/ if ('undefined' === typeof Array.prototype.map) { Array.prototype.map = function (callbackfn) { var thisArg = arguments[1]; if ('function' !== typeof callbackfn) { throw new Error; // TypeError } var count = this.length; var result = new Array(count); var i; for (i = 0; i < count; i++) { if (i in this) { result[i] = callbackfn.call(thisArg, this[i], i, this); } } return result; }; } if ('undefined' === typeof Array.map) { Array.map = function (call, map) { return function (arg, callbackfn) { return call.apply(map, arguments); }; }( Function.prototype.call, Array.prototype.map); } //////////////////////////////////////////////////////////////////////// function As_DOM_Object(arg) { if (arguments.length > 0) { var name; for (name in arg) { if (arg.hasOwnProperty(name)) { this[name] = arg[name]; } } } } (function () { this.constructor = As_DOM_Object; }).call(As_DOM_Object.prototype); //////////////////////////////////////////////////////////////////////// (function () { // RangeExceptionCode this.BAD_BOUNDARYPOINTS_ERR = 1; this.INVALID_NODE_TYPE_ERR = 2; }).call(As_DOM_RangeException); function As_DOM_RangeException(code) { if (arguments.length > 0) { if (arg) { As_DOM_Object.apply(this, arguments); } } } As_DOM_RangeException.prototype = new As_DOM_Object; (function () { this.constructor = As_DOM_RangeException; this.code = null; }).call(As_DOM_RangeException.prototype); //////////////////////////////////////////////////////////////////////// (function () { // CompareHow this.START_TO_START = 0; this.START_TO_END = 1; this.END_TO_END = 2; this.END_TO_START = 3; // NodeType this.ELEMENT_NODE = 1; this.ATTRIBUTE_NODE = 2; this.TEXT_NODE = 3; this.CDATA_SECTION_NODE = 4; this.ENTITY_REFERENCE_NODE = 5; this.ENTITY_NODE = 6; this.PROCESSING_INSTRUCTION_NODE = 7; this.COMMENT_NODE = 8; this.DOCUMENT_NODE = 9; this.DOCUMENT_TYPE_NODE = 10; this.DOCUMENT_FRAGMENT_NODE = 11; this.NOTATION_NODE = 12; // DocumentPosition this.DOCUMENT_POSITION_DISCONNECTED = 0x01; this.DOCUMENT_POSITION_PRECEDING = 0x02; this.DOCUMENT_POSITION_FOLLOWING = 0x04; this.DOCUMENT_POSITION_CONTAINS = 0x08; this.DOCUMENT_POSITION_CONTAINED_BY = 0x10; this.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; }).call(As_DOM_Range); function As_DOM_Range(arg) { if (arguments.length > 0) { if (arg) { As_DOM_Object.apply(this, arguments); } } } (function () { this.constructor = As_DOM_Range; this.startContainer = null; this.startOffset = null; this.endContainer = null; this.endOffset = null; this.collapsed = null; this.commonAncestorContainer = null; // extension this.detached = false; this.ownerDocument = null; }).call(As_DOM_Range.prototype); (function () { var XML_S = /^[\u0009\u000A\u000D\u0020]*$/; this['[NodeGetTextContent:1]'] = function (node) { var txt; if ('undefined' !== typeof (txt = node.textContent)) { return txt; } switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: /*@{if('undefined'!==typeof(s=node.innerText)||'undefined'!==typeof(s=node.innerHTML)){return s}}@*/ case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: var doc = node.ownerDocument; var impl = doc.implementation; /*@{if(impl.hasFeature('MS-DOM','1.0')){if('undefined'!==typeof(s=node.text)){return s}}}@*/ if (impl.hasFeature('Range', '2.0')) { var range = doc.createRange(); range.selectNodeContents(node); txt = range.toString(); range.detach(); return txt; } return this['[NodeGetTextContent:2]'](node); case As_DOM_Range.TEXT_NODE: try { if (!node.isElementContentWhitespace()) { return node.data; } return ''; } catch (err) { if (!XML_S.test(node.data)) { return node.data; } return ''; } case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: return node.nodeValue; case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: return null; } }; this['[NodeGetTextContent:2]'] = function (node) { switch (node.nodeType) { case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: return node.nodeValue; case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: if (node.hasChildNodes()) { return Array.prototype.concat.apply([], Array.map(node.childNodes, arguments.callee)).join(''); } case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: return ''; } }; this['[NodeGetContextRoot]'] = function (node) { var n; do { n = node; } while ((node = node.parentNode)); return n; }; this['[NodeGetChildIndex]'] = function (node) { var i = 0; for (i = 0; node = node.previousSibling; i += 1); return i; }; this['[NodeGetMaxOffset]'] = function (node) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: return node.childNodes.length; case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.COMMENT_NODE: return node.length; case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: return node.data.length; case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; } }; this['[NodeContainsOther]'] = function (node, other) { /*@{if('undefined'!==typeof node.contains&&'undefined'!==typeof other.contains){return node.contains(other)}}@*/ if (node === other) { return false; } try { return (0 !== (node.compareDocumentPosition(other) & Node.DOCUMENT_POSITION_CONTAINED_BY)); } catch (err) { while ((other = other.parentNode)) { if (node === other) { break; } } return Boolean(other); } }; this['[NodeCompareDocumentPosition:1]'] = function (node, other) { if (node === other) { return 0; } if (this['[NodeGetContextRoot]'](node) !== this['[NodeGetContextRoot]'](other)) { return As_DOM_Range.DOCUMENT_POSITION_DISCONNECTED | As_DOM_Range.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; } /*@{if('undefined'!==typeof node.contains&&'undefined'!==typeof other.contains){if(node.contains(other)){return 0x04|0x10}if(other.contains(node)){return 0x02|0x08}}if('undefined'!==typeof node.sourceIndex&&'undefined'!==typeof other.sourceIndex){if(node.sourceIndex<other.sourceIndex){return 0x04}if(node.sourceIndex>other.sourceIndex){return 0x02}}}@*/ return this['[NodeCompareDocumentPosition:2]'](node, other); }; this['[NodeCompareDocumentPosition:2]'] = function (node, other) { var path1 = this['[NodeGetSnapshotOffsets]'](node); var path2 = this['[NodeGetSnapshotOffsets]'](other); var p1; var p2; while (true) { p1 = path1.pop(); p2 = path2.pop(); if (p1 < p2) { return As_DOM_Range.DOCUMENT_POSITION_FOLLOWING; } if (p1 > p2) { return As_DOM_Range.DOCUMENT_POSITION_PRECEDING; } if (path1.length === 0) { return As_DOM_Range.DOCUMENT_POSITION_FOLLOWING | As_DOM_Range.DOCUMENT_POSITION_CONTAINED_BY; } if (path2.length === 0) { return As_DOM_Range.DOCUMENT_POSITION_PRECEDING | As_DOM_Range.DOCUMENT_POSITION_CONTAINS; } } }; this['[NodeGetSnapshotOffsets]'] = function (node, from) { var root = from || this.ownerDocument; var path = []; for (; node; node = node.parentNode) { if (node === root) { return path; } path[path.length] = this['[NodeGetChildIndex]'](node); } throw new Error; }; this['[NodeGetOrderedSnapshotOffsets]'] = function (node, from) { return this['[NodeGetSnapshotOffsets]'](node, from).reverse(); }; this['[NodeIsValidContainer]'] = function (node) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: return true; case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: return false; default: throw new Error; // RangeException.INVALID_NODEYPE_ERR(2) } }; this['[NodeIsContextual]'] = function (node) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: return true; case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: case As_DOM_Range.NOTATION_NODE: return false; default: throw new Error; // RangeException.INVALID_NODEYPE_ERR(2) } }; this['[OffsetIsValid]'] = function (node, offset) { return (offset >= 0) && (offset <= this['[NodeGetMaxOffset]'](node)); }; this['[NodeHasValidRoot]'] = function (node) { switch (this['[NodeGetContextRoot]'](node).nodeType) { case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: return true; case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: return false; default: throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } }; this['[ComparePoints]'] = function (compareOffsets, getAncestorOffset) { return function (container1, offset1, container2, offset2) { var k; if (container1 === container2) { return compareOffsets.call(this, offset1, offset2); } try { k = container1.compareDocumentPosition(container2); } catch (err) { k = this['[NodeCompareDocumentPosition:1]'](container1, container2); } if (0 !== (k & As_DOM_Range.DOCUMENT_POSITION_CONTAINED_BY)) { return compareOffsets.call(this, offset1, getAncestorOffset.call(this, container2, container1)) || -1; } if (0 !== (k & As_DOM_Range.DOCUMENT_POSITION_CONTAINS)) { return compareOffsets.call(this, getAncestorOffset.call(this, container1, container2), offset2) || 1; } if (0 !== (k & As_DOM_Range.DOCUMENT_POSITION_FOLLOWING)) { return -1; } if (0 !== (k & As_DOM_Range.DOCUMENT_POSITION_PRECEDING)) { return 1; } throw new Error; // DOMException.WRONG_DOCUMENT_ERR(4) }; }( function (n1, n2) { if (n1 < n2) { return -1; } if (n1 > n2) { return 1; } return 0; }, function (n1, n2) { while (n1.parentNode !== n2) { n1 = n1.parentNode; } return this['[NodeGetChildIndex]'](n1); }); this['[CollapseBoundary]'] = function () { var node = this.startContainer; if (this['[NodeGetMaxOffset]'](node) !== this.startOffset) { this.collapse(true); } do { if (!node || node === this.commonAncestorContainer) { this.collapse(true); return; } if (node.nextSibling) { this.setStartAfter(node); this.collapse(true); return; } } while ((node = node.parentNode)); }; this['[GetCommonAncestorContainer]'] = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (this.startContainer === this.endContainer) { return this.startContainer; } if (this['[NodeContainsOther]'](this.startContainer, this.endContainer)) { return this.startContainer; } if (this['[NodeContainsOther]'](this.endContainer, this.startContainer)) { return this.endContainer; } var endContainer = this.endContainer; var node = this.startContainer; while (!this['[NodeContainsOther]'](node, endContainer)) { node = node.parentNode; } return node; }; this['[SetCommonAncestorContainer]'] = function (node) { this.commonAncestorContainer = node; }; this['[NodeAppendContents]'] = function (node, arg) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: return node.appendChild(arg); case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: return this['[NodeReplaceBy]'](node, arg); case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } }; this['[NodeReplaceBy]'] = function (node, newNode) { /*@{if('undefined'!==typeof node.replaceNode){return node.replaceNode(newNode)}}@*/ var n; if ((n = node.parentNode)) { return n.replaceChild(newNode, node); } if ((n = newNode.parentNode)) { n.removeChild(newNode); } return node; }; this.setStart = function (refNode, offset) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeIsValidContainer]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } if (!this['[OffsetIsValid]'](refNode, offset)) { throw new Error; // DOMException.INDEX_SIZE_ERR(1) } this['[SetStart:1]'](refNode, offset); }; this['[SetStart:1]'] = function (refNode, offset) { this['[SetStart:2]'](refNode, offset); this['[SetStart:3]'](); }; this['[SetStart:2]'] = function (refNode, offset) { this.startContainer = refNode; this.startOffset = offset; }; this['[SetStart:3]'] = function (range) { if (this.compareBoundaryPoints(As_DOM_Range.END_TO_START, this) >= 0) { this.collapse(true); } else { this.collapsed = false; this['[SetCommonAncestorContainer]'](this['[GetCommonAncestorContainer]']()); } }; this.setEnd = function (refNode, offset) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeIsValidContainer]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } if (!this['[OffsetIsValid]'](refNode, offset)) { throw new Error; // DOMException.INDEX_SIZE_ERR(1) } this['[SetEnd:1]'](refNode, offset); }; this['[SetEnd:1]'] = function (refNode, offset) { this['[SetEnd:2]'](refNode, offset); this['[SetEnd:3]'](); }; this['[SetEnd:2]'] = function (refNode, offset) { this.endContainer = refNode; this.endOffset = offset; }; this['[SetEnd:3]'] = function () { if (this.compareBoundaryPoints(As_DOM_Range.START_TO_END, this) <= 0) { this.collapse(false); } else { this.collapsed = false; this['[SetCommonAncestorContainer]'](this['[GetCommonAncestorContainer]']()); } }; this.setStartBefore = function (refNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeHasValidRoot]'](refNode) || !this['[NodeIsContextual]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } this['[SetStart:1]'](refNode.parentNode, this['[NodeGetChildIndex]'](refNode)); }; this.setStartAfter = function (refNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeHasValidRoot]'](refNode) || !this['[NodeIsContextual]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } this['[SetStart:1]'](refNode.parentNode, this['[NodeGetChildIndex]'](refNode) + 1); }; this.setEndBefore = function (refNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeHasValidRoot]'](refNode) || !this['[NodeIsContextual]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } this['[SetEnd:1]'](refNode.parentNode, this['[NodeGetChildIndex]'](refNode)); }; this.setEndAfter = function (refNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeHasValidRoot]'](refNode) || !this['[NodeIsContextual]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } this['[SetEnd:1]'](refNode.parentNode, this['[NodeGetChildIndex]'](refNode) + 1); }; this.collapse = function (toStart) { this.collapsed = true; if (toStart) { this.endContainer = this.startContainer; this.endOffset = this.startOffset; } else { this.startContainer = this.endContainer; this.startOffset = this.endOffset; } this.commonAncestorContainer = this.startContainer; }; this.selectNode = function (refNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeHasValidRoot]'](refNode) || !this['[NodeIsContextual]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } this['[SetStart:2]'](refNode.parentNode, this['[NodeGetChildIndex]'](refNode)); this['[SetEnd:1]'](refNode.parentNode, this['[NodeGetChildIndex]'](refNode) + 1); }; this.selectNodeContents = function (refNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } if (!this['[NodeHasValidRoot]'](refNode)) { throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } this['[SetStart:2]'](refNode, 0); this['[SetEnd:1]'](refNode, this['[NodeGetMaxOffset]'](refNode)); }; this.compareBoundaryPoints = function (how, sourceRange) { switch (how) { case As_DOM_Range.START_TO_START: return this['[ComparePoints]'](this.startContainer, this.startOffset, sourceRange.startContainer, sourceRange.startOffset); case As_DOM_Range.START_TO_END: return this['[ComparePoints]'](this.endContainer, this.endOffset, sourceRange.startContainer, sourceRange.startOffset); case As_DOM_Range.END_TO_END: return this['[ComparePoints]'](this.endContainer, this.endOffset, sourceRange.endContainer, sourceRange.endOffset); case As_DOM_Range.END_TO_START: return this['[ComparePoints]'](this.startContainer, this.startOffset, sourceRange.endContainer, sourceRange.endOffset); default: throw new Error; // DOMException.NOT_SUPPORTED_ERR(9) } }; this.detach = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } this.commonAncestorContainer = null; this.detached = true; }; this.extractContents = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } var df = this['[ExtractContents:1]'](); this['[CollapseBoundary]'](); return df; }; this['[ExtractContents:1]'] = function () { return function () { if (this.commonAncestorContainer === this.startContainer) { if (this.commonAncestorContainer === this.endContainer) { return this['[ExtractNodeContents]'](this.commonAncestorContainer, this.startOffset, this.endOffset); } var df = this.ownerDocument.createDocumentFragment(); var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); df.appendChild(this['[ExtractNodeContents]'](this.commonAncestorContainer, this.startOffset, offsets2[0])); processRight.call(this, df, offsets2[0], offsets2); // different from cloneContents return df; } if (this.commonAncestorContainer === this.endContainer) { var df = this.ownerDocument.createDocumentFragment(); var offsets1 = this['[NodeGetOrderedSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); processLeft.call(this, df, offsets1, this.endOffset); return df; } var df = this.ownerDocument.createDocumentFragment(); var offsets1 = this['[NodeGetOrderedSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); processLeft.call(this, df, offsets1, offsets2[0]); processRight.call(this, df, offsets1[0] + 1, offsets2); // different from cloneContents return df; }; function processLeft(df, offsets1, endOffset) { var oldContent = this.commonAncestorContainer.childNodes[offsets1[0]]; var newContent = df.appendChild(oldContent.cloneNode(false)); var offset1Count = offsets1.length; var offset; var child; var i; for (i = 1; i < offset1Count; i++) { offset = offsets1[i]; child = oldContent.childNodes[offset]; newContent.appendChild(child.cloneNode(false)); newContent.appendChild(this['[ExtractNodeContents]'](oldContent, offset + 1)); newContent = newContent.firstChild; oldContent = child; } this['[NodeAppendContents]'](newContent, this['[ExtractNodeContents]'](this.startContainer, this.startOffset)); df.appendChild(this['[ExtractNodeContents]'](this.commonAncestorContainer, offsets1[0] + 1, endOffset)); } function processRight(df, startOffset, offsets2) { var oldContent = this.commonAncestorContainer.childNodes[startOffset]; var newContent = df.appendChild(oldContent.cloneNode(false)); var offset2Count = offsets2.length; var offset; var child; var i; for (i = 1; i < offset2Count; i++) { offset = offsets2[i]; child = oldContent.childNodes[offset]; newContent.appendChild(this['[ExtractNodeContents]'](oldContent, 0, offset)); newContent.appendChild(child.cloneNode(false)); newContent = newContent.lastChild; oldContent = child; } this['[NodeAppendContents]'](newContent, this['[ExtractNodeContents]'](this.endContainer, 0, this.endOffset)); } }(); this['[ExtractNodeContents]'] = function (node, startOffset, endOffset) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: var childNodes = node.childNodes; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = childNodes.length; } var count = endOffset - startOffset; var type = As_DOM_Range.DOCUMENT_TYPE_NODE; var df = this.ownerDocument.createDocumentFragment(); var n; var i; for (i = 0; i < count; i++) { n = childNodes[startOffset]; if (n.nodeType === type) { throw new Error; // DOMException.HIERARCHY_REQUEST_ERR(3) } df.appendChild(node.removeChild(n)); } return df; case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: var cnt = this['[CloneNodeContents]'](node, startOffset, endOffset); this['[DeleteNodeContents]'](node, startOffset, endOffset); return cnt; case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } }; this.cloneContents = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } var df = this['CloneContents:1'](); return df; }; this['CloneContents:1'] = function () { return function () { if (this.commonAncestorContainer === this.startContainer) { if (this.commonAncestorContainer === this.endContainer) { return this['[CloneNodeContents]'](this.commonAncestorContainer, this.startOffset, this.endOffset); } var df = this.ownerDocument.createDocumentFragment(); var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); df.appendChild(this['[CloneNodeContents]'](this.commonAncestorContainer, this.startOffset, offsets2[0])); processRight.call(this, df, offsets2[0], offsets2); // different from extractContents return df; } if (this.commonAncestorContainer === this.endContainer) { var df = this.ownerDocument.createDocumentFragment(); var offsets1 = this['[NodeGetOrderedSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); processLeft.call(this, df, offsets1, this.endOffset); return df; } var df = this.ownerDocument.createDocumentFragment(); var offsets1 = this['[NodeGetOrderedSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); processLeft.call(this, df, offsets1, offsets2[0]); processRight.call(this, df, offsets2[0], offsets2); // different from extractContents return df; }; function processLeft(df, offsets1, endOffset) { var oldContent = this.commonAncestorContainer.childNodes[offsets1[0]]; var newContent = df.appendChild(oldContent.cloneNode(false)); var offset1Count = offsets1.length; var offset; var child; var i; for (i = 1; i < offset1Count; i++) { offset = offsets1[i]; child = oldContent.childNodes[offset]; newContent.appendChild(child.cloneNode(false)); newContent.appendChild(this['[CloneNodeContents]'](oldContent, offset + 1)); newContent = newContent.firstChild; oldContent = child; } this['[NodeAppendContents]'](newContent, this['[CloneNodeContents]'](this.startContainer, this.startOffset)); df.appendChild(this['[CloneNodeContents]'](this.commonAncestorContainer, offsets1[0] + 1, endOffset)); } function processRight(df, startOffset, offsets2) { var oldContent = this.commonAncestorContainer.childNodes[startOffset]; var newContent = df.appendChild(oldContent.cloneNode(false)); var offset2Count = offsets2.length; var offset; var child; var i; for (i = 1; i < offset2Count; i++) { offset = offsets2[i]; child = oldContent.childNodes[offset]; newContent.appendChild(this['[CloneNodeContents]'](oldContent, 0, offset)); newContent.appendChild(child.cloneNode(false)); newContent = newContent.lastChild; oldContent = child; } this['[NodeAppendContents]'](newContent, this['[CloneNodeContents]'](this.endContainer, 0, this.endOffset)); } }(); this['[CloneNodeContents]'] = function (node, startOffset, endOffset) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: var childNodes = node.childNodes; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = childNodes.length; } var count = endOffset; var type = As_DOM_Range.DOCUMENT_TYPE_NODE; var df = this.ownerDocument.createDocumentFragment(); var i; var n; for (i = startOffset; i < count; i++) { n = childNodes[i]; if (n.nodeType === type) { throw new Error; // DOMException.HIERARCHY_REQUEST_ERR(3) } df.appendChild(n.cloneNode(true)); } return df; case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: var cnt = node.cloneNode(false); var txt = cnt.data; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = txt.length; } cnt.data = txt.substring(startOffset, endOffset); return cnt; case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } }; this.deleteContents = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } this['[DeleteContents:1]'](); this['[CollapseBoundary]'](); }; this['[DeleteContents:1]'] = function () { return function () { if (this.commonAncestorContainer === this.startContainer) { if (this.commonAncestorContainer === this.endContainer) { this['[DeleteNodeContents]'](this.commonAncestorContainer, this.startOffset, this.endOffset); return; } var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); this['[DeleteNodeContents]'] (this.commonAncestorContainer, this.startOffset, offsets2[0]); processRight.call(this, offsets2[0], offsets2); return; } if (this.commonAncestorContainer === this.endContainer) { var offsets1 = this['[NodeGetOrderedSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); processLeft.call(this, offsets1, this.endOffset); return; } var offsets1 = this['[NodeGetOrderedSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); processLeft.call(this, offsets1, offsets2[0]); processRight.call(this, offsets1[0] + 1, offsets2); return; }; function processLeft(offsets1, endOffset) { var child = this.commonAncestorContainer.childNodes[offsets1[0]]; var offset1Count = offsets1.length; var offset; var i; for (i = 1; i < offset1Count; i++) { offset = offsets1[i]; this['[DeleteNodeContents]'](child, offset + 1); child = child.childNodes[offset]; } this['[DeleteNodeContents]'](this.startContainer, this.startOffset); this['[DeleteNodeContents]'](this.commonAncestorContainer, offsets1[0] + 1, endOffset); } function processRight(startOffset, offsets2) { var child = this.commonAncestorContainer.childNodes[startOffset]; var offset2Count = offsets2.length; var offset; var i; for (i = 1; i < offset2Count; i++) { offset = offsets2[i]; this['[DeleteNodeContents]'](child, 0, offset); child = child.childNodes[offset]; } this['[DeleteNodeContents]'](this.endContainer, 0, this.endOffset); } }(); this['[DeleteNodeContents]'] = function (node, startOffset, endOffset) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: var childNodes = node.childNodes; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = childNodes.length; } var count = endOffset - startOffset; var i; for (i = 0; i < count; i++) { node.removeChild(childNodes[startOffset]); } return; case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: var cnt = node.cloneNode(false); var txt = cnt.data; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = txt.length; } node.data = txt.substring(0, startOffset) + txt.substring(endOffset); return; case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } }; this.toString = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } var result = this['[ToString:1]'](); return result; }; this['[ToString:1]'] = function () { return function () { if (this.commonAncestorContainer === this.startContainer) { if (this.commonAncestorContainer === this.endContainer) { return this['[NodeGetString]'](this.commonAncestorContainer, this.startOffset, this.endOffset); } var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); var result = []; result[result.length] = this['[NodeGetString]'](this.commonAncestorContainer, this.startOffset, offsets2[0]); processRight.call(this, result, offsets2[0], offsets2); return result.join(''); } if (this.commonAncestorContainer === this.endContainer) { var offsets1 = this['[NodeGetSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); var result = []; processLeft.call(this, result, offsets1, this.endOffset); return result.join(''); } var offsets1 = this['[NodeGetSnapshotOffsets]'](this.startContainer, this.commonAncestorContainer); var offsets2 = this['[NodeGetOrderedSnapshotOffsets]'](this.endContainer, this.commonAncestorContainer); var result = []; processLeft.call(this, result, offsets1, offsets2[0]); processRight.call(this, result, this.startOffset, offsets2); return result.join(''); }; function processLeft(result, offsets1, endOffset) { var parent = this.startContainer; var offset1Count = offsets1.length - 1; var offset; var i; result[result.length] = this['[NodeGetString]'](parent, this.startOffset); for (i = 0; i < offset1Count; i++) { offset = offsets1[i]; parent = parent.parentNode; result[result.length] = this['[NodeGetString]'](parent, offset + 1); } result[result.length] = this['[NodeGetString]'](this.commonAncestorContainer, offsets1[offset1Count] + 1, endOffset); } function processRight(result, startOffset, offsets2) { var child = this.commonAncestorContainer.childNodes[offsets2[0]]; var offset2Count = offsets2.length; var offset; var i; for (i = 1; i < offset2Count; i++) { offset = offsets2[i]; result[result.length] = this['[NodeGetString]'](child, 0, offset); child = child.childNodes[offset]; } result[result.length] = this['[NodeGetString]'](this.endContainer, 0, this.endOffset); } }(); this['[NodeGetString]'] = function (node, startOffset, endOffset) { switch (node.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: var childNodes = node.childNodes; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = childNodes.length; } var count = endOffset; var type1 = As_DOM_Range.PROCESSING_INSTRUCTION_NODE; var type2 = As_DOM_Range.COMMENT_NODE; var txt = []; var n; var i; for (i = startOffset; i < count; i++) { n = childNodes[i]; switch (node.nodeType) { case type1: case type2: break; default: txt[txt.length] = this['[NodeGetTextContent:1]'](n); } } return txt.join(''); case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: var txt = node.data; if (isNaN(startOffset)) { startOffset = 0; } if (isNaN(endOffset)) { endOffset = txt.length; } return txt.substring(startOffset, endOffset); case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODE_TYPE_ERR(2) } }; this.insertNode = function (newNode) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } switch (newNode.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: break; case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODEYPE_ERR(2) } if (newNode.ownerDocument !== this.ownerDocument) { throw new Error; // DOMException.WRONG_DOCUMENT_ERR(4) } if (this['[NodeContainsOther]'](newNode, this.startContainer)) { throw new Error; // DOMException.HIERARCHY_REQUEST_ERR(3) } return this['[InsertNode:1]'](newNode); }; this['[InsertNode:1]'] = function (newNode) { var startContainer = this.startContainer; switch (startContainer.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: var target = startContainer.childNodes[this.startOffset]; /*@{ if (! target) target = null; }@*/ var endContainer = this.endContainer; if (startContainer === endContainer) { var childNodes = endContainer.childNodes; var childCount = childNodes.length; startContainer.insertBefore(newNode, target); this.endOffset += childNodes.length - childCount; } else { startContainer.insertBefore(newNode, target); } return; case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: var startOffset = this.startOffset; var endContainer = this.endContainer; var cnt = startContainer.splitText(startOffset); if (startContainer === endContainer) { this.endContainer = cnt; this.endOffset -= startOffset; } cnt.parentNode.insertBefore(newNode, cnt); return; case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.HIERARCHY_REQUEST_ERR(3) } }; this.surroundContents = function (newParent) { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } switch (newParent.nodeType) { case As_DOM_Range.ELEMENT_NODE: case As_DOM_Range.TEXT_NODE: case As_DOM_Range.CDATA_SECTION_NODE: case As_DOM_Range.ENTITY_REFERENCE_NODE: case As_DOM_Range.PROCESSING_INSTRUCTION_NODE: case As_DOM_Range.COMMENT_NODE: break; case As_DOM_Range.ATTRIBUTE_NODE: case As_DOM_Range.ENTITY_NODE: case As_DOM_Range.DOCUMENT_TYPE_NODE: case As_DOM_Range.DOCUMENT_NODE: case As_DOM_Range.DOCUMENT_FRAGMENT_NODE: case As_DOM_Range.NOTATION_NODE: default: throw new Error; // RangeException.INVALID_NODEYPE_ERR(2) } if (newParent.ownerDocument !== this.ownerDocument) { throw new Error; // DOMException.WRONG_DOCUMENT_ERR(4) } if (this['[NodeContainsOther]'](newParent, this.startContainer)) { throw new Error; // DOMException.HIERARCHY_REQUEST_ERR(3) } return this['[SurroundContents:1]'](newParent); }; this['[SurroundContents:1]'] = function (newParent) { if (this['[NodeContainsOther]'](newParent, this.endContainer)) { this.endContainer = newParent; this.endOffset = 0; } while (newParent.hasChildNodes()) { newParent.removeChild(newParent.lastChild); } // var df = this.extractContents(); this.insertNode(newParent); newParent.appendChild(df); this.selectNode(newParent); }; this.cloneRange = function () { if (this.detached) { throw new Error; // DOMException.INVALID_STATE_ERR(11) } // var range = new this.constructor(null); As_DOM_Object.call(range, this); return range; }; }).call(As_DOM_Range.prototype); //////////////////////////////////////////////////////////////////////// var as_DOM_DocumentRange_createRange = function (doc) { return new As_DOM_Range({ startContainer: doc, startOffset: 0, endContainer: doc, endOffset: 0, collapsed: true, commonAncestorContainer: doc, ownerDocument: doc, detached: false }); };
- 初出 2011-08-25/26/27