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:
    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 ...

    ______________________
    The text is prepared in the Blog Editor by © SoftCoder.ru

    Also popular now: