Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More โ†’
Socket
Sign inDemoInstall
Socket

dom-render

Package Overview
Dependencies
Maintainers
1
Versions
98
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dom-render

dom-render

  • 1.0.54
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
8
decreased by-83.33%
Maintainers
1
Weekly downloads
ย 
Created
Source

Single Page Application Framworks npm version license Chat Github

Our primary goals are

  • view template engine
  • Dom control and reorder
  • all internal variables are managed by proxy. (DomRenderProxy)

๐Ÿš€ Quick start

npm install dom-render

๐Ÿ˜ƒ examples


๐Ÿ“„ Code description

initialized

<!doctype html><html lang="en"><body id="app"></body></html>
const target = document.querySelector('#app');
const data = DomRender.run({name: 'my name is dom-render'}, target);
data.name = 'modify name';

print and call

<div>${this.name}</div>
<div>${this.office.addr.first}, ${this.office.addr.last}, ${this.office.addr.street} (${this.office.name})</div>
<div dr="this.office.addr.street">${this.getOfficeFullAddr()}</div>

dr-if

<div dr-if="true">true</div>
<div dr-if="this.gender==='M'">gender: M</div>

dr-for, dr-for-of

<div dr-for="var i = 0; i < this.friends.length; i++"> friend</div>
<div dr-for-of="this.friends"> ${#it#.name}</div>
<div dr-for-of="$range(10, 20)"><div>${#it#}</div><div>
<div dr-for="var i = 1 ; i <= 9 ; i++" dr-it="i">
    ${#it#} *
    <scope dr-for="var y = 1 ; y <= 9 ; y++" dr-it="y" dr-var="superIt=#it#" dr-strip="true">
        #it# = ${var.superIt * #it#}
    </scope>
</div>

dr-repeat

<div dr-repeat="10"><div>#it#</div></div>
<div dr-repeat="$range(10, 20)"><div>#it#</div></div>
<div dr-repeat="$range(10, 20, 5)"><div>#it#</div></div>
<div dr-repeat="$range('10..5, 2')"><div>#it#</div></div>

dr-inner-text, dr-inner-html

<div dr-inner-text="'<b>aa</b> <button dr-event-click=\'alert(1)\'>aa</button>'"> friend</div>
<div dr-inner-html="'<b>aa</b> <button dr-event-click=\'alert(1)\'>aa</button>'"> friend</div>

event

dr-event-(name)

  • click, mousedown, mouseup, dblclick, mouseover, mouseout, mousemove, mouseenter, mouseleave, contextmenu, keyup, keydown, keypress, change, input, submit, resize, focus, blur
  • ref: element
  • variable: $event, $target
click: <button dr-event-click="this.name = 'name' + new Date()">click</button> <br>
change: <input type="text" dr-event-change="this.name = $target.value"> <br>
input: <input type="text" dr-event-input="this.name = $target.value"> <br>
keyup: <input type="text" dr-event-keyup="this.name = $target.value"> <br>
...
keydown: <input type="text" dr-event-keydown="this.name = $target.value"><br>
submit: <form dr-event-submit="console.log($event); $event.preventDefault();"><input type="text"> <button type="submit">submit</button></form><br>

dr-window-event-popstate

  • ref: window
  • variable: $target
window-event-popstate: <input type="text" dr-window-event-popstate="alert(this.name)"><br>

dr-event

  • other event
  • ref: element
  • variable: $params, $event
<input dr-event:bind='eventName1, eventName2' dr-event="console.log('event', $params, $event)"  type="text">

dr-value

  • The value is assigned the first time.

dr-value-link

  • Value and variable values are referencing each other. It affects each other when changing. (Immediate reflection event: input)
dr-value: <input type="text" dr-value="this.office.name"> <br>
dr-value-link: <input type="text" dr-value-link="this.office.addr.street"> <br>

dr-attr

<textarea dr-attr="{rows: this.age/2, cols: this.age}"></textarea>
<div dr-attr="{wow: '123', good: 123444}"></div>
<div dr-attr="['wow=123', 'good=123444']"></div>
<div dr-attr="'wow=123, good=123444'"></div>

dr-class

<div dr-class="{big: this.age > 50, red: this.age > 50}">
<div dr-class="'big yellow ' + (this.age > 50 ? 'old' : 'young')">
<div dr-class="['small', 'yellow']">

dr-style

<div dr-style="{fontSize: this.age + 'px'}"> style </div>
<div dr-style="{'font-size': '20px'}"> style</div>
<div dr-style="'font-size: ' + this.age +'px; margin: ' + this.age + 'px'"> style </div>
<div dr-style="['font-size: ' + this.age +'px', 'margin: ' + this.age + 'px']"> style </div>

dr-strip

as-is

<div dr-strip="true"><span>hello</span></div>

to-be

<span>hello</span>

dr-on-init

<input dr-on-init="this.onInitElement">

dr-before, dr-after

<div dr-before="console.log('process before')" dr-after="console.log('process after')"></div>

dr-complete

<select dr-value-link="this.currentContry" dr-event-change="this.contryChange($event)">
    <option dr-for-of="this.languages" dr-value="#it#.key" dr-complete="this.currentContry='defaultValue'">${#it#.title}</option>
</select>

LifeCycle

* OnInitRender
  - onInitRender(): init render call

Script

new DomRender.run(obj, target, {
  scripts: {
    concat: function (head: string, tail: string) {
      return head + tail; 
    }
  }
});

using script

const data = config.scripts.concat('head', 'tail')
<div>${$scripts.concat('head', 'tail')}</div>
<div dr-if="$scripts.concat('wow', 'good') === 'wowgood'"> is wowgood</div>

Component

export namespace Profile {
  export const templat = '<div>aaaaa${this.name}aaaaa </div>';
  export const styles = ['p {color: red}', 'div {margin: ${this.margin} + \'px\' }'];
  export class Component {
    public name = 'default name';
    public margin = 5;
    public say() {
        console.log('say!~')
    }
  }
}

new DomRender.run(obj, target, {
  targetElements: [
    RawSet.createComponentTargetElement('my-element', (e, o, r) => new Profile.Component(), Profile.templat, Profile.styles, scripts)
  ],
});

using component

<my-element dr-on-init="$component.say();"></my-element>
  • attribute
    • dr-on-init: component created init call script
      • $component: component instance
      • $element: element instance
      • $attribute: element attribute object
      • $innerHTML: element innerHTML string

dr-form

  • event: change
  • modify change: dr-form:event="input"
class User {
  form = {};
  submit() {
    const form = (this.form as any)
    console.log('submit->', form, form.name, form.age, form.addr);
  }
}
<form dr-form="this.form" dr-event-submit="this.submit(); $event.preventDefault();">
  name: <input name="name">
  age: <input name="age">
  addr: <input dr-form:event="input" name="addr">
  <button type="submit"> aa</button>
</form>

validation

  <div class="row mb-3">
        <div class="col">
            <span>์•„์ด๋””</span>
            <input class="w-100" type="text" name="id" placeholder="์•„์ด๋””" dr-value-link="this.form.id.value" dr-event-blur="this.form.id.valid()" required/>
            <span dr-on-init="this.form.id.msgElement" class="d-none"></span>
        </div>
    </div>
    <div class="row mb-3">
        <div class="col">
            <span>๋น„๋ฐ€๋ฒˆํ˜ธ</span>
            <input class="w-100" type="password" name="id" placeholder="์ˆซ์ž, ์˜๋ฌธ, ํŠน์ˆ˜๋ฌธ์ž ์กฐํ•ฉ ์ตœ์†Œ 8์ž~20์ž" dr-value-link="this.form.password.value" dr-event-blur="this.form.password.valid()" required/>
            <span dr-on-init="this.form.password.msgElement" >password valid message section</span>
            <input class="w-100" type="password" name="id" placeholder="๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์ž…๋ ฅ"  dr-value-link="this.form.confirmPassword" required/>
            <span dr-class="{'d-block': this.form.password != this.form.confirmPassword, 'text-danger': this.form.password != this.form.confirmPassword}">2nd input password valid message section</span>
        </div>
    </div>
    <div class="row mb-3">
        <div class="col">
            <span>์ด๋ฉ”์ผ</span>
            <input class="w-100" type="email" name="id" placeholder="์ด๋ฉ”์ผ" dr-value-link="this.form.email" required/>
            <span class="">2nd input password valid message section</span>
        </div>
    </div>
</div>
class SignUp {
 public form = new class extends Validation {
        id = new class extends Validation {
            public msgElement!: HTMLElement;
            valid(): boolean {
                let valid = false;
                if (this.length == 0) {
                    this.msgElement.className = 'd-block text-danger';
                    this.msgElement.textContent = '์•„์ด๋””๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.';
                } else if (this.length < 3 || this.length > 20) {
                    this.msgElement.className = 'd-block text-danger';
                    this.msgElement.textContent = '์•„์ด๋””๋Š” 4๊ธ€์ž ์ด์ƒ 20์ž ๋ฏธ๋งŒ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.';
                } else {
                    let isExist = false;
                    if (isExist) {
                        this.msgElement.className = 'd-block text-danger';
                        this.msgElement.textContent = '์ด๋ฏธ ์‚ฌ์šฉ์ค‘์ธ ์•„์ด๋””์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์•„์ด๋””๋ฅผ ์ด์šฉํ•ด์ฃผ์„ธ์š”.';
                    } else {
                        this.msgElement.className = 'd-block text-success';
                        this.msgElement.textContent = '์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์•„์ด๋””์ž…๋‹ˆ๋‹ค.';
                        valid = true;
                    }
                }
                return valid;
            }
        }();
        password = new class extends Validation {
            public msgElement!: HTMLElement;
            valid(): boolean {
                let valid = false;
                let regExp = /^.*(?=.)(?=.*[0-9])(?=.*[a-zA-Z]).*$/;
                const ERROR_REQUIRE_PW = '๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.';
                const ERROR_PW_LENGTH = '๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 8๊ธ€์ž~20๊ธ€์ž๋กœ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.';
                const ERROR_PW_REGEXP = '๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์ˆซ์ž, ์˜๋ฌธ, ํŠน์ˆ˜๋ฌธ์ž ์กฐํ•ฉ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.';
                const SUCCESS_AVAILABLE_USER_PW = '์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.';
                if (this.length == 0) {
                    this.msgElement.className = 'd-block text-danger';
                    this.msgElement.textContent = ERROR_REQUIRE_PW;
                } else if (this.length < 8 || this.length > 20) {
                    this.msgElement.className = 'd-block text-danger';
                    this.msgElement.textContent = ERROR_PW_LENGTH;
                } else {
                    if (regExp.test(this.value)) {
                        this.msgElement.className = 'd-block text-success';
                        this.msgElement.textContent = SUCCESS_AVAILABLE_USER_PW;
                        valid = true;
                    } else {
                        this.msgElement.className = 'd-block text-danger';
                        this.msgElement.textContent = ERROR_PW_REGEXP;
                    }
                }
                return valid;
            }
        }();
        confirmPassword = new class extends Validation {
            value = '';
            valid(): boolean {
                return true;
            }
        }();
        email = new class extends Validation {
            value = '';
            valid(): boolean {
                return true;
            }
        }();
        valid() {
            return this.childValid()
        }
    }();
}

dr-form (normal)

form = new class extends Validation {
    id = new class extends Validation {
        valid(): boolean {
            return false;
        }
    }()

    valid(): boolean {
        return false;
    }
}();
console.log(form.id.value)
<form dr-form="this.form" dr-event-submit="this.submit(); $event.preventDefault();">
    <input name="id"> <!-- id value -->
    <input name=""> <!-- root value -->
    <button type="submit"> submit</button>
</form>

dr-form (multiple validation)

form = new class extends Validation {
    id = new class extends Validation {
        valid(): boolean {
            return this.length > 0;
        }
    }();

    all = new class extends Validations<string, HTMLInputElement> {
        valid(): boolean {
            const inChecked = this.values?.filter(it => it.target && !it.target.checked) ?? [];
            return !(inChecked.length > 0)
        }
    }()

    gender = new class extends Validations<string, HTMLInputElement> {
        valid(): boolean {
            const inChecked = this.values?.filter(it => it.target && !it.target.checked) ?? [];
            return inChecked.length > 0
        }
    }()

    valid(): boolean {
        return this.valids();
    }
}();

submit() {
  const form = (this.form as any)
  console.log('submit222->', form.valid());
}
<form dr-form="this.form" dr-event-submit="this.submit(); $event.preventDefault();">
    <h2>name</h2>
    name: <input name="id">
    <h2>all check required</h2>
    <input name="all" type="checkbox" value="a">a
    <input name="all" type="checkbox" value="b">b

    <h2>gender chose one</h2>
    <input name="gender" type="radio" value="male"> male
    <input name="gender" type="radio" value="female"> Female
    <br>
    <button type="submit">check valid</button>
</form>

Detect Get, Set

OnBeforeReturnSet

export interface OnBeforeReturnSet {
    onBeforeReturnSet(name: string, value: any, fullPath?: string[]): void;
}

OnBeforeReturnGet

export interface OnBeforeReturnGet {
    onBeforeReturnGet(name: string, value: any, fullPath?: string[]): void;
}

using detect

{
    name: 'dom-render'
    onBeforeReturnSet: (name: string, value: any, fullpath: string[]) => {
        console.log('set name-->', name, value, fullpath);
    }
    onBeforeReturnGet: (name: string, value: any, fullpath: string[]) => {
        console.log('get name-->', name, value, fullpath);
    }
}

exclude detect property: Config

  • proxyExcludeOnBeforeReturnGets: ['propertyName']
  • proxyExcludeOnBeforeReturnSets: ['propertyName']

Proxy

all internal variables are managed by proxy. (DomRenderProxy)

exclude proxy (situation: Maximum call stack error)

exclude detect property: Config

  • proxyExcludeTyps: [Class...]

Code base

// frezz
{name : Object.freeze({...})}

// Shield Object type: {[k: string]: any}
{name : new Shield()}

// DomRenderProxy Final
{name : DomRenderProxy.final({...})}

Config

export type TargetElement = {
    _name: string,
    template?: string,
    styles?: string[],
    callBack: (target: Element, obj: any, rawSet: RawSet) => DocumentFragment,
    complete?: (target: Element, obj: any, rawSet: RawSet) => void
};

export type TargetAttr = {
    name: string,
    callBack: (target: Element, attrValue: string, obj: any, rawSet: RawSet) => DocumentFragment,
    complete?: (target: Element, attrValue: string, obj: any, rawSet: RawSet) => void
};

export interface Config {
    targetElements?: TargetElement[];
    targetAttrs?: TargetAttr[];
    onElementInit?: (name: string, obj: any, rawSet: RawSet) => void;
    onAttrInit?: (name: string, attrValue: string, obj: any, rawSet: RawSet) => void;
    proxyExcludeTyps?: ConstructorType<any>[];
    proxyExcludeOnBeforeReturnSets?: string[];
    proxyExcludeOnBeforeReturnGets?: string[];
    scripts?: { [n: string]: any };
    applyEvents?: { attrName: string, callBack: (elements: Element, attrValue: string, obj: any) => void }[];
}

License

Keywords

FAQs

Package last updated on 18 Oct 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc