mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 05:31:22 +00:00
GUACAMOLE-630: Tolerate insufficient JavaScript features to run "Pickr" color picker (Internet Explorer).
This commit is contained in:
@@ -19,36 +19,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A directive which implements a color input field, leveraging the "Pickr"
|
* A directive which implements a color input field, leveraging the "Pickr"
|
||||||
* color picker.
|
* 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
|
||||||
|
* directive will become read-only, functioning essentially as a color preview.
|
||||||
*/
|
*/
|
||||||
angular.module('form').directive('guacInputColor', [function guacInputColor() {
|
angular.module('form').directive('guacInputColor', [function guacInputColor() {
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given color is relatively dark. A color is
|
|
||||||
* considered dark if white text would be more visible over a background
|
|
||||||
* of that color (provide better contrast) than black text.
|
|
||||||
*
|
|
||||||
* @param {HSVaColor} color
|
|
||||||
* The color to test.
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
* true if the given color is relatively dark (white text would provide
|
|
||||||
* better contrast than black), false otherwise.
|
|
||||||
*/
|
|
||||||
var isDark = function isDark(color) {
|
|
||||||
|
|
||||||
var rgb = color.toRGBA();
|
|
||||||
|
|
||||||
// Convert RGB to luminance in HSL space (as defined by the
|
|
||||||
// relative luminance formula given by the W3C for accessibility)
|
|
||||||
var luminance = 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
|
|
||||||
|
|
||||||
// Consider the background to be dark if white text over that
|
|
||||||
// background would provide better contrast than black
|
|
||||||
return luminance <= 153; // 153 is the component value 0.6 converted from 0-1 to the 0-255 range
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
replace: true,
|
replace: true,
|
||||||
@@ -86,13 +63,44 @@ angular.module('form').directive('guacInputColor', [function guacInputColor() {
|
|||||||
var $translate = $injector.get('$translate');
|
var $translate = $injector.get('$translate');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the color currently selected is "dark" in the sense that the
|
* Whether the color picker ("Pickr") cannot be used. In general, all
|
||||||
* color white will have higher contrast against it than the color
|
* browsers should support Pickr with the exception of Internet
|
||||||
* black.
|
* Explorer.
|
||||||
*
|
*
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
*/
|
*/
|
||||||
$scope.dark = false;
|
$scope.colorPickerUnavailable = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the color currently selected is "dark" in the sense
|
||||||
|
* that the color white will have higher contrast against it than the
|
||||||
|
* color black.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
* true if the currently selected color is relatively dark (white
|
||||||
|
* text would provide better contrast than black), false otherwise.
|
||||||
|
*/
|
||||||
|
$scope.isDark = function isDark() {
|
||||||
|
|
||||||
|
// Assume not dark if color is invalid or undefined
|
||||||
|
var rgb = $scope.model && /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/.exec($scope.model);
|
||||||
|
if (!rgb)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Parse color component values as hexadecimal
|
||||||
|
var red = parseInt(rgb[1], 16);
|
||||||
|
var green = parseInt(rgb[2], 16);
|
||||||
|
var blue = parseInt(rgb[3], 16);
|
||||||
|
|
||||||
|
// Convert RGB to luminance in HSL space (as defined by the
|
||||||
|
// relative luminance formula given by the W3C for accessibility)
|
||||||
|
var luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
||||||
|
|
||||||
|
// Consider the background to be dark if white text over that
|
||||||
|
// background would provide better contrast than black
|
||||||
|
return luminance <= 153; // 153 is the component value 0.6 converted from 0-1 to the 0-255 range
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// Init color picker after required translation strings are available
|
// Init color picker after required translation strings are available
|
||||||
$q.all({
|
$q.all({
|
||||||
@@ -100,81 +108,90 @@ angular.module('form').directive('guacInputColor', [function guacInputColor() {
|
|||||||
'cancel' : $translate('APP.ACTION_CANCEL')
|
'cancel' : $translate('APP.ACTION_CANCEL')
|
||||||
}).then(function stringsRetrieved(strings) {
|
}).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],
|
* An instance of the "Pickr" color picker, bound to the underlying
|
||||||
|
* element of this directive.
|
||||||
|
*
|
||||||
|
* @type Pickr
|
||||||
|
*/
|
||||||
|
var pickr = Pickr.create({
|
||||||
|
|
||||||
// Wrap color picker dialog in Guacamole-specific class for
|
// Bind color picker to the underlying element of this directive
|
||||||
// sake of additional styling
|
el : $element[0],
|
||||||
appClass : 'guac-input-color-picker',
|
|
||||||
|
|
||||||
// Display color details as hex
|
// Wrap color picker dialog in Guacamole-specific class for
|
||||||
defaultRepresentation : 'HEX',
|
// sake of additional styling
|
||||||
|
appClass : 'guac-input-color-picker',
|
||||||
|
|
||||||
// Use "monolith" theme, as a nice balance between "nano" (does
|
// Display color details as hex
|
||||||
// not work in Internet Explorer) and "classic" (too big)
|
defaultRepresentation : 'HEX',
|
||||||
theme : 'monolith',
|
|
||||||
|
|
||||||
// Leverage the container element as the button which shows the
|
// Use "monolith" theme, as a nice balance between "nano" (does
|
||||||
// picker, relying on our own styling for that button
|
// not work in Internet Explorer) and "classic" (too big)
|
||||||
useAsButton : true,
|
theme : 'monolith',
|
||||||
appendToBody : true,
|
|
||||||
|
|
||||||
// Do not include opacity controls
|
// Leverage the container element as the button which shows the
|
||||||
lockOpacity : true,
|
// picker, relying on our own styling for that button
|
||||||
|
useAsButton : true,
|
||||||
|
appendToBody : true,
|
||||||
|
|
||||||
// Include a selection of palette entries for convenience and
|
// Do not include opacity controls
|
||||||
// reference
|
lockOpacity : true,
|
||||||
swatches : $scope.palette || [],
|
|
||||||
|
|
||||||
components: {
|
// Include a selection of palette entries for convenience and
|
||||||
|
// reference
|
||||||
|
swatches : $scope.palette || [],
|
||||||
|
|
||||||
// Include hue and color preview controls
|
components: {
|
||||||
preview : true,
|
|
||||||
hue : true,
|
|
||||||
|
|
||||||
// Display only a text color input field and the save and
|
// Include hue and color preview controls
|
||||||
// cancel buttons (no clear button)
|
preview : true,
|
||||||
interaction: {
|
hue : true,
|
||||||
input : true,
|
|
||||||
save : true,
|
|
||||||
cancel : 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
|
|
||||||
|
|
||||||
});
|
// 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();
|
|
||||||
$scope.dark = isDark(pickr.getColor());
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Keep color picker in sync with changes to the model
|
// Hide color picker after user clicks "cancel"
|
||||||
pickr.on('init', function pickrReady(color) {
|
pickr.on('cancel', function colorChangeCanceled() {
|
||||||
$scope.$watch('model', function modelChanged(model) {
|
pickr.hide();
|
||||||
pickr.setColor(model);
|
|
||||||
$scope.dark = isDark(pickr.getColor());
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
// 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);
|
}, angular.noop);
|
||||||
|
|
||||||
|
@@ -67,6 +67,10 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-field .terminal-color-scheme-field .custom-color-scheme .guac-input-color.read-only {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color button font colors
|
* Color button font colors
|
||||||
*/
|
*/
|
||||||
|
@@ -1,3 +1,10 @@
|
|||||||
<div class="guac-input-color" ng-class="{ 'dark' : dark }" ng-style="{ 'background-color' : model }">
|
<div class="guac-input-color"
|
||||||
|
ng-class="{
|
||||||
|
'dark' : isDark(),
|
||||||
|
'read-only' : colorPickerUnavailable
|
||||||
|
}"
|
||||||
|
ng-style="{
|
||||||
|
'background-color' : model
|
||||||
|
}">
|
||||||
<ng-transclude></ng-transclude>
|
<ng-transclude></ng-transclude>
|
||||||
</div>
|
</div>
|
Reference in New Issue
Block a user