Skip to content

Commit

Permalink
fix: field preview updates
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinchappell committed Nov 7, 2024
1 parent 81815a1 commit 5de9636
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 163 deletions.
91 changes: 28 additions & 63 deletions src/lib/js/common/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const iconFontTemplates = {
fontello: icon => `<i class="${iconPrefix}${icon}">${icon}</i>`,
}

const inputTags = new Set(['input', 'textarea', 'select'])

/**
* General purpose markup utilities and generator.
*/
Expand All @@ -31,35 +33,31 @@ class DOM {
* Set defaults, store references to key elements
* like stages, rows, columns etc
*/
constructor() {
this.options = Object.create(null)
this.styleSheet = (() => {
const style = document.createElement('style')
style.setAttribute('media', 'screen')
style.setAttribute('type', 'text/css')
style.appendChild(document.createTextNode(''))
document.head.appendChild(style)
return style.sheet
})()
constructor(options = Object.create(null)) {
this.options = options
}

set setOptions(options) {
this.options = merge(Object.assign({}, this.options, options))
this.options = merge(this.options, options)
}

/**
* Ensure elements have proper tagName
* @param {Object|String} elem
* @return {Object} valid element object
*/
processTagName(elem) {
processTagName(elemArg) {
let elem = elemArg
let tagName
if (typeof elem === 'string') {
tagName = elem
elem = { tag: tagName }
return elem
}

if (elem.attrs) {
const { tag, ...restAttrs } = elem.attrs
// this is used for interchangeable tagNames like h1, h2, h3 etc
if (tag) {
if (typeof tag === 'string') {
tagName = tag
Expand Down Expand Up @@ -92,12 +90,11 @@ class DOM {
* @return {Object} DOM Object
*/
create = (elemArg, isPreview = false) => {
let elem = elemArg
if (!elem) {
if (!elemArg) {
return
}

elem = this.processTagName(elem)
const { className, options, ...elem } = this.processTagName(elemArg)
const _this = this
let childType
const { tag } = elem
Expand Down Expand Up @@ -147,41 +144,29 @@ class DOM {
processed.push('tag')

// check for root className property
if (elem.className) {
const { className } = elem
elem.attrs = Object.assign({}, elem.attrs, { className })
delete elem.className
if (className) {
elem.attrs = { ...elem.attrs, className }
}

// Append Element Content
if (elem.options) {
let { options } = elem
options = this.processOptions(options, elem, isPreview)
if (options) {
const processedOptions = this.processOptions(options, elem, isPreview)
if (this.holdsContent(element) && tag !== 'button') {
// mainly used for <select> tag
appendChildren.array.call(this, options)
delete elem.content
appendChildren.array.call(this, processedOptions)
elem.content = undefined
} else {
h.forEach(options, option => {
h.forEach(processedOptions, option => {
wrap.children.push(_this.create(option, isPreview))
})
if (elem.attrs.className) {
wrap.className = elem.attrs.className
}
wrap.config = Object.assign({}, elem.config)
wrap.config = { ...elem.config }
return this.create(wrap, isPreview)
}
processed.push('options')
}

// disabling all initially selected options because we are setting them manualy at #330
if (element.tagName === 'OPTION') {
const timeout = setTimeout(() => {
element.selected = false
clearTimeout(timeout)
}, 0)
}

// Set element attributes
if (elem.attrs) {
_this.processAttrs(elem, element, isPreview)
Expand Down Expand Up @@ -361,17 +346,7 @@ class DOM {
}

if (value) {
// if multiple options are being used and they are being selected automatically, the browser wants the element
// to be rendered before setting the selected-attribute. Hence, we're setting the 'selected'-property at the beginning of
// the next iteration of the event-loop.
if (element.tagName === 'OPTION' && name === 'selected') {
const timeout = setTimeout(() => {
element.setAttribute(name, value)
clearTimeout(timeout)
}, 0)
} else {
element.setAttribute(name, value)
}
element.setAttribute(name, value === true ? '' : value)
}
}
}
Expand Down Expand Up @@ -429,17 +404,6 @@ class DOM {
}
}

makeOption = ([value, label], selected, i18nKey) => {
const option = {
value,
label: i18n.get(`${i18nKey}.${label}`) || label,
}
if (value === selected) {
option.selected = true
}
return option
}

/**
* Extend Array of option config objects
* @param {Array} options
Expand Down Expand Up @@ -558,11 +522,12 @@ class DOM {
* @param {String|Object} tag tagName or DOM element
* @return {Boolean} isInput
*/
isInput(tag) {
isInput(tagArg) {
let tag = tagArg
if (typeof tag !== 'string') {
tag = tag.tagName
}
return ['input', 'textarea', 'select'].indexOf(tag) !== -1
return inputTags.has(tag)
}

/**
Expand Down Expand Up @@ -621,7 +586,7 @@ class DOM {

if (fMap) {
// for attribute will prevent label focus
delete fieldLabel.attrs.for
fieldLabel.attrs.for = undefined
fieldLabel.attrs.contenteditable = true
fieldLabel.fMap = fMap
}
Expand Down Expand Up @@ -707,9 +672,8 @@ class DOM {
if (!children.length) {
if (!this.isStage(parent)) {
return this.removeEmpty(parent)
} else {
this.emptyClass(parent)
}
return this.emptyClass(parent)
}
}

Expand Down Expand Up @@ -833,7 +797,8 @@ class DOM {
* @param {Object} elem DOM element
* @param {Boolean} state
*/
toggleSortable(elem, state) {
toggleSortable(elem, stateArg) {
let state = stateArg
const fType = componentType(elem)
if (!fType) {
return
Expand Down
35 changes: 25 additions & 10 deletions src/lib/js/common/utils/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
COMPONENT_TYPE_CLASSNAMES_REGEXP,
COMPONENT_TYPE_CLASSNAMES_LOOKUP,
CHILD_TYPE_MAP,
ANIMATION_SPEED_SLOW,
} from '../../constants.js'
import mergeWith from 'lodash/mergeWith.js'

Expand Down Expand Up @@ -273,20 +274,34 @@ export const typeIsChildOf = (childType, parentType) => CHILD_TYPE_MAP.get(paren
* @param {number} limit - The number of milliseconds to throttle invocations to.
* @returns {Function} - Returns the new throttled function.
*/
export function throttle(callback, limit) {
let wait = false
return function () {
if (!wait) {
callback(...arguments)
wait = true
const timeout = setTimeout(() => {
wait = false
clearTimeout(timeout)
}, limit)
export function throttle(callback, limit = ANIMATION_SPEED_SLOW) {
let lastCall = 0
return function (...args) {
const now = Date.now()
if (now - lastCall >= limit) {
lastCall = now
callback.apply(this, args)
}
}
}

/**
* Creates a debounced function that delays invoking the provided function until after the specified delay.
*
* @param {Function} fn - The function to debounce.
* @param {number} [delay=ANIMATION_SPEED_SLOW] - The number of milliseconds to delay invocation.
* @returns {Function} - A new debounced function.
*/
export function debounce(fn, delay = ANIMATION_SPEED_SLOW) {
let timeoutID
return function (...args) {
if (timeoutID) {
clearTimeout(timeoutID)
}
timeoutID = setTimeout(() => fn.apply(this, args), delay)
}
}

export function identity(value) {
return value
}
Expand Down
Loading

0 comments on commit 5de9636

Please sign in to comment.