An Extremely simple JS library to create Reactive UIS.
These Lib it's not production ready yet, and if you want to use into your application make sure to save the current release, and be ready for bugs.
If you want to contribute, just read the TODO.md and then, implement the required feature.
For Running , you just need to copy the script tag into your code
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
if you want to edit the source code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
let element = createElement404((main_interface)=>{
main_interface.div(()=>{
main_interface.h1("Hello World",{inline_style:{color:'red'}})
})
},target)
element.render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
for defining a trigger, you just need to pass, the trigger with the prefix "render_" if you want to update the ui otherwise just pass the trigger,but the ui will not be updated.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
var num =0;
let target = document.body;
let element = createElement404((main_interface)=>{
main_interface.div(()=>{
main_interface.h1(`the value of num is ${num}`)
main_interface.button(`remove 1 from num`,{full_render_click:()=> num--},)
main_interface.button(`add 1 to num`,{full_render_click:()=> num++})
})
},target)
element.render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
If you don't want to use States, you can handle inputs, by using the normal input implementation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
let element = createElement404((main_interface)=>{
main_interface.div(()=>{
main_interface.h1("Hello World",{inline_style:{color:'red'}})
})
},target)
element.render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
With MiniDom you can find, and modify parts of elements individually
in these Example we find a value of an input , then we alert it
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
createElement404(element=>{
element.div(()=>{
element.div(()=>{
let created_input = element.input({placeholder:"type something"})
created_input.input_name = 'test';
})
})
let button =element.button("visualize");
button.set_prop('click',()=>{
let founded_input = element.findOne(value => value.input_name === 'test');
alert("you typed: "+ founded_input.get_value());
})
},target).render();
}
window.addEventListener('load',main);
</script>
</body>
</html>
with render match system you can render specif parts of the code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
let value1 = 0;
let value2 = 0;
function main(){
let target = document.body;
createElement404(element=>{
element.div((current)=>{
current.div_name = 'div1';
element.p("the value1 is " + value1);
})
element.div((current)=>{
current.div_name = 'div2';
element.p("the value2 is " + value2);
})
let button1 =element.button("update div1");
button1.set_prop('click',()=>{
value1+=1;
element.renderMatch(value => value.div_name === 'div1');
})
let button2 =element.button("update div2");
button2.set_prop('click',()=>{
value2+=1;
element.renderMatch(value => value.div_name === 'div2');
});
},target).render();
}
window.addEventListener('load',main);
</script>
</body>
</html>
The easiest way of switch interface context, its by adding callback modifiers but remember that they will be affected by the render process
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
createElement404((main_interface)=>{
let page = main_interface.div();
let nav_style = {
"width":"33vw",
"margin-left":"33vw",
"display":"grid",
"grid-template-columns":"33% 33% 33%"
}
let all_links = {
cursor:"pointer",
hover_state:{
state:"hover",
color:"red"
}
}
let selected = {
color:"red"
}
function default_page(){
page.clear()
page.nav(()=>{
page.p("Default",{outline_style:[selected,all_links]})
page.p("Page 1",{outline_style:all_links, click:page1})
page.p("Page 3",{outline_style:all_links, click:page2})
},{outline_style:nav_style})
page.h1("you are in the default page")
}
default_page()
function page1(){
page.clear()
page.nav(()=>{
page.nav(()=>{
page.p("Default",{outline_style:all_links,click:default_page})
page.p("Page 1",{outline_style:[selected,all_links]})
page.p("Page 3",{outline_style:all_links, click:page2})
},{outline_style:nav_style})
})
page.h1("you are in the page1")
}
function page2(){
page.clear()
page.nav(()=>{
page.p("Default",{outline_style:all_links,click:default_page})
page.p("Page 1",{outline_style:all_links, click:page1})
page.p("Page 2",{outline_style:[selected,all_links]})
},{outline_style:nav_style})
page.h1("you are in the page 2")
}
},target).render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
You also can switch context by creating sub elements404, the advantage of it, its that they dont affect other parts of the render
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
let num = 0;
function main(){
let target = document.body;
createElement404((main_interface)=>{
let nav_style = {
"width":"33vw",
"margin-left":"33vw",
"display":"grid",
"grid-template-columns":"33% 33% 33%"
}
let all_links = {
cursor:"pointer"
}
let selected = {
color:"red"
}
let page = main_interface.div();
function default_page(){
page.clear()
page.nav(()=>{
page.p("Default",{inline_style:[selected,all_links]})
page.p("Page 1",{inline_style:all_links, click:page1})
},{inline_style:nav_style})
page.h1("you are in the default page")
}
default_page()
function page1(){
page.clear()
page.nav(()=>{
page.nav(()=>{
page.p("Default",{inline_style:all_links,click:default_page})
page.p("Page 1",{inline_style:[selected,all_links]})
},{inline_style:nav_style})
})
page.h1("you are in the page1")
}
let hit_counter_div = main_interface.div();
let hit_counter = createElement404(sub=>{
sub.p(`the value of num is ${num}`)
sub.button("Decrease num",{full_render_click:()=>num-=1})
sub.button("Increase num",{full_render_click:()=>num+=1})
},hit_counter_div).render()
},target).render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
You also can apply is_inline_style to elements by using the is_inline_style tag
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
let element = createElement404((main_interface)=>{
let div_props = {
inline_style:{
position:"absolute",
top:"50vh",
left:"50vw",
transform:"translate(-50%,-50%)",
width:"100%",
"text-align":"center"
}
}
main_interface.div(()=>{
let h1_props = {
inline_style:{
"font-size":"10rem",
"font-weight":"bold",
color:"red"
}
}
main_interface.h1("404",h1_props)
let h2_props = {
inline_style:{
"font-size":"2rem",
"font-weight":"bold",
color:"red"
}
}
main_interface.h2("Page Not Found",h2_props)
},div_props)
},target)
element.render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
If you want to generate response styles, or use props like hover or active you can use the tag outline_style
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
createElement404(element=>{
const NORMAL = {
color:"white",
position:"absolute"
}
const HORIZONTAL = {
media:'screen and (orientation: landscape)',
'background-color':'green',
width: '30vw',
height: '15vw'
};
const VERTICAL = {
media:'screen and (orientation: portrait)',
width: '15vw',
height:"30vw",
'background-color':'blue'
};
const MOUSE_PROPS = {
state:['hover','active'],
'background-color':'yellow'
}
let div_style = [NORMAL,MOUSE_PROPS,HORIZONTAL,VERTICAL]
let right_div = [div_style,{left:"60vw"}];
element.div("value of div",{outline_style:div_style})
element.div("value of div",{outline_style:right_div})
},target).render();
}
window.addEventListener('load',main);
</script>
</body>
</html>
with The States system,you can generate interactive forms easily you just need to pass the container and the props you want to pass
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
let element = createElement404((main_interface)=>{
//make sure to enable these to allow rerender on state change
main_interface.allow_state_quantum_render = true;
//creating an is_inline_style input more sofisticated
let style_input = {
border:'none',
color:'rgb(71,78,86)',
'background-color':'rgb(231,231,248)'
}
main_interface.stateInput("name",{placeholder:"name",inline_style:style_input})
main_interface.br()
main_interface.stateInput("email",{placeholder:"email",inline_style:style_input})
main_interface.br()
let age_input = undefined;
main_interface.div().superposition(()=>{
age_input = main_interface.stateInput("age",{
placeholder:"age",
inline_style:style_input,
value:18,
type:'number'
})
main_interface.stateDecrease("age",1,"-")
main_interface.stateIncrease("age",1,"+")
}).re_colapse_always_if(()=>{
let input_value = age_input.get_value()
let age_value = main_interface.getStateValue('age');
return parseInt(input_value) !== age_value;
})
main_interface.stateSelect("gender",["Man","Woman"],{default_value:"Woman"})
main_interface.br()
main_interface.stateInput("password",{placeholder:"password",inline_style:style_input, type:"password"})
main_interface.div().superposition(()=>{
let p_style = {
color:'rgb(71,78,86)',
'font-size':'0.75em'
}
let name = main_interface.getStateValue('name');
let email = main_interface.getStateValue('email');
let password = main_interface.getStateValue('password');
let age =main_interface.getStateValue('age');
let gender = main_interface.getStateValue('gender');
main_interface.p(`name: ${name}`).inline_style(p_style);
main_interface.p(`email: ${email}`).inline_style(p_style);
main_interface.p(`password: ${password}`).inline_style(p_style);
main_interface.p(`age: ${age}`).inline_style(p_style);
main_interface.p(`gender ${gender}`).inline_style(p_style);
main_interface.pre(()=>{
main_interface.code(
JSON.stringify(element.getFullState(), null, 4)
)
}).inline_style({
width:"30vw",
height:"30vh",
color:'white',
"background-color":"rgb(38,42,85)",
})
}).always_colapse();
},target)
element.render()
}
window.addEventListener('load',main);
</script>
</body>
</html>
With Lockers , you can lock the entire UI, to avoid concurrency problems
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/OUIsolutions/Element-404@main/versions/Element404_v0.51.js"></script>
</head>
<body>
<script>
function main(){
let target = document.body;
let element = createElement404((main_interface)=>{
main_interface.state_full_render = true;
main_interface.stateSelect("gender",["Man","Woman"]);
main_interface.br()
main_interface.stateInput("num",{placeholder:"num"})
main_interface.stateDecrease("num",1,"-")
main_interface.stateIncrease("num",1,"+")
main_interface.br()
if(main_interface.locked){
main_interface.button("unlock",{
inline_style:{color: "red"},
not_lock_full_render_click:()=>{
main_interface.unlock();
}
})
}
if(!main_interface.locked){
main_interface.button("lock",{
inline_style:{color: "blue"},
full_render_click:()=>{
main_interface.lock();
main_interface.render()
}
})
}
},target)
element.render()
}
window.addEventListener('load',main);
</script>
</body>
</html>