Home | History | Annotate | Download | only in pagepopups
      1 "use strict";
      2 /*
      3  * Copyright (C) 2012 Google Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 /**
     27  * @param {!string} id
     28  */
     29 function $(id) {
     30     return document.getElementById(id);
     31 }
     32 
     33 /**
     34  * @param {!string} tagName
     35  * @param {string=} opt_class
     36  * @param {string=} opt_text
     37  * @return {!Element}
     38  */
     39 function createElement(tagName, opt_class, opt_text) {
     40     var element = document.createElement(tagName);
     41     if (opt_class)
     42         element.setAttribute("class", opt_class);
     43     if (opt_text)
     44         element.appendChild(document.createTextNode(opt_text));
     45     return element;
     46 }
     47 
     48 /**
     49  * @constructor
     50  * @param {!number|Rectangle|Object} xOrRect
     51  * @param {!number} y
     52  * @param {!number} width
     53  * @param {!number} height
     54  */
     55 function Rectangle(xOrRect, y, width, height) {
     56     if (typeof xOrRect === "object") {
     57         y = xOrRect.y;
     58         width = xOrRect.width;
     59         height = xOrRect.height;
     60         xOrRect = xOrRect.x;
     61     }
     62     this.x = xOrRect;
     63     this.y = y;
     64     this.width = width;
     65     this.height = height;
     66 }
     67 
     68 Rectangle.prototype = {
     69     get maxX() { return this.x + this.width; },
     70     get maxY() { return this.y + this.height; },
     71     toString: function() { return "Rectangle(" + this.x + "," + this.y + "," + this.width + "," + this.height + ")"; }
     72 };
     73 
     74 /**
     75  * @param {!Rectangle} rect1
     76  * @param {!Rectangle} rect2
     77  * @return {?Rectangle}
     78  */
     79 Rectangle.intersection = function(rect1, rect2) {
     80     var x = Math.max(rect1.x, rect2.x);
     81     var maxX = Math.min(rect1.maxX, rect2.maxX);
     82     var y = Math.max(rect1.y, rect2.y);
     83     var maxY = Math.min(rect1.maxY, rect2.maxY);
     84     var width = maxX - x;
     85     var height = maxY - y;
     86     if (width < 0 || height < 0)
     87         return null;
     88     return new Rectangle(x, y, width, height);
     89 };
     90 
     91 /**
     92  * @param {!number} width
     93  * @param {!number} height
     94  */
     95 function resizeWindow(width, height) {
     96     setWindowRect(adjustWindowRect(width, height, width, height));
     97 }
     98 
     99 /**
    100  * @param {!number} width
    101  * @param {!number} height
    102  * @param {?number} minWidth
    103  * @param {?number} minHeight
    104  * @return {!Rectangle}
    105  */
    106 function adjustWindowRect(width, height, minWidth, minHeight) {
    107     if (typeof minWidth !== "number")
    108         minWidth = 0;
    109     if (typeof minHeight !== "number")
    110         minHeight = 0;
    111 
    112     var windowRect = new Rectangle(0, 0, width, height);
    113 
    114     if (!global.params.anchorRectInScreen)
    115         return windowRect;
    116 
    117     var anchorRect = new Rectangle(global.params.anchorRectInScreen);
    118     var availRect = new Rectangle(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
    119 
    120     _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight);
    121     _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth);
    122 
    123     return windowRect;
    124 }
    125 
    126 function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight) {
    127     var availableSpaceAbove = anchorRect.y - availRect.y;
    128     availableSpaceAbove = Math.max(0, Math.min(availRect.height, availableSpaceAbove));
    129 
    130     var availableSpaceBelow = availRect.maxY - anchorRect.maxY;
    131     availableSpaceBelow = Math.max(0, Math.min(availRect.height, availableSpaceBelow));
    132 
    133     if (windowRect.height > availableSpaceBelow && availableSpaceBelow < availableSpaceAbove) {
    134         windowRect.height = Math.min(windowRect.height, availableSpaceAbove);
    135         windowRect.height = Math.max(windowRect.height, minHeight);
    136         windowRect.y = anchorRect.y - windowRect.height;
    137     } else {
    138         windowRect.height = Math.min(windowRect.height, availableSpaceBelow);
    139         windowRect.height = Math.max(windowRect.height, minHeight);
    140         windowRect.y = anchorRect.maxY;
    141     }
    142     windowRect.y = Math.min(windowRect.y, availRect.maxY - windowRect.height);
    143     windowRect.y = Math.max(windowRect.y, availRect.y);
    144 }
    145 
    146 function _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth) {
    147     windowRect.width = Math.min(windowRect.width, availRect.width);
    148     windowRect.width = Math.max(windowRect.width, minWidth);
    149     windowRect.x = anchorRect.x;
    150     if (global.params.isRTL)
    151         windowRect.x += anchorRect.width - windowRect.width;
    152     windowRect.x = Math.min(windowRect.x, availRect.maxX - windowRect.width);
    153     windowRect.x = Math.max(windowRect.x, availRect.x);
    154 }
    155 
    156 /**
    157  * @param {!Rectangle} rect
    158  */
    159 function setWindowRect(rect) {
    160     if (window.frameElement) {
    161         window.frameElement.style.width = rect.width + "px";
    162         window.frameElement.style.height = rect.height + "px";
    163     } else {
    164         if (isWindowHidden()) {
    165             window.moveTo(rect.x - window.screen.availLeft, rect.y - window.screen.availTop);
    166             window.resizeTo(rect.width, rect.height);
    167         } else {
    168             window.resizeTo(rect.width, rect.height);
    169             window.moveTo(rect.x - window.screen.availLeft, rect.y - window.screen.availTop);
    170         }
    171     }
    172 }
    173 
    174 function hideWindow() {
    175     resizeWindow(1, 1);
    176 }
    177 
    178 /**
    179  * @return {!boolean}
    180  */
    181 function isWindowHidden() {
    182     return window.innerWidth === 1 && window.innerHeight === 1;
    183 }
    184 
    185 window.addEventListener("resize", function() {
    186     if (isWindowHidden())
    187         window.dispatchEvent(new CustomEvent("didHide"));
    188     else
    189         window.dispatchEvent(new CustomEvent("didOpenPicker"));
    190 }, false);
    191 
    192 /**
    193  * @return {!number}
    194  */
    195 function getScrollbarWidth() {
    196     if (typeof window.scrollbarWidth === "undefined") {
    197         var scrollDiv = document.createElement("div");
    198         scrollDiv.style.opacity = "0";
    199         scrollDiv.style.overflow = "scroll";
    200         scrollDiv.style.width = "50px";
    201         scrollDiv.style.height = "50px";
    202         document.body.appendChild(scrollDiv);
    203         window.scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
    204         scrollDiv.parentNode.removeChild(scrollDiv);
    205     }
    206     return window.scrollbarWidth;
    207 }
    208 
    209 /**
    210  * @param {!string} className
    211  * @return {?Element}
    212  */
    213 function enclosingNodeOrSelfWithClass(selfNode, className)
    214 {
    215     for (var node = selfNode; node && node !== selfNode.ownerDocument; node = node.parentNode) {
    216         if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains(className))
    217             return node;
    218     }
    219     return null;
    220 };
    221 
    222 /**
    223  * @constructor
    224  * @param {!Element} element
    225  * @param {!Object} config
    226  */
    227 function Picker(element, config) {
    228     this._element = element;
    229     this._config = config;
    230 }
    231 
    232 /**
    233  * @enum {number}
    234  */
    235 Picker.Actions = {
    236     SetValue: 0,
    237     Cancel: -1,
    238     ChooseOtherColor: -2
    239 };
    240 
    241 /**
    242  * @param {!string} value
    243  */
    244 Picker.prototype.submitValue = function(value) {
    245     window.pagePopupController.setValue(value);
    246     window.pagePopupController.closePopup();
    247 }
    248 
    249 Picker.prototype.handleCancel = function() {
    250     window.pagePopupController.closePopup();
    251 }
    252 
    253 Picker.prototype.chooseOtherColor = function() {
    254     window.pagePopupController.setValueAndClosePopup(Picker.Actions.ChooseOtherColor, "");
    255 }
    256 
    257 Picker.prototype.cleanup = function() {};
    258