15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview LIS Standalone hack 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file contains the code necessary to make the Touch LIS work 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as a stand-alone application (as opposed to being embedded into chrome). 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is useful for rapid development and testing, but does not actually form 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * part of the product. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this file never gets concatenated and embeded into Chrome, so we 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can enable strict mode for the whole file just like normal. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'use strict'; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For non-Chrome browsers, create a dummy chrome object 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if (!window.chrome) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var chrome = {}; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A replacement chrome.send method that supplies static data for the 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * key APIs used by the LIS. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that the real chrome object also supplies data for most-viewed and 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * recently-closed pages, but the tangent LIS doesn't use that data so we 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * don't bother simulating it here. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We create this object by applying an anonymous function so that we can have 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * local variables (avoid polluting the global object) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)chrome.send = (function() { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var users = [ 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Alan Beaker', 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) emailAddress: 'beaker@chromium.org', 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) imageUrl: '../../app/theme/avatar_beaker.png', 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canRemove: false 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Alex Briefcase', 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) emailAddress: 'briefcase@chromium.org', 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) imageUrl: '../../app/theme/avatar_briefcase.png', 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canRemove: true 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Alex Circles', 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) emailAddress: 'circles@chromium.org', 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) imageUrl: '../../app/theme/avatar_circles.png', 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canRemove: true 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Guest', 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) emailAddress: '', 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) imageUrl: '', 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canRemove: false 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Invoke the getAppsCallback function with a snapshot of the current app 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * database. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function sendGetUsersCallback() 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to hand out our array directly because the NTP will 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // assume it owns the array and is free to modify it. For now we make a 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one-level deep copy of the array (since cloning the whole thing is 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more work and unnecessary at the moment). 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getUsersCallback(users.slice(0)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Like Array.prototype.indexOf but calls a predicate to test for match 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array} array The array to search. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function(Object): boolean} predicate The function to invoke on 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * each element. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} First index at which predicate returned true, or -1. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function indexOfPred(array, predicate) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < array.length; i++) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (predicate(array[i])) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Get index into apps of an application object 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Requires the specified app to be present 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} id The ID of the application to locate. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index in apps for an object with the specified ID. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getUserIndex(name) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var i = indexOfPred(apps, function(e) { return e.name === name;}); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == -1) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alert('Error: got unexpected App ID'); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Get an user object given the user name 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Requires 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name The user name to search for. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Object} The corresponding user object. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getUser(name) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return users[getUserIndex(name)]; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Simlulate the login of a user 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} email_address the email address of the user logging in. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} password the password of the user logging in. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function login(email_address, password) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.log('password', password); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (password == 'correct') { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The chrome server communication entrypoint. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} command Name of the command to send. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array} args Array of command-specific arguments. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function(command, args) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome API is async 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(function() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called to populate the list of applications 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'GetUsers': 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sendGetUsersCallback(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called when a user is removed. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'RemoveUser': 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called when a user attempts to login. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'Login': 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login(args[0], args[1]); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called when an app is moved to a different page 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'MoveUser': 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'SetGuestPosition': 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new Error('Unexpected chrome command: ' + command); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 0); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})(); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * On iOS we need a hack to avoid spurious click events 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In particular, if the user delays briefly between first touching and starting 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to drag, when the user releases a click event will be generated. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that this seems to happen regardless of whether we do preventDefault on 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * touchmove events. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if (/iPhone|iPod|iPad/.test(navigator.userAgent) && 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(/Chrome/.test(navigator.userAgent))) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have a real iOS device (no a ChromeOS device pretending to be iOS) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (function() { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True if a gesture is occuring that should cause clicks to be swallowed 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var gestureActive = false; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The position a touch was last started 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastTouchStartPosition; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Distance which a touch needs to move to be considered a drag 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var DRAG_DISTANCE = 3; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.addEventListener('touchstart', function(event) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastTouchStartPosition = { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x: event.touches[0].clientX, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y: event.touches[0].clientY 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A touchstart ALWAYS preceeds a click (valid or not), so cancel any 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // outstanding gesture. Also, any multi-touch is a gesture that should 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prevent clicks. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gestureActive = event.touches.length > 1; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, true); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.addEventListener('touchmove', function(event) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we see a move, measure the distance from the last touchStart 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a multi-touch then the work here is irrelevant 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (gestureActive is already true) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var t = event.touches[0]; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Math.abs(t.clientX - lastTouchStartPosition.x) > DRAG_DISTANCE || 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Math.abs(t.clientY - lastTouchStartPosition.y) > DRAG_DISTANCE) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gestureActive = true; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, true); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.addEventListener('click', function(event) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we got here without gestureActive being set then it means we had 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a touchStart without any real dragging before touchEnd - we can allow 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the click to proceed. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gestureActive) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.preventDefault(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.stopPropagation(); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, true); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) })(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Hack to add Element.classList to older browsers that don't yet support it. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) From https://developer.mozilla.org/en/DOM/element.classList. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if (typeof Element !== 'undefined' && 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !Element.prototype.hasOwnProperty('classList')) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (function() { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var classListProp = 'classList', 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protoProp = 'prototype', 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elemCtrProto = Element[protoProp], 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objCtr = Object, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strTrim = String[protoProp].trim || function() { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.replace(/^\s+|\s+$/g, ''); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrIndexOf = Array[protoProp].indexOf || function(item) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0, len = this.length; i < len; i++) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i in this && this[i] === item) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vendors: please allow content code to instantiate DOMExceptions 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @constructor */ 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOMEx = function(type, message) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.name = type; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.code = DOMException[type]; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.message = message; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkTokenAndGetIndex = function(classList, token) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (token === '') { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new DOMEx( 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'SYNTAX_ERR', 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'An invalid or illegal string was specified' 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (/\s/.test(token)) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new DOMEx( 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'INVALID_CHARACTER_ERR', 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'String contains an invalid character' 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return arrIndexOf.call(classList, token); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @constructor 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @extends {Array} */ 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClassList = function(elem) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var trimmedClasses = strTrim.call(elem.className), 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0, len = classes.length; i < len; i++) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.push(classes[i]); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._updateClassName = function() { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elem.className = this.toString(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto = ClassList[protoProp] = [], 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListGetter = function() { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ClassList(this); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Most DOMException implementations don't allow calling DOMException's 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // toString() on non-DOMExceptions. Error's toString() is sufficient here. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOMEx[protoProp] = Error[protoProp]; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto.item = function(i) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this[i] || null; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto.contains = function(token) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token += ''; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return checkTokenAndGetIndex(this, token) !== -1; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto.add = function(token) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token += ''; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checkTokenAndGetIndex(this, token) === -1) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.push(token); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._updateClassName(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto.remove = function(token) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token += ''; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = checkTokenAndGetIndex(this, token); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index !== -1) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.splice(index, 1); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._updateClassName(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto.toggle = function(token) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token += ''; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checkTokenAndGetIndex(this, token) === -1) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.add(token); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.remove(token); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classListProto.toString = function() { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.join(' '); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (objCtr.defineProperty) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var classListDescriptor = { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get: classListGetter, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enumerable: true, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) configurable: true 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objCtr.defineProperty(elemCtrProto, classListProp, classListDescriptor); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (objCtr[protoProp].__defineGetter__) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elemCtrProto.__defineGetter__(classListProp, classListGetter); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }()); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Hack to add Function.bind to older browsers that don't yet support it. From: 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if (!Function.prototype.bind) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object} selfObj Specifies the object which |this| should 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * point to when the function is run. If the value is null or undefined, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it will default to the global object. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {...*} var_args Additional arguments that are partially 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * applied to the function. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!Function} A partially-applied form of the function bind() was 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * invoked as a method of. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @suppress {duplicate} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Function.prototype.bind = function(selfObj, var_args) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var slice = [].slice, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args = slice.call(arguments, 1), 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self = this, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @constructor */ 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nop = function() {}, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound = function() { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.apply(this instanceof nop ? this : (selfObj || {}), 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.concat(slice.call(arguments))); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nop.prototype = self.prototype; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound.prototype = new nop(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bound; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 364