Skip to content

Commit

Permalink
Merge branch 'i18n'
Browse files Browse the repository at this point in the history
  • Loading branch information
simonwep committed May 6, 2020
2 parents 26a0c0e + 0a50674 commit dea9587
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 73 deletions.
30 changes: 22 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h1 align="center">
<h1 align="center">
<img src="https://user-images.githubusercontent.com/30767528/57573928-1e78db80-7430-11e9-940c-aecbf3226b7c.png" alt="Logo">
</h1>

Expand Down Expand Up @@ -62,7 +62,7 @@
* Responsive and auto-positioning
* Supports touch devices
* Swatches for quick-selection
* Fully accessible
* Fully accessible and i18n
* [Shadow-dom support](#selection-through-a-shadow-dom)

### Themes
Expand Down Expand Up @@ -331,11 +331,26 @@ const pickr = new Pickr({
},
},

// Button strings, brings the possibility to use a language other than English.
strings: {
save: 'Save', // Default for save button
clear: 'Clear', // Default for clear button
cancel: 'Cancel' // Default for cancel button
// Translations, these are the default values.
i18n: {

// Strings visible in the UI
'ui:dialog': 'color picker dialog',
'btn:toggle': 'toggle color picker dialog',
'btn:swatch': 'color swatch',
'btn:last-color': 'use previous color',
'btn:save': 'Save',
'btn:cancel': 'Cancel',
'btn:clear': 'Clear',

// Strings used for aria-labels
'aria:btn:save': 'save and close',
'aria:btn:cancel': 'cancel and close',
'aria:btn:clear': 'clear and close',
'aria:input': 'color input field',
'aria:palette': 'color selection area',
'aria:hue': 'hue selection slider',
'aria:opacity': 'selection slider'
}
});
```
Expand Down Expand Up @@ -414,7 +429,6 @@ If `silent` is true (Default is false), the button won't change the current colo
* off(elements`:HTMLElement(s)`, event`:String(s)`, fn`:Function`[, options `:Object`]) _- Remove an event handler._
* createElementFromString(html`:String`)`:HTMLElement` _- Creates an new HTML Element out of this string._
* eventPath(evt`:Event`)`:[HTMLElement]` _- A polyfill for the event-path event propery._
* removeAttribute(el`:HTMLElement`, name`:String`) _- Removes an attribute from a HTMLElement and returns the value._
* createFromTemplate(str`:String`) _- See [inline doumentation](https://github.com/Simonwep/pickr/blob/master/src/js/lib/utils.js#L88)._
* resolveElement(val`:String|HTMLElement`) _- Resolves a `HTMLElement`, supports `>>>` as shadow dom selector._
* adjustableInputNumbers(el`:InputElement`, mapper`:Function`) _- Creates the possibility to change the numbers in an inputfield via mouse scrolling.
Expand Down
2 changes: 1 addition & 1 deletion dist/pickr.es5.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/pickr.es5.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/pickr.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/pickr.min.js.map

Large diffs are not rendered by default.

78 changes: 53 additions & 25 deletions src/js/pickr.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,42 @@ import buildPickr from './template';

class Pickr {

// Expose pickr utils
static utils = _;

// Expose libraries for easier integration in things build on top of it
static libs = {
HSVaColor,
Moveable,
Nanopop,
Selectable
};

// Assign version and export
static version = version;

// Default strings
static I18N_DEFAULTS = {

// Strings visible in the UI
'ui:dialog': 'color picker dialog',
'btn:toggle': 'toggle color picker dialog',
'btn:swatch': 'color swatch',
'btn:last-color': 'use previous color',
'btn:save': 'Save',
'btn:cancel': 'Cancel',
'btn:clear': 'Clear',

// Strings used for aria-labels
'aria:btn:save': 'save and close',
'aria:btn:cancel': 'cancel and close',
'aria:btn:clear': 'clear and close',
'aria:input': 'color input field',
'aria:palette': 'color selection area',
'aria:hue': 'hue selection slider',
'aria:opacity': 'selection slider'
};

// Will be used to prevent specific actions during initilization
_initializingActive = true;

Expand Down Expand Up @@ -52,11 +88,12 @@ class Pickr {
lockOpacity: false,
autoReposition: true,
container: 'body',

components: {
interaction: {}
},

strings: {},
i18n: {},
swatches: null,
inline: false,
sliders: null,
Expand Down Expand Up @@ -107,7 +144,7 @@ class Pickr {

// Initialize accessibility
button.setAttribute('role', 'button');
button.setAttribute('aria-label', 'toggle color picker dialog');
button.setAttribute('aria-label', this._t('btn:toggle'));

// Initilization is finish, pickr is visible and ready for usage
const that = this;
Expand Down Expand Up @@ -138,25 +175,28 @@ class Pickr {
}));
}

// Create instance via method
static create = options => new Pickr(options);

// Does only the absolutly basic thing to initialize the components
_preBuild() {
const opt = this.options;
const {options} = this;

// Resolve elements
for (const type of ['el', 'container']) {
opt[type] = _.resolveElement(opt[type]);
options[type] = _.resolveElement(options[type]);
}

// Create element and append it to body to
// Prevent initialization errors
this._root = buildPickr(opt);
this._root = buildPickr(this);

// Check if a custom button is used
if (opt.useAsButton) {
this._root.button = opt.el; // Replace button with customized button
if (options.useAsButton) {
this._root.button = options.el; // Replace button with customized button
}

opt.container.appendChild(this._root.root);
options.container.appendChild(this._root.root);
}

_finalBuild() {
Expand Down Expand Up @@ -540,6 +580,10 @@ class Pickr {
this._eventListener[event].forEach(cb => cb(...args, this));
}

_t(key) {
return this.options.i18n[key] || Pickr.I18N_DEFAULTS[key];
}

on(event, cb) {

// Validate
Expand Down Expand Up @@ -578,7 +622,7 @@ class Pickr {

// Create new swatch HTMLElement
const el = _.createElementFromString(
`<button type="button" style="color: ${color.toRGBA().toString(0)}" aria-label="color swatch"/>`
`<button type="button" style="color: ${color.toRGBA().toString(0)}" aria-label="${this._t('btn:swatch')}"/>`
);

// Append element and save swatch data
Expand Down Expand Up @@ -864,20 +908,4 @@ class Pickr {
}
}

// Expose pickr utils
Pickr.utils = _;

// Expose libraries for easier integration in things build on top of it
Pickr.libs = {
HSVaColor,
Moveable,
Nanopop,
Selectable
};

// Create instance via method
Pickr.create = options => new Pickr(options);

// Assign version and export
Pickr.version = version;
export default Pickr;
56 changes: 34 additions & 22 deletions src/js/template.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
import * as _ from './utils/utils';

export default ({components: c, strings: s, useAsButton, inline, appClass, theme, lockOpacity: lo}) => {
export default instance => {

const {
components,
useAsButton,
inline,
appClass,
theme,
lockOpacity
} = instance.options;

// Utils
const hidden = con => con ? '' : 'style="display:none" hidden';
const t = str => instance._t(str);

const root = _.createFromTemplate(`
<div :ref="root" class="pickr">
${useAsButton ? '' : '<button type="button" :ref="button" class="pcr-button"></button>'}
<div :ref="app" class="pcr-app ${appClass || ''}" data-theme="${theme}" ${inline ? 'style="position: unset"' : ''} aria-label="color picker dialog" role="form">
<div class="pcr-selection" ${hidden(c.palette)}>
<div :obj="preview" class="pcr-color-preview" ${hidden(c.preview)}>
<button type="button" :ref="lastColor" class="pcr-last-color" aria-label="use previous color"></button>
<div :ref="app" class="pcr-app ${appClass || ''}" data-theme="${theme}" ${inline ? 'style="position: unset"' : ''} aria-label="${t('ui:dialog', 'color picker dialog')}" role="window">
<div class="pcr-selection" ${hidden(components.palette)}>
<div :obj="preview" class="pcr-color-preview" ${hidden(components.preview)}>
<button type="button" :ref="lastColor" class="pcr-last-color" aria-label="${t('btn:last-color')}"></button>
<div :ref="currentColor" class="pcr-current-color"></div>
</div>
<div :obj="palette" class="pcr-color-palette">
<div :ref="picker" class="pcr-picker"></div>
<div :ref="palette" class="pcr-palette" tabindex="0" aria-label="color selection area" role="listbox"></div>
<div :ref="palette" class="pcr-palette" tabindex="0" aria-label="${t('aria:palette')}" role="listbox"></div>
</div>
<div :obj="hue" class="pcr-color-chooser" ${hidden(c.hue)}>
<div :obj="hue" class="pcr-color-chooser" ${hidden(components.hue)}>
<div :ref="picker" class="pcr-picker"></div>
<div :ref="slider" class="pcr-hue pcr-slider" tabindex="0" aria-label="hue selection slider" role="slider"></div>
<div :ref="slider" class="pcr-hue pcr-slider" tabindex="0" aria-label="${t('aria:hue')}" role="slider"></div>
</div>
<div :obj="opacity" class="pcr-color-opacity" ${hidden(c.opacity)}>
<div :obj="opacity" class="pcr-color-opacity" ${hidden(components.opacity)}>
<div :ref="picker" class="pcr-picker"></div>
<div :ref="slider" class="pcr-opacity pcr-slider" tabindex="0" aria-label="opacity selection slider" role="slider"></div>
<div :ref="slider" class="pcr-opacity pcr-slider" tabindex="0" aria-label="${t('aria:opacity', 'opacity selection slider')}" role="slider"></div>
</div>
</div>
<div class="pcr-swatches ${c.palette ? '' : 'pcr-last'}" :ref="swatches"></div>
<div class="pcr-swatches ${components.palette ? '' : 'pcr-last'}" :ref="swatches"></div>
<div :obj="interaction" class="pcr-interaction" ${hidden(Object.keys(c.interaction).length)}>
<input :ref="result" class="pcr-result" type="text" spellcheck="false" ${hidden(c.interaction.input)}>
<div :obj="interaction" class="pcr-interaction" ${hidden(Object.keys(components.interaction).length)}>
<input :ref="result" class="pcr-result" type="text" spellcheck="false" ${hidden(components.interaction.input)} aria-label="${t('aria:input', 'color input field')}">
<input :arr="options" class="pcr-type" data-type="HEXA" value="${lo ? 'HEX' : 'HEXA'}" type="button" ${hidden(c.interaction.hex)}>
<input :arr="options" class="pcr-type" data-type="RGBA" value="${lo ? 'RGB' : 'RGBA'}" type="button" ${hidden(c.interaction.rgba)}>
<input :arr="options" class="pcr-type" data-type="HSLA" value="${lo ? 'HSL' : 'HSLA'}" type="button" ${hidden(c.interaction.hsla)}>
<input :arr="options" class="pcr-type" data-type="HSVA" value="${lo ? 'HSV' : 'HSVA'}" type="button" ${hidden(c.interaction.hsva)}>
<input :arr="options" class="pcr-type" data-type="CMYK" value="CMYK" type="button" ${hidden(c.interaction.cmyk)}>
<input :arr="options" class="pcr-type" data-type="HEXA" value="${lockOpacity ? 'HEX' : 'HEXA'}" type="button" ${hidden(components.interaction.hex)}>
<input :arr="options" class="pcr-type" data-type="RGBA" value="${lockOpacity ? 'RGB' : 'RGBA'}" type="button" ${hidden(components.interaction.rgba)}>
<input :arr="options" class="pcr-type" data-type="HSLA" value="${lockOpacity ? 'HSL' : 'HSLA'}" type="button" ${hidden(components.interaction.hsla)}>
<input :arr="options" class="pcr-type" data-type="HSVA" value="${lockOpacity ? 'HSV' : 'HSVA'}" type="button" ${hidden(components.interaction.hsva)}>
<input :arr="options" class="pcr-type" data-type="CMYK" value="CMYK" type="button" ${hidden(components.interaction.cmyk)}>
<input :ref="save" class="pcr-save" value="${s.save || 'Save'}" type="button" ${hidden(c.interaction.save)} aria-label="save and exit">
<input :ref="cancel" class="pcr-cancel" value="${s.cancel || 'Cancel'}" type="button" ${hidden(c.interaction.cancel)} aria-label="cancel and exit">
<input :ref="clear" class="pcr-clear" value="${s.clear || 'Clear'}" type="button" ${hidden(c.interaction.clear)} aria-label="clear and exit">
<input :ref="save" class="pcr-save" value="${t('btn:save')}" type="button" ${hidden(components.interaction.save)} aria-label="${t('aria:btn:save')}">
<input :ref="cancel" class="pcr-cancel" value="${t('btn:cancel')}" type="button" ${hidden(components.interaction.cancel)} aria-label="${t('aria:btn:cancel')}">
<input :ref="clear" class="pcr-clear" value="${t('btn:clear')}" type="button" ${hidden(components.interaction.clear)} aria-label="${t('aria:btn:clear')}">
</div>
</div>
</div>
Expand All @@ -55,7 +67,7 @@ export default ({components: c, strings: s, useAsButton, inline, appClass, theme
// Select option which is not hidden
int.options.find(o => !o.hidden && !o.classList.add('active'));

// Create method to find currenlty active option
// Append method to find currently active option
int.type = () => int.options.find(e => e.classList.contains('active'));
return root;
}
24 changes: 10 additions & 14 deletions src/js/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,6 @@ export function createElementFromString(html) {
return div.firstElementChild;
}

/**
* Removes an attribute from a HTMLElement and returns the value.
* @param el
* @param name
* @return {string}
*/
export function removeAttribute(el, name) {
const value = el.getAttribute(name);
el.removeAttribute(name);
return value;
}

/**
* Creates a new html element, every element which has
* a ':ref' attribute will be saved in a object (which will be returned)
Expand All @@ -78,10 +66,18 @@ export function removeAttribute(el, name) {
*
* @param str - The HTML String.
*/

export function createFromTemplate(str) {

// Removes an attribute from a HTMLElement and returns the value.
const removeAttribute = (el, name) => {
const value = el.getAttribute(name);
el.removeAttribute(name);
return value;
};

// Recursive function to resolve template
function resolve(element, base = {}) {
const resolve = (element, base = {}) => {

// Check key and container attribute
const con = removeAttribute(element, ':obj');
Expand All @@ -103,7 +99,7 @@ export function createFromTemplate(str) {
}

return base;
}
};

return resolve(createElementFromString(str));
}
Expand Down

0 comments on commit dea9587

Please sign in to comment.