mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	Merge 1.1.0 changes back to master.
This commit is contained in:
		| @@ -18,11 +18,11 @@ | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A directive which implements a color input field, leveraging the "Pickr" | ||||
|  * color picker. If the "Picker" color picker cannot be used because it relies | ||||
|  * on JavaScript features not supported by the browser (Internet Explorer), a | ||||
|  * "guacInputColorUnavailable" event will be emitted up the scope, and this | ||||
|  * A directive which implements a color input field. If the underlying color | ||||
|  * picker implementation cannot be used due to a lack of browser support, this | ||||
|  * directive will become read-only, functioning essentially as a color preview. | ||||
|  * | ||||
|  * @see colorPickerService | ||||
|  */ | ||||
| angular.module('form').directive('guacInputColor', [function guacInputColor() { | ||||
|  | ||||
| @@ -59,17 +59,12 @@ angular.module('form').directive('guacInputColor', [function guacInputColor() { | ||||
|         function guacInputColorController($scope, $element, $injector) { | ||||
|  | ||||
|         // Required services | ||||
|         var $q         = $injector.get('$q'); | ||||
|         var $translate = $injector.get('$translate'); | ||||
|         var colorPickerService = $injector.get('colorPickerService'); | ||||
|  | ||||
|         /** | ||||
|          * Whether the color picker ("Pickr") cannot be used. In general, all | ||||
|          * browsers should support Pickr with the exception of Internet | ||||
|          * Explorer. | ||||
|          * | ||||
|          * @type Boolean | ||||
|          * @borrows colorPickerService.isAvailable() | ||||
|          */ | ||||
|         $scope.colorPickerUnavailable = false; | ||||
|         $scope.isColorPickerAvailable = colorPickerService.isAvailable; | ||||
|  | ||||
|         /** | ||||
|          * Returns whether the color currently selected is "dark" in the sense | ||||
| @@ -102,98 +97,18 @@ angular.module('form').directive('guacInputColor', [function guacInputColor() { | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         // Init color picker after required translation strings are available | ||||
|         $q.all({ | ||||
|             'save'   : $translate('APP.ACTION_SAVE'), | ||||
|             'cancel' : $translate('APP.ACTION_CANCEL') | ||||
|         }).then(function stringsRetrieved(strings) { | ||||
|  | ||||
|             try { | ||||
|  | ||||
|                 /** | ||||
|                  * An instance of the "Pickr" color picker, bound to the underlying | ||||
|                  * element of this directive. | ||||
|                  * | ||||
|                  * @type Pickr | ||||
|                  */ | ||||
|                 var pickr = Pickr.create({ | ||||
|  | ||||
|                     // Bind color picker to the underlying element of this directive | ||||
|                     el : $element[0], | ||||
|  | ||||
|                     // Wrap color picker dialog in Guacamole-specific class for | ||||
|                     // sake of additional styling | ||||
|                     appClass : 'guac-input-color-picker', | ||||
|  | ||||
|                     // 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 : $scope.palette || [], | ||||
|  | ||||
|                     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 | ||||
|                         } | ||||
|  | ||||
|                     }, | ||||
|  | ||||
|                     // Use translation strings for buttons | ||||
|                     strings : strings | ||||
|  | ||||
|                 }); | ||||
|  | ||||
|                 // Hide color picker after user clicks "cancel" | ||||
|                 pickr.on('cancel', function colorChangeCanceled() { | ||||
|                     pickr.hide(); | ||||
|                 }); | ||||
|  | ||||
|                 // Keep model in sync with changes to the color picker | ||||
|                 pickr.on('save', function colorChanged(color) { | ||||
|                     $scope.$evalAsync(function updateModel() { | ||||
|                         $scope.model = color.toHEXA().toString(); | ||||
|                     }); | ||||
|                 }); | ||||
|  | ||||
|                 // Keep color picker in sync with changes to the model | ||||
|                 pickr.on('init', function pickrReady(color) { | ||||
|                     $scope.$watch('model', function modelChanged(model) { | ||||
|                         pickr.setColor(model); | ||||
|                     }); | ||||
|                 }); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // If the "Pickr" color picker cannot be loaded (Internet Explorer), | ||||
|             // let the scope above us know | ||||
|             catch (e) { | ||||
|                 $scope.colorPickerUnavailable = true; | ||||
|                 $scope.$emit('guacInputColorUnavailable', e); | ||||
|             } | ||||
|  | ||||
|         }, angular.noop); | ||||
|         /** | ||||
|          * Prompts the user to choose a color by displaying a color selection | ||||
|          * dialog. If the user chooses a color, this directive's model is | ||||
|          * automatically updated. If the user cancels the dialog, the model is | ||||
|          * left untouched. | ||||
|          */ | ||||
|         $scope.selectColor = function selectColor() { | ||||
|             colorPickerService.selectColor($element[0], $scope.model, $scope.palette) | ||||
|             .then(function colorSelected(color) { | ||||
|                 $scope.model = color; | ||||
|             }, angular.noop); | ||||
|         }; | ||||
|  | ||||
|     }]; | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,268 @@ | ||||
| /* | ||||
|  * 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; | ||||
|  | ||||
|     }]; | ||||
|  | ||||
| }); | ||||
| @@ -220,10 +220,45 @@ angular.module('form').provider('formService', function formServiceProvider() { | ||||
|         var $q               = $injector.get('$q'); | ||||
|         var $templateRequest = $injector.get('$templateRequest'); | ||||
|  | ||||
|         /** | ||||
|          * Map of module name to the injector instance created for that module. | ||||
|          * | ||||
|          * @type {Object.<String, injector>} | ||||
|          */ | ||||
|         var injectors = {}; | ||||
|  | ||||
|         var service = {}; | ||||
|  | ||||
|         service.fieldTypes = provider.fieldTypes; | ||||
|  | ||||
|         /** | ||||
|          * Given the name of a module, returns an injector instance which | ||||
|          * injects dependencies within that module. A new injector may be | ||||
|          * created and initialized if no such injector has yet been requested. | ||||
|          * If the injector available to formService already includes the | ||||
|          * requested module, that injector will simply be returned. | ||||
|          * | ||||
|          * @param {String} module | ||||
|          *     The name of the module to produce an injector for. | ||||
|          * | ||||
|          * @returns {injector} | ||||
|          *     An injector instance which injects dependencies for the given | ||||
|          *     module. | ||||
|          */ | ||||
|         var getInjector = function getInjector(module) { | ||||
|  | ||||
|             // Use the formService's injector if possible | ||||
|             if ($injector.modules[module]) | ||||
|                 return $injector; | ||||
|  | ||||
|             // If the formService's injector does not include the requested | ||||
|             // module, create the necessary injector, reusing that injector for | ||||
|             // future calls | ||||
|             injectors[module] = injectors[module] || angular.injector(['ng', module]); | ||||
|             return injectors[module]; | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Compiles and links the field associated with the given name to the given | ||||
|          * scope, producing a distinct and independent DOM Element which functions | ||||
| @@ -304,7 +339,7 @@ angular.module('form').provider('formService', function formServiceProvider() { | ||||
|  | ||||
|                 // Populate scope using defined controller | ||||
|                 if (fieldType.module && fieldType.controller) { | ||||
|                     var $controller = angular.injector(['ng', fieldType.module]).get('$controller'); | ||||
|                     var $controller = getInjector(fieldType.module).get('$controller'); | ||||
|                     $controller(fieldType.controller, { | ||||
|                         '$scope'   : scope, | ||||
|                         '$element' : angular.element(fieldContainer.childNodes) | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| <div class="guac-input-color" | ||||
|      ng-class="{ | ||||
|          'dark' : isDark(), | ||||
|          'read-only' : colorPickerUnavailable | ||||
|          'read-only' : !isColorPickerAvailable() | ||||
|      }" | ||||
|      ng-click="selectColor()" | ||||
|      ng-style="{ | ||||
|         'background-color' : model | ||||
|      }"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user