15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Apple Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     its contributors may be used to endorse or promote products derived
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     from this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Contains diff method based on Javascript Diff Algorithm By John Resig
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * http://ejohn.org/files/jsdiff.js (released under the MIT license).
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
34f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {number} offset
35f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {string} stopCharacters
36f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Node} stayWithinNode
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string=} direction
385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!Range}
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var startNode;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var startOffset = 0;
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var endNode;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var endOffset = 0;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!stayWithinNode)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stayWithinNode = this;
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!direction || direction === "backward" || direction === "both") {
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var node = this;
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (node) {
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node === stayWithinNode) {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!startNode)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    startNode = stayWithinNode;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node.nodeType === Node.TEXT_NODE) {
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (var i = start; i >= 0; --i) {
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        startNode = node;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        startOffset = i + 1;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (startNode)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            node = node.traversePreviousNode(stayWithinNode);
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!startNode) {
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            startNode = stayWithinNode;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            startOffset = 0;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startNode = this;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startOffset = offset;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!direction || direction === "forward" || direction === "both") {
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = this;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (node) {
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node === stayWithinNode) {
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!endNode)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    endNode = stayWithinNode;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node.nodeType === Node.TEXT_NODE) {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var start = (node === this ? offset : 0);
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (var i = start; i < node.nodeValue.length; ++i) {
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        endNode = node;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        endOffset = i;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (endNode)
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            node = node.traverseNextNode(stayWithinNode);
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!endNode) {
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            endNode = stayWithinNode;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endNode = this;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endOffset = offset;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var result = this.ownerDocument.createRange();
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.setStart(startNode, startOffset);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.setEnd(endNode, endOffset);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
1285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {!Node=} stayWithin
1295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Node}
1305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.traverseNextTextNode = function(stayWithin)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var node = this.traverseNextNode(stayWithin);
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node)
1355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return null;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (node && node.nodeType !== Node.TEXT_NODE)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = node.traverseNextNode(stayWithin);
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return node;
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
1445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {number} offset
1455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!{container: !Node, offset: number}}
1465d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.rangeBoundaryForOffset = function(offset)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var node = this.traverseNextTextNode(this);
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (node && offset > node.nodeValue.length) {
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        offset -= node.nodeValue.length;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = node.traverseNextTextNode(this);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return { container: this, offset: 0 };
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return { container: node, offset: offset };
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number|undefined} x
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number|undefined} y
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @param {!Element=} relativeTo
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)Element.prototype.positionAt = function(x, y, relativeTo)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    var shift = {x: 0, y: 0};
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (relativeTo)
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)       shift = relativeTo.boxInWindow(this.ownerDocument.defaultView);
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof x === "number")
17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        this.style.setProperty("left", (shift.x + x) + "px");
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.style.removeProperty("left");
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof y === "number")
17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        this.style.setProperty("top", (shift.y + y) + "px");
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.style.removeProperty("top");
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
1825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {boolean}
1835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.isScrolledToBottom = function()
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
186d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // This code works only for 0-width border.
187d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Both clientHeight and scrollHeight are rounded to integer values, so we tolerate
188d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // one pixel error.
189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return Math.abs(this.scrollTop + this.clientHeight - this.scrollHeight) <= 1;
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
193a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {!Node} fromNode
194a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {!Node} toNode
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function removeSubsequentNodes(fromNode, toNode)
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var node = fromNode; node && node !== toNode; ) {
199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var nodeToRemove = node;
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        node = node.nextSibling;
201591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        nodeToRemove.remove();
202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
207aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {!Size} minimum
208aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {?Size=} preferred
209aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch */
210aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochfunction Constraints(minimum, preferred)
211aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
212aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    /**
213aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch     * @type {!Size}
214aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch     */
215aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    this.minimum = minimum;
216aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
217aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    /**
218aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch     * @type {!Size}
219aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch     */
220aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    this.preferred = preferred || minimum;
221aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
222aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (this.minimum.width > this.preferred.width || this.minimum.height > this.preferred.height)
223aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        throw new Error("Minimum size is greater than preferred.");
224aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch}
225aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
226aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch/**
227aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {?Constraints} constraints
228aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @return {boolean}
229aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch */
230aafa69cb17c9d6606c07663ade5f81388a2c5986Ben MurdochConstraints.prototype.isEqual = function(constraints)
231aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
232aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    return !!constraints && this.minimum.isEqual(constraints.minimum) && this.preferred.isEqual(constraints.preferred);
2335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
234aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
235aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch/**
236aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {!Constraints|number} value
237aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @return {!Constraints}
238aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch */
239aafa69cb17c9d6606c07663ade5f81388a2c5986Ben MurdochConstraints.prototype.widthToMax = function(value)
240aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
241aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (typeof value === "number")
242aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        return new Constraints(this.minimum.widthToMax(value), this.preferred.widthToMax(value));
243aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    return new Constraints(this.minimum.widthToMax(value.minimum), this.preferred.widthToMax(value.preferred));
2445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
245aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
246aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch/**
247aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {!Constraints|number} value
248aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @return {!Constraints}
249aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch */
250aafa69cb17c9d6606c07663ade5f81388a2c5986Ben MurdochConstraints.prototype.addWidth = function(value)
251aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
252aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (typeof value === "number")
253aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        return new Constraints(this.minimum.addWidth(value), this.preferred.addWidth(value));
254aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    return new Constraints(this.minimum.addWidth(value.minimum), this.preferred.addWidth(value.preferred));
2555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
256aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
257aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch/**
258aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {!Constraints|number} value
259aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @return {!Constraints}
260aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch */
261aafa69cb17c9d6606c07663ade5f81388a2c5986Ben MurdochConstraints.prototype.heightToMax = function(value)
262aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
263aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (typeof value === "number")
264aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        return new Constraints(this.minimum.heightToMax(value), this.preferred.heightToMax(value));
265aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    return new Constraints(this.minimum.heightToMax(value.minimum), this.preferred.heightToMax(value.preferred));
2665d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
267aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
268aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch/**
269aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @param {!Constraints|number} value
270aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch * @return {!Constraints}
271aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch */
272aafa69cb17c9d6606c07663ade5f81388a2c5986Ben MurdochConstraints.prototype.addHeight = function(value)
273aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
274aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (typeof value === "number")
275aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        return new Constraints(this.minimum.addHeight(value), this.preferred.addHeight(value));
276aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    return new Constraints(this.minimum.addHeight(value.minimum), this.preferred.addHeight(value.preferred));
2775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
278aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
279aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch/**
280a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {?Element=} containerElement
281a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @return {!Size}
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
28353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Element.prototype.measurePreferredSize = function(containerElement)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
28553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    containerElement = containerElement || document.body;
28653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    containerElement.appendChild(this);
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.positionAt(0, 0);
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var result = new Size(this.offsetWidth, this.offsetHeight);
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.positionAt(undefined, undefined);
290591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this.remove();
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
295a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {!Event} event
29651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @return {boolean}
29751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
29851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)Element.prototype.containsEventPoint = function(event)
29951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
30051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var box = this.getBoundingClientRect();
30151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return box.left < event.x  && event.x < box.right &&
30251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)           box.top < event.y && event.y < box.bottom;
30351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
30451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
3055d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
3065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {!Array.<string>} nameArray
3075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Node}
3085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) {
3125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        for (var i = 0; i < nameArray.length; ++i) {
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return node;
3155d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
3165d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return null;
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3205d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
3215d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {string} nodeName
3225d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Node}
3235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
329926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} className
331a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {!Element=} stayWithin
3325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Element}
333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Node.prototype.enclosingNodeOrSelfWithClass = function(className, stayWithin)
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (var node = this; node && node !== stayWithin && node !== this.ownerDocument; node = node.parentNode) {
337a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains(className))
3385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return /** @type {!Element} */ (node);
3395d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return null;
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
3445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {string} query
3455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Node}
3465d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.query = function(query)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.removeChildren = function()
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (this.firstChild)
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.textContent = "";
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
3595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {boolean}
3605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.isInsertionCaretInside = function()
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selection = window.getSelection();
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!selection.rangeCount || !selection.isCollapsed)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selectionRange = selection.getRangeAt(0);
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return selectionRange.startContainer.isSelfOrDescendant(this);
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
37119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * @param {string} elementName
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string=} className
3735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!Element}
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
37519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)Document.prototype.createElementWithClass = function(elementName, className)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
37719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    var element = this.createElement(elementName);
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (className)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        element.className = className;
38019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    return element;
38119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)}
38219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)
38319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)/**
384f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {string} elementName
38519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * @param {string=} className
3865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!Element}
38719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) */
38819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)Element.prototype.createChild = function(elementName, className)
38919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){
39019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    var element = this.ownerDocument.createElementWithClass(elementName, className);
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.appendChild(element);
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return element;
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DocumentFragment.prototype.createChild = Element.prototype.createChild;
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} text
3995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!Text}
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.createTextChild = function(text)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var element = this.ownerDocument.createTextNode(text);
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.appendChild(element);
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return element;
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild;
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
411197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch * @param {...string} var_args
412197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch */
413197021e6b966cfb06891637935ef33fff06433d1Ben MurdochElement.prototype.createTextChildren = function(var_args)
414197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
415197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    for (var i = 0, n = arguments.length; i < n; ++i)
416197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        this.createTextChild(arguments[i]);
417197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
419197021e6b966cfb06891637935ef33fff06433d1Ben MurdochDocumentFragment.prototype.createTextChildren = Element.prototype.createTextChildren;
420197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
421197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch/**
422197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch * @param {...!Element} var_args
423197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch */
424197021e6b966cfb06891637935ef33fff06433d1Ben MurdochElement.prototype.appendChildren = function(var_args)
425197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
426197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    for (var i = 0, n = arguments.length; i < n; ++i)
427197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        this.appendChild(arguments[i]);
428197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
429197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
430197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch/**
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {number}
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.totalOffsetLeft = function()
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.totalOffset().left;
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {number}
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.totalOffsetTop = function()
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.totalOffset().top;
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
4475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!{left: number, top: number}}
4485d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.totalOffset = function()
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
45119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    var rect = this.getBoundingClientRect();
45219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    return { left: rect.left, top: rect.top };
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
4565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!{left: number, top: number}}
4575d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.scrollOffset = function()
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var curLeft = 0;
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var curTop = 0;
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var element = this; element; element = element.scrollParent) {
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        curLeft += element.scrollLeft;
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        curTop += element.scrollTop;
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return { left: curLeft, top: curTop };
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number=} x
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number=} y
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number=} width
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number=} height
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function AnchorBox(x, y, width, height)
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.x = x || 0;
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.y = y || 0;
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.width = width || 0;
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.height = height || 0;
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
48509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @param {!AnchorBox} box
48609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @return {!AnchorBox}
48709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) */
48809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)AnchorBox.prototype.relativeTo = function(box)
48909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
49009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return new AnchorBox(
49109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        this.x - box.x, this.y - box.y, this.width, this.height);
4925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
49309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
49409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/**
49509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @param {!Element} element
49609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @return {!AnchorBox}
49709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) */
49809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)AnchorBox.prototype.relativeToElement = function(element)
49909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
50009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView));
5015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
50209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
50309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/**
504f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu * @param {?AnchorBox} anchorBox
505f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu * @return {boolean}
506f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu */
507f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuAnchorBox.prototype.equals = function(anchorBox)
508f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
509f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && this.width === anchorBox.width && this.height === anchorBox.height;
5105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
511f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
512f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu/**
513a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {!Window} targetWindow
514a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @return {!AnchorBox}
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.offsetRelativeToWindow = function(targetWindow)
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var elementOffset = new AnchorBox();
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var curElement = this;
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var curWindow = this.ownerDocument.defaultView;
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (curWindow && curElement) {
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        elementOffset.x += curElement.totalOffsetLeft();
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        elementOffset.y += curElement.totalOffsetTop();
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (curWindow === targetWindow)
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        curElement = curWindow.frameElement;
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        curWindow = curWindow.parent;
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return elementOffset;
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {!Window=} targetWindow
536a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @return {!AnchorBox}
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.boxInWindow = function(targetWindow)
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    targetWindow = targetWindow || this.ownerDocument.defaultView;
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var anchorBox = this.offsetRelativeToWindow(window);
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    anchorBox.width = Math.min(this.offsetWidth, window.innerWidth - anchorBox.x);
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    anchorBox.height = Math.min(this.offsetHeight, window.innerHeight - anchorBox.y);
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return anchorBox;
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} text
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.setTextAndTitle = function(text)
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.textContent = text;
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.title = text;
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)KeyboardEvent.prototype.__defineGetter__("data", function()
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Emulate "data" attribute from DOM 3 TextInput event.
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (this.type) {
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case "keypress":
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!this.ctrlKey && !this.metaKey)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return String.fromCharCode(this.charCode);
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return "";
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case "keydown":
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case "keyup":
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!this.ctrlKey && !this.metaKey && !this.altKey)
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return String.fromCharCode(this.which);
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return "";
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)});
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {boolean=} preventDefault
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Event.prototype.consume = function(preventDefault)
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.stopImmediatePropagation();
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (preventDefault)
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.preventDefault();
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.handled = true;
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
5895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {number=} start
5905d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {number=} end
5915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {!Text}
5925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Text.prototype.select = function(start, end)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    start = start || 0;
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    end = end || this.textContent.length;
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start < 0)
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        start = end + start;
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selection = this.ownerDocument.defaultView.getSelection();
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selection.removeAllRanges();
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var range = this.ownerDocument.createRange();
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    range.setStart(this, start);
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    range.setEnd(this, end);
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selection.addRange(range);
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this;
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
6115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?number}
6125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element.prototype.selectionLeftOffset = function()
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Calculate selection offset relative to the current element.
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selection = window.getSelection();
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!selection.containsNode(this, true))
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var leftOffset = selection.anchorOffset;
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var node = selection.anchorNode;
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (node !== this) {
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (node.previousSibling) {
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            node = node.previousSibling;
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            leftOffset += node.textContent.length;
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = node.parentNode;
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return leftOffset;
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
6365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {?Node} node
6375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {boolean}
6385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.isAncestor = function(node)
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node)
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var currentNode = node.parentNode;
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (currentNode) {
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this === currentNode)
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentNode = currentNode.parentNode;
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
6545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {?Node} descendant
6555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {boolean}
6565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.isDescendant = function(descendant)
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !!descendant && descendant.isAncestor(this);
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
6635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {?Node} node
6645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {boolean}
6655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.isSelfOrAncestor = function(node)
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !!node && (node === this || this.isAncestor(node));
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
6725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {?Node} node
6735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {boolean}
6745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.isSelfOrDescendant = function(node)
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !!node && (node === this || this.isDescendant(node));
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
6815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {!Node=} stayWithin
6825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Node}
6835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.traverseNextNode = function(stayWithin)
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var node = this.firstChild;
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (node)
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return node;
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (stayWithin && this === stayWithin)
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    node = this.nextSibling;
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (node)
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return node;
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    node = this;
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin))
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = node.parentNode;
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node)
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return node.nextSibling;
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
7075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @param {!Node=} stayWithin
7085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @return {?Node}
7095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node.prototype.traversePreviousNode = function(stayWithin)
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (stayWithin && this === stayWithin)
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var node = this.previousSibling;
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (node && node.lastChild)
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = node.lastChild;
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (node)
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return node;
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.parentNode;
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
72209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/**
723d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * @param {*} text
724d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * @param {string=} placeholder
725d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * @return {boolean} true if was truncated
726d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) */
727d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)Node.prototype.setTextContentTruncatedIfNeeded = function(text, placeholder)
728d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
729d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Huge texts in the UI reduce rendering performance drastically.
730d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Moreover, Blink/WebKit uses <unsigned short> internally for storing text content
731d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // length, so texts longer than 65535 are inherently displayed incorrectly.
732d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const maxTextContentLength = 65535;
733d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
734d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (typeof text === "string" && text.length > maxTextContentLength) {
735d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        this.textContent = typeof placeholder === "string" ? placeholder : text.trimEnd(maxTextContentLength);
736d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return true;
737d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
738d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
739d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    this.textContent = text;
740d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return false;
741d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
742d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
743d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)/**
74409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @return {boolean}
74509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) */
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function isEnterKey(event) {
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check if in IME.
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return event.keyCode !== 229 && event.keyIdentifier === "Enter";
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function consumeEvent(e)
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    e.consume();
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
755