18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang *
284576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang * Contains diff method based on Javascript Diff Algorithm By John Resig
294576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang * http://ejohn.org/files/jsdiff.js (released under the MIT license).
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectFunction.prototype.bind = function(thisObject)
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var func = this;
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var args = Array.prototype.slice.call(arguments, 1);
36545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    function bound()
37545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    {
38545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0)));
39545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    }
40545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    bound.toString = function() {
41545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        return "bound: " + func;
42545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    };
43545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    return bound;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var startNode;
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var startOffset = 0;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var endNode;
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var endOffset = 0;
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!stayWithinNode)
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        stayWithinNode = this;
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!direction || direction === "backward" || direction === "both") {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var node = this;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (node) {
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node === stayWithinNode) {
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!startNode)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    startNode = stayWithinNode;
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node.nodeType === Node.TEXT_NODE) {
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                for (var i = start; i >= 0; --i) {
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        startNode = node;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        startOffset = i + 1;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (startNode)
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            node = node.traversePreviousNode(stayWithinNode);
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!startNode) {
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            startNode = stayWithinNode;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            startOffset = 0;
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startNode = this;
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startOffset = offset;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!direction || direction === "forward" || direction === "both") {
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = this;
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (node) {
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node === stayWithinNode) {
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!endNode)
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    endNode = stayWithinNode;
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node.nodeType === Node.TEXT_NODE) {
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                var start = (node === this ? offset : 0);
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                for (var i = start; i < node.nodeValue.length; ++i) {
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        endNode = node;
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        endOffset = i;
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (endNode)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            node = node.traverseNextNode(stayWithinNode);
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!endNode) {
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            endNode = stayWithinNode;
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endNode = this;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endOffset = offset;
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var result = this.ownerDocument.createRange();
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    result.setStart(startNode, startOffset);
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    result.setEnd(endNode, endOffset);
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockNode.prototype.traverseNextTextNode = function(stayWithin)
1348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{
1358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    var node = this.traverseNextNode(stayWithin);
1368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!node)
1378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return;
1388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    while (node && node.nodeType !== Node.TEXT_NODE)
1408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        node = node.traverseNextNode(stayWithin);
1418a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return node;
1438a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block}
1448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockNode.prototype.rangeBoundaryForOffset = function(offset)
1468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{
1478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    var node = this.traverseNextTextNode(this);
1488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    while (node && offset > node.nodeValue.length) {
1498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        offset -= node.nodeValue.length;
1508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        node = node.traverseNextTextNode(this);
1518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
1528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!node)
1538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return { container: this, offset: 0 };
1548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return { container: node, offset: offset };
1558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block}
1568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.removeStyleClass = function(className)
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block    this.classList.remove(className);
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.removeMatchingStyleClasses = function(classNameRegex)
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)");
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (regex.test(this.className))
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.className = this.className.replace(regex, " ");
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.addStyleClass = function(className)
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block    this.classList.add(className);
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.hasStyleClass = function(className)
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1762bde8e466a4451c7319e3a072d118917957d6554Steve Block    return this.classList.contains(className);
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockElement.prototype.positionAt = function(x, y)
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    this.style.left = x + "px";
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    this.style.top = y + "px";
183231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockElement.prototype.pruneEmptyTextNodes = function()
186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
187dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    var sibling = this.firstChild;
188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    while (sibling) {
189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var nextSibling = sibling.nextSibling;
190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (sibling.nodeType === this.TEXT_NODE && sibling.nodeValue === "")
191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            this.removeChild(sibling);
192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        sibling = nextSibling;
193dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
196f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochElement.prototype.isScrolledToBottom = function()
197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
19881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // This code works only for 0-width border
19981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return this.scrollTop + this.clientHeight === this.scrollHeight;
200f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
204231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (var i = 0; i < nameArray.length; ++i)
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return node;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return null;
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.enclosingNodeOrSelfWithClass = function(className)
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
218231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return node;
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return null;
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.enclosingNodeWithClass = function(className)
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!this.parentNode)
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return null;
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.parentNode.enclosingNodeOrSelfWithClass(className);
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.query = function(query)
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.removeChildren = function()
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
238dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (this.firstChild)
239dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        this.textContent = "";
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.isInsertionCaretInside = function()
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var selection = window.getSelection();
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!selection.rangeCount || !selection.isCollapsed)
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var selectionRange = selection.getRangeAt(0);
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return selectionRange.startContainer === this || selectionRange.startContainer.isDescendant(this);
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2516c2af9490927c3c5959b5cb07461b646f8b32f6cKristian MonsenElement.prototype.createChild = function(elementName, className)
2526c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{
2536c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    var element = document.createElement(elementName);
2546c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    if (className)
2556c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        element.className = className;
2566c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    this.appendChild(element);
2576c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    return element;
2586c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen}
2596c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.__defineGetter__("totalOffsetLeft", function()
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var total = 0;
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var element = this; element; element = element.offsetParent)
264692e5dbf12901edacf14812a6fae25462920af42Steve Block        total += element.offsetLeft + (this !== element ? element.clientLeft : 0);
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return total;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project});
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement.prototype.__defineGetter__("totalOffsetTop", function()
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var total = 0;
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var element = this; element; element = element.offsetParent)
272692e5dbf12901edacf14812a6fae25462920af42Steve Block        total += element.offsetTop + (this !== element ? element.clientTop : 0);
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return total;
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project});
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
276231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockElement.prototype.offsetRelativeToWindow = function(targetWindow)
277231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    var elementOffset = {x: 0, y: 0};
279231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    var curElement = this;
280231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    var curWindow = this.ownerDocument.defaultView;
281231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    while (curWindow && curElement) {
282231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        elementOffset.x += curElement.totalOffsetLeft;
283231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        elementOffset.y += curElement.totalOffsetTop;
284231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (curWindow === targetWindow)
285231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            break;
286231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
287231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        curElement = curWindow.frameElement;
288231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        curWindow = curWindow.parent;
289231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
290231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
291231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return elementOffset;
292231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
29406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenKeyboardEvent.prototype.__defineGetter__("data", function()
29506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
29606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Emulate "data" attribute from DOM 3 TextInput event.
29706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data
29806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    switch (this.type) {
29906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        case "keypress":
30006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            if (!this.ctrlKey && !this.metaKey)
30106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                return String.fromCharCode(this.charCode);
30206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            else
30306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                return "";
30406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        case "keydown":
30506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        case "keyup":
30606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            if (!this.ctrlKey && !this.metaKey && !this.altKey)
30706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                return String.fromCharCode(this.which);
30806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            else
30906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                return "";
31006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    }
31106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen});
31206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
31306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenText.prototype.select = function(start, end)
31406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
31506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    start = start || 0;
31606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    end = end || this.textContent.length;
31706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
31806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (start < 0)
31906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        start = end + start;
32006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
32106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    var selection = window.getSelection();
32206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    selection.removeAllRanges();
32306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    var range = document.createRange();
32406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    range.setStart(this, start);
32506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    range.setEnd(this, end);
32606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    selection.addRange(range);
32706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return this;
32806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
32906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
33006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenElement.prototype.__defineGetter__("selectionLeftOffset", function() {
33106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Calculate selection offset relative to the current element.
33206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
33306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    var selection = window.getSelection();
33406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (!selection.containsNode(this, true))
33506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return null;
33606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
33706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    var leftOffset = selection.anchorOffset;
33806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    var node = selection.anchorNode;
33906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
34006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    while (node !== this) {
34106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        while (node.previousSibling) {
34206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            node = node.previousSibling;
34306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            leftOffset += node.textContent.length;
34406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        }
34506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        node = node.parentNode;
34606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    }
34706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
34806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return leftOffset;
34906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen});
35006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.isWhitespace = isNodeWhitespace;
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.displayName = nodeDisplayName;
353231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockNode.prototype.isAncestor = function(node)
354231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
355231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return isAncestorNode(this, node);
356231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.isDescendant = isDescendantNode;
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.traverseNextNode = traverseNextNode;
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode.prototype.traversePreviousNode = traversePreviousNode;
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.prototype.hasSubstring = function(string, caseInsensitive)
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!caseInsensitive)
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this.indexOf(string) !== -1;
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.match(new RegExp(string.escapeForRegExp(), "i"));
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
36865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochString.prototype.findAll = function(string)
36965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
37065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    var matches = [];
37165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    var i = this.indexOf(string);
37265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    while (i !== -1) {
37365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        matches.push(i);
37465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        i = this.indexOf(string, i + string.length);
37565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
37665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return matches;
37765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
37865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
37981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochString.prototype.lineEndings = function()
38081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
38181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!this._lineEndings) {
38281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        this._lineEndings = this.findAll("\n");
38381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        this._lineEndings.push(this.length);
38481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
38581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return this._lineEndings;
38681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
38781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
388a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochString.prototype.asParsedURL = function()
389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // RegExp groups:
391a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // 1 - scheme
392a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // 2 - hostname
393a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // 3 - ?port
394a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // 4 - ?path
395a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // 5 - ?fragment
396a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    var match = this.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
397a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!match)
398a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return null;
399a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    var result = {};
400a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    result.scheme = match[1].toLowerCase();
401a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    result.host = match[2];
402a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    result.port = match[3];
403a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    result.path = match[4] || "/";
404a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    result.fragment = match[5];
405a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return result;
406a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
407a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.prototype.escapeCharacters = function(chars)
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var foundChar = false;
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var i = 0; i < chars.length; ++i) {
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this.indexOf(chars.charAt(i)) !== -1) {
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            foundChar = true;
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!foundChar)
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var result = "";
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var i = 0; i < this.length; ++i) {
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (chars.indexOf(this.charAt(i)) !== -1)
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            result += "\\";
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result += this.charAt(i);
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.prototype.escapeForRegExp = function()
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.escapeCharacters("^[]{}()\\.$*+?|");
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.prototype.escapeHTML = function()
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4385af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.prototype.collapseWhitespace = function()
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.replace(/[\s\xA0]+/g, " ");
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.prototype.trimURL = function(baseURLDomain)
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
448dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    var result = this.replace(/^(https|http|file):\/\//i, "");
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (baseURLDomain)
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochString.prototype.removeURLFragment = function()
4552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var fragmentIndex = this.indexOf("#");
4572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (fragmentIndex == -1)
4582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        fragmentIndex = this.length;
4592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return this.substring(0, fragmentIndex);
4602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfunction isNodeWhitespace()
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!this || this.nodeType !== Node.TEXT_NODE)
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!this.nodeValue.length)
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.nodeValue.match(/^[\s\xA0]+$/);
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfunction nodeDisplayName()
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!this)
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return "";
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (this.nodeType) {
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case Node.DOCUMENT_NODE:
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return "Document";
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case Node.ELEMENT_NODE:
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var name = "<" + this.nodeName.toLowerCase();
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (this.hasAttributes()) {
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                var value = this.getAttribute("id");
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (value)
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    name += " id=\"" + value + "\"";
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                value = this.getAttribute("class");
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (value)
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    name += " class=\"" + value + "\"";
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (this.nodeName.toLowerCase() === "a") {
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("name");
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " name=\"" + value + "\"";
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("href");
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " href=\"" + value + "\"";
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else if (this.nodeName.toLowerCase() === "img") {
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("src");
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " src=\"" + value + "\"";
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else if (this.nodeName.toLowerCase() === "iframe") {
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("src");
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " src=\"" + value + "\"";
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else if (this.nodeName.toLowerCase() === "input") {
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("name");
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " name=\"" + value + "\"";
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("type");
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " type=\"" + value + "\"";
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else if (this.nodeName.toLowerCase() === "form") {
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    value = this.getAttribute("action");
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (value)
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        name += " action=\"" + value + "\"";
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return name + ">";
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case Node.TEXT_NODE:
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isNodeWhitespace.call(this))
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return "(whitespace)";
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return "\"" + this.nodeValue + "\"";
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case Node.COMMENT_NODE:
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return "<!--" + this.nodeValue + "-->";
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case Node.DOCUMENT_TYPE_NODE:
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var docType = "<!DOCTYPE " + this.nodeName;
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (this.publicId) {
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                docType += " PUBLIC \"" + this.publicId + "\"";
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (this.systemId)
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    docType += " \"" + this.systemId + "\"";
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else if (this.systemId)
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                docType += " SYSTEM \"" + this.systemId + "\"";
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (this.internalSubset)
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                docType += " [" + this.internalSubset + "]";
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return docType + ">";
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.nodeName.toLowerCase().collapseWhitespace();
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
545231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockfunction isAncestorNode(ancestor, node)
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
547231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!node || !ancestor)
548058ccc7ba0a4d59b9f6e92808332aa9895425fc7Andrei Popescu        return false;
549058ccc7ba0a4d59b9f6e92808332aa9895425fc7Andrei Popescu
550231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    var currentNode = node.parentNode;
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (currentNode) {
552231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (ancestor === currentNode)
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        currentNode = currentNode.parentNode;
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfunction isDescendantNode(descendant)
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
561231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return isAncestorNode(descendant, this);
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
564231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockfunction traverseNextNode(stayWithin)
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!this)
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var node = this.firstChild;
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node)
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node;
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
573231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (stayWithin && this === stayWithin)
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return null;
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
576231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    node = this.nextSibling;
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node)
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node;
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    node = this;
581231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin))
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node.parentNode;
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return null;
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
586231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return node.nextSibling;
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
589231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockfunction traversePreviousNode(stayWithin)
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!this)
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
593231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (stayWithin && this === stayWithin)
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return null;
595231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    var node = this.previousSibling;
596231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    while (node && node.lastChild)
597231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        node = node.lastChild;
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node)
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node;
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return this.parentNode;
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
603231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockfunction getDocumentForNode(node)
604231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
605231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockfunction parentNode(node)
609231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
610231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return node.parentNode;
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
61365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochNumber.millisToString = function(ms, higherResolution)
6140617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{
61565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return Number.secondsToString(ms / 1000, higherResolution);
6160617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
6170617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
61865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochNumber.secondsToString = function(seconds, higherResolution)
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
620643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (seconds === 0)
621643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return "0";
622643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var ms = seconds * 1000;
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (higherResolution && ms < 1000)
62565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.3fms", ms);
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (ms < 1000)
62765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.0fms", ms);
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (seconds < 60)
63065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.2fs", seconds);
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var minutes = seconds / 60;
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (minutes < 60)
63465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.1fmin", minutes);
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var hours = minutes / 60;
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hours < 24)
63865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.1fhrs", hours);
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var days = hours / 24;
64165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return WebInspector.UIString("%.1f days", days);
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
64465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochNumber.bytesToString = function(bytes, higherResolution)
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
646231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (typeof higherResolution === "undefined")
647231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        higherResolution = true;
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (bytes < 1024)
65065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.0fB", bytes);
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var kilobytes = bytes / 1024;
653231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (higherResolution && kilobytes < 1024)
65465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.2fKB", kilobytes);
655231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    else if (kilobytes < 1024)
65665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.0fKB", kilobytes);
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var megabytes = kilobytes / 1024;
659231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (higherResolution)
66065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.2fMB", megabytes);
661231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    else
66265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return WebInspector.UIString("%.0fMB", megabytes);
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNumber.constrain = function(num, min, max)
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (num < min)
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        num = min;
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (num > max)
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        num = max;
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return num;
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectHTMLTextAreaElement.prototype.moveCursorToEnd = function()
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var length = this.value.length;
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.setSelectionRange(length, length);
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
68065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochObject.defineProperty(Array.prototype, "remove", { value: function(value, onlyFirst)
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (onlyFirst) {
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var index = this.indexOf(value);
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (index !== -1)
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.splice(index, 1);
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var length = this.length;
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var i = 0; i < length; ++i) {
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this[i] === value)
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.splice(i, 1);
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
69465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}});
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
69665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochObject.defineProperty(Array.prototype, "keySet", { value: function()
697d0825bca7fe65beaee391d30da42e937db621564Steve Block{
698d0825bca7fe65beaee391d30da42e937db621564Steve Block    var keys = {};
699d0825bca7fe65beaee391d30da42e937db621564Steve Block    for (var i = 0; i < this.length; ++i)
700d0825bca7fe65beaee391d30da42e937db621564Steve Block        keys[this[i]] = true;
701d0825bca7fe65beaee391d30da42e937db621564Steve Block    return keys;
70265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}});
703d0825bca7fe65beaee391d30da42e937db621564Steve Block
704ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen MurdochObject.defineProperty(Array.prototype, "upperBound", { value: function(value)
705ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
706ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    var first = 0;
707ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    var count = this.length;
708ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    while (count > 0) {
709ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch      var step = count >> 1;
710ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch      var middle = first + step;
711ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch      if (value >= this[middle]) {
712ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch          first = middle + 1;
713ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch          count -= step + 1;
714ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch      } else
715ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch          count = step;
716ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
717ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return first;
718ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}});
719ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
7204576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangArray.diff = function(left, right)
7214576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{
7224576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    var o = left;
7234576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    var n = right;
7244576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7254576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    var ns = {};
7264576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    var os = {};
7274576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7284576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (var i = 0; i < n.length; i++) {
7294576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (ns[n[i]] == null)
7304576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            ns[n[i]] = { rows: [], o: null };
7314576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        ns[n[i]].rows.push(i);
7324576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
7334576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7344576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (var i = 0; i < o.length; i++) {
7354576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (os[o[i]] == null)
7364576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            os[o[i]] = { rows: [], n: null };
7374576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        os[o[i]].rows.push(i);
7384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
7394576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7404576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (var i in ns) {
7414576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
7424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            n[ns[i].rows[0]] = { text: n[ns[i].rows[0]], row: os[i].rows[0] };
7434576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            o[os[i].rows[0]] = { text: o[os[i].rows[0]], row: ns[i].rows[0] };
7444576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        }
7454576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
7464576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7474576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (var i = 0; i < n.length - 1; i++) {
7484576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) {
7494576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            n[i + 1] = { text: n[i + 1], row: n[i].row + 1 };
7504576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1 };
7514576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        }
7524576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
7534576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7544576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (var i = n.length - 1; i > 0; i--) {
7554576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
7564576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            n[i - 1] == o[n[i].row - 1]) {
7574576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            n[i - 1] = { text: n[i - 1], row: n[i].row - 1 };
7584576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1 };
7594576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        }
7604576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
7614576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7624576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    return { left: o, right: n };
7634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang}
7644576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
76506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenArray.convert = function(list)
76606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
76706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Cast array-like object to an array.
76806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return Array.prototype.slice.call(list);
76906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
77006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
7712bde8e466a4451c7319e3a072d118917957d6554Steve Blockfunction binarySearch(object, array, comparator)
7728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
7738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    var first = 0;
7742bde8e466a4451c7319e3a072d118917957d6554Steve Block    var last = array.length - 1;
7758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    while (first <= last) {
7772bde8e466a4451c7319e3a072d118917957d6554Steve Block        var mid = (first + last) >> 1;
7782bde8e466a4451c7319e3a072d118917957d6554Steve Block        var c = comparator(object, array[mid]);
7798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (c > 0)
7808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            first = mid + 1;
7818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        else if (c < 0)
7828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            last = mid - 1;
7832bde8e466a4451c7319e3a072d118917957d6554Steve Block        else
7842bde8e466a4451c7319e3a072d118917957d6554Steve Block            return mid;
7858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
7868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7872bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Return the nearest lesser index, "-1" means "0, "-2" means "1", etc.
7882bde8e466a4451c7319e3a072d118917957d6554Steve Block    return -(first + 1);
7892bde8e466a4451c7319e3a072d118917957d6554Steve Block}
7902bde8e466a4451c7319e3a072d118917957d6554Steve Block
7912bde8e466a4451c7319e3a072d118917957d6554Steve BlockObject.defineProperty(Array.prototype, "binaryIndexOf", { value: function(value, comparator)
7922bde8e466a4451c7319e3a072d118917957d6554Steve Block{
7932bde8e466a4451c7319e3a072d118917957d6554Steve Block    var result = binarySearch(value, this, comparator);
7942bde8e466a4451c7319e3a072d118917957d6554Steve Block    return result >= 0 ? result : -1;
7952bde8e466a4451c7319e3a072d118917957d6554Steve Block}});
7962bde8e466a4451c7319e3a072d118917957d6554Steve Block
7972bde8e466a4451c7319e3a072d118917957d6554Steve Blockfunction insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
7982bde8e466a4451c7319e3a072d118917957d6554Steve Block{
7992bde8e466a4451c7319e3a072d118917957d6554Steve Block    var index = binarySearch(anObject, aList, aFunction);
8002bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (index < 0)
8012bde8e466a4451c7319e3a072d118917957d6554Steve Block        // See binarySearch implementation.
8022bde8e466a4451c7319e3a072d118917957d6554Steve Block        return -index - 1;
8032bde8e466a4451c7319e3a072d118917957d6554Steve Block    else {
8042bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Return the first occurance of an item in the list.
8052bde8e466a4451c7319e3a072d118917957d6554Steve Block        while (index > 0 && aFunction(anObject, aList[index - 1]) === 0)
8062bde8e466a4451c7319e3a072d118917957d6554Steve Block            index--;
8072bde8e466a4451c7319e3a072d118917957d6554Steve Block        return index;
8082bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
8098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.sprintf = function(format)
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.tokenizeFormatString = function(format)
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var tokens = [];
8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var substitutionIndex = 0;
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    function addStringToken(str)
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        tokens.push({ type: "string", value: str });
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    function addSpecifierToken(specifier, precision, substitutionIndex)
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var index = 0;
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        addStringToken(format.substring(index, precentIndex));
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        index = precentIndex + 1;
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (format[index] === "%") {
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            addStringToken("%");
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ++index;
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!isNaN(format[index])) {
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The first character is a number, it might be a substitution index.
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var number = parseInt(format.substring(index));
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (!isNaN(format[index]))
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ++index;
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If the number is greater than zero and ends with a "$",
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // then this is a substitution index.
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (number > 0 && format[index] === "$") {
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                substitutionIndex = (number - 1);
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ++index;
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var precision = -1;
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (format[index] === ".") {
8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This is a precision specifier. If no digit follows the ".",
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // then the precision should be zero.
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ++index;
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            precision = parseInt(format.substring(index));
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isNaN(precision))
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                precision = 0;
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (!isNaN(format[index]))
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ++index;
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        addSpecifierToken(format[index], precision, substitutionIndex);
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ++substitutionIndex;
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ++index;
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    addStringToken(format.substring(index));
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return tokens;
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.standardFormatters = {
8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    d: function(substitution)
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
881f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) === "number")
882231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            substitution = substitution.description;
8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        substitution = parseInt(substitution);
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !isNaN(substitution) ? substitution : 0;
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    f: function(substitution, token)
8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
889f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) === "number")
890231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            substitution = substitution.description;
8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        substitution = parseFloat(substitution);
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (substitution && token.precision > -1)
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            substitution = substitution.toFixed(token.precision);
8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    s: function(substitution)
8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
899f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) !== "null")
900231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            substitution = substitution.description;
9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return substitution;
9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.vsprintf = function(format, substitutions)
9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString.format = function(format, substitutions, formatters, initialValue, append)
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!format || !substitutions || !substitutions.length)
9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    function prettyFunctionName()
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    function warn(msg)
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        console.warn(prettyFunctionName() + ": " + msg);
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    function error(msg)
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        console.error(prettyFunctionName() + ": " + msg);
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var result = initialValue;
9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var tokens = String.tokenizeFormatString(format);
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var usedSubstitutionIndexes = {};
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var i = 0; i < tokens.length; ++i) {
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var token = tokens[i];
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (token.type === "string") {
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            result = append(result, token.value);
9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (token.type !== "specifier") {
9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            error("Unknown token type \"" + token.type + "\" found.");
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (token.substitutionIndex >= substitutions.length) {
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If there are not enough substitutions for the current substitutionIndex
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // just output the format specifier literally and move on.
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        usedSubstitutionIndexes[token.substitutionIndex] = true;
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!(token.specifier in formatters)) {
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Encountered an unsupported format character, treat as a string.
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            result = append(result, substitutions[token.substitutionIndex]);
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    var unusedSubstitutions = [];
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (var i = 0; i < substitutions.length; ++i) {
9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (i in usedSubstitutionIndexes)
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unusedSubstitutions.push(substitutions[i]);
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
976cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
977cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockfunction isEnterKey(event) {
978cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // Check if in IME.
979cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    return event.keyCode !== 229 && event.keyIdentifier === "Enter";
980cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
981692e5dbf12901edacf14812a6fae25462920af42Steve Block
982692e5dbf12901edacf14812a6fae25462920af42Steve Blockfunction highlightSearchResult(element, offset, length)
983692e5dbf12901edacf14812a6fae25462920af42Steve Block{
98481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    var result = highlightSearchResults(element, [{offset: offset, length: length }]);
98581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return result.length ? result[0] : null;
98681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
98781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
98881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochfunction highlightSearchResults(element, resultRanges)
98981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
99081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    var highlightNodes = [];
991692e5dbf12901edacf14812a6fae25462920af42Steve Block    var lineText = element.textContent;
99281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    var textNodeSnapshot = document.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
99381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
99481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    var snapshotLength = textNodeSnapshot.snapshotLength;
99581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    var snapshotNodeOffset = 0;
99681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    var currentSnapshotItem = 0;
99781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
99881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (var i = 0; i < resultRanges.length; ++i) {
99981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var resultLength = resultRanges[i].length;
100081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var startOffset = resultRanges[i].offset;
100181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var endOffset = startOffset + resultLength;
100281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var length = resultLength;
100381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var textNode;
100481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var textNodeOffset;
100581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var found;
100681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
100781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        while (currentSnapshotItem < snapshotLength) {
100881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
100981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            var textNodeLength = textNode.nodeValue.length;
101081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (snapshotNodeOffset + textNodeLength >= startOffset) {
101181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                textNodeOffset = startOffset - snapshotNodeOffset;
101281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                snapshotNodeOffset += textNodeLength;
101381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                found = true;
101481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                break;
101581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            }
101681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            snapshotNodeOffset += textNodeLength;
101781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
1018692e5dbf12901edacf14812a6fae25462920af42Steve Block
101981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!found) {
102081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode = element;
102181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNodeOffset = 0;
102281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
1023692e5dbf12901edacf14812a6fae25462920af42Steve Block
102481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var highlightNode = document.createElement("span");
102581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        highlightNode.className = "webkit-search-result";
102681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        highlightNode.textContent = lineText.substring(startOffset, endOffset);
1027692e5dbf12901edacf14812a6fae25462920af42Steve Block
1028692e5dbf12901edacf14812a6fae25462920af42Steve Block        var text = textNode.textContent;
102981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (textNodeOffset + resultLength < text.length) {
103081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            // Selection belongs to a single split mode.
103181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode.textContent = text.substring(textNodeOffset + resultLength);
103281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode.parentElement.insertBefore(highlightNode, textNode);
103381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            var prefixNode = document.createTextNode(text.substring(0, textNodeOffset));
103481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode.parentElement.insertBefore(prefixNode, highlightNode);
103581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
103681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            highlightNodes.push(highlightNode);
103781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            continue;
103881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
103981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
104081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var parentElement = textNode.parentElement;
104181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var anchorElement = textNode.nextSibling;
104281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
104381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        length -= text.length - textNodeOffset;
104481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        textNode.textContent = text.substring(0, textNodeOffset);
104581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
104681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        while (currentSnapshotItem < snapshotLength) {
104781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
104881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            snapshotNodeOffset += textNode.nodeValue.length;
104981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            var text = textNode.textContent;
105081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (length < text.length) {
105181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                textNode.textContent = text.substring(length);
105281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                break;
105381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            }
105481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
105581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            length -= text.length;
105681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textNode.textContent = "";
1057692e5dbf12901edacf14812a6fae25462920af42Steve Block        }
1058692e5dbf12901edacf14812a6fae25462920af42Steve Block
105981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        parentElement.insertBefore(highlightNode, anchorElement);
106081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        highlightNodes.push(highlightNode);
1061692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
1062692e5dbf12901edacf14812a6fae25462920af42Steve Block
106381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return highlightNodes;
1064692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1065692e5dbf12901edacf14812a6fae25462920af42Steve Block
106681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochfunction createSearchRegex(query, extraFlags)
1067692e5dbf12901edacf14812a6fae25462920af42Steve Block{
1068692e5dbf12901edacf14812a6fae25462920af42Steve Block    var regex = "";
1069692e5dbf12901edacf14812a6fae25462920af42Steve Block    for (var i = 0; i < query.length; ++i) {
1070692e5dbf12901edacf14812a6fae25462920af42Steve Block        var char = query.charAt(i);
1071692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (char === "]")
1072692e5dbf12901edacf14812a6fae25462920af42Steve Block            char = "\\]";
1073692e5dbf12901edacf14812a6fae25462920af42Steve Block        regex += "[" + char + "]";
1074692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
107581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return new RegExp(regex, "i" + (extraFlags || ""));
1076692e5dbf12901edacf14812a6fae25462920af42Steve Block}
107768513a70bcd92384395513322f1b801e7bf9c729Steve Block
107868513a70bcd92384395513322f1b801e7bf9c729Steve Blockfunction offerFileForDownload(contents)
107968513a70bcd92384395513322f1b801e7bf9c729Steve Block{
108068513a70bcd92384395513322f1b801e7bf9c729Steve Block    var builder = new BlobBuilder();
108168513a70bcd92384395513322f1b801e7bf9c729Steve Block    builder.append(contents);
108268513a70bcd92384395513322f1b801e7bf9c729Steve Block    var blob = builder.getBlob("application/octet-stream");
108365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    var url = window.webkitURL.createObjectURL(blob);
108468513a70bcd92384395513322f1b801e7bf9c729Steve Block    window.open(url);
108568513a70bcd92384395513322f1b801e7bf9c729Steve Block}
1086