fix : keyboard accessibility for colorpicker inpus
This commit is contained in:
parent
334d6ad21f
commit
561d016a45
6 changed files with 171 additions and 90 deletions
|
@ -66,7 +66,8 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.color-picker-slider {
|
||||
.color-picker-slider,
|
||||
.color-picker-input {
|
||||
padding: 0 10px;
|
||||
height : 25px;
|
||||
overflow: hidden;
|
||||
|
@ -91,6 +92,14 @@
|
|||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.color-picker-input {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.color-picker-input .textfield{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"][data-dimension="h"] {
|
||||
background-image:linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
}
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
.color-preview {
|
||||
width: 170px;
|
||||
height: 76px;
|
||||
height: 70px;
|
||||
margin: 11px;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,3 +46,7 @@ body {
|
|||
.pull-left {
|
||||
left:0;
|
||||
}
|
||||
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,10 @@ if (!Function.prototype.bind) {
|
|||
return hash;
|
||||
};
|
||||
|
||||
ns.copy = function (object) {
|
||||
return JSON.parse(JSON.stringify(object));
|
||||
};
|
||||
|
||||
var entityMap = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
ns.HslRgbColorPicker = function (container, colorUpdatedCallback) {
|
||||
this.container = container;
|
||||
this.colorUpdatedCallback = colorUpdatedCallback;
|
||||
|
||||
this.tinyColor = null;
|
||||
this.hsvColor = null;
|
||||
this.rgbColor = null;
|
||||
|
||||
this.lastInputTimestamp_ = 0;
|
||||
};
|
||||
|
||||
|
@ -12,16 +17,15 @@
|
|||
var changeEvent = isChromeOrFirefox ? 'input' : 'change';
|
||||
this.container.addEventListener(changeEvent, this.onPickerChange_.bind(this));
|
||||
this.container.addEventListener('keydown', this.onKeydown_.bind(this));
|
||||
this.container.addEventListener('focusout', this.onBlur_.bind(this));
|
||||
|
||||
this.spectrumEl = this.container.querySelector('.color-picker-spectrum');
|
||||
|
||||
$(this.spectrumEl).spectrum({
|
||||
flat: true,
|
||||
showInput: true,
|
||||
showButtons: false,
|
||||
move : this.setColor.bind(this),
|
||||
change : this.setColor.bind(this),
|
||||
preferredFormat: 'hex'
|
||||
change : this.setColor.bind(this)
|
||||
});
|
||||
|
||||
this.setColor("#000000");
|
||||
|
@ -34,49 +38,72 @@
|
|||
|
||||
ns.HslRgbColorPicker.prototype.onPickerChange_ = function (evt) {
|
||||
var target = evt.target;
|
||||
|
||||
if (target.dataset.dimension) {
|
||||
var model = target.dataset.model;
|
||||
var dimension = target.dataset.dimension;
|
||||
var value = target.value;
|
||||
|
||||
var value = parseInt(target.value, 10);
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = value/100;
|
||||
this.updateColor_(value, model, dimension);
|
||||
}
|
||||
|
||||
var color;
|
||||
if (model === 'rgb') {
|
||||
color = this.tinyColor.toRgb();
|
||||
} else if (model === 'hsv') {
|
||||
color = this.hsvColor;
|
||||
}
|
||||
|
||||
if (isNaN(value)) {
|
||||
value = color[dimension];
|
||||
} else {
|
||||
color[dimension] = value;
|
||||
}
|
||||
|
||||
this.setColor(color);
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.onKeydown_ = function (evt) {
|
||||
var target = evt.target;
|
||||
|
||||
if (target.getAttribute('type').toLowerCase() === 'text') {
|
||||
var value = parseInt(target.value, 10);
|
||||
var dimension = target.dataset.dimension;
|
||||
var isInputText = target.getAttribute('type').toLowerCase() === 'text';
|
||||
if (isInputText && target.dataset.dimension) {
|
||||
var model = target.dataset.model;
|
||||
|
||||
if (model === 'rgb' || model === 'hsv') {
|
||||
var increment = this.getIncrement_(evt);
|
||||
if (increment) {
|
||||
var dimension = target.dataset.dimension;
|
||||
var value = parseInt(target.value, 10);
|
||||
this.updateColor_(value + increment, model, dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.getIncrement_ = function (evt) {
|
||||
var increment = 0;
|
||||
var key = pskl.service.keyboard.KeycodeTranslator.toChar(evt.keyCode);
|
||||
if (key === 'up') {
|
||||
value = value + 1;
|
||||
increment = 1;
|
||||
} else if (key === 'down') {
|
||||
value = value - 1;
|
||||
increment = -1;
|
||||
}
|
||||
|
||||
value = this.normalizeDimension_(value, dimension);
|
||||
if (evt.shiftKey) {
|
||||
increment = increment * 5;
|
||||
}
|
||||
|
||||
target.value = value;
|
||||
this.onPickerChange_(evt);
|
||||
return increment;
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.updateColor_ = function (inputValue, model, dimension) {
|
||||
var value = this.toModelValue_(inputValue, model, dimension);
|
||||
if (model === 'hsv' || model === 'rgb') {
|
||||
if (!isNaN(value)) {
|
||||
var color = this.getColor_(model);
|
||||
color[dimension] = this.normalizeDimension_(value, dimension);
|
||||
this.setColor(color);
|
||||
}
|
||||
} else if (model === 'hex') {
|
||||
if (/^#([a-f0-9]{3}){1,2}$/i.test(value)) {
|
||||
this.setColor(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.onBlur_ = function (evt) {
|
||||
var target = evt.target;
|
||||
|
||||
var isInputText = target.getAttribute('type').toLowerCase() === 'text';
|
||||
if (isInputText && target.dataset.dimension) {
|
||||
var model = target.dataset.model;
|
||||
var dimension = target.dataset.dimension;
|
||||
target.value = this.toInputValue_(model, dimension);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -86,6 +113,7 @@
|
|||
|
||||
this.hsvColor = this.toHsvColor_(inputColor);
|
||||
this.tinyColor = this.toTinyColor_(inputColor);
|
||||
this.rgbColor = this.tinyColor.toRgb();
|
||||
|
||||
this.updateInputs();
|
||||
$(".color-picker-spectrum").spectrum("set", this.tinyColor);
|
||||
|
@ -98,30 +126,85 @@
|
|||
|
||||
ns.HslRgbColorPicker.prototype.updateInputs = function () {
|
||||
var inputs = this.container.querySelectorAll('input');
|
||||
var rgb = this.tinyColor.toRgb();
|
||||
|
||||
|
||||
for (var i = 0 ; i < inputs.length ; i++) {
|
||||
var input = inputs[i];
|
||||
var dimension = input.dataset.dimension;
|
||||
var model = input.dataset.model;
|
||||
|
||||
if (model === 'rgb') {
|
||||
input.value = rgb[dimension];
|
||||
} else if (model === 'hsv') {
|
||||
var value = this.hsvColor[dimension];
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = 100 * value;
|
||||
var value = this.toInputValue_(model, dimension);
|
||||
if (input.value != value) {
|
||||
input.value = value;
|
||||
}
|
||||
input.value = Math.round(value);
|
||||
}
|
||||
|
||||
if (input.getAttribute('type') === 'range') {
|
||||
this.updateSliderBackground(input);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toInputValue_ = function (model, dimension) {
|
||||
var value;
|
||||
|
||||
if (model === 'rgb' || model === 'hsv') {
|
||||
var color = this.getColor_(model);
|
||||
value = color[dimension];
|
||||
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = 100 * value;
|
||||
}
|
||||
value = Math.round(value);
|
||||
} else if (model === 'hex') {
|
||||
value = this.tinyColor.toHexString(true);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toModelValue_ = function (value, model, dimension) {
|
||||
var modelValue;
|
||||
|
||||
if (model === 'rgb' || model === 'hsv') {
|
||||
modelValue = parseInt(value, 10);
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
modelValue = modelValue/100;
|
||||
}
|
||||
} else if (model === 'hex') {
|
||||
modelValue = value;
|
||||
}
|
||||
|
||||
return modelValue;
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toTinyColor_ = function (color) {
|
||||
var isTinyColor = typeof color == 'object' && color.hasOwnProperty('_tc_id');
|
||||
if (isTinyColor) {
|
||||
return color;
|
||||
} else {
|
||||
return window.tinycolor(pskl.utils.copy(color));
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toHsvColor_ = function (color) {
|
||||
var isHsvColor = ['h','s','v'].every(color.hasOwnProperty.bind(color));
|
||||
if (isHsvColor) {
|
||||
return {
|
||||
h : this.normalizeDimension_(color.h, 'h'),
|
||||
s : this.normalizeDimension_(color.s, 's'),
|
||||
v : this.normalizeDimension_(color.v, 'v')
|
||||
};
|
||||
} else {
|
||||
return this.toTinyColor_(color).toHsv();
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.normalizeDimension_ = function (value, dimension) {
|
||||
var range = this.getDimensionRange_(dimension);
|
||||
return Math.max(range[0], Math.min(range[1], value));
|
||||
};
|
||||
|
||||
/**
|
||||
* Update background colors for range inputs
|
||||
*/
|
||||
ns.HslRgbColorPicker.prototype.updateSliderBackground = function (slider) {
|
||||
var dimension = slider.dataset.dimension;
|
||||
var model = slider.dataset.model;
|
||||
|
@ -135,20 +218,13 @@
|
|||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.getSliderBackgroundColors_ = function (model, dimension) {
|
||||
var start, end;
|
||||
if (model === 'hsv') {
|
||||
start = JSON.parse(JSON.stringify(this.hsvColor));
|
||||
start[dimension] = 0;
|
||||
var color = this.getColor_(model);
|
||||
var start = pskl.utils.copy(color);
|
||||
var end = pskl.utils.copy(color);
|
||||
|
||||
end = JSON.parse(JSON.stringify(this.hsvColor));
|
||||
end[dimension] = 1;
|
||||
} else {
|
||||
start = this.tinyColor.toRgb();
|
||||
start[dimension] = 0;
|
||||
|
||||
end = this.tinyColor.toRgb();
|
||||
end[dimension] = 255;
|
||||
}
|
||||
var range = this.getDimensionRange_(dimension);
|
||||
start[dimension] = range[0];
|
||||
end[dimension] = range[1];
|
||||
|
||||
return {
|
||||
start : window.tinycolor(start).toRgbString(),
|
||||
|
@ -156,39 +232,24 @@
|
|||
};
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toTinyColor_ = function (color) {
|
||||
if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
|
||||
ns.HslRgbColorPicker.prototype.getDimensionRange_ = function (d) {
|
||||
if (d === 'h') {
|
||||
return [0, 359];
|
||||
} else if (d === 's' || d === 'v') {
|
||||
return [0, 1];
|
||||
} else if (d === 'r' || d === 'g' || d === 'b') {
|
||||
return [0, 255];
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.getColor_ = function (model) {
|
||||
var color;
|
||||
if (model === 'hsv') {
|
||||
color = this.hsvColor;
|
||||
} else if (model === 'rgb'){
|
||||
color = this.rgbColor;
|
||||
}
|
||||
return color;
|
||||
} else {
|
||||
return window.tinycolor(JSON.parse(JSON.stringify(color)));
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toHsvColor_ = function (color) {
|
||||
var isHsvColor = ['h','s','v'].every(color.hasOwnProperty.bind(color));
|
||||
if (isHsvColor) {
|
||||
return {
|
||||
h : Math.max(0, Math.min(359, color.h)),
|
||||
s : Math.max(0, Math.min(1, color.s)),
|
||||
v : Math.max(0, Math.min(1, color.v))
|
||||
};
|
||||
} else {
|
||||
return this.toTinyColor_(color).toHsv();
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.normalizeDimension_ = function (value, dimension) {
|
||||
var ranges = {
|
||||
'h' : [0, 359],
|
||||
's' : [0, 100],
|
||||
'v' : [0, 100],
|
||||
'r' : [0, 255],
|
||||
'g' : [0, 255],
|
||||
'b' : [0, 255]
|
||||
};
|
||||
var range = ranges[dimension];
|
||||
return Math.max(range[0], Math.min(range[1], value));
|
||||
} ;
|
||||
|
||||
|
||||
})();
|
|
@ -25,6 +25,9 @@
|
|||
<ul class="colors-list"></ul>
|
||||
<div class="color-picker-container">
|
||||
<div class="color-picker-spectrum"></div>
|
||||
<div class="color-picker-input">
|
||||
<input type="text" data-model="hex" data-dimension="*" class="textfield uppercase" value="#000000" />
|
||||
</div>
|
||||
<div class="color-picker-slider">
|
||||
<span>H</span>
|
||||
<input type="range" data-model="hsv" data-dimension="h" value="0" min="0" max="359" tabindex="-1"/>
|
||||
|
|
Loading…
Reference in a new issue