blob: 191fc556fec09f9f4109db2a03830f2d988de980 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
function arrayContains(array,value)
{
for (var i = 0; i < array.length; i++) {
if (array[i] == value)
return true;
}
return false;
}
// Note: you can use slice() to copy a real javascript array, but this function can be used to copy
// DOM NodeLists (e.g. as returned by document.getElementsByTagName) as well, since they don't
// support the slice method
function arrayCopy(array)
{
if (array == null)
return null;
var copy = new Array();
for (var i = 0; i < array.length; i++)
copy.push(array[i]);
return copy;
}
function quoteString(str)
{
if (str == null)
return null;
if (str.indexOf('"') < 0)
return str;
var quoted = "";
for (var i = 0; i < str.length; i++) {
if (str.charAt(i) == '"')
quoted += "\\\"";
else
quoted += str.charAt(i);
}
return quoted;
}
function nodeString(node)
{
if (node == null)
return "null";
var id = "";
if (window.debugIds)
id = node._nodeId+":";
if (node.nodeType == Node.TEXT_NODE) {
return id+JSON.stringify(node.nodeValue);
}
else if (node.nodeType == Node.ELEMENT_NODE) {
var name = (node.namespaceURI == null) ? node.nodeName.toUpperCase() : node.nodeName;
if (node.hasAttribute("id"))
return id+name+"#"+node.getAttribute("id");
else
return id+name;
}
else {
return id+node.toString();
}
}
function rectString(rect)
{
if (rect == null)
return null;
else
return "("+rect.left+","+rect.top+") - ("+rect.right+","+rect.bottom+")";
}
function rectIsEmpty(rect)
{
return ((rect == null) ||
((rect.width == 0) && (rect.height == 0)));
}
function rectContainsPoint(rect,x,y)
{
return ((x >= rect.left) && (x < rect.right) &&
(y >= rect.top) && (y < rect.bottom));
}
function clone(object)
{
var result = new Object();
for (var name in object)
result[name] = object[name];
return result;
}
function nodeHasContent(node)
{
switch (node._type) {
case HTML_TEXT:
return !isWhitespaceString(node.nodeValue);
case HTML_IMG:
case HTML_TABLE:
return true;
default:
if (isOpaqueNode(node))
return true;
for (var child = node.firstChild; child != null; child = child.nextSibling) {
if (nodeHasContent(child))
return true;
}
return false;
}
}
function isWhitespaceString(str)
{
return (str.match(isWhitespaceString.regexp) != null);
}
isWhitespaceString.regexp = /^\s*$/;
function normalizeWhitespace(str)
{
str = str.replace(/^\s+/,"");
str = str.replace(/\s+$/,"");
str = str.replace(/\s+/g," ");
return str;
}
function DoublyLinkedList()
{
this.first = null;
this.last = null;
}
DoublyLinkedList.prototype.insertAfter = function(item,after)
{
item.prev = null;
item.next = null;
if (this.first == null) { // empty list
this.first = item;
this.last = item;
}
else if (after == null) { // insert at start
item.next = this.first;
this.first = item;
}
else {
item.next = after.next;
item.prev = after;
if (this.last == after)
this.last = item;
}
if (item.next != null)
item.next.prev = item;
if (item.prev != null)
item.prev.next = item;
};
DoublyLinkedList.prototype.remove = function(item)
{
if (this.first == item)
this.first = this.first.next;
if (this.last == item)
this.last = this.last.prev;
if (item.prev != null)
item.prev.next = item.next;
if (item.next != null)
item.next.prev = item.prev;
item.prev = null;
item.next = null;
};
function diff(src,dest)
{
var traces = new Array();
traces[1] = new DiffEntry(0,0,0,0,null);
for (var distance = 0; true; distance++) {
for (var k = -distance; k <= distance; k += 2) {
var srcEnd;
var prev;
var del = traces[k-1];
var ins = traces[k+1];
if (((k == -distance) && ins) ||
((k != distance) && ins && del && (del.srcEnd < ins.srcEnd))) {
// Down - insertion
prev = ins;
srcEnd = prev.srcEnd;
}
else if (del) {
// Right - deletion
prev = del;
srcEnd = prev.srcEnd+1;
}
else {
traces[k] = null;
continue;
}
destEnd = srcEnd - k;
var srcStart = srcEnd;
var destStart = destEnd;
while ((srcEnd < src.length) && (destEnd < dest.length) &&
(src[srcEnd] == dest[destEnd])) {
srcEnd++;
destEnd++;
}
if ((srcEnd > src.length) || (destEnd > dest.length))
traces[k] = null;
else
traces[k] = new DiffEntry(srcStart,destStart,srcEnd,destEnd,prev);
if ((srcEnd >= src.length) && (destEnd >= dest.length)) {
return entryToArray(src,dest,traces[k]);
}
}
}
function DiffEntry(srcStart,destStart,srcEnd,destEnd,prev)
{
this.srcStart = srcStart;
this.destStart = destStart;
this.srcEnd = srcEnd;
this.destEnd = destEnd;
this.prev = prev;
}
function entryToArray(src,dest,entry)
{
var results = new Array();
results.push(entry);
for (entry = entry.prev; entry != null; entry = entry.prev) {
if ((entry.srcStart != entry.srcEnd) || (entry.destStart != entry.destEnd))
results.push(entry);
}
return results.reverse();
}
}
function TimingEntry(name,time)
{
this.name = name;
this.time = time;
}
function TimingInfo()
{
this.entries = new Array();
this.total = 0;
this.lastTime = null;
}
TimingInfo.prototype.start = function()
{
this.entries.length = 0;
this.lastTime = new Date();
};
TimingInfo.prototype.addEntry = function(name)
{
if (this.lastTime == null)
this.start();
var now = new Date();
var interval = now - this.lastTime;
this.entries.push(new TimingEntry(name,interval));
this.total += interval;
this.lastTime = now;
};
TimingInfo.prototype.print = function(title)
{
debug(title);
for (var i = 0; i < this.entries.length; i++) {
var entry = this.entries[i];
debug(" "+entry.name+": "+entry.time+"ms");
}
};
function readFileApp(filename)
{
var req = new XMLHttpRequest("file:///read/"+filename);
req.open("POST","/read/"+encodeURI(filename),false);
req.send();
if (req.status == 404)
return null; // file not found
else if ((req.status != 200) && (req.status != 0))
throw new Error(req.status+": "+req.responseText);
var doc = req.responseXML;
if (doc != null)
DOM_assignNodeIds(doc);
return doc;
}
function readFileTest(filename)
{
var req = new XMLHttpRequest();
req.open("GET",filename,false);
req.send();
var xml = req.responseXML;
if (xml == null)
return null;
DOM_assignNodeIds(xml.documentElement);
return xml;
}
function fromTokenList(value)
{
var result = new Object();
if (value != null) {
var components = value.toLowerCase().split(/\s+/);
for (var i = 0; i < components.length; i++) {
if (components[i].length > 0)
result[components[i]] = true;
}
}
return result;
}
function toTokenList(properties)
{
var tokens = new Array();
if (properties != null) {
// Sort the names to ensure deterministic results in test cases
var names = Object.getOwnPropertyNames(properties).sort();
for (var i = 0; i < names.length; i++) {
var name = names[i];
if (properties[name])
tokens.push(name);
}
}
if (tokens.length == null)
return null;
else
return tokens.join(" ");
}
function xywhAbsElementRect(element)
{
var rect = element.getBoundingClientRect();
return { x: rect.left + window.scrollX,
y: rect.top + window.scrollY,
width: rect.width,
height: rect.height };
}