Speed Coded HTML Templating Thoughts
copy const tmpl = ` main h1 Welcome hr nav button one button two button three hr p this is a test p this is another test textarea hello ul li alpha li beta li zeta ul li organize li things li and stuff hr footer 2022 ` let htm = parse( tmpl) ; document.body .innerHTML += htm console.log ( htm) function isTag( tag) { return !/ Unknown/ .test ( document.createElement ( tag) + '' ) } function parse( input) { let lines = input.split ( /\n/ ) let html = [ ] let closeTags = [ ] let lastIndent = 0 ; for ( let i = 1 ; i < lines.length ; i++ ) { let indent = 0 ; let tag = '' ; let content = '' let line = lines[ i] let mode = 'start' ; for ( let j = 0 ; j < line.length ; j++ ) { const char = line[ j] if ( char == ' ' && mode === 'start' ) { indent++; } else if ( char != ' ' && mode != 'content' ) { mode = 'tag' tag += char } else { mode = 'content' content += char ; } } if ( indent <= lastIndent && closeTags.length > 0 ) { let back = lastIndent while( back >= indent) { html.push ( closeTags.pop ( ) ) back -= 2 } } if ( tag.length > 0 ) { let xtra = '' let origTag = tag; if ( ! isTag( tag) ) { tag = 'div' xtra = ` class= "${origTag}" ` } closeTags.push ( `</ ${ tag} > `) html.push ( `< ${ tag + xtra} > `) if ( content.length > 0 ) html.push ( content) } lastIndent = indent; } return [ ...html , ...closeTags .reverse ( ) ] .join ( '' ) }
Try it out…
Parse a minimalistic html template inspired by the likes of jade, haml, pug etc… This is very speed-coded. I may revisit the same thing with a bit more of an elegant approach in the future.
Check if HTML Tag is Valid
copy const isTag = tag => { return !/ Unknown/ .test ( document.createElement ( tag) + '' ) } console.log ( 'section:' , isTag( 'section' ) ) console.log ( 'div:' , isTag( 'div' ) ) console.log ( 'nav:' , isTag( 'nav' ) ) console.log ( 'banana:' , isTag( 'banana' ) )
Try it out
Check if a tagName
is a valid html element.
When casting a dom node to a string, you’ll get a class name like this:
copy document.createElement ( 'div' ) + '' // '[object HTMLDivElement]' // you can cast to a string with `toString` if // you want things to be more readable document.createElement ( 'section' ) .toString ( ) // '[object HTMLElement]' document.createElement ( 'input' ) + '' // '[object HTMLInputElement]'
When you try to create something with an unknown tagName
you’ll end up with:
copy document.createElement ( 'banana' ) + '' // '[object HTMLUnknownElement]'
So, testing for the presence of the string Unknown
is an easy way to check if a tagName
is valid in a given browser. This is the perfect kind of thing to memoize:
copy const tags = { } const isTag = tag => { if ( tags[ tag] != null ) { // already calculated console.log ( 'loking up: ' , tag, tags[ tag] ) ; return tags[ tag] } const result = !/ Unknown/ .test ( document.createElement ( tag) + '' ) tags[ tag] = result return result } console.log ( 'calculator' , isTag( 'calculator' ) ) console.log ( 'calculator' , isTag( 'calculator' ) ) console.log ( 'strong' , isTag( 'strong' ) ) console.log ( 'strong' , isTag( 'strong' ) )
Try it out
Tab Timer
copy < title id= t></ title> < script> st = Date .now ( ) setInterval( _ => { s = Date .now ( ) - st t.innerHTML = ~~( s/ 6e4) + ':' + ( ~~( s/ 1e3) % 60) } , 500 ) </ script>
I speed coded this recently to put a timer in a brower tab.
Have a look at it here in a new tab…
Obviously this is pretty odd – but it does work for my purposes 😉
Gravity Dots 2
copy d = document b = d.body b.style .margin = 0 b.style .background = 'black' r = ( v = 1 ) => Math .random ( ) * v with( b.appendChild ( d.createElement `canvas` ) .getContext `2d`) { onresize = ( ) => { canvas.width = innerWidth canvas.height = innerHeight } onresize( ) fillStyle = 'red' dot = ( x = r( innerWidth) , y = 0 , mass = 20 , sr = r( 2 ) + 2 , R = sr, dx, dy, col = '#005eb0' , dist, vx = .2, vy = 0 ) => { return ( ) => { fillStyle = col R = sr if ( r( ) < .001) { vx = r( ) * 4 - 2 R = sr * 2 fillStyle = 'red' col = `hsl( ${ r( 360 ) } deg, 50 %, 50 % ) ` } dx = innerWidth / 2 - x dy = innerHeight / 2 - y dist = Math .sqrt ( dx * dx + dy * dy) dist *= dist vx += dx / dist * mass vy += dy / dist * mass x += vx y += vy beginPath( ) arc( x, y, R, 0 , 6.29 ) fill( ) } } const dots = [ ] for ( let i = 0 ; i < 100 ; i++ ) dots.push ( dot( ) ) loop = ( ) => { fillStyle = 'rgba(0, 0, 0, 0.05)' fillRect( 0 , 0 , canvas.width , canvas.height ) dots.map ( d => d( ) ) } setInterval( loop, 16 ) }
Try it out…
A variation on this recent post.