util.js revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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/*
112 * Handles a click or mouseup on a link. If the link points to a chrome: or
113 * file: url, then call into the browser to do the navigation.
114 * @return {Object} e The click or mouseup event.
115 */
116function handleLinkClickOrMouseUp(e) {
117  // Allow preventDefault to work.
118  if (!e.returnValue)
119    return;
120
121  var el = e.target;
122  if (el.nodeType == Node.ELEMENT_NODE &&
123      el.webkitMatchesSelector('A, A *')) {
124    while (el.tagName != 'A') {
125      el = el.parentElement;
126    }
127
128    if ((el.protocol == 'file:' || el.protocol == 'about:') &&
129        ((e.button == 0 && e.type == 'click') ||
130        (e.button == 1 && e.type == 'mouseup'))) {
131      chrome.send('navigateToUrl',
132          [el.href, e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]);
133      e.preventDefault();
134    }
135  }
136}
137
138document.addEventListener('click', handleLinkClickOrMouseUp);
139document.addEventListener('mouseup', handleLinkClickOrMouseUp);
140