1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** 6 * The global object. 7 * @type {!Object} 8 */ 9const global = this; 10 11// TODO(estade): This should be removed and calls replaced with cr.isMac 12const IS_MAC = /^Mac/.test(navigator.platform); 13 14/** 15 * Alias for document.getElementById. 16 * @param {string} id The ID of the element to find. 17 * @return {HTMLElement} The found element or null if not found. 18 */ 19function $(id) { 20 return document.getElementById(id); 21} 22 23/** 24 * Calls chrome.send with a callback and restores the original afterwards. 25 * @param {string} name The name of the message to send. 26 * @param {!Array} params The parameters to send. 27 * @param {string} callbackName The name of the function that the backend calls. 28 * @param {!Function} The function to call. 29 */ 30function chromeSend(name, params, callbackName, callback) { 31 var old = global[callbackName]; 32 global[callbackName] = function() { 33 // restore 34 global[callbackName] = old; 35 36 var args = Array.prototype.slice.call(arguments); 37 return callback.apply(global, args); 38 }; 39 chrome.send(name, params); 40} 41 42/** 43 * Generates a CSS url string. 44 * @param {string} s The URL to generate the CSS url for. 45 * @return {string} The CSS url string. 46 */ 47function url(s) { 48 // http://www.w3.org/TR/css3-values/#uris 49 // Parentheses, commas, whitespace characters, single quotes (') and double 50 // quotes (") appearing in a URI must be escaped with a backslash 51 var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1'); 52 // WebKit has a bug when it comes to URLs that end with \ 53 // https://bugs.webkit.org/show_bug.cgi?id=28885 54 if (/\\\\$/.test(s2)) { 55 // Add a space to work around the WebKit bug. 56 s2 += ' '; 57 } 58 return 'url("' + s2 + '")'; 59} 60 61/** 62 * Parses query parameters from Location. 63 * @param {string} s The URL to generate the CSS url for. 64 * @return {object} Dictionary containing name value pairs for URL 65 */ 66function parseQueryParams(location) { 67 var params = {}; 68 var query = unescape(location.search.substring(1)); 69 var vars = query.split("&"); 70 for (var i=0; i < vars.length; i++) { 71 var pair = vars[i].split("="); 72 params[pair[0]] = pair[1]; 73 } 74 return params; 75} 76 77function findAncestorByClass(el, className) { 78 return findAncestor(el, function(el) { 79 if (el.classList) 80 return el.classList.contains(className); 81 return null; 82 }); 83} 84 85/** 86 * Return the first ancestor for which the {@code predicate} returns true. 87 * @param {Node} node The node to check. 88 * @param {function(Node) : boolean} predicate The function that tests the 89 * nodes. 90 * @return {Node} The found ancestor or null if not found. 91 */ 92function findAncestor(node, predicate) { 93 var last = false; 94 while (node != null && !(last = predicate(node))) { 95 node = node.parentNode; 96 } 97 return last ? node : null; 98} 99 100function swapDomNodes(a, b) { 101 var afterA = a.nextSibling; 102 if (afterA == b) { 103 swapDomNodes(b, a); 104 return; 105 } 106 var aParent = a.parentNode; 107 b.parentNode.replaceChild(a, b); 108 aParent.insertBefore(b, afterA); 109} 110 111// Handle click on a link. If the link points to a chrome: or file: url, then 112// call into the browser to do the navigation. 113document.addEventListener('click', function(e) { 114 // Allow preventDefault to work. 115 if (!e.returnValue) 116 return; 117 118 var el = e.target; 119 if (el.nodeType == Node.ELEMENT_NODE && 120 el.webkitMatchesSelector('A, A *')) { 121 while (el.tagName != 'A') { 122 el = el.parentElement; 123 } 124 125 if ((el.protocol == 'file:' || el.protocol == 'about:') && 126 (e.button == 0 || e.button == 1)) { 127 chrome.send('navigateToUrl', [ 128 el.href, 129 el.target, 130 e.button, 131 e.altKey, 132 e.ctrlKey, 133 e.metaKey, 134 e.shiftKey 135 ]); 136 e.preventDefault(); 137 } 138 } 139}); 140