blob: eac482d0bda47eba006e3a31b633324e2acb5ab6 [file] [log] [blame]
"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.
*/
var global = {
argumentsReceived: false,
params: null
};
/**
* @param {Event} event
*/
function handleMessage(event) {
initialize(JSON.parse(event.data));
global.argumentsReceived = true;
}
/**
* @param {!Object} args
*/
function initialize(args) {
global.params = args;
var main = $("main");
main.innerHTML = "";
var errorString = validateArguments(args);
if (errorString) {
main.textContent = "Internal error: " + errorString;
resizeWindow(main.offsetWidth, main.offsetHeight);
} else
new ColorPicker(main, args);
}
// The DefaultColorPalette is used when the list of values are empty.
var DefaultColorPalette = ["#000000", "#404040", "#808080", "#c0c0c0",
"#ffffff", "#980000", "#ff0000", "#ff9900", "#ffff00", "#00ff00", "#00ffff",
"#4a86e8", "#0000ff", "#9900ff", "#ff00ff"];
function handleArgumentsTimeout() {
if (global.argumentsReceived)
return;
var args = {
values : DefaultColorPalette,
otherColorLabel: "Other..."
};
initialize(args);
}
/**
* @param {!Object} args
* @return {?string} An error message, or null if the argument has no errors.
*/
function validateArguments(args) {
if (!args.values)
return "No values.";
if (!args.otherColorLabel)
return "No otherColorLabel.";
return null;
}
function ColorPicker(element, config) {
Picker.call(this, element, config);
this._config = config;
if (this._config.values.length === 0)
this._config.values = DefaultColorPalette;
this._container = null;
this._layout();
document.body.addEventListener("keydown", this._handleKeyDown.bind(this));
this._element.addEventListener("mousemove", this._handleMouseMove.bind(this));
this._element.addEventListener("mousedown", this._handleMouseDown.bind(this));
}
ColorPicker.prototype = Object.create(Picker.prototype);
var SwatchBorderBoxWidth = 24; // keep in sync with CSS
var SwatchBorderBoxHeight = 24; // keep in sync with CSS
var SwatchesPerRow = 5;
var SwatchesMaxRow = 4;
ColorPicker.prototype._layout = function() {
var container = createElement("div", "color-swatch-container");
container.addEventListener("click", this._handleSwatchClick.bind(this), false);
for (var i = 0; i < this._config.values.length; ++i) {
var swatch = createElement("button", "color-swatch");
swatch.dataset.index = i;
swatch.dataset.value = this._config.values[i];
swatch.title = this._config.values[i];
swatch.style.backgroundColor = this._config.values[i];
container.appendChild(swatch);
}
var containerWidth = SwatchBorderBoxWidth * SwatchesPerRow;
if (this._config.values.length > SwatchesPerRow * SwatchesMaxRow)
containerWidth += getScrollbarWidth();
container.style.width = containerWidth + "px";
container.style.maxHeight = (SwatchBorderBoxHeight * SwatchesMaxRow) + "px";
this._element.appendChild(container);
var otherButton = createElement("button", "other-color", this._config.otherColorLabel);
otherButton.addEventListener("click", this.chooseOtherColor.bind(this), false);
this._element.appendChild(otherButton);
this._container = container;
this._otherButton = otherButton;
var elementWidth = this._element.offsetWidth;
var elementHeight = this._element.offsetHeight;
resizeWindow(elementWidth, elementHeight);
};
ColorPicker.prototype.selectColorAtIndex = function(index) {
index = Math.max(Math.min(this._container.childNodes.length - 1, index), 0);
this._container.childNodes[index].focus();
};
ColorPicker.prototype._handleMouseMove = function(event) {
if (event.target.classList.contains("color-swatch"))
event.target.focus();
};
ColorPicker.prototype._handleMouseDown = function(event) {
// Prevent blur.
if (event.target.classList.contains("color-swatch"))
event.preventDefault();
};
ColorPicker.prototype._handleKeyDown = function(event) {
var key = event.key;
if (key === "Escape")
this.handleCancel();
else if (key == "ArrowLeft" || key == "ArrowUp" || key == "ArrowRight" || key == "ArrowDown") {
var selectedElement = document.activeElement;
var index = 0;
if (selectedElement.classList.contains("other-color")) {
if (key != "ArrowRight" && key != "ArrowUp")
return;
index = this._container.childNodes.length - 1;
} else if (selectedElement.classList.contains("color-swatch")) {
index = parseInt(selectedElement.dataset.index, 10);
switch (key) {
case "ArrowLeft":
index--;
break;
case "ArrowRight":
index++;
break;
case "ArrowUp":
index -= SwatchesPerRow;
break;
case "ArrowDown":
index += SwatchesPerRow;
break;
}
if (index > this._container.childNodes.length - 1) {
this._otherButton.focus();
return;
}
}
this.selectColorAtIndex(index);
}
event.preventDefault();
};
ColorPicker.prototype._handleSwatchClick = function(event) {
if (event.target.classList.contains("color-swatch"))
this.submitValue(event.target.dataset.value);
};
if (window.dialogArguments) {
initialize(dialogArguments);
} else {
window.addEventListener("message", handleMessage, false);
window.setTimeout(handleArgumentsTimeout, 1000);
}