Parable of the patterns
- Hello * with a wide smile waving in the face * friend.
- Wah! * with a bright sparkle in wide-open eyes * Aunt Asya has arrived!
- Yes, and I have a new fairy tale for you * sat down and took the baby by the arms * do you want to listen?
- Of course! * slightly embarrassed and looked away * Uncle told me such terrible stories ...
- Well, I hope my story will not scare you * patted his hair * She should teach you how to think in a patterned way.
- Uh? * face twisted from a misunderstanding * How's that?
- M ... now you know * winked and picked it up * Here when you need to insert variables into a string - what do you do?
- Well ... * took a pencil and chirkanul on a piece of paper lying nearby * something like this:
“Have you forgotten anything?” * raised her head victoriously *
- Yes, it seems no ... * buried his nose in the code, carefully checking it again *
- What if the user enters ... * sustained a significant pause and added *
- Ah, well, yes * guilty attributed the shielding *
- Well done ... * exhaled disappointedly * Only now I'm afraid - this is not the last time you forgot to neutralize the data .. but how will you fasten language localization to this code?
- Well ... * the hard work of thought squandered a once pretty little forehead * I will take it out in a separate array:
- And it’s not a vlom that these texts [n] will write to you every time, alternating them with the data? * took a pencil and, crossing out his scribble, drew her * Look, it’s much easier to use:
- Yes * trying to digest * Probably ...
- But when there are more than one parameters - it is better to give them speaking names * a few more movements with a pencil * for clarity:
- Ha! * joyfully jumped * It turned out even longer than mine!
- Not a problem! * confidently crossed out too much * We will use auto-screening:
- So now ... * thought about the latest code * I don’t even have to worry about data shielding?! 7
- Exactly! * touched the tip of his nose with a finger * All data will be screened, except for those for which you will not explicitly say to turn off filtering:
- And what kind of function is this * with a broad gesture poked a finger at the sheet * TT.value?
- She just creates a function * slightly stumbled, deciding to illustrate her words * which always returns a certain value:
- That is, if instead of data we pass a function that returns data, then the template engine will assume that the data returned by the function is safe to insert into the template? * ofigel himself that said such a difficult phrase * Yes?
- Exactly! * spread her arms * But, look, another interesting function:
“What is she doing?” * carefully peers into the magic method *
- She takes a set of filters and arranges them in one chain * realized that there is no example here * Here, look, the following two lines are equivalent:
- Brr * shook his head * some mystic!
- This is what! * grinned * The template engine itself is even cooler:
- Yyyy * almost crying * You promised not to scare!
- Come on! * hugged in an armful * But what glamorous plug-ins are based on it:
- What is it? * sniffles, with her nose buried in her chest *
- This is the template for the URI * gave him a pencil in his hand * Write:
- Um ... * even amused * And what about html?
- Yes, the same thing:
- Krutbl!
“But that's not all!” * furiously gesturing * For html, you can also make it so that an HTMLNode with the corresponding content is displayed:
- And how to use it? * sparks of a freebie lit up in my eyes *
- Yes, it’s very simple * spread the thought over a sheet of paper *
- Um ... * slowly pulling off the source * Really not difficult ...
______________________
- Wah! * with a bright sparkle in wide-open eyes * Aunt Asya has arrived!
- Yes, and I have a new fairy tale for you * sat down and took the baby by the arms * do you want to listen?
- Of course! * slightly embarrassed and looked away * Uncle told me such terrible stories ...
- Well, I hope my story will not scare you * patted his hair * She should teach you how to think in a patterned way.
- Uh? * face twisted from a misunderstanding * How's that?
- M ... now you know * winked and picked it up * Here when you need to insert variables into a string - what do you do?
- Well ... * took a pencil and chirkanul on a piece of paper lying nearby * something like this:
var query= 'xxx'
var resultCount= 512
var message= 'По запросу ' + query + ' найдено страниц: ' + resultCount
“Have you forgotten anything?” * raised her head victoriously *
- Yes, it seems no ... * buried his nose in the code, carefully checking it again *
- What if the user enters ... * sustained a significant pause and added *
<iframe src="javascript:alert('ahtung')">iframe>
- Ah, well, yes * guilty attributed the shielding *
var message= 'По запросу ' + query.escapeHTML() + ' найдено страниц: ' + resultCount
- Well done ... * exhaled disappointedly * Only now I'm afraid - this is not the last time you forgot to neutralize the data .. but how will you fasten language localization to this code?
- Well ... * the hard work of thought squandered a once pretty little forehead * I will take it out in a separate array:
var texts= [ 'По запросу ', ' найдено страниц: ' ]
var message= texts[0] + query.escapeHTML() + texts[1] + resultCount
- And it’s not a vlom that these texts [n] will write to you every time, alternating them with the data? * took a pencil and, crossing out his scribble, drew her * Look, it’s much easier to use:
var template= TT.template( 'По запросу {0} найдено страниц: {1}' )
var message= template([ query.escapeHTML(), resultCount ])
- Yes * trying to digest * Probably ...
- But when there are more than one parameters - it is better to give them speaking names * a few more movements with a pencil * for clarity:
var template= TT.template( 'По запросу {query} найдено страниц: {count}' )
var message= template({ query: query.escapeHTML(), count: resultCount })
- Ha! * joyfully jumped * It turned out even longer than mine!
- Not a problem! * confidently crossed out too much * We will use auto-screening:
var template= TT.html( 'По запросу {query} найдено страниц: {count}' )
var message= template({ query: query, count: resultCount })
- So now ... * thought about the latest code * I don’t even have to worry about data shielding?! 7
- Exactly! * touched the tip of his nose with a finger * All data will be screened, except for those for which you will not explicitly say to turn off filtering:
var message= template({ query: TT.value( highLightedQuery ), count: resultCount })
- And what kind of function is this * with a broad gesture poked a finger at the sheet * TT.value?
- She just creates a function * slightly stumbled, deciding to illustrate her words * which always returns a certain value:
TT.value= function( data ){
returnfunction( ){
return data
}
}
- That is, if instead of data we pass a function that returns data, then the template engine will assume that the data returned by the function is safe to insert into the template? * ofigel himself that said such a difficult phrase * Yes?
- Exactly! * spread her arms * But, look, another interesting function:
TT.pipe= function( list ){
if( !list ) list= []
var len= list.length
returnfunction( data ){
for( var i= 0; i < len; ++i ) data= list[ i ]( data )
return data
}
}
“What is she doing?” * carefully peers into the magic method *
- She takes a set of filters and arranges them in one chain * realized that there is no example here * Here, look, the following two lines are equivalent:
var text= decodeURIComponent( encodeURIComponent( text ) )
var text= TT.pipe([ encodeURIComponent, decodeURIComponent ])( text )
- Brr * shook his head * some mystic!
- This is what! * grinned * The template engine itself is even cooler:
TT.template= newfunction( ){
var searcher= /((?:[^\{\}]|\{\{|\}\})*)(?:\{|$)|([^\{\}]*)(?:\})/g
returnfunction( str, filter ){
if( !filter ) filter= TT.pipe()
var parts= []
String( str ).replace
( searcher
, function( str, val, sel ){
if( sel !== void 0 ){
parts.push( function( data ){
data= data[ sel ]
switch( typeof data ){
case 'undefined': return '{' + sel + '}'
case 'function': return data()
default: return filter( data )
}
})
} elseif( val ){
val= val.split( '{{' ).join( '{' ).split( '}}' ).join( '}' )
parts.push( TT.value( val ) )
}
}
)
return TT.concater( parts )
}
}
- Yyyy * almost crying * You promised not to scare!
- Come on! * hugged in an armful * But what glamorous plug-ins are based on it:
TT.uri= function( tpl ){
return TT.template( tpl, TT.uri.encoder() )
}
TT.uri.encoder= TT.value( encodeURIComponent )
TT.uri.decoder= TT.value( decodeURIComponent )
- What is it? * sniffles, with her nose buried in her chest *
- This is the template for the URI * gave him a pencil in his hand * Write:
var searchURI= TT.uri( '/search/?q={query}&count={count}' )
location.href= searchURI({ query: '&&&', count: 10 })
- Um ... * even amused * And what about html?
- Yes, the same thing:
TT.html= function( tpl ){
return TT.template( tpl, TT.html.encoder() )
}
TT.html.encoder= newfunction( ){
var parent= document.createElement('div')
var child= parent.appendChild( document.createTextNode( '' ) )
return TT.value( function( data ){
child.nodeValue= data
return parent.innerHTML.split( '"' ).join( '"' ).split( "'" ).join( ''' )
})
}
TT.html.decoder= newfunction( ){
var parent= document.createElement('div')
return TT.value( function( data ){
parent.innerHTML= data
return parent.firstChild.nodeValue
})
}
- Krutbl!
“But that's not all!” * furiously gesturing * For html, you can also make it so that an HTMLNode with the corresponding content is displayed:
TT.dom= function( tpl ){
return TT.pipe([ TT.html( tpl ), TT.dom.parser() ])
}
TT.dom.parser= newfunction(){
var parent= document.createElement( 'div' )
return TT.value( function( html ){
parent.innerHTML= html
var childs= parent.childNodes
if( childs.length === 1 ) return childs[0]
var fragment= document.createDocumentFragment()
while( childs[0] ) fragment.appendChild( childs[0] )
return fragment
})
}
TT.dom.serializer= newfunction(){
var parent= document.createElement( 'div' )
var child= parent.appendChild( document.createTextNode( '' ) )
return TT.value( function( node ){
parent.replaceChild( node.cloneNode( true ), parent.firstChild )
return parent.innerHTML
})
}
- And how to use it? * sparks of a freebie lit up in my eyes *
- Yes, it’s very simple * spread the thought over a sheet of paper *
var link= TT.dom( '{title}' )({ uri: '/', title: 'на старт' }) // HTMLAnchorElement
var userName= TT.dom( '{head}{tail}' )({ head: 'T', tail: 'enshi' }) // HTMLFragment
- Um ... * slowly pulling off the source * Really not difficult ...
______________________