Documentation Neobiz.js 4.7.x
A simple view engine that has 100% JS features
Neobiz.js is pure in JS lang, transform Object into HTML
fix error outFIle
Updates:
- fix event bugs
- Boolean attributes / non-value attribute (example: disabled, readonly)
prev update:
-
render
method change to**\_render**
to avoid conflict with another library and add safety check - render option props improve
- fix bug on child order
features:
- eventHandler
- Reusable & editable style/css
- Altering object
- Registering component
- Explicit tag name supported
read /example dir to better understanding
for browser usage use browser.js
file.
vue
in browser
Example with page.js
import "neobiz";
({
div: {
script: [
{ src: "https://unpkg.com/vue@3/dist/vue.global.js" },
{ src: "https://unpkg.com/neobiz@3.1.0/browser.js" },
{ src: "./my-component.js" },
],
id: "app",
},
script: {
html() {
const { createApp } = Vue;
createApp(myComponent).mount("#app");
},
},
}.outFile("./welcome.html"));
my-component.js
const myComponent = {
data() {
return { msg: "hi, this is example" };
},
template: { h1: { text: "{{msg}}" } }._render,
};
properties | caller | return-type | description |
---|---|---|---|
_render | Object | string | rendering to HTML |
outFile | Object @params destination[string] | void | generate static HTML file |
range | Array @params length[int], start[int] | Array | shortcut for looping in a range |
repulse | String | Object | generate object from HTML string |
css | Object | Object | generate css from object |
cssText | Object | Object | inline css |
alter [trials] | Object @params cb[function] | Object | altering object before rendering |
reg | Object | void | registring an object |
regm | Object | void | updating the existing registered object |
load | Object | Object | read an existing registered object |
unred | Object | void | removing an existing registered object |
renderOption | Object @params option[Object] | void | set the option for rendering |
Why use this?
- Easy maintance innerHTML rather than literal string
- Generate static html file
- Full control of view. Such as filtering, encrypting the data before serve, or just like conditional and loop case
- Almost no need to learn anything. Just need to learn how to render
- Limitless potential, because it's just js. Almost all library should be compatible
Basic syntax
How to use? just import this:
import "neobiz";
It's just an Object! wrap in () to create a statement or just assign to a var
{
// text property is same as innerText
h1: {
text: "Hello World!",
},
}._render;
// <h1>Hello World!</h1>
or use call method
_render.call({
// text property is same as innerText
h1: {
text: "Hello World!",
},
});
Comments:
{
// this is comment
/*
this is multi line
*/
h1: {
text: "This is heading";
}
}
properties dom
{
h1: {
class:"heading",
text: "Hello World!",
style:"color: #DC1E1E",
}
}
// <h1 class="heading" style="color: #DC1E1E">Hello World!</h1>
boolean attributes
use Null
to indicate non-value attributes, do not confuse Null
to null
{
button: { text: "Hello World!", disabled: Null },
}._render
innerText & innerHTML:
{
h1: { text: "<b>this is a text</b>" },
ul: { html: "<li>this will be render as html</li>" },
}
nested dom:
{
body: {
h1: {
text: "Hello World!",
}
}
}
expression & operator
{
span: [
{ text: 24 + 12 / 6 },
{ text: !false },
],
}
siblings dom:
There is a case like this:
<li>orange</li>
<li>banana</li>
Object can not use 2 keys with the same name
// Don't do this
{
li:{text:"orange"},
li:{text:"banana"},
}
// Do this
{
li:[
{text:"orange"},
{text:"banana"},
]
}
Render Option
renderOption({
camelCase: false,
once: false,
nodoctype: false,
ignoreTag: false,
prefixTag: false,
prefixAttr: false,
});
set once to true
to use option only for once,
set nodoctype to true
to remove <!doctype html>
in the beninging,
set ignoreTag to true
to unused tag
properties,
set prefixTag to something
to add text before tag
,
use noprefix:true
to skip on specific object
set prefixAttr to something
to add text before attribute
,
use nopAttr:true
to skip in specific object
set camelCase
true
to convert camelCase properties to kebab-case
make sure to set the option before rendering
renderOption({
camelCase: true,
});
render.call({
ionRouter: {},
});
result
<ion-router></ion-router>
Explicit tag name
What if there is somethings in the middle of list?
<li>orange</li>
<p>
<span>This is in the middle</span>
</p>
<li>banana</li>
if we use an array there will share the tag name right? just use this:
use string as key could distinc an element with just a space no need to worry, it will render without space
{
li:{text:"orange"},
p:{span:{text:"This is in the middle"}},
"li ":{text:"banana"},
}
or write the tag name:
{
li: [
{ text: "orange" },
{ tag: "p", span: { text: "This is in the middle" } },
{ text: "banana" },
],
}
also with specifying tag name, we can name it differently:
{
PersonList: ["Arthur", "Zoro"].map((person) => ({
tag: "li",
text: person,
})),
}
Modify an Object
use alter
properties, with function as params. no need to return a value
const y = {
h1: { text: "Hello World!" },
p: { text: "this is a p" }.alter((e) => (e.class = "lorem")),
}.alter((e) => {
e.h1.text = "thi is altered text";
e.h1.style = { color: "red", fontSize: "150%" }.cssText;
});
console.log(y.render);
Components / Partials
import header from "./header.v.js"; //function type
import footer from "./footer.v.js"; //object type
{
div: header({ user: "dim24" }),
p: { text: "this is text" },
div: footer,
}.render;
header.v.js
export default ({ user }) => ({ h1: { text: `Hi, ${user}` } });
footer.v.js
export default {
script: { src: "/assets/js/main.js" },
span: { text: "this is footer" },
};
reg, regm, load & unreg Components
The idea is to make object has resuability
reg & load
this function need a single argument to set a name of registering object,
there is 2 ways to registering an component:
- through properties method:
{ name:"viewport"}.reg("viewport")
- via call method:
reg.call({ name: "viewport" }, "viewport");
now we can load it's value whenever we want
{
meta:load("viewport"),
body: {
}
}
regm
this function will replace an existing registered object with a new value:
const newValue = load("viewport");
newValue.content = "width=device-width, initial-scale=1.0";
newValue.regm("viewport");
unreg
when we the object doesn't needed anymore, just unreg it:
unreg("viewport");
Style
use camel case to css properties
inline CSS:
{
h1:{
text:"Hello World",
style:{
color:"#1B73F8",
fontSize:"150%"
}.cssText
}
}
use style :
global-style.js
:
export default {
h1: {
color: "red",
},
body: {
margin: "0px",
textAlign: "center",
},
};
why should use object css rather than direct css?
we can easily modify the style
main-page.js
:
import style from "./global-style.js";
style.body.margin = "12px";
{
style:style.css,
div:{
h1:{text:"Hello World!"}
}
}.render
reusable style / mixin
const flex = (justify, align, direction = "row") => ({
display: "flex",
justifyContent: justify,
alignItems: align,
flexDirection: direction,
});
const space = {
padding: "6px 8px",
margin: "6px 10px",
};
console.log({
style: { div: flex("center", "center"), button: { border: "none", ...space } }
.css,
});
Interacting with DOM
use script
to interact with browser with html property
wrap the script with a function, or use string
{
button:{onclick:"sayHi(this)",id:"hi-button"},
script:{
html(){
document.getElementById("hi-button").innerText="Click me!";
function sayHi(el){
el.innerText="Hi!";
}
}
}
}
Event
you can add an event this
keyword always refered to the node itseft
{
input:{type:"password",onkeypress(){
if(event.keyCode==13)
alert(this.value)
}},
button:{text:"Click me!",onclick(){
this.innerText = this.innerText=="clicked"?"Click me!":"clicked";
}}
}
Repulse
If you already have an html file and want to modify it, or make it as a template, just use this
this function is still has a lot issues, use only in a simple case
- need to wrap all tag into a single parent
- recommended to use external script and css
- repetitive / nested could caused weird behavior (help me, please!)
I still try to improve this feature. if you can provide some help just tell me please... :)
const { div } = `
<div>
<h1>Hello dims!</h1>
</div>
`.repulse;
div.id = "main";
div.h1.class = "heading";
div.p = { text: "this is a whole text" };
console.log({ div }.render);
result
<div id="main">
<h1 class="heading">Hello dims!</h1>
<p>this is a whole text</p>
</div>
Pass Value
use shorthand anonym function
console.log(((user) => ({ h1: { text: `Hello, ${user}` } }))("Vins").render);
or
const greeting = (user) => ({ h1: `Hello, ${user}` });
console.log(greeting("Vins").render);
Control Flow
ternary:
{
h1: status
? { text: "Hello World!" }
: {
a: { href: "#", text: "You are offline!" },
},
}
IIFE if-else
{
h1: (() => {
let result;
if (status) result = { text: "Hello World!" };
else
result = {
a: { href: "#", text: "You are offline!" },
};
return result;
})(),
}
normal if else
let result;
if (status) result = { text: "Hello World!" };
else
result = {
a: { href: "#", text: "You are offline!" },
};
//use
{
h1: result,
}
IIFE switch-case
{
h1: (() => {
let result;
switch (status) {
case true:
result = { text: "Hello World!" };
break;
case false:
result = {
a: { href: "#", text: "You are offline!" },
};
}
return result;
})(),
}
Loop & array manipulation
range & map:
{
ul: {
li: [].range(8, 1).map((item) => ({ text: "data-" + item })),
},
}
map
{
ul: {
li: ["grape", "banana", "apple"].map((text) => ({ text })),
},
}
filter
{
ul: {
li: [].range(8, 1).filter( num => num % 2 == 0 ).map((item) => ({ text: "data-" + item })),
},
}
for
{
ul: {
li: (() => {
const result = [];
for (let i = 1; i < 9; i++) result.push({ text: "data-" + i });
return result;
})(),
},
}
while
{
ul: {
li: (() => {
const result = [];
let i = 0;
while (++i < 9) result.push({ text: "data-" + i });
return result;
})(),
},
}
templating
this example use single file usage. for modular usage leave to you, or just read the example dir
//template file
const template = (content) => ({
div: {
class: "main wrapper",
div: content,
},
});
//content file
template({
h1: { text: "Hello World!" },
});