Dominic
Helper to quickly build up dom in javascript object format
v.0.1.42 contains breaking changes. See changelog
Basic feature list:
Just dom
Basic dom construction by javascript object format
Event
Reference
Template by function
Components
Server side render to Html (with helper, see API) (temporarily)
Version: 0.1.47
Outline
And here's some code! 👍
Basic 1:
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
items : [
{ tag : ' div ' , width : 50 , height : 50 , text : ' Intro ' , display : ' inline-block ' , background : ' yellowgreen ' } ,
{ tag : ' div ' , width : 200 , background : ' lightgreen ' ,
items : [
{ tag : ' div ' , width : 20 , height : 20 , background : ' red ' } ,
{ tag : ' div ' , width : 20 , height : 20 , background : ' orange ' } ,
] ,
created : function ( el , root ) {
}
}
] ,
created : function ( el , root ) {
} ,
appended : function ( ) {
}
} )
Result
Styling
color
, backgroundColor
, background
, display
, position
, border
,
transform
, opacity
, fontSize
will be applied directly to element style without the need of putting them
in a style object. Same with:
width
, height
, minHeight
, maxHeight
, minWidth
, maxWidth
margin
, padding
, margin
and padding
+ (Top - Left - Right - Bottom)
will be converted to proper CSS value if value is number
Basic 2: Function as item & div all the elements
Tag name is 'div' by default
var outerScopeDataSource = [
{ name : ' yellow ' } ,
{ name : ' green ' } ,
{ name : ' pink ' }
]
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
items : [
{ width : 50 , height : 50 , text : ' Intro ' , display : ' inline-block ' , background : ' yellowgreen ' ,
items : [
function ( ) {
return outerScopeDataSource . map ( function ( data ) {
return { tag : ' custom-el ' , text : data . name }
} )
}
]
} ,
{ width : 200 , background : ' lightgreen ' ,
items : [ ' color ' , ' material ' ] . map ( function ( val ) {
return { text : val }
} )
}
]
} )
Result
Basic 3a: Share configs
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
width : ' 100% ' ,
height : ' 100% ' ,
defaults : {
display : ' inline-block ' ,
height : ' 100% ' ,
cls : ' default-class ' ,
style : {
verticalAlign : ' top '
}
} ,
items : [
{ cls : ' sidebar ' , width : 200 , ref : ' sidebar ' , background : ' lightgreen ' } ,
{ cls : ' main ' , width : ' calc(100% - 200px) ' , ref : ' main ' , background : ' lightblue ' ,
defaults : {
background : ' tomato ' ,
margin : 5 ,
height : 50 ,
width : 50 ,
display : ' inline-block '
} ,
items : [
{ text : 1 } ,
{ text : 2 } ,
[ 3 , 4 , 5 , 6 ] . map ( function ( v ) { return { text : v } } ) ,
function ( ) {
return [ 5 , 6 , 7 , 8 ] . map ( function ( v ) { return { text : v } } )
}
]
} ,
{ tag : ' test ' }
]
} )
All direct children of root will have display = 'inline-block', height = '100%'
Only last child of root will have class = 'default-class'
Result
Basic 3b: Share configs with extra class
xtraCls
, xCls
: string
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
width : ' 100% ' ,
height : ' 100% ' ,
defaults : {
cls : ' default-class ' ,
} ,
items : [
{ xCls : ' sidebar ' } ,
{ xtraCls : ' main ' } ,
{ tag : ' test ' }
]
} )
Result
Basic 4: Condition if
/ hide
var root = Dominic . create ( {
className : ' root ' ,
parent : document . body ,
width : ' 100% ' ,
height : ' 100% ' ,
defaults : {
display : ' inline-block ' ,
height : ' 100% ' ,
className : ' default-class ' ,
style : {
verticalAlign : ' top '
}
} ,
items : [
{ cls : ' sidebar ' , width : 200 , ref : ' sidebar ' , background : ' lightgreen ' } ,
{ cls : ' main ' ,
width : ' calc(100% - 200px) ' ,
ref : ' main ' ,
background : ' lightblue ' ,
defaults : {
background : ' tomato ' ,
margin : 5 ,
height : 50 ,
width : 50 ,
display : ' inline-block '
} ,
items : [
{ text : ' First ' } ,
{ text : ' Second ' } ,
[ 3 , 4 , 5 , 6 ] . map ( function ( v , i ) {
return { text : ' Value is: ' + v , if : v < 4 }
} ) ,
function ( ) {
return [ 5 , 6 , 7 , 8 ] . map ( function ( v ) { return { text : v , hide : v > 6 } } )
}
]
}
]
} )
Result
Attributes
var root = Dominic . create ( {
className : ' root ' ,
id : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
padding : 5 ,
attrs : {
class : ' original ' ,
dataTooltip : ' halo this is tip ' ,
' data-id ' : 5
}
} )
Result
Reference 1
var root = Dominic . create ( {
className : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
items : [
{ width : 50 , height : 50 , text : ' Intro ' , display : ' inline-block ' } ,
{ width : 200 , ref : ' orange ' ,
items : [
{ width : 20 , height : 20 , background : ' red ' ,
ref : ' lightgreen '
} ,
{ width : 20 , height : 20 , background : ' orange ' ,
ref : ' orange ' , refScope : ' parent '
} ,
]
}
]
} )
Reference 2: Direct reference
var root = Dominic . create ( {
className : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
items : [
{ width : 50 , height : 50 , text : ' Intro ' , display : ' inline-block ' } ,
{ width : 200 , ref : ' orange ' ,
items : [
{ width : 20 , height : 20 , background : ' red ' ,
ref : ' lightgreen '
} ,
{ width : 20 , height : 20 , background : ' orange ' ,
directRef : ' orange-f2 '
} ,
]
}
]
} )
Dominic . register ( ' input ' , function ( defs ) {
return {
items : [
{ tag : ' span ' , text : defs . label } ,
{ tag : ' input ' , placeholder : ' Choose name... ' }
]
}
} )
var root = Dominic . create ( {
cls : ' root ' ,
items : [
{ ctype : ' input ' , ref : ' nameInput ' , label : ' Name: ' } ,
{ ctype : ' input ' , directRef : ' nameInput2 ' , label : ' Name 2: ' }
]
} )
Events 1:
Reserved keyword for events:
Mouse: click
mousedown
mouseup
mouseover
mouseout
mouseenter
mouseleave
mousemove
Drag: dragstart
dragend
drag
dragover
dragenter
dragleave
drop
Focus: blur
focus
Keyboard: keydown
keypress
keyup
Form: change
input
submit
Touch: touchstart
touchmove
touchend
Scroll: wheel
scroll
var root = Dominic . create ( {
className : ' root ' ,
id : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
items : [
{ tag : ' div ' , width : 50 , height : 50 , text : ' Intro ' , display : ' inline-block ' , background : ' yellowgreen ' } ,
{ tag : ' div ' , width : 200 , background : ' lightgreen ' ,
items : [
{ tag : ' div ' , className : ' red ' , width : 20 , height : 20 , background : ' red ' ,
click : {
handler : function ( e ) {
console . log ( ' This is: ' , this . localName + ' . ' + this . className )
}
}
} ,
{ tag : ' div ' , className : ' orange ' , width : 20 , height : 20 , background : ' orange ' ,
click : {
scope : ' root ' ,
handler : function ( e ) {
console . log ( ' This is: ' , this . localName + ' . ' + this . className )
}
} ,
events : [
{ type : ' custom:event ' , handler : function ( ) {
console . log ( ' This is div.orange ' )
} }
]
} ,
{ tag : ' div ' , className : ' yellow ' , width : 20 , height : 20 , background : ' yellow ' ,
click : {
scope : ' root ' ,
handler : ' onClickYellow ' ,
capture : true
}
}
]
}
] ,
onClickYellow : function ( e ) {
var t = e . target
console . log ( ' From ' , t . localName + ' . ' + t . className + ' to ' + this . localName + ' . ' + this . className )
} ,
events : [
{ type : ' mouseout ' , handler : function ( e ) {
console . log ( ' Out of: ' , e . target )
} }
]
} )
Events 2: Delegate
var root = Dominic . create ( {
cls : ' root ' ,
id : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
items : [
{ width : 50 , height : 50 , text : ' Intro ' , display : ' inline-block ' , background : ' yellowgreen ' } ,
{ width : 200 , background : ' lightgreen ' ,
items : [
{ cls : ' child red ' , width : 20 , height : 20 , background : ' red ' } ,
{ cls : ' child orange ' , width : 20 , height : 20 , background : ' orange ' } ,
{ cls : ' child yellow ' , width : 20 , height : 20 , background : ' yellow ' }
] ,
click : { scope : ' root ' , handler : ' onClickLightgreen ' , delegate : ' .child ' }
}
] ,
onClickLightgreen : function ( e , match , delegate ) {
console . log ( ' This is: ' + match . localName + ' . ' + match . className . replace ( ' ' , ' . ' ) )
}
} )
Events 3: Key code hook
Only trigger key event with specified key codes
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
width : ' 100% ' ,
height : ' 100% ' ,
defaults : {
cls : ' default-class ' ,
} ,
items : [
{ xCls : ' sidebar ' } ,
{ xtraCls : ' main ' } ,
{ tag : ' input ' ,
keydown : { scope : ' root ' , handler : ' sayHelo ' , key : 13 }
} ,
{ tag : ' input ' ,
keydown : { scope : ' root ' , handler : ' onArrowKey ' , key : [ 37 , 38 , 39 , 40 ] }
}
] ,
sayHelo : function ( e ) {
console . log ( ' helo ' , e . target . value )
} ,
onArrowKey : function ( e ) {
console . log ( ' Navigating: ' , e . keyCode )
}
} )
Events 4: Event counter
, finishCount
and validator
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
width : ' 100% ' ,
height : ' 100% ' ,
defaults : {
cls : ' default-class ' ,
} ,
items : [
{ xCls : ' sidebar ' } ,
{ xtraCls : ' main ' } ,
{ tag : ' input ' ,
keydown : { scope : ' root ' , handler : ' sayHelo ' , key : 13 ,
count : 1 ,
validator : function ( e ) {
return e . target . value
} ,
finishCount : function DoSomethingAfterInputName ( e ) {
}
}
} ,
{ tag : ' input ' ,
keydown : { scope : ' root ' , handler : ' onArrowKey ' , key : [ 37 , 38 , 39 , 40 ] ,
validator : ' isAllowedToGo '
count : 10 ,
}
}
] ,
sayHelo : function ( e ) {
this . name = e . target . value
console . log ( ' helo ' , e . target . value )
} ,
onArrowKey : function ( e ) {
console . log ( ' Navigating: ' , e . keyCode )
} ,
isAllowedToGo : function ( ) {
return this . name
}
} )
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
point : 0 ,
items : [
{ tag : ' input ' , placeholder : ' Choose a name to start the game... ' ,
display : ' block ' ,
width : 300 ,
keydown : { scope : ' root ' , handler : ' sayHelo ' , key : 13 ,
count : 1 ,
validator : function ( e ) {
return e . target . value
} ,
finishCount : function hideInput ( e ) {
e . target . style . display = ' none '
this . guessInput . disabled = false
this . guessInput . focus ( )
}
}
} ,
{ tag : ' input ' ,
cls : ' guess-name ' ,
directRef : ' guessInput ' ,
placeholder : ' Guess the name 3 times... ' ,
disabled : true
}
] ,
keydown : {
delegate : ' .guess-name ' ,
count : 3 ,
validator : ' validateGuess ' ,
handler : ' onGuess ' ,
finishCount : ' gameFinish ' ,
key : 13
} ,
sayHelo : function ( e ) {
this . name = e . target . value
console . log ( ' helo ' , e . target . value , ' \n Lets start ' )
} ,
validateGuess : function ( e , match ) {
return match . value
} ,
onGuess : function ( e , match ) {
console . log ( ' Your guess: ' , match . value )
var point = match . value === this . name ? 1 : 0
console . log ( ' You got: ' , point , ' point ' )
this . point += point
match . value = ' '
} ,
gameFinish : function ( e , match ) {
console . log ( ' ---- \n Finish. \n Your points: ' , this . point )
if ( this . point < 3 )
return console . info ( ' Game over. Did you type in the name? ' )
console . info ( ' You won!!! ' )
match . disabled = true
}
} )
Template 1a
for
: data source
TplFn
: function (item, itemIndex)
If data source provided is an array, item is record of array and itemIndex is record index
If data source provided is an object, item is data object and itemIndex will be undefined
var root = Dominic . create ( {
className : ' root ' ,
id : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
padding : 5 ,
items : {
for : [
{ name : ' apple ' , cost : 0 . 5 } ,
{ name : ' mango ' , cost : 0 . 5 } ,
{ name : ' grape ' , cost : 0 . 6 ,
suppliers : { data : [
{ name : ' US ' , time : 5 } ,
{ name : ' UK ' , time : 4 }
] }
}
] ,
tplFn : function ( item , itemIdx ) {
return { tag : ' div ' , text : item . name , padding : 5 , margin : ' 5px 0 0 5px ' , background : ' tomato ' ,
items : {
for : item . suppliers ,
root : ' data ' ,
tplFn : function ( sup , supIdx ) {
return { tag : ' div ' ,
padding : 5 ,
background : ' lightblue ' ,
text : sup . name + ' . Time: ' + sup . time + ' days '
}
}
}
}
}
}
} )
Result
Template 1b: Object loop
Can also loop through object property if specified with alwaysIterate
.
var root = Dominic . create ( {
cls : ' root ' ,
parent : document . body ,
defaults : {
cls : ' default-class '
} ,
items : [
{ for : { a : 5 , b : 6 , c : 7 } ,
observeProp : ' data1 ' ,
alwaysIterate : true ,
tplFn : function ( v , key ) {
return { text : ' Value is: [ ' + v + ' ]. Key is: [ ' + key + ' ] ' }
}
} ,
{ xCls : ' sidebar ' } ,
{ xtraCls : ' main ' , items : {
for : [ 5 , 6 , 7 , 8 ] ,
observeProp : ' data2 ' ,
tplFn : function ( v ) { return v }
} } ,
]
} )
root . observe . data1 = { name : ' Dominic ' , purpose : ' Helper ' , target : ' quick dom for test ' }
root . observe . data2 = [ ' Helo ' , ' This ' , ' is ' , ' a ' , ' test ' ]
Result
Template with data change reaction
var src = [
{ name : ' apple ' , cost : 0 . 5 } ,
{ name : ' mango ' , cost : 0 . 5 } ,
{ name : ' grape ' , cost : 0 . 6 ,
suppliers : { data : [
{ name : ' US ' , time : 5 } ,
{ name : ' UK ' , time : 4 }
] }
}
]
var root = Dominic . create ( {
className : ' root ' ,
id : ' root ' ,
parent : document . body ,
width : 300 ,
height : 300 ,
background : ' darkgreen ' ,
padding : 5 ,
items : {
for : null ,
observeProp : ' data ' ,
tplFn : function ( item , itemIdx ) {
return { tag : ' div ' , text : item . name , padding : 5 , margin : ' 5px 0 0 5px ' , background : ' tomato ' ,
items : {
for : item . suppliers ,
root : ' data ' ,
tplFn : function ( sup , supIdx ) {
return {
tag : ' div ' ,
padding : 5 ,
background : ' lightblue ' ,
text : sup . name + ' . Time: ' + sup . time + ' days ' ,
click : { scope : ' root ' , handler : ' onClickSupplier ' }
}
}
}
}
}
} ,
onClickSupplier : function ( e ) {
} ,
events : [
{ type : ' mouseout ' , handler : function ( e ) {
console . log ( ' Out of: ' , e . target )
} }
]
} )
root . observe . data = src
root . observe . push ( ' data ' , {
name : ' mangox ' ,
cost : 0 . 5 ,
suppliers : { data : [
{ name : ' Russia ' , time : 4 } ,
{ name : ' China ' , time : 5 }
] }
} )
All template functions
Only work when template data is array
Now support multiple templates observing same property
APIs:
push (now real push, was previously reset)
insert
remove
pop
shift
unshift
Example:
root . observe . push ( observeProperty , data )
root . observe . insert ( observeProperty , index , data )
root . observe . remove ( observeProperty , indexes )
root . observe . pop ( observeProperty )
root . observe . shift ( observeProperty )
root . observe . unshift ( observeProperty , data )
Component (v.0.1.42)
Basic 1
Dominic . register ( ' input ' , function Input ( defs ) {
return {
tag : ' label ' ,
parent : defs . parent ,
display : ' block ' ,
items : [
{ tag : ' span ' , items : { tag : ' b ' , text : ' Label name: ' } } ,
{ tag : ' input ' , placeholder : ' Choose label name ' }
]
}
} )
Dominic . create ( {
ctype : ' input ' ,
parent : document . body
} )
Result
Basic 2
Dominic . register ( ' input ' , function Input ( defs ) {
return {
tag : ' label ' ,
display : ' block ' ,
items : [
{ tag : ' span ' , items : { tag : ' b ' , text : defs . label } } ,
{ tag : ' input ' , placeholder : ' Choose label name ' }
]
}
} )
Dominic . register ( ' tab ' , function Tab ( defs ) {
var configs = {
cls : ' d-tab-ct ' ,
parent : defs . parent ,
items : [
{ cls : ' d-tab-btns ' ,
defaults : {
tag : ' span ' ,
display : ' inline-block ' ,
height : 22 ,
padding : 4
} ,
items : {
for : defs . tabs ,
observeProp : ' tabs ' ,
tplFn : function ( tab , i ) {
return { text : tab . name }
}
}
} ,
{ cls : ' d-tab-tabs ' , items : {
for : defs . tabs ,
observeProp : ' tabs ' ,
tplFn : function ( tab , i ) {
console . log ( ' tab data is ' , tab )
return { ctype : ' input ' , label : ' Tab number ' + i }
}
} } ,
]
}
if ( defs . created )
configs . created = defs . created
if ( defs . appended )
configs . appended = defs . appended
return configs
} )
Dominic . create ( {
ctype : ' tab ' ,
parent : document . body ,
tabs : [
{ name : ' Tab 1 ' } ,
{ name : ' Tab 2 ' } ,
{ name : ' Tab 3 ' }
] ,
created : function ( ) {
console . log ( ' finished initiating tab ' )
} ,
appended : function ( ) {
console . log ( ' Now in document ' )
}
} )
Result
Motivation
Prototyping some design and testing event/ interaction made a bit more convinient when
No dependencies & everything in javascript
There are Events & reference & template supports
Installation
<script src="dominic.min.js"></script>
API
Create new DOM element
Register a component
Dominic . register ( name , fn )
Plan
License
.MIT