Skip to content

Commit

Permalink
Merge pull request #12 from Group-One-Technology/jr.feat/checked-attr…
Browse files Browse the repository at this point in the history
…ibute

Fix: :checked attribute when set to false
  • Loading branch information
jorenrui authored Feb 14, 2024
2 parents a129aa8 + 17caa09 commit 9c978f6
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 42 deletions.
2 changes: 1 addition & 1 deletion lib/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Events } from './entity/events'
import { Attributes } from './entity/attributes'
import { State } from './state'

export default class Entity {
export class Entity {
constructor(el) {
this.element = el
this.tagName = el.tagName
Expand Down
93 changes: 54 additions & 39 deletions lib/entity/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,19 @@ export class Attributes {
}
}

_handleError(attr, error) {
if (!this.base.isExists()) return
console.error(
`Failed to evaluate ${attr} for Entity#${this.base.id}:`,
error
)
}

async evaluate() {
await this.evaluateClass()
await this.evaluateText()
await this.evaluateValue()
await this.evaluateChecked()

for (const attr of this.dynamicAttributes) {
if (Attributes.CUSTOM_ATTRIBUTES.includes(attr)) continue
Expand All @@ -62,7 +71,8 @@ export class Attributes {
if (attr === ':parent') this.evaluateParent()
else if (attr === ':class') await this.evaluateClass()
else if (attr === ':text') await this.evaluateText()
else if ([':value', ':checked'].includes(attr)) await this.evaluateValue()
else if (attr === ':value') await this.evaluateValue()
else if (attr === ':checked') await this.evaluateChecked()
else if (attr === ':each') await this.evaluateEach()
else {
if (!this.dynamicAttributes.includes(attr))
Expand All @@ -89,8 +99,7 @@ export class Attributes {

this.base.element.setAttribute('class', updatedClassNames)
} catch (error) {
if (!this.base.isExists()) return
throw error
this._handleError(':class', error)
}
}

Expand All @@ -101,54 +110,55 @@ export class Attributes {
try {
const newText = await this.base._interpret(textExpr)

if (newText || newText == '') this.base.element.innerText = newText
if (newText || newText == '') this.base.element.textContent = newText
} catch (error) {
if (!this.base.isExists()) return
throw error
this._handleError(':text', error)
}
}

async evaluateValue() {
const valueExpr = this.base.element.getAttribute(':value')
if (!valueExpr) return
try {
const valueExpr = this.base.element.getAttribute(':value')

if (valueExpr) {
const newValue = await this.base._interpret(valueExpr)
const newValue = await this.base._interpret(valueExpr)

if (this.base.element.value !== newValue && newValue != null)
this.base.element.value = newValue
}
if (this.base.element.value !== newValue && newValue != null)
this.base.element.value = newValue
} catch (error) {
this._handleError(':value', error)
}
}

const checkedExpr = this.base.element.getAttribute(':checked')
async evaluateChecked() {
const checkedExpr = this.base.element.getAttribute(':checked')
if (!checkedExpr) return

if (checkedExpr) {
const newValue = await this.base._interpret(checkedExpr)
try {
const isChecked = await this.base._interpret(checkedExpr)

if (newValue) this.base.element.checked = newValue
}
if (this.base.element.checked !== isChecked && isChecked != null)
this.base.element.checked = isChecked
} catch (error) {
if (!this.base.isExists()) return
throw error
this._handleError(':checked', error)
}
}

async evaluateOtherAttributes() {
try {
for (const attr of this.dynamicAttributes) {
if (Attributes.CUSTOM_ATTRIBUTES.includes(attr)) continue
for (const attr of this.dynamicAttributes) {
if (Attributes.CUSTOM_ATTRIBUTES.includes(attr)) continue

const expr = this.base.element.getAttribute(attr)
if (!expr) return
const expr = this.base.element.getAttribute(attr)
if (!expr) return

try {
const newValue = await this.base._interpret(expr)
const nativeAttr = attr.slice(1)

if (this.base.element[nativeAttr] !== newValue && newValue != null)
this.base.element[nativeAttr] = newValue
} catch (error) {
this._handleError(attr, error)
}
} catch (error) {
if (!this.base.isExists()) return
throw error
}
}

Expand All @@ -159,19 +169,24 @@ export class Attributes {

const [args, iterable] = eachExpr.split(' in ')
const [variable, indexName] = args.split(',').map((v) => v.trim())
const items = await this.base._interpret(iterable)
this.childClone ||= this.base.element.innerHTML

let newHTML = ''
try {
const items = await this.base._interpret(iterable)
this.childClone ||= this.base.element.innerHTML

items.forEach((item, index) => {
// TODO: Use the lexer to replace the variables
newHTML += this.childClone
.replaceAll(indexName, index)
.replaceAll(variable, `'${escapeHTML(item)}'`)
})
let newHTML = ''

// ObserveDOM will be called for updated DOM to initialize the entities
this.base.element.innerHTML = newHTML
items.forEach((item, index) => {
// TODO: Use the lexer to replace the variables
newHTML += this.childClone
.replaceAll(indexName, index)
.replaceAll(variable, `'${escapeHTML(item)}'`)
})

// ObserveDOM will be called for updated DOM to initialize the entities
this.base.element.innerHTML = newHTML
} catch (error) {
this._handleError(':each', error)
}
}
}
14 changes: 13 additions & 1 deletion lib/entity/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ export class Events {
)
}

_handleError(attr, error) {
if (!this.base.isExists()) return
console.error(
`Failed to evaluate ${attr} for Entity#${this.base.id}:`,
error
)
}

apply() {
this.dispose()
this.evaluate(':load')
Expand Down Expand Up @@ -240,7 +248,11 @@ export class Events {
MiniJS.state.attachVariableHelpers(elVariables, this.base.id)
}

await this.base._interpret(value)
try {
await this.base._interpret(value)
} catch (error) {
this._handleError(attr, error)
}
}

disposeEvent(attr) {
Expand Down
2 changes: 1 addition & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Entity from './entity'
import { Entity } from './entity'
import { Lexer } from './generators/lexer'
import { observeDOM } from './generators/observer'
import { State } from './state'
Expand Down

0 comments on commit 9c978f6

Please sign in to comment.