-
-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
temporary fix for optional-chaining support
- Loading branch information
Showing
12 changed files
with
310 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export const defaults = { | ||
classNames: { | ||
active: 'gl-active', | ||
base: 'gl-star-rating', | ||
selected: 'gl-selected', | ||
}, | ||
clearable: true, | ||
maxStars: 10, | ||
stars: null, | ||
tooltip: 'Select a Rating', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
export const addRemoveClass = (el, bool, className) => { | ||
el.classList[bool ? 'add' : 'remove'](className); | ||
} | ||
|
||
export const createSpanEl = (attributes) => { | ||
const el = document.createElement('span'); | ||
attributes = attributes || {}; | ||
for (let key in attributes) { | ||
el.setAttribute(key, attributes[key]); | ||
} | ||
return el; | ||
} | ||
|
||
export const inRange = (value, min, max) => { | ||
return /^\d+$/.test(value) && min <= value && value <= max; | ||
} | ||
|
||
export const insertSpanEl = (el, after, attributes) => { | ||
const newEl = createSpanEl(attributes); | ||
el.parentNode.insertBefore(newEl, after ? el.nextSibling : el); | ||
return newEl; | ||
} | ||
|
||
export const isEmpty = (el) => { | ||
return null === el.getAttribute('value') || '' === el.value; | ||
} | ||
|
||
export const merge = (...args) => { // adapted from https://github.com/firstandthird/aug | ||
const results = {}; | ||
args.forEach(prop => { | ||
Object.keys(prop || {}).forEach(propName => { | ||
if (args[0][propName] === undefined) return; // restrict keys to the defaults | ||
const propValue = prop[propName]; | ||
if (type(propValue) === 'Object' && type(results[propName]) === 'Object') { | ||
results[propName] = merge(results[propName], propValue); | ||
return; | ||
} | ||
results[propName] = propValue; | ||
}); | ||
}); | ||
return results; | ||
} | ||
|
||
export const type = (value) => { | ||
return {}.toString.call(value).slice(8, -1); | ||
}; | ||
|
||
export const values = (selectEl) => { | ||
const values = []; | ||
[].forEach.call(selectEl.options, (el) => { | ||
const value = parseInt(el.value, 10) || 0; | ||
if (value > 0) { | ||
values.push({ | ||
index: el.index, | ||
text: el.text, | ||
value: value, | ||
}) | ||
} | ||
}); | ||
return values.sort((a, b) => a.value - b.value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/**! | ||
* Star Rating | ||
* @version: 4.0.2 | ||
* @author: Paul Ryley (http://geminilabs.io) | ||
* @url: https://github.com/pryley/star-rating.js | ||
* @license: MIT | ||
*/ | ||
|
||
import { defaults } from './defaults' | ||
import { merge, type } from './helpers' | ||
import { Widget } from './widget' | ||
|
||
class StarRating { | ||
constructor (selector, props) { // (HTMLSelectElement|NodeList|string, object):void | ||
this.destroy = this.destroy.bind(this); | ||
this.rebuild = this.rebuild.bind(this); | ||
this.widgets = []; | ||
this.buildWidgets(selector, props); | ||
} | ||
|
||
buildWidgets(selector, props) { // (HTMLSelectElement|NodeList|string, object):void | ||
this.queryElements(selector).forEach(el => { | ||
const options = merge(defaults, props, JSON.parse(el.getAttribute('data-options'))); | ||
if ('SELECT' === el.tagName && !el.parentNode.classList.contains(options.classNames.base)) { | ||
this.widgets.push(new Widget(el, options)); | ||
} | ||
}); | ||
} | ||
|
||
destroy () { // ():void | ||
this.widgets.forEach(widget => widget.destroy()); | ||
} | ||
|
||
queryElements (selector) { // (HTMLSelectElement|NodeList|string):array | ||
if ('HTMLSelectElement' === type(selector)) { | ||
return [selector]; | ||
} | ||
if ('NodeList' === type(selector)) { | ||
return [].slice.call(selector); | ||
} | ||
if ('String' === type(selector)) { | ||
return [].slice.call(document.querySelectorAll(selector)) | ||
} | ||
return [] | ||
} | ||
|
||
rebuild () { // ():void | ||
this.widgets.forEach(widget => widget.build()); | ||
} | ||
} | ||
|
||
export default StarRating |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import { addRemoveClass, createSpanEl, inRange, insertSpanEl, isEmpty, values } from './helpers' | ||
import { supportsPassiveEvents } from 'detect-it' | ||
|
||
export class Widget { | ||
constructor (el, props) { // (HTMLElement, object):void | ||
this.direction = window.getComputedStyle(el, null).getPropertyValue('direction'); | ||
this.el = el; | ||
this.events = { | ||
change: this.onChange.bind(this), | ||
keydown: this.onKeyDown.bind(this), | ||
mousedown: this.onPointerDown.bind(this), | ||
mouseleave: this.onPointerLeave.bind(this), | ||
mousemove: this.onPointerMove.bind(this), | ||
reset: this.onReset.bind(this), | ||
touchend: this.onPointerDown.bind(this), | ||
touchmove: this.onPointerMove.bind(this), | ||
}; | ||
this.indexActive = null; // the active span index | ||
this.indexSelected = null; // the selected span index | ||
this.props = props; | ||
this.tick = null; | ||
this.ticking = false; | ||
this.values = values(el); | ||
this.widgetEl = null; | ||
if (inRange(this.values.length, 1, this.props.maxStars)) { | ||
this.build(); | ||
} else { | ||
this.destroy(); | ||
} | ||
} | ||
|
||
build () { // ():void | ||
this.destroy(); | ||
this.buildWidget(); | ||
this.changeIndexTo((this.indexSelected = this.selected()), true); // set the initial value | ||
this.handleEvents('add'); | ||
} | ||
|
||
buildWidget () { // ():void | ||
const parentEl = insertSpanEl(this.el, false, { class: this.props.classNames.base }); | ||
parentEl.appendChild(this.el); | ||
parentEl.classList.add(this.props.classNames.base + '--' + this.direction); | ||
const widgetEl = insertSpanEl(this.el, true, { class: this.props.classNames.base + '--stars' }); | ||
this.values.forEach((item, index) => { | ||
const el = createSpanEl({ 'data-index': index, 'data-value': item.value }); | ||
if ('function' === typeof this.props.stars) { | ||
this.props.stars.call(this, el, item, index); | ||
} | ||
[].forEach.call(el.children, el => el.style.pointerEvents = 'none'); | ||
widgetEl.innerHTML += el.outerHTML; | ||
}) | ||
if (this.props.tooltip) { | ||
widgetEl.setAttribute('role', 'tooltip'); | ||
} | ||
this.widgetEl = widgetEl; | ||
} | ||
|
||
changeIndexTo (index, force) { // (int):void | ||
if (this.indexActive !== index || force) { | ||
this.widgetEl.childNodes.forEach((el, i) => { // i starts at zero | ||
addRemoveClass(el, i <= index, this.props.classNames.active); | ||
addRemoveClass(el, i === this.indexSelected, this.props.classNames.selected); | ||
}); | ||
if ('function' !== typeof this.props.stars) { // @v3 compat | ||
this.widgetEl.classList.remove('s' + (10 * (this.indexActive + 1))); | ||
this.widgetEl.classList.add('s' + (10 * (index + 1))); | ||
} | ||
if (this.props.tooltip) { | ||
const label = index < 0 ? this.props.tooltip : this.values[index].text; | ||
this.widgetEl.setAttribute('aria-label', label); | ||
} | ||
this.indexActive = index; | ||
} | ||
this.ticking = false; | ||
} | ||
|
||
destroy () { // ():void | ||
this.indexActive = null; // the active span index | ||
this.indexSelected = this.selected(); // the selected span index | ||
const wrapEl = this.el.parentNode; | ||
if (wrapEl.classList.contains(this.props.classNames.base)) { | ||
this.handleEvents('remove'); | ||
wrapEl.parentNode.replaceChild(this.el, wrapEl); | ||
} | ||
} | ||
|
||
eventListener (el, action, events, items) { // (HTMLElement, string, array, object):void | ||
events.forEach(ev => el[action + 'EventListener'](ev, this.events[ev], items || false)); | ||
} | ||
|
||
handleEvents (action) { // (string):void | ||
const formEl = this.el.closest('form'); | ||
if (formEl && formEl.tagName === 'FORM') { | ||
this.eventListener(formEl, action, ['reset']); | ||
} | ||
this.eventListener(this.el, action, ['change']); // always trigger the change event, even when SELECT is disabled | ||
if ('add' === action && this.el.disabled) return; | ||
this.eventListener(this.el, action, ['keydown']); | ||
this.eventListener(this.widgetEl, action, ['mousedown', 'mouseleave', 'mousemove', 'touchend', 'touchmove'], | ||
supportsPassiveEvents ? { passive: false } : false | ||
); | ||
} | ||
|
||
indexFromEvent (ev) { // (MouseEvent|TouchEvent):void | ||
const origin = ev.touches?.[0] || ev.changedTouches?.[0] || ev; | ||
const el = document.elementFromPoint(origin.clientX, origin.clientY); | ||
return parseInt(el.dataset.index || -1, 10); | ||
} | ||
|
||
onChange () { // ():void | ||
this.changeIndexTo(this.selected(), true); | ||
} | ||
|
||
onKeyDown (ev) { // (KeyboardEvent):void | ||
const key = ev.key.slice(5); | ||
if (!~['Left', 'Right'].indexOf(key)) return; | ||
let increment = key === 'Left' ? -1 : 1; | ||
if (this.direction === 'rtl') { | ||
increment *= -1; | ||
} | ||
const maxIndex = this.values.length - 1; | ||
const minIndex = -1; | ||
const index = Math.min(Math.max(this.selected() + increment, minIndex), maxIndex); | ||
this.selectValue(index); | ||
} | ||
|
||
onPointerDown (ev) { // (MouseEvent|TouchEvent):void | ||
ev.preventDefault(); | ||
this.el.focus(); // highlight the rating field | ||
let index = this.indexFromEvent(ev); | ||
if (this.props.clearable && index === this.indexSelected) { | ||
index = -1; // remove the value | ||
} | ||
this.selectValue(index); | ||
} | ||
|
||
onPointerLeave (ev) { // (MouseEvent):void | ||
ev.preventDefault(); | ||
cancelAnimationFrame(this.tick); | ||
requestAnimationFrame(() => this.changeIndexTo(this.indexSelected)); | ||
} | ||
|
||
onPointerMove (ev) { // (MouseEvent|TouchEvent):void | ||
ev.preventDefault(); | ||
if (!this.ticking) { | ||
this.tick = requestAnimationFrame(() => this.changeIndexTo(this.indexFromEvent(ev))); | ||
this.ticking = true; | ||
} | ||
} | ||
|
||
onReset () { // ():void | ||
const index = this.el.querySelector('[selected]')?.index; | ||
this.selectValue(this.values.findIndex(val => val.index === index)); | ||
} | ||
|
||
selected () { // ():int | ||
return this.values.findIndex(val => val.value === +this.el.value); // get the selected span index | ||
} | ||
|
||
selectValue (index) { // (int):void | ||
this.el.value = this.values[index]?.value || ''; // first set the value | ||
this.indexSelected = this.selected(); // get the actual index from the selected value | ||
this.el.dispatchEvent(new Event('change')); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"plugins": [ | ||
"@babel/plugin-proposal-optional-chaining", | ||
["prismjs", { | ||
"css": false, | ||
"languages": ["javascript", "php", "html", "css"], | ||
"plugins": ["line-numbers"] | ||
}] | ||
], | ||
"presets": [ | ||
"@wordpress/default" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
.* | ||
!.babelrc | ||
!.gitattributes | ||
!.gitignore | ||
!.jshintrc | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters