| "use strict"; |
| /* |
| * Copyright (C) 2012 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @param {!string} id |
| */ |
| function $(id) { |
| return document.getElementById(id); |
| } |
| |
| /** |
| * @param {!string} tagName |
| * @param {string=} opt_class |
| * @param {string=} opt_text |
| * @return {!Element} |
| */ |
| function createElement(tagName, opt_class, opt_text) { |
| var element = document.createElement(tagName); |
| if (opt_class) |
| element.setAttribute("class", opt_class); |
| if (opt_text) |
| element.appendChild(document.createTextNode(opt_text)); |
| return element; |
| } |
| |
| /** |
| * @constructor |
| * @param {!number|Rectangle|Object} xOrRect |
| * @param {!number} y |
| * @param {!number} width |
| * @param {!number} height |
| */ |
| function Rectangle(xOrRect, y, width, height) { |
| if (typeof xOrRect === "object") { |
| y = xOrRect.y; |
| width = xOrRect.width; |
| height = xOrRect.height; |
| xOrRect = xOrRect.x; |
| } |
| this.x = xOrRect; |
| this.y = y; |
| this.width = width; |
| this.height = height; |
| } |
| |
| Rectangle.prototype = { |
| get maxX() { return this.x + this.width; }, |
| get maxY() { return this.y + this.height; }, |
| toString: function() { return "Rectangle(" + this.x + "," + this.y + "," + this.width + "," + this.height + ")"; } |
| }; |
| |
| /** |
| * @param {!Rectangle} rect1 |
| * @param {!Rectangle} rect2 |
| * @return {?Rectangle} |
| */ |
| Rectangle.intersection = function(rect1, rect2) { |
| var x = Math.max(rect1.x, rect2.x); |
| var maxX = Math.min(rect1.maxX, rect2.maxX); |
| var y = Math.max(rect1.y, rect2.y); |
| var maxY = Math.min(rect1.maxY, rect2.maxY); |
| var width = maxX - x; |
| var height = maxY - y; |
| if (width < 0 || height < 0) |
| return null; |
| return new Rectangle(x, y, width, height); |
| }; |
| |
| /** |
| * @param {!number} width |
| * @param {!number} height |
| */ |
| function resizeWindow(width, height) { |
| setWindowRect(adjustWindowRect(width, height, width, height)); |
| } |
| |
| /** |
| * @param {!number} width |
| * @param {!number} height |
| * @param {?number} minWidth |
| * @param {?number} minHeight |
| * @return {!Rectangle} |
| */ |
| function adjustWindowRect(width, height, minWidth, minHeight) { |
| if (typeof minWidth !== "number") |
| minWidth = 0; |
| if (typeof minHeight !== "number") |
| minHeight = 0; |
| |
| var windowRect = new Rectangle(0, 0, width, height); |
| |
| if (!global.params.anchorRectInScreen) |
| return windowRect; |
| |
| var anchorRect = new Rectangle(global.params.anchorRectInScreen); |
| var availRect = new Rectangle(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight); |
| |
| _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight); |
| _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth); |
| |
| return windowRect; |
| } |
| |
| function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight) { |
| var availableSpaceAbove = anchorRect.y - availRect.y; |
| availableSpaceAbove = Math.max(0, Math.min(availRect.height, availableSpaceAbove)); |
| |
| var availableSpaceBelow = availRect.maxY - anchorRect.maxY; |
| availableSpaceBelow = Math.max(0, Math.min(availRect.height, availableSpaceBelow)); |
| |
| if (windowRect.height > availableSpaceBelow && availableSpaceBelow < availableSpaceAbove) { |
| windowRect.height = Math.min(windowRect.height, availableSpaceAbove); |
| windowRect.height = Math.max(windowRect.height, minHeight); |
| windowRect.y = anchorRect.y - windowRect.height; |
| } else { |
| windowRect.height = Math.min(windowRect.height, availableSpaceBelow); |
| windowRect.height = Math.max(windowRect.height, minHeight); |
| windowRect.y = anchorRect.maxY; |
| } |
| windowRect.y = Math.min(windowRect.y, availRect.maxY - windowRect.height); |
| windowRect.y = Math.max(windowRect.y, availRect.y); |
| } |
| |
| function _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth) { |
| windowRect.width = Math.min(windowRect.width, availRect.width); |
| windowRect.width = Math.max(windowRect.width, minWidth); |
| windowRect.x = anchorRect.x; |
| if (global.params.isRTL) |
| windowRect.x += anchorRect.width - windowRect.width; |
| windowRect.x = Math.min(windowRect.x, availRect.maxX - windowRect.width); |
| windowRect.x = Math.max(windowRect.x, availRect.x); |
| } |
| |
| /** |
| * @param {!Rectangle} rect |
| */ |
| function setWindowRect(rect) { |
| if (window.frameElement) { |
| window.frameElement.style.width = rect.width + "px"; |
| window.frameElement.style.height = rect.height + "px"; |
| } else { |
| if (isWindowHidden()) { |
| window.moveTo(rect.x - window.screen.availLeft, rect.y - window.screen.availTop); |
| window.resizeTo(rect.width, rect.height); |
| } else { |
| window.resizeTo(rect.width, rect.height); |
| window.moveTo(rect.x - window.screen.availLeft, rect.y - window.screen.availTop); |
| } |
| } |
| } |
| |
| function hideWindow() { |
| resizeWindow(1, 1); |
| } |
| |
| /** |
| * @return {!boolean} |
| */ |
| function isWindowHidden() { |
| return window.innerWidth === 1 && window.innerHeight === 1; |
| } |
| |
| window.addEventListener("resize", function() { |
| if (isWindowHidden()) |
| window.dispatchEvent(new CustomEvent("didHide")); |
| else |
| window.dispatchEvent(new CustomEvent("didOpenPicker")); |
| }, false); |
| |
| /** |
| * @return {!number} |
| */ |
| function getScrollbarWidth() { |
| if (typeof window.scrollbarWidth === "undefined") { |
| var scrollDiv = document.createElement("div"); |
| scrollDiv.style.opacity = "0"; |
| scrollDiv.style.overflow = "scroll"; |
| scrollDiv.style.width = "50px"; |
| scrollDiv.style.height = "50px"; |
| document.body.appendChild(scrollDiv); |
| window.scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; |
| scrollDiv.parentNode.removeChild(scrollDiv); |
| } |
| return window.scrollbarWidth; |
| } |
| |
| /** |
| * @param {!string} className |
| * @return {?Element} |
| */ |
| function enclosingNodeOrSelfWithClass(selfNode, className) |
| { |
| for (var node = selfNode; node && node !== selfNode.ownerDocument; node = node.parentNode) { |
| if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains(className)) |
| return node; |
| } |
| return null; |
| }; |
| |
| /** |
| * @constructor |
| * @param {!Element} element |
| * @param {!Object} config |
| */ |
| function Picker(element, config) { |
| this._element = element; |
| this._config = config; |
| } |
| |
| /** |
| * @enum {number} |
| */ |
| Picker.Actions = { |
| SetValue: 0, |
| Cancel: -1, |
| ChooseOtherColor: -2 |
| }; |
| |
| /** |
| * @param {!string} value |
| */ |
| Picker.prototype.submitValue = function(value) { |
| window.pagePopupController.setValue(value); |
| window.pagePopupController.closePopup(); |
| } |
| |
| Picker.prototype.handleCancel = function() { |
| window.pagePopupController.closePopup(); |
| } |
| |
| Picker.prototype.chooseOtherColor = function() { |
| window.pagePopupController.setValueAndClosePopup(Picker.Actions.ChooseOtherColor, ""); |
| } |
| |
| Picker.prototype.cleanup = function() {}; |