| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /** |
| * A service for prompting the user to choose a color using the "Pickr" color |
| * picker. As the Pickr color picker might not be available if the JavaScript |
| * features it requires are not supported by the browser (Internet Explorer), |
| * the isAvailable() function should be used to test for usability. |
| */ |
| angular.module('form').provider('colorPickerService', function colorPickerServiceProvider() { |
| |
| /** |
| * A singleton instance of the "Pickr" color picker, shared by all users of |
| * this service. Pickr does not initialize synchronously, nor is it |
| * supported by all browsers. If Pickr is not yet initialized, or is |
| * unsupported, this will be null. |
| * |
| * @type {Pickr} |
| */ |
| var pickr = null; |
| |
| /** |
| * Whether Pickr has completed initialization. |
| * |
| * @type {Boolean} |
| */ |
| var pickrInitComplete = false; |
| |
| /** |
| * The HTML element to provide to Pickr as the root element. |
| * |
| * @type {HTMLDivElement} |
| */ |
| var pickerContainer = document.createElement('div'); |
| pickerContainer.className = 'shared-color-picker'; |
| |
| /** |
| * An instance of Deferred which represents an active request for the |
| * user to choose a color. The promise associated with the Deferred will |
| * be resolved with the chosen color once a color is chosen, and rejected |
| * if the request is cancelled or Pickr is not available. If no request is |
| * active, this will be null. |
| * |
| * @type {Deferred} |
| */ |
| var activeRequest = null; |
| |
| /** |
| * Resolves the current active request with the given color value. If no |
| * color value is provided, the active request is rejected. If no request |
| * is active, this function has no effect. |
| * |
| * @param {String} [color] |
| * The color value to resolve the active request with. |
| */ |
| var completeActiveRequest = function completeActiveRequest(color) { |
| if (activeRequest) { |
| |
| // Hide color picker, if shown |
| pickr.hide(); |
| |
| // Resolve/reject active request depending on value provided |
| if (color) |
| activeRequest.resolve(color); |
| else |
| activeRequest.reject(); |
| |
| // No active request |
| activeRequest = null; |
| |
| } |
| }; |
| |
| try { |
| pickr = Pickr.create({ |
| |
| // Bind color picker to the container element |
| el : pickerContainer, |
| |
| // Wrap color picker dialog in Guacamole-specific class for |
| // sake of additional styling |
| appClass : 'guac-input-color-picker', |
| |
| 'default' : '#000000', |
| |
| // Display color details as hex |
| defaultRepresentation : 'HEX', |
| |
| // Use "monolith" theme, as a nice balance between "nano" (does |
| // not work in Internet Explorer) and "classic" (too big) |
| theme : 'monolith', |
| |
| // Leverage the container element as the button which shows the |
| // picker, relying on our own styling for that button |
| useAsButton : true, |
| appendToBody : true, |
| |
| // Do not include opacity controls |
| lockOpacity : true, |
| |
| // Include a selection of palette entries for convenience and |
| // reference |
| swatches : [], |
| |
| components: { |
| |
| // Include hue and color preview controls |
| preview : true, |
| hue : true, |
| |
| // Display only a text color input field and the save and |
| // cancel buttons (no clear button) |
| interaction: { |
| input : true, |
| save : true, |
| cancel : true |
| } |
| |
| } |
| |
| }); |
| |
| // Hide color picker after user clicks "cancel" |
| pickr.on('cancel', function colorChangeCanceled() { |
| completeActiveRequest(); |
| }); |
| |
| // Keep model in sync with changes to the color picker |
| pickr.on('save', function colorChanged(color) { |
| completeActiveRequest(color.toHEXA().toString()); |
| activeRequest = null; |
| }); |
| |
| // Keep color picker in sync with changes to the model |
| pickr.on('init', function pickrReady() { |
| pickrInitComplete = true; |
| }); |
| } |
| catch (e) { |
| // If the "Pickr" color picker cannot be loaded (Internet Explorer), |
| // the available flag will remain set to false |
| } |
| |
| // Factory method required by provider |
| this.$get = ['$injector', function colorPickerServiceFactory($injector) { |
| |
| // Required services |
| var $q = $injector.get('$q'); |
| var $translate = $injector.get('$translate'); |
| |
| var service = {}; |
| |
| /** |
| * Promise which is resolved when Pickr initialization has completed |
| * and rejected if Pickr cannot be used. |
| * |
| * @type {Promise} |
| */ |
| var pickrPromise = (function getPickr() { |
| |
| var deferred = $q.defer(); |
| |
| // Resolve promise when Pickr has completed initialization |
| if (pickrInitComplete) |
| deferred.resolve(); |
| else if (pickr) |
| pickr.on('init', deferred.resolve); |
| |
| // Reject promise if Pickr cannot be used at all |
| else |
| deferred.reject(); |
| |
| return deferred.promise; |
| |
| })(); |
| |
| /** |
| * Returns whether the underlying color picker (Pickr) can be used by |
| * calling selectColor(). If the browser cannot support the color |
| * picker, false is returned. |
| * |
| * @returns {Boolean} |
| * true if the underlying color picker can be used by calling |
| * selectColor(), false otherwise. |
| */ |
| service.isAvailable = function isAvailable() { |
| return !!pickr; |
| }; |
| |
| /** |
| * Prompts the user to choose a color, returning the color chosen via a |
| * Promise. |
| * |
| * @param {Element} element |
| * The element that the user interacted with to indicate their |
| * desire to choose a color. |
| * |
| * @param {String} current |
| * The color that should be selected by default, in standard |
| * 6-digit hexadecimal RGB format, including "#" prefix. |
| * |
| * @param {String[]} [palette] |
| * An array of color choices which should be exposed to the user |
| * within the color chooser for convenience. Each color must be in |
| * standard 6-digit hexadecimal RGB format, including "#" prefix. |
| * |
| * @returns {Promise.<String>} |
| * A Promise which is resolved with the color chosen by the user, |
| * in standard 6-digit hexadecimal RGB format with "#" prefix, and |
| * rejected if the selection operation was cancelled or the color |
| * picker cannot be used. |
| */ |
| service.selectColor = function selectColor(element, current, palette) { |
| |
| // Show picker once the relevant translation strings have been |
| // retrieved and Pickr is ready for use |
| return $q.all({ |
| 'saveString' : $translate('APP.ACTION_SAVE'), |
| 'cancelString' : $translate('APP.ACTION_CANCEL'), |
| 'pickr' : pickrPromise |
| }).then(function dependenciesReady(deps) { |
| |
| // Cancel any active request |
| completeActiveRequest(); |
| |
| // Reset state of color picker to provided parameters |
| pickr.setColor(current); |
| element.appendChild(pickerContainer); |
| |
| // Assign translated strings to button text |
| var pickrRoot = pickr.getRoot(); |
| pickrRoot.interaction.save.value = deps.saveString; |
| pickrRoot.interaction.cancel.value = deps.cancelString; |
| |
| // Replace all color swatches with the palette of colors given |
| while (pickr.removeSwatch(0)) {} |
| angular.forEach(palette, pickr.addSwatch.bind(pickr)); |
| |
| // Show color picker and wait for user to complete selection |
| activeRequest = $q.defer(); |
| pickr.show(); |
| return activeRequest.promise; |
| |
| }); |
| |
| }; |
| |
| return service; |
| |
| }]; |
| |
| }); |