mirror of
https://github.com/locomotivemtl/locomotive-boilerplate.git
synced 2026-01-15 00:55:08 +08:00
178 lines
3.6 KiB
JavaScript
178 lines
3.6 KiB
JavaScript
/**
|
|
* Escape HTML string
|
|
* @param {string} str - string to escape
|
|
* @return {string} escaped string
|
|
*/
|
|
|
|
const escapeHtml = str =>
|
|
str.replace(/[&<>'"]/g, tag => ({
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
"'": ''',
|
|
'"': '"'
|
|
}[tag]))
|
|
|
|
|
|
/**
|
|
* Unescape HTML string
|
|
* @param {string} str - string to unescape
|
|
* @return {string} unescaped string
|
|
*/
|
|
|
|
const unescapeHtml = str =>
|
|
str.replace('&', '&')
|
|
.replace('<', '<')
|
|
.replace('>', '>')
|
|
.replace(''', "'")
|
|
.replace('"', '"')
|
|
|
|
|
|
/**
|
|
* Get element data attributes
|
|
* @param {HTMLElement} node - node element
|
|
* @return {array} node data
|
|
*/
|
|
|
|
const getNodeData = node => {
|
|
|
|
// All attributes
|
|
const attributes = node.attributes
|
|
|
|
// Regex Pattern
|
|
const pattern = /^data\-(.+)$/
|
|
|
|
// Output
|
|
const data = {}
|
|
|
|
for (let i in attributes) {
|
|
if (!attributes[i]) {
|
|
continue
|
|
}
|
|
|
|
// Attributes name (ex: data-module)
|
|
let name = attributes[i].name
|
|
|
|
// This happens.
|
|
if (!name) {
|
|
continue
|
|
}
|
|
|
|
let match = name.match(pattern)
|
|
if (!match) {
|
|
continue
|
|
}
|
|
|
|
// If this throws an error, you have some
|
|
// serious problems in your HTML.
|
|
data[match[1]] = getData(node.getAttribute(name))
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Parse value to data type.
|
|
*
|
|
* @link https://github.com/jquery/jquery/blob/3.1.1/src/data.js
|
|
* @param {string} data - value to convert
|
|
* @return {mixed} value in its natural data type
|
|
*/
|
|
|
|
const rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/
|
|
const getData = data => {
|
|
if (data === 'true') {
|
|
return true
|
|
}
|
|
|
|
if (data === 'false') {
|
|
return false
|
|
}
|
|
|
|
if (data === 'null') {
|
|
return null
|
|
}
|
|
|
|
// Only convert to a number if it doesn't change the string
|
|
if (data === +data+'') {
|
|
return +data
|
|
}
|
|
|
|
if (rbrace.test(data)) {
|
|
return JSON.parse(data)
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns an array containing all the parent nodes of the given node
|
|
* @param {HTMLElement} $el - DOM Element
|
|
* @return {array} parent nodes
|
|
*/
|
|
|
|
const getParents = $el => {
|
|
|
|
// Set up a parent array
|
|
let parents = []
|
|
|
|
// Push each parent element to the array
|
|
for (; $el && $el !== document; $el = $el.parentNode) {
|
|
parents.push($el)
|
|
}
|
|
|
|
// Return our parent array
|
|
return parents
|
|
}
|
|
|
|
|
|
/**
|
|
* Find every closest parent to element
|
|
* @param {HTMLElement} $el - DOM Element
|
|
* @param {string} select - parent elements seelctor
|
|
* @return {array} parent nodes
|
|
*/
|
|
|
|
const queryClosestParent = ($el, selector) => {
|
|
|
|
// Element.matches() polyfill
|
|
if (!Element.prototype.matches) {
|
|
Element.prototype.matches =
|
|
Element.prototype.matchesSelector ||
|
|
Element.prototype.mozMatchesSelector ||
|
|
Element.prototype.msMatchesSelector ||
|
|
Element.prototype.oMatchesSelector ||
|
|
Element.prototype.webkitMatchesSelector ||
|
|
function(s) {
|
|
const matches = (this.document || this.ownerDocument).querySelectorAll(s)
|
|
const i = matches.length
|
|
while (--i >= 0 && matches.item(i) !== this) {}
|
|
return i > -1
|
|
}
|
|
}
|
|
|
|
// Get the closest matching element
|
|
for (; $el && $el !== document; $el = $el.parentNode) {
|
|
if ($el.matches(selector)) {
|
|
return $el
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
|
|
export {
|
|
escapeHtml,
|
|
unescapeHtml,
|
|
getNodeData,
|
|
getData,
|
|
getParents,
|
|
queryClosestParent
|
|
}
|