Skip to content

Commit

Permalink
Merge pull request #21 from Group-One-Technology/jr.refactor/entity-v…
Browse files Browse the repository at this point in the history
…ariables-restructure

Refactor: Entity Variable Restructure
  • Loading branch information
jorenrui authored Feb 27, 2024
2 parents a6adeed + bcb1765 commit 3db67f4
Show file tree
Hide file tree
Showing 15 changed files with 458 additions and 270 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
# MiniJS

## Installation

To setup MiniJS in your local machine, you can do the following:

1. Clone the [repository](https://github.com/Group-One-Technology/minijs).
2. Run `yarn` to install dependencies.
3. Run `yarn build` to create the `dist` folder -> output for MiniJS.
4. Run `yarn dev` to run the demo page locally.
5. Run `yarn build-watch` on another terminal to build the code whenever the Mini.js code changes.
6. Run `yarn test` to run the tests.

## The Idea

- HTML is great because it's easy to learn and extremely accessible. But HTML has shortcomings when it comes to building interfaces with interactivity.
Expand All @@ -22,6 +11,17 @@ To setup MiniJS in your local machine, you can do the following:

Read the [documentation](https://jorenrui.notion.site/Mini-js-7a51523e0a5845c782097782f49a5bae?pvs=74)

## Installation

To setup MiniJS in your local machine, you can do the following:

1. Clone the [repository](https://github.com/Group-One-Technology/minijs).
2. Run `yarn` to install dependencies.
3. Run `yarn build` to create the `dist` folder -> output for MiniJS.
4. Run `yarn dev` to run the demo page locally.
5. Run `yarn build-watch` on another terminal to build the code whenever the Mini.js code changes.
6. Run `yarn test` to run the tests.

## Setting State

`State` are variables that changes the UI or the DOM that uses it when they get updated.
Expand Down
2 changes: 1 addition & 1 deletion demo/observer.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<li>
<button
:click="this.parentNode.parentNode.removeChild(this.parentNode)"
:text="`my id is ${this.getAttribute('id')} (hover me to change) list item (click to delete)`"
:text="`look at my id list item (click to delete)`"
:mouseenter="el.isHovered = true"
:mouseleave="el.isHovered = false"
:class="el.isHovered ? 'bg-red-200' : ''"
Expand Down
15 changes: 8 additions & 7 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,14 @@ <h3 class="font-bold font-mono">AirBnB Search Bar:</h3>
:change="destination = this.value;
filteredDestinations = destinations.search(destination)
if (filteredDestinations.length)
selectedDestination = filteredDestinations.first
else {
const region = regions.find((region) => region.name === destination)
if (region) selectedDestination = region.name
else selectedDestination = null
}"
const region = regions.find((region) => region.name === destination)
if (region)
selectedDestination = region.name
else if (filteredDestinations.length)
selectedDestination = filteredDestinations.first
else
selectedDestination = null"
:keyup.up="selectedDestination = filteredDestinations.previousItem(selectedDestination)"
:keyup.down="selectedDestination = filteredDestinations.nextItem(selectedDestination)"
placeholder="Search destinations"
Expand Down
121 changes: 11 additions & 110 deletions lib/entity.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Lexer } from './generators/lexer'
import { Events } from './entity/events'
import { Attributes } from './entity/attributes'
import { State } from './state'
import { Mini } from './main'
import { State } from '@/state'
import { Mini } from '@/main'

const IGNORED_IDS = ['$', 'this']
import { Lexer } from '@/generators/lexer'

import { Events } from '@/entity/events'
import { Attributes } from '@/entity/attributes'
import { Data } from '@/entity/data'

export class Entity {
constructor(el, dynamicScripts = []) {
Expand All @@ -13,11 +14,10 @@ export class Entity {
this.tagName = el.tagName
this.dynamicScripts = dynamicScripts

this.variables = []
this.groupVariables = []
this.id = this.generateEntityUUID()

this.state = {}
this.data = new Data(this)
this.events = new Events(this)
this.attributes = new Attributes(this)
this.base.state.addEntity(this)
Expand Down Expand Up @@ -89,106 +89,7 @@ export class Entity {
}

getVariables() {
this._getVariablesFromAttributes()
this._getVariablesFromEvents()
this._initVariables()
}

_getVariablesFromAttributes() {
this.attributes.dynamicAttributes.forEach((name) => {
const attr = this.element.attributes[name]
if (!attr) return

if (name === ':each') {
const [_, variable] = attr.value.split(' in ')

const isNativeVariable =
typeof window[variable] === 'function' &&
window[variable].toString().indexOf('[native code]') === -1

if (isNativeVariable) return
if (variable in this.state) return
this.variables.push(variable)
}

if (!attr.value) return

const lexer = new Lexer(attr.value)

const identifiers = lexer.identifiers.filter((value) => {
if (IGNORED_IDS.includes(value)) return false
const variable = value.split('.')[0]
return !(variable in this.state)
})

if (name === ':group') this.groupVariables.push(...identifiers)
else this.variables.push(...identifiers)
})
}

_getVariablesFromEvents() {
this.events.dynamicEvents.forEach((event) => {
const expr = this.element.getAttribute(event)
if (!expr) return

const lexer = new Lexer(expr)

const identifiers = lexer.identifiers.filter((value) => {
if (IGNORED_IDS.includes(value)) return false
const variable = value.split('.')[0]
return !(variable in this.state)
})

this.variables.push(...identifiers)
})
}

_initVariables() {
this.variables = [...new Set(this.variables)]

this.variables.forEach((variable) => {
if (State.isElState(variable)) {
this.setAsGroup()

if (window[this.id] == null) {
window[this.id] = this.base.state.create({}, this.id)
}

this.base.state.addVariable(this.id, this.id)

if (variable !== State.EL_STATE) {
const [_, varName] = variable.split('.')
this.base.state.addEntityVariable(this.id, varName, this.id)
}
} else if (State.isGroupState(variable)) {
if (!this.group) this.group = this.getGroup()

// Cases where group is not found:
// - an each item with a :group directive being removed due to re-evaluation of :each attribute
if (this.group == null) return

if (window[this.group.id] == null) {
window[this.group.id] = this.base.state.create({}, this.group.id)
}

this.base.state.addVariable(this.group.id, this.id)

if (variable !== State.GROUP_STATE) {
const [_, varName] = variable.split('.')
this.base.state.addEntityVariable(this.group.id, varName, this.id)
}
} else if (typeof window[variable] === 'function') {
this.variables.splice(this.variables.indexOf(variable), 1)
} else {
try {
const [identifier] = variable.split('.')
window[identifier] = this.base.state.getState(identifier)
this.base.state.addVariable(identifier, this.id)
} catch (error) {
console.error('Failed to initialize variable:', variable, error)
}
}
})
this.data.init()
}

getGroup() {
Expand Down Expand Up @@ -271,15 +172,15 @@ export class Entity {

if (!entity) continue

variables.push(...entity.variables)
variables.push(...entity.data.variables)
entity.events.dispose()
this.base.state.removeEntity(entity)
}

// Clean up unused variables
const usedVariables = entities
.filter((entity) => !elements.includes(entity.element))
.reduce((acc, entity) => acc.concat(entity.variables), [])
.reduce((acc, entity) => acc.concat(entity.data.variables), [])

const unusedVariables = variables.filter(
(variable) => !usedVariables.includes(variable)
Expand Down
Loading

0 comments on commit 3db67f4

Please sign in to comment.