jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
A limited comparison of some popular JavaScript templating engines on a short template: 6 header tags, and 10 list items. Compared templating engines:
<script>
;//../../jin/jin.jam.js?=HNF0UJJC
this.$jin = new function $jin( ){ }
;//../../jin/func/jin_func.jam.js?=HN966P0O
this.$jin.func = {}
this.$jin.func.make = function $jin_func_make( name ){
eval( 'var func = function ' + name + '( ){\
return func.execute( this, arguments )\
}' )
return func
}
this.$jin.func.name = function $jin_func_name( func, name ){
if( arguments.length > 1 ) return func.$jin_func_name = name
return func.name
|| func.$jin_func_name
|| func.toString().match( /^\s*function\s*([$\w]*)\s*\(/ )[ 1 ]
}
;//../../jin/value/jin-value.jam.js?=HJWMNOGW
this.$jin.value = function $jin_value( value ){
var func = function $jin_value_instance( ){
return func.$jin_value
}
func.$jin_value = value
return func
}
;//../../jin/root/jin_root.jam.js?=HJWMOH0O
this.$jin.root = $jin.value( this )
;//../../jin/glob/jin_glob.jam.js?=HJWNFZRC
this.$jin.glob = function $jin_glob( name, value ){
var keyList = name.split( '_' )
var current = $jin.root()
var currentName = ''
while( keyList.length > 1 ){
var key = keyList.shift() || 'prototype'
currentName += ( currentName ? '_' : '' ) + ( key === 'prototype' ? '' : key )
if(!( key in current )){
current[ key ] = $jin.trait.make( currentName )
}
current = current[ key ]
}
var key = keyList.shift() || 'prototype'
if( arguments.length > 1 ){
current[ key ] = value
} else {
value = current[ key ]
}
return value
}
;//../../jin/trait/jin_trait.jam.js?=HN96NIQ8
this.$jin.trait = function $jin_trait( name ){
var trait = $jin.glob( name )
if( trait ) return trait
trait = $jin.trait.make( name )
return $jin.glob( name, trait )
}
this.$jin.trait.make = function $jin_trait_make( name ){
eval( 'var trait= function ' + name + '( ){ \
return ( this instanceof trait ) ? this : trait.apply( trait, arguments ) \
}' )
trait.name = name
trait.apply = function( ){ return trait }
return trait
}
;//../../jin/mixin/jin_mixin.jam.js?=HO0FZ4PK
this.$jin.mixin = function( ){ // arguments: sourceName+, targetName
var trait = $jin.mixin.object.apply( this, arguments )
for( var index = 0; index < arguments.length; ++index ){
arguments[ index ] += '_'
}
$jin.mixin.object.apply( this, arguments )
return trait
}
this.$jin.mixin.object = function( ){ // arguments: sourceName+, targetName
var sourcePathList = [].slice.call( arguments )
var targetPath = sourcePathList.pop()
var target = $jin.trait( targetPath )
sourcePathList.forEach( function( sourcePath ){
var source = $jin.trait( sourcePath )
source.$jin_mixin_slaveList = source.$jin_mixin_slaveList || []
if( ~source.$jin_mixin_slaveList.indexOf( targetPath ) ) return
source.$jin_mixin_slaveList.push( targetPath )
for( var key in source ){
var func = source[ key ]
if(( typeof func !== 'function' )||( !func.$jin_method_name )){
if(!( key in target )) target[ key ] = void 0
continue
}
var methodName = func.$jin_method_name.replace( /^([$\w]+_)+/, '' )
$jin.method.define( targetPath + '_' + methodName, func )
}
})
return target
}
;//../../jin/method/jin_method.jam.js?=HNUF10CW
this.$jin.method = function $jin_method( ){ // arguments: resolveName*, func
var resolveList = [].slice.call( arguments )
var func = resolveList.pop()
var name = $jin.func.name( func )
if( !name ) throw new Error( 'Can not register anonymous function' )
func.$jin_method_name = name
func.$jin_method_resolveList = resolveList
$jin.method.define( name, func )
}
this.$jin.method.define = function $jin_method_define( name, func ){
var funcName = func.$jin_method_name
if( !funcName ) func.$jin_method_name = name
//throw new Error( '$jin_method_name is not defined in [' + func + ']' )
var nameList = name.split( '_' )
var methodName = nameList.pop()
var ownerPath = nameList.join( '_' )
var owner = $jin.trait( ownerPath )
var slaveList = owner.$jin_mixin_slaveList
owner[ funcName ]= func
if( slaveList ) slaveList.forEach( function( slavePath ){
$jin.method.define( slavePath + '_' + methodName, func )
})
var existFunc = owner[ methodName ]
checkConflict: {
if( existFunc === void 0 ) break checkConflict
if( typeof existFunc !== 'function' ){
throw new Error( 'Can not redefine [' + existFunc + '] by [' + funcName + ']' )
}
if( func === existFunc ) return existFunc
if( !existFunc.$jin_method_name ) break checkConflict
func = $jin.method.merge( existFunc, func, name )
}
owner[ methodName ]= func
if( slaveList ) slaveList.forEach( function( slavePath ){
$jin.method.define( slavePath + '_' + methodName, func )
})
return func
}
this.$jin.method.merge = function $jin_method_merge( left, right, name ){
var leftConflicts = left.$jin_method_conflictList || [ left ]
var rightConflicts = right.$jin_method_conflictList || [ right ]
var conflictList = leftConflicts.concat( rightConflicts )
var leftResolves = left.$jin_method_resolveList || []
var rightResolves = right.$jin_method_resolveList || []
var resolveList = leftResolves.concat( rightResolves )
conflictList = conflictList.filter( function( conflict ){
return !~resolveList.indexOf( conflict.$jin_method_name )
})
if( conflictList.length === 0 ){
throw new Error( 'Can not resolve conflict ' + name + ' because cyrcullar resolving' )
} else if( conflictList.length === 1 ){
var func = conflictList[0]
} else if( conflictList.length > 1 ){
var func = $jin.func.make( name )
func.execute = function( ){
throw new Error( "Conflict in [" + func.$jin_method_name + "] by [" + func.$jin_method_conflictList + "]" )
}
func.$jin_method_name = name
func.$jin_method_conflictList = conflictList
}
func.$jin_method_resolveList = resolveList
return func
}
;//../../jin/property/jin_property.jam.js?=HO0FS3MG
this.$jin.property = function $jin_property( ){ // arguments: resolveName*, filter
var resolveList = [].slice.call( arguments )
var filter = resolveList.pop()
var name = filter.name = filter.name || filter.toString().match( /^\s*function\s*([$\w]*)\s*\(/ )[ 1 ]
if( !name ) throw new Error( 'Can not register anonymous property' )
$jin.property.define.apply( $jin.property, resolveList.concat([ name, filter ]) )
}
this.$jin.property.define = function $jin_property_define( ){ // arguments: resolveName*, name, filter
var resolveList = [].slice.call( arguments )
var filter = resolveList.pop()
var name = resolveList.pop()
var fieldName = '_' + name
var ownerName = name.replace( /_[a-z0-9]+$/i, '' )
$jin.trait( ownerName )[ fieldName ] = void 0
eval( 'var property = function ' + name + '( ){ \
return property.apply( this, arguments ) \
}' )
property.apply = function $jin_property_apply( obj, args ){
if( args.length ){
if( args[0] === void 0 ){
obj[ fieldName ] = void 0
} else {
obj[ fieldName ] = property.$jin_property_filter.apply( obj, args )
}
return obj
} else {
if( obj[ fieldName ] === void 0 ){
return obj[ fieldName ] = property.$jin_property_filter.apply( obj, args )
} else {
return obj[ fieldName ]
}
}
}
property.$jin_property_filter = filter || function( value ){ return value }
return $jin.method.apply( $jin, resolveList.concat([ property ]) )
}
;//../../jin/klass/jin_klass.jam.js?=HNILZW2W
$jin.klass = function $jin_klass( ){ // arguments: sourceName*, targetName
$jin.mixin.apply( this, arguments )
var name = arguments[ arguments.length - 1 ]
return $jin.mixin( '$jin_klass', name )
}
$jin.method( function $jin_klass_apply( context, args ){
var obj = new this
obj.init.apply( obj, args )
return obj
} )
$jin.method( function $jin_klass_id( ){
return this.$jin_method_name || this.name
} )
$jin.method( function $jin_klass_toString( ){
return this.id()
} )
$jin.method( function $jin_klass__init( json ){
return this.json( json )
} )
$jin.property.define( '$jin_klass__entangleList', Array )
$jin.method( function $jin_klass__entangle( value ){
this.entangleList().push( value )
return this
} )
$jin.method( function $jin_klass__destroy( ){
this.entangleList().forEach( function( entangle ){
entangle.destroy()
} )
for( var key in this ){
delete this[ key ]
}
return this
} )
$jin.method( function $jin_klass__json( json ){
if( !arguments.length ) return null
if( !json ) return this
for( var key in json ){
this[ key ]( json[ key ] )
}
return this
} )
$jin.property.define( '$jin_klass__methodList', Object )
$jin.method( function $jin_klass__method( name ){
var hash = this.methodHash()
var method = hash[ '_' + name ]
if( method ) return method
method = function $jin_klass__method_instance( ){
return method.content[ method.methodName ].call( method.content, arguments )
}
return hash[ '_' + name ] = method
} )
;//../../jin/wrapper/jin_wrapper.jam.js?=HNIHPODS
$jin.wrapper = function $jin_wrapper( ){ // arguments: sourceName*, targetName
$jin.mixin.apply( this, arguments )
var name = arguments[ arguments.length - 1 ]
return $jin.mixin( '$jin_wrapper', name )
}
$jin.mixin( '$jin_klass', '$jin_wrapper' )
$jin.property.define( '$jin_wrapper__raw', null )
$jin.method( '$jin_klass_apply', function $jin_wrapper_apply( wrapper, args ){
var obj = args[0]
if( obj instanceof wrapper ) return obj
if( obj.$jin_wrapper__raw ) obj = args[0] = obj.raw()
return wrapper.$jin_klass_apply( wrapper, args )
} )
$jin.method( '$jin_klass__init', function $jin_wrapper__init( obj ){
this.raw( obj )
return this
} )
;//../../jin/env/jin_env.jam.js?=HJWSZD88
this.$jin.env = $jin.value( function(){ return this }() )
;//../../jin/event/jin_event.jam.js?=HM9HTEKW
$jin.klass( '$jin_event' )
$jin.property( function $jin_event_type( ){
return String( this )
} )
$jin.method( function $jin_event_listen( crier, handler ){
return crier.listen( this.type(), handler )
} )
$jin.property.define( '$jin_event__target', null )
$jin.property.define( '$jin_event__catched', Boolean )
$jin.property( function $jin_event__type( type ){
if( arguments.length ) return String( type )
return String( this.constructor )
} )
$jin.method( function $jin_event__scream( crier ){
crier.scream( this )
return this
} )
;//../../jin/support/jin_support.env=web.jam.js?=HKMWXZ1K
$jin.property( function $jin_support_xmlModel( ){
return ( window.DOMParser && window.XMLSerializer && window.XSLTProcessor ) ? 'w3c' : 'ms'
} )
$jin.property( function $jin_support_htmlModel( ){
return document.createElement( 'html:div' ).namespaceURI !== void 0 ? 'w3c' : 'ms'
} )
$jin.property( function $jin_support_eventModel( ){
return ( 'addEventListener' in document.createElement( 'div' ) ) ? 'w3c' : 'ms'
} )
$jin.property( function $jin_support_textModel( ){
return ( 'createRange' in document ) ? 'w3c' : 'ms'
} )
$jin.property( function $jin_support_vml( ){
return /*@cc_on!@*/ false
} )
;//../../jin/dom/event/jin_dom_event.env=web.jam.js?=HKWZJK20
$jin.klass( '$jin_wrapper', '$jin_event', '$jin_dom_event' )
$jin.property( '$jin_dom_event_bubbles', Boolean )
$jin.property( '$jin_dom_event_cancelable', Boolean )
$jin.method( function $jin_dom_event__nativeEvent( ){
var raw = this.raw()
if( raw ) return raw
var Event = this.constructor
var type = Event.type()
var bubbles = Event.bubbles()
var cancelable = Event.cancelable()
if( $jin.support.eventModel() === 'ms' ){
raw= document.createEventObject()
raw.type = type
raw.bubbles = bubbles
raw.cancelable = cancelable
} else {
raw = document.createEvent( 'Event' )
raw.initEvent( type, bubbles, cancelable )
}
this.raw( raw )
return raw
} )
$jin.method( '$jin_event__target', function $jin_dom_event__target( ){
return this.nativeEvent().target
} )
$jin.method( '$jin_event__type', function $jin_dom_event__type( type ){
var nativeEvent = this.nativeEvent()
type = String( type )
if( !arguments.length ){
return nativeEvent.$jin_dom_event_type || nativeEvent.type
}
nativeEvent.initEvent( type, this.bubbles(), this.cancelable() )
nativeEvent.$jin_dom_event_type= nativeEvent.type= type
return this
} )
$jin.method( function $jin_dom_event__bubbles( bubbles ){
var nativeEvent = this.nativeEvent()
if( !arguments.length ){
return nativeEvent.bubbles
}
nativeEvent.initEvent( this.type(), Boolean( bubbles ), this.cancelable() )
return this
} )
$jin.method( function $jin_dom_event__cancelable( cancelable ){
var nativeEvent = this.nativeEvent()
if( !arguments.length ){
return nativeEvent.cancelable
}
nativeEvent.initEvent( this.type(), this.bubbles(), Boolean( cancelable ) )
return this
} )
$jin.method( function $jin_dom_event__catched( catched ){
var nativeEvent = this.nativeEvent()
if( !arguments.length ){
return nativeEvent.defaultPrevented || nativeEvent.$jin_dom_event_catched
}
nativeEvent.returnValue= !catched
if( catched && nativeEvent.preventDefault ){
nativeEvent.preventDefault()
}
nativeEvent.$jin_dom_event_catched = nativeEvent.defaultPrevented = !!catched
return this
} )
$jin.method( function $jin_dom_event__keyCode( ){
return this.nativeEvent().keyCode
} )
$jin.method( function $jin_dom_event__mouseButton( ){
return this.nativeEvent().button
} )
;//../../jin/listener/jin_listener.jam.js?=HMDEZN88
$jin.klass( '$jin_listener' )
$jin.property.define( '$jin_listener__crier', null )
$jin.property.define( '$jin_listener__eventName', String )
$jin.property.define( '$jin_listener__handler', null )
$jin.method( function $jin_listener__forget( ){
this.crier().forget( this.eventName(), this.handler() )
return this
} )
$jin.method( '$jin_klass__destroy', function $jin_listener__destroy( ){
this.forget()
this.$jin_klass__destroy()
} )
;//../../jin/dom/jin_dom.jam.js?=HO0G94A0
$jin.klass( '$jin_wrapper', '$jin_dom' )
$jin.method( '$jin_wrapper_apply', function $jin_dom_apply( wrapper, args ){
var node = args[0]
if( node instanceof wrapper ) return node
if( node[ wrapper ] instanceof wrapper ) return node[ wrapper ]
if( node.$jin_wrapper__raw ) node = args[0] = node.raw()
var obj = this.$jin_klass_apply( wrapper, args )
try {
node[ wrapper ] = obj
} catch( e ){}
return obj
} )
$jin.method( function $jin_dom_env( ){
return $jin.env()
} )
$jin.method( function $jin_dom_parse( str ){
var parser = new( $jin.dom.env().DOMParser )
var doc = parser.parseFromString( String( str ), 'text/xml' )
return $jin.dom( doc.documentElement || doc )
} )
$jin.method( function $jin_dom_escape( val ){
return val.replace( /&/g, '&' ).replace( /</g, '<' ).replace( />/g, '>' ).replace( /"/g, '"' )
} )
$jin.method( function $jin_dom__nativeDoc( ){
var node = this.raw()
return node.ownerDocument || node
} )
$jin.method( function $jin_dom__nativeNode( ){
return this.raw()
} )
$jin.method( function $jin_dom__toString( ){
var serializer= new( $jin.dom.env().XMLSerializer )
return serializer.serializeToString( this.nativeNode() )
} )
$jin.method( function $jin_dom__transform( stylesheet ){
var proc= new( $jin.dom.env().XSLTProcessor )
proc.importStylesheet( $jin.dom( stylesheet ).nativeDoc() )
var doc= proc.transformToDocument( this.nativeNode() )
return $jin.dom( doc )
} )
$jin.method( function $jin_dom__render( from, to ){
from= $jin.dom( from ).nativeNode()
to= $jin.dom( to ).nativeNode()
var proc= new( $jin.dom.env().XSLTProcessor )
proc.importStylesheet( this.nativeDoc() )
var res= proc.transformToFragment( from, to.ownerDocument )
to.innerHTML= ''
to.appendChild( res )
return this
} )
$jin.method( function $jin_dom__name( ){
return this.nativeNode().nodeName
} )
$jin.method( function $jin_dom__attr( name, value ){
if( arguments.length > 1 ){
if( value == null ) this.nativeNode().removeAttribute( name )
else this.nativeNode().setAttribute( name, value )
return this
} else {
return this.nativeNode().getAttribute( name )
}
} )
$jin.method( function $jin_dom__attrList( ){
var nodes= this.nativeNode().attributes
if( !nodes ) return []
var list= []
for( var i= 0; i < nodes.length; ++i ){
list.push( $jin.dom( nodes[ i ] ) )
}
return list
} )
$jin.method( function $jin_dom__text( value ){
var node = this.nativeNode()
if( arguments.length ){
node.textContent = String( value )
return this
} else {
return node.textContent
}
} )
$jin.method( function $jin_dom__clear( ){
var node = this.nativeNode()
var child
while( child= node.firstChild ){
node.removeChild( child )
}
return this
} )
$jin.method( function $jin_dom__parent( parent ){
var node = this.nativeNode()
if( arguments.length ){
if( parent == null ){
parent= node.parentNode
if( parent ) parent.removeChild( node )
} else {
$jin.dom( parent ).nativeNode().appendChild( node )
}
return this
} else {
parent= node.parentNode || node.ownerElement
return parent ? $jin.dom( parent ) : parent
}
} )
$jin.method( function $jin_dom__next( next ){
var node = this.nativeNode()
if( !arguments.length ){
var next = node.nextSibling
if( next ) next = $jin.dom( next )
return next
}
throw new Error( 'Not implemented' )
this.parent().nativeNode().insertBefore( $jin.dom( prev ).nativeNode(), node.nextSibling )
return this
} )
$jin.method( function $jin_dom__prev( prev ){
var node = this.nativeNode()
if( !arguments.length ){
var prev = node.previousSibling
if( prev ) prev = $jin.dom( prev )
return prev
}
this.parent().nativeNode().insertBefore( $jin.dom( prev ).nativeNode(), node )
return this
} )
$jin.method( function $jin_dom__head( dom ){
var node = this.nativeNode()
if( !arguments.length ){
var node = node.firstChild
if( node ) node = $jin.dom( node )
return node
}
node.insertBefore( $jin.dom( dom ).nativeNode(), this.head().nativeNode() )
return this
} )
$jin.method( function $jin_dom__tail( dom ){
var node = this.nativeNode()
if( !arguments.length ){
var node = node.lastChild
if( node ) node = $jin.dom( node )
return node
}
$jin.dom( dom ).parent( this )
return this
} )
$jin.method( function $jin_dom__childList( ){
var nodes= this.nativeNode().childNodes
var list= []
for( var i= 0; i < nodes.length; ++i ){
list.push( $jin.dom( nodes[ i ] ) )
}
return list
} )
$jin.method( function $jin_dom__select( xpath ){
var list= []
var found= this.nativeDoc().evaluate( xpath, this.nativeNode(), null, null, null )
for( var node; node= found.iterateNext(); ) list.push( $jin.dom( node ) )
return list
} )
$jin.method( function $jin_dom__xpath( xpath ){
var node= this.nativeDoc().evaluate( xpath, this.nativeNode(), null, null, null ).iterateNext()
if( !node ) return node
return $jin.dom( node )
} )
$jin.method( function $jin_dom__css( css ){
var node = this.nativeNode().querySelector( css )
if( !node ) return node
return $jin.dom( node )
} )
$jin.method( function $jin_dom__clone( ){
return $jin.dom( this.nativeNode().cloneNode() )
} )
$jin.method( function $jin_dom__cloneTree( ){
return $jin.dom( this.nativeNode().cloneNode( true ) )
} )
$jin.method( function $jin_dom__makeText( value ){
return $jin.dom( this.nativeDoc().createTextNode( value ) )
} )
$jin.method( function $jin_dom__makeFragment( ){
return $jin.dom( this.nativeDoc().createDocumentFragment() )
} )
$jin.method( function $jin_dom__makePI( name, content ){
return $jin.dom( this.nativeDoc().createProcessingInstruction( name, content ) )
} )
$jin.method( function $jin_dom__makeElement( name, ns ){
if( arguments.length > 1 ){
return $jin.dom( this.nativeDoc().createElementNS( ns, name ) )
} else {
return $jin.dom( this.nativeDoc().createElement( name ) )
}
} )
$jin.method( function $jin_dom__makeTree( json ){
if( !json ) return this.makeFragment()
if( ~[ 'string', 'number' ].indexOf( typeof json ) ) return this.makeText( json )
var result = this.makeFragment()
for( var key in json ){
if( !json.hasOwnProperty( key ) ) continue
var val = json[ key ]
if( !key || Number( key ) == key ){
this.makeTree( val ).parent( result )
} else {
var dom = this.makeElement( key )
this.makeTree( val ).parent( dom )
dom.parent( result )
}
}
return result
} )
$jin.method( function $jin_dom__listen( eventName, handler ){
var wrappedHandler = function( event ){
return handler( $jin.dom.event( event ) )
}
this.nativeNode().addEventListener( eventName, wrappedHandler, false )
return $jin.listener().crier( this ).eventName( eventName ).handler( wrappedHandler )
} )
$jin.method( function $jin_dom__forget( eventName, handler ){
this.nativeNode().removeEventListener( eventName, handler, false )
return this
} )
$jin.method( function $jin_dom__scream( event ){
event = $jin.dom.event( event )
this.nativeNode().dispatchEvent( event.nativeEvent() )
return this
} )
;//../../jin/dom/jin_dom.env=web.jam.js?=HNUI9BUW
$jin.method( function $jin_dom__html( html ){
if( arguments.length ){
this.nativeNode().innerHTML = html
return this
} else {
return this.nativeNode().innerHTML
}
} )
if( $jin.support.xmlModel() === 'ms' ){
$jin.mixin( '$jin_dom_ms', '$jin_dom' )
$jin.method( '$jin_dom__toString', function $jin_dom_ms__toString( ){
return String( this.nativeNode().xml )
} )
// works incorrectly =( use render instead
$jin.method( '$jin_dom__transform', function $jin_dom_ms__transform( stylesheet ){
var result= this.nativeNode().transformNode( $jin.dom( stylesheet ).nativeNode() )
return $jin.dom.parse( result )
} )
$jin.method( '$jin_dom__render', function $jin_dom_ms__render( from, to ){
from= $jin.dom( from ).nativeNode()
to= $jin.dom( to ).nativeNode()
to.innerHTML= from.transformNode( this.nativeDoc() )
} )
$jin.method( '$jin_dom__text', function $jin_dom_ms__text( value ){
var node = this.nativeNode()
if( arguments.length ){
node.innerText = value
return this
} else {
return node.innerText
}
} )
$jin.method( '$jin_dom__select', function $jin_dom_ms__select( xpath ){
var list= []
var found= this.nativeNode().selectNodes( xpath )
for( var i= 0; i < found.length; ++i ) list.push( $jin.dom( found[ i ] ) )
return list
} )
$jin.method( '$jin_dom_parse', function $jin_dom_ms_parse( str ){
var doc= new ActiveXObject( 'MSXML2.DOMDocument' )
doc.async= false
doc.loadXML( str )
return $jin.dom( doc.documentElement || doc )
} )
}
if( $jin.support.eventModel() === 'ms' ){
$jin.method( '$jin_dom_listen', function $jin_dom_ms__listen( eventName, handler ){
eventName = this.normalizeEventName( eventName )
this.nativeNode().attachEvent( eventName, function( ){
var ev = $jin.dom.event( event )
if( event.type() !== eventName ) return
return handler( event )
} )
return this
} )
$jin.method( '$jin_dom_forget', function $jin_dom_ms__forget( eventName, handler ){
eventName = this.normalizeEventName( eventName )
this.nativeNode().detachEvent( eventName, handler )
return this
} )
$jin.method( '$jin_dom_scream', function $jin_dom_ms__scream( event ){
event = $jin.dom.event( event )
var eventName = this.normalizeEventName( event.type() )
this.nativeNode().fireEvent( eventName, event.nativeEvent() )
return this
} )
$jin.method( function $jin_dom_ms__normalizeEventName( eventName ){
return /^[a-zA-Z]+$/.test( eventName ) ? 'on' + eventName : 'onbeforeeditfocus'
} )
}
;//../../jin/sample/jin_sample.jam.js?=HO0F4RCG
$jin.method( function $jin_sample( name ){
return $jin.sample.make( document.getElementById( name ) )
})
$jin.method( function $jin_sample_make( proto ){
proto = $jin.dom( proto )
return function( ){
return proto.cloneTree()
}
} )
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.2.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.1.2/handlebars.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.2.716/js/kendo.all.min.js"></script>
<script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js"></script>
<script src="http://www.jsviews.com/download/jsrender.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hogan.js/2.0.0/hogan.js"></script>
<script src="https://raw.github.com/twitter/hogan.js/master/lib/compiler.js"></script>
<script src="http://olado.github.io/doT/doT.min.js">
</script>
<div id="jin_sample_root">
<h1 class="jin_sample_header"></h1>
<h2 class="jin_sample_header2"></h2>
<h3 class="jin_sample_header3"></h3>
<h4 class="jin_sample_header4"></h4>
<h5 class="jin_sample_header5"></h5>
<h6 class="jin_sample_header6"></h6>
<ul class="jin_sample_list"></ul>
</div>
<li id="jin_sample_item" class="jin_sample_item"></li>
<!--External Template Definitions-->
<script type="text/x-kendo-template" id="kendoUIextTemplate">
<div>
<h1 class='header'>#= data.header #</h1>
<h2 class='header2'>#= data.header2 #</h2>
<h3 class='header3'>#= data.header3 #</h3>
<h4 class='header4'>#= data.header4 #</h4>
<h5 class='header5'>#= data.header5 #</h5>
<h6 class='header6'>#= data.header6 #</h6>
<ul class='list'>
# for (var i = 0, l = data.list.length; i < l; i++) { #
<li class='item'>#= data.list[i] #</li>
# } #
</ul>
</div>
</script>
<script>
window.sharedVariables = {
header: "Header",
header2: "Header2",
header3: "Header3",
header4: "Header4",
header5: "Header5",
header6: "\"'><i>if italic then need escaping",
list: ['<b>if bold then need escaping', '2', '3', '4', '5', '6', '7', '8', '9', '10']
};
window.jinTemplateRoot = $jin.sample( 'jin_sample_root' )
window.jinTemplateItem = $jin.sample( 'jin_sample_item' )
//JsRender compiled template (no encoding)
window.jsRenderTemplate = $.templates("<div><h1 class='header'>{{>header}}</h1><h2 class='header2'>{{>header2}}</h2><h3 class='header3'>{{>header3}}</h3><h4 class='header4'>{{>header4}}</h4><h5 class='header5'>{{>header5}}</h5><h6 class='header6' title='{{>header6}}' name=\"{{>header6}}\">{{>header6}}</h6><ul class='list'>{{for list}}<li class='item'>{{>#data}}</li>{{/for}}</ul></div>");
window.mustacheTemplate = "<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6' title='{{header6}}' name=\"{{header6}}\">{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{.}}</li>{{/list}}</ul></div>";
window.handlebarsTemplate = Handlebars.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6' title='{{header6}}' name=\"{{header6}}\">{{header6}}</h6><ul class='list'>{{#each list}}<li class='item'>{{this}}</li>{{/each}}</ul></div>");
window.kendouiTemplate = kendo.template("<div><h1 class='header'>#= data.header #</h1><h2 class='header2'>#= data.header2 #</h2><h3 class='header3'>#= data.header3 #</h3><h4 class='header4'>#= data.header4 #</h4><h5 class='header5'>#= data.header5 #</h5><h6 class='header6'>#= data.header6 #</h6><ul class='list'># for (var i = 0, l = data.list.length; i < l; i++) { #<li class='item'>#= data.list[i] #</li># } #</ul></div>", {useWithBlock:true});
window.kendouiTemplate2 = kendo.template("<div><h1 class='header'>#= data.header #</h1><h2 class='header2'>#= data.header2 #</h2><h3 class='header3'>#= data.header3 #</h3><h4 class='header4'>#= data.header4 #</h4><h5 class='header5'>#= data.header5 #</h5><h6 class='header6'>#= data.header6 #</h6><ul class='list'># for (var i = 0, l = data.list.length; i < l; i++) { #<li class='item'>#= data.list[i] #</li># } #</ul></div>", {useWithBlock:false});
//Use external template definition
window.kendoUIAlt = kendo.template($("#kendoUIextTemplate").html());
window.kendoUIAlt2 = kendo.template($("#kendoUIextTemplate").html(), {useWithBlock:false});
window.underscoreTemplate = _.template("<div><h1 class='header'><%- header %></h1><h2 class='header2'><%- header2 %></h2><h3 class='header3'><%- header3 %></h3><h4 class='header4'><%- header4 %></h4><h5 class='header5'><%- header5 %></h5><h6 class='header6' title='<%-header6%>' name=\"<%-header6%>\"><%- header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%- list[i] %></li><% } %></ul></div>");
window.underscoreTemplateNoWith = _.template("<div><h1 class='header'><%- data.header %></h1><h2 class='header2'><%- data.header2 %></h2><h3 class='header3'><%- data.header3 %></h3><h4 class='header4'><%- data.header4 %></h4><h5 class='header5'><%- data.header5 %></h5><h6 class='header6' title='<%-data.header6%>' name=\"<%-data.header6%>\"><%- data.header6 %></h6><ul class='list'><% for (var i = 0, l = data.list.length; i < l; i++) { %><li class='item'><%- data.list[i] %></li><% } %></ul></div>", null, {variable: 'data'});
window.baseHtml = "<div><h1 class='header'></h1><h2 class='header2'></h2><h3 class='header3'></h3><h4 class='header4'></h4><h5 class='header5'></h5><h6 class='header6'></h6><ul class='list'><li class='item'></li></ul></div>";
window.doTtemplate = doT.template("<div><h1 class='header'>{{!it.header}}</h1><h2 class='header2'>{{!it.header2}}</h2><h3 class='header3'>{{!it.header3}}</h3><h4 class='header4'>{{!it.header4}}</h4><h5 class='header5'>{{!it.header5}}</h5><h6 class='header6'>{{!it.header6}}</h6><ul class='list'>{{for(var i = 0,l=it.list.length;i<l;i++) { }}<li class='item'>{{!it.list[i]}}</li>{{ } }}</ul></div>", {append:false});
//Resig Template Function (modified to support ')
function tmpl(str) {
var strFunc =
"var p=[];" +
"with(obj){p.push('" +
str.replace(/[\r\t\n]/g, " ")
.replace(/'(?=[^#]*#>)/g, "\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(/<#=(.+?)#>/g, "',$1,'")
.split("<#").join("');")
.split("#>").join("p.push('")
+ "');}return p.join('');";
return new Function("obj", strFunc);
}
window.resig = tmpl("<div><h1 class='header'><#= header #></h1><h2 class='header2'><#= header2 #></h2><h3 class='header3'><#= header3 #></h3><h4 class='header4'><#= header4 #></h4><h5 class='header5'><#= header5 #></h5><h6 class='header6'><#= header6 #></h6><ul class='list'><# for (var i = 0, l = list.length; i < l; i++) { #><li class='item'><#= list[i] #></li><# } #></ul></div>");
//Resig modified template function (no "with" block)
function tmpl2(str) {
var strFunc =
"var p=[];" +
"p.push('" +
str.replace(/[\r\t\n]/g, " ")
.replace(/'(?=[^#]*#>)/g, "\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(/<#=(.+?)#>/g, "',$1,'")
.split("<#").join("');")
.split("#>").join("p.push('")
+ "');return p.join('');";
return new Function("data", strFunc);
}
window.resig2 = tmpl2("<div><h1 class='header'><#= data.header #></h1><h2 class='header2'><#= data.header2 #></h2><h3 class='header3'><#= data.header3 #></h3><h4 class='header4'><#= data.header4 #></h4><h5 class='header5'><#= data.header5 #></h5><h6 class='header6'><#= data.header6 #></h6><ul class='list'><# for (var i = 0, l = data.list.length; i < l; i++) { #><li class='item'><#= data.list[i] #></li><# } #></ul></div>");
window.hoganTemplate = Hogan.compile("<div><h1 class='header'>{{> header}}</h1><h2 class='header2'>{{> header2}}</h2><h3 class='header3'>{{> header3}}</h3><h4 class='header4'>{{> header4}}</h4><h5 class='header5'>{{> header5}}</h5><h6 class='header6' title='{{> header6}}' name=\"{{> header6}}\">{{> header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{> .}}</li>{{/list}}</ul></div>");
window.xslTemplate = $jin.dom.parse(
'<xsl:stylesheet\
version="1.0"\
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\
>\
<xsl:template match="root">\
<div><xsl:apply-templates /></div>\
</xsl:template>\
<xsl:template match="header">\
<h1 class="header"><xsl:apply-templates /></h1>\
</xsl:template>\
<xsl:template match="header2">\
<h2 class="header2"><xsl:apply-templates /></h2>\
</xsl:template>\
<xsl:template match="header3">\
<h3 class="header3"><xsl:apply-templates /></h3>\
</xsl:template>\
<xsl:template match="header4">\
<h4 class="header4"><xsl:apply-templates /></h4>\
</xsl:template>\
<xsl:template match="header5">\
<h5 class="header5"><xsl:apply-templates /></h5>\
</xsl:template>\
<xsl:template match="header6">\
<h6 class="header6" title="{.}" name="{.}"><xsl:apply-templates /></h6>\
</xsl:template>\
<xsl:template match="list">\
<ul class="list"><xsl:apply-templates /></ul>\
</xsl:template>\
<xsl:template match="item">\
<li class="item"><xsl:apply-templates /></li>\
</xsl:template>\
</xsl:stylesheet>\
')
var root = {}
for( var key in sharedVariables ) root[ key ] = sharedVariables[ key ]
root.list = root.list.map( function( item ){ return { item: item } } )
var sharedVariablesAsDom = $jin.dom.parse('<x/>').makeTree({ root: root })
</script>
<div id="template" style="display:none"></div>
<div id="output"></div>
<script>
window.output = document.getElementById('output')
window.wrappedOutput = $jin.dom( output )
</script>
output.innerHTML = ''
Ready to run.
Test | Ops/sec | |
---|---|---|
Mustache |
| ready |
jin_sample |
| ready |
jin_dom__render (xslt) |
| ready |
Handlebars |
| ready |
Underscore |
| ready |
JsRender |
| ready |
Underscore (no with) |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.