|
(function () { |
|
'use strict'; |
|
|
|
function appendNode ( node, target ) { |
|
target.appendChild( node ); |
|
} |
|
|
|
function insertNode ( node, target, anchor ) { |
|
target.insertBefore( node, anchor ); |
|
} |
|
|
|
function detachNode ( node ) { |
|
node.parentNode.removeChild( node ); |
|
} |
|
|
|
function createElement ( name ) { |
|
return document.createElement( name ); |
|
} |
|
|
|
function createText ( data ) { |
|
return document.createTextNode( data ); |
|
} |
|
|
|
function createComment ( data ) { |
|
return document.createComment( data ); |
|
} |
|
|
|
function get ( key ) { |
|
return key ? this._state[ key ] : this._state; |
|
} |
|
|
|
function fire ( eventName, data ) { |
|
var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); |
|
if ( !handlers ) return; |
|
|
|
for ( var i = 0; i < handlers.length; i += 1 ) { |
|
handlers[i].call( this, data ); |
|
} |
|
} |
|
|
|
function observe ( key, callback, options ) { |
|
var group = ( options && options.defer ) ? this._observers.pre : this._observers.post; |
|
|
|
( group[ key ] || ( group[ key ] = [] ) ).push( callback ); |
|
|
|
if ( !options || options.init !== false ) { |
|
callback.__calling = true; |
|
callback.call( this, this._state[ key ] ); |
|
callback.__calling = false; |
|
} |
|
|
|
return { |
|
cancel: function () { |
|
var index = group[ key ].indexOf( callback ); |
|
if ( ~index ) group[ key ].splice( index, 1 ); |
|
} |
|
}; |
|
} |
|
|
|
function on ( eventName, handler ) { |
|
var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] ); |
|
handlers.push( handler ); |
|
|
|
return { |
|
cancel: function () { |
|
var index = handlers.indexOf( handler ); |
|
if ( ~index ) handlers.splice( index, 1 ); |
|
} |
|
}; |
|
} |
|
|
|
function noop () {} |
|
|
|
function dispatchObservers ( component, group, newState, oldState ) { |
|
for ( var key in group ) { |
|
if ( !( key in newState ) ) continue; |
|
|
|
var newValue = newState[ key ]; |
|
var oldValue = oldState[ key ]; |
|
|
|
if ( newValue === oldValue && typeof newValue !== 'object' ) continue; |
|
|
|
var callbacks = group[ key ]; |
|
if ( !callbacks ) continue; |
|
|
|
for ( var i = 0; i < callbacks.length; i += 1 ) { |
|
var callback = callbacks[i]; |
|
if ( callback.__calling ) continue; |
|
|
|
callback.__calling = true; |
|
callback.call( component, newValue, oldValue ); |
|
callback.__calling = false; |
|
} |
|
} |
|
} |
|
|
|
function renderMainFragment$1 ( root, component ) { |
|
var div = createElement( 'div' ); |
|
|
|
var p = createElement( 'p' ); |
|
|
|
appendNode( p, div ); |
|
|
|
var strong = createElement( 'strong' ); |
|
|
|
appendNode( strong, p ); |
|
var text = createText( root.person.name ); |
|
appendNode( text, strong ); |
|
appendNode( createText( " " ), p ); |
|
var ifBlock_anchor = createComment( "#if isLeader" ); |
|
appendNode( ifBlock_anchor, p ); |
|
|
|
function getBlock ( root ) { |
|
if ( root.isLeader ) return renderIfBlock_0; |
|
return null; |
|
} |
|
|
|
var currentBlock = getBlock( root ); |
|
var ifBlock = currentBlock && currentBlock( root, component ); |
|
|
|
if ( ifBlock ) ifBlock.mount( ifBlock_anchor.parentNode, ifBlock_anchor ); |
|
appendNode( createText( "\n\t" ), div ); |
|
|
|
var button = createElement( 'button' ); |
|
|
|
function clickHandler ( event ) { |
|
var root = this.__svelte.root; |
|
|
|
component.fire("select", { person: root.person }); |
|
} |
|
|
|
button.addEventListener( 'click', clickHandler, false ); |
|
|
|
button.disabled = root.isLeader; |
|
|
|
button.__svelte = { |
|
root: root |
|
}; |
|
|
|
appendNode( button, div ); |
|
appendNode( createText( "make leader" ), button ); |
|
|
|
return { |
|
mount: function ( target, anchor ) { |
|
insertNode( div, target, anchor ); |
|
}, |
|
|
|
update: function ( changed, root ) { |
|
text.data = root.person.name; |
|
|
|
var _currentBlock = currentBlock; |
|
currentBlock = getBlock( root ); |
|
if ( _currentBlock === currentBlock && ifBlock) { |
|
ifBlock.update( changed, root ); |
|
} else { |
|
if ( ifBlock ) ifBlock.teardown( true ); |
|
ifBlock = currentBlock && currentBlock( root, component ); |
|
if ( ifBlock ) ifBlock.mount( ifBlock_anchor.parentNode, ifBlock_anchor ); |
|
} |
|
|
|
button.disabled = root.isLeader; |
|
|
|
button.__svelte.root = root; |
|
}, |
|
|
|
teardown: function ( detach ) { |
|
if ( ifBlock ) ifBlock.teardown( false ); |
|
button.removeEventListener( 'click', clickHandler, false ); |
|
|
|
if ( detach ) { |
|
detachNode( div ); |
|
} |
|
}, |
|
}; |
|
} |
|
|
|
function renderIfBlock_0 ( root, component ) { |
|
var text = createText( "(leader)" ); |
|
|
|
return { |
|
mount: function ( target, anchor ) { |
|
insertNode( text, target, anchor ); |
|
}, |
|
|
|
update: noop, |
|
|
|
teardown: function ( detach ) { |
|
if ( detach ) { |
|
detachNode( text ); |
|
} |
|
}, |
|
}; |
|
} |
|
|
|
function Person ( options ) { |
|
options = options || {}; |
|
|
|
this._state = options.data || {}; |
|
|
|
this._observers = { |
|
pre: Object.create( null ), |
|
post: Object.create( null ) |
|
}; |
|
|
|
this._handlers = Object.create( null ); |
|
|
|
this._root = options._root; |
|
this._yield = options._yield; |
|
|
|
this._fragment = renderMainFragment$1( this._state, this ); |
|
if ( options.target ) this._fragment.mount( options.target, null ); |
|
} |
|
|
|
Person.prototype.get = get; |
|
Person.prototype.fire = fire; |
|
Person.prototype.observe = observe; |
|
Person.prototype.on = on; |
|
|
|
Person.prototype.set = function set ( newState ) { |
|
var oldState = this._state; |
|
this._state = Object.assign( {}, oldState, newState ); |
|
|
|
dispatchObservers( this, this._observers.pre, newState, oldState ); |
|
if ( this._fragment ) this._fragment.update( newState, this._state ); |
|
dispatchObservers( this, this._observers.post, newState, oldState ); |
|
}; |
|
|
|
Person.prototype.teardown = function teardown ( detach ) { |
|
this.fire( 'teardown' ); |
|
|
|
this._fragment.teardown( detach !== false ); |
|
this._fragment = null; |
|
|
|
this._state = {}; |
|
}; |
|
|
|
var template = (function () { |
|
return { |
|
data: function () { |
|
return { |
|
leader: null, |
|
people: [ |
|
{ name: 'Alice' }, |
|
{ name: 'Bob' }, |
|
{ name: 'Carol' } |
|
] |
|
}; |
|
}, |
|
|
|
components: { |
|
Person |
|
} |
|
} |
|
}()); |
|
|
|
function renderMainFragment ( root, component ) { |
|
var eachBlock_anchor = createComment( "#each people" ); |
|
var eachBlock_value = root.people; |
|
var eachBlock_iterations = []; |
|
|
|
for ( var i = 0; i < eachBlock_value.length; i += 1 ) { |
|
eachBlock_iterations[i] = renderEachBlock( root, eachBlock_value, eachBlock_value[i], i, component ); |
|
} |
|
|
|
return { |
|
mount: function ( target, anchor ) { |
|
insertNode( eachBlock_anchor, target, anchor ); |
|
|
|
for ( var i = 0; i < eachBlock_iterations.length; i += 1 ) { |
|
eachBlock_iterations[i].mount( eachBlock_anchor.parentNode, eachBlock_anchor ); |
|
} |
|
}, |
|
|
|
update: function ( changed, root ) { |
|
var eachBlock_value = root.people; |
|
|
|
for ( var i = 0; i < eachBlock_value.length; i += 1 ) { |
|
if ( !eachBlock_iterations[i] ) { |
|
eachBlock_iterations[i] = renderEachBlock( root, eachBlock_value, eachBlock_value[i], i, component ); |
|
eachBlock_iterations[i].mount( eachBlock_anchor.parentNode, eachBlock_anchor ); |
|
} else { |
|
eachBlock_iterations[i].update( changed, root, eachBlock_value, eachBlock_value[i], i ); |
|
} |
|
} |
|
|
|
for ( var i = eachBlock_value.length; i < eachBlock_iterations.length; i += 1 ) { |
|
eachBlock_iterations[i].teardown( true ); |
|
} |
|
|
|
eachBlock_iterations.length = eachBlock_value.length; |
|
}, |
|
|
|
teardown: function ( detach ) { |
|
for ( var i = 0; i < eachBlock_iterations.length; i += 1 ) { |
|
eachBlock_iterations[i].teardown( detach ); |
|
} |
|
|
|
if ( detach ) { |
|
detachNode( eachBlock_anchor ); |
|
} |
|
}, |
|
}; |
|
} |
|
|
|
function renderEachBlock ( root, eachBlock_value, person, person__index, component ) { |
|
var person1_initialData = { |
|
isLeader: root.leader === person, |
|
person: person |
|
}; |
|
var person1 = new template.components.Person({ |
|
target: null, |
|
_root: component._root || component, |
|
data: person1_initialData |
|
}); |
|
|
|
person1.on( 'select', function ( event ) { |
|
component.set({ leader: event.person }); |
|
}); |
|
|
|
return { |
|
mount: function ( target, anchor ) { |
|
person1._fragment.mount( target, anchor ); |
|
}, |
|
|
|
update: function ( changed, root, eachBlock_value, person, person__index ) { |
|
var person = eachBlock_value[person__index]; |
|
|
|
var person1_changes = {}; |
|
|
|
if ( 'leader' in changed||'people' in changed ) person1_changes.isLeader = root.leader === person; |
|
if ( 'people' in changed ) person1_changes.person = person; |
|
|
|
if ( Object.keys( person1_changes ).length ) person1.set( person1_changes ); |
|
}, |
|
|
|
teardown: function ( detach ) { |
|
person1.teardown( detach ); |
|
}, |
|
}; |
|
} |
|
|
|
function App ( options ) { |
|
options = options || {}; |
|
|
|
this._state = Object.assign( template.data(), options.data ); |
|
|
|
this._observers = { |
|
pre: Object.create( null ), |
|
post: Object.create( null ) |
|
}; |
|
|
|
this._handlers = Object.create( null ); |
|
|
|
this._root = options._root; |
|
this._yield = options._yield; |
|
|
|
this._renderHooks = []; |
|
|
|
this._fragment = renderMainFragment( this._state, this ); |
|
if ( options.target ) this._fragment.mount( options.target, null ); |
|
|
|
while ( this._renderHooks.length ) { |
|
var hook = this._renderHooks.pop(); |
|
hook.fn.call( hook.context ); |
|
} |
|
} |
|
|
|
App.prototype.get = get; |
|
App.prototype.fire = fire; |
|
App.prototype.observe = observe; |
|
App.prototype.on = on; |
|
|
|
App.prototype.set = function set ( newState ) { |
|
var oldState = this._state; |
|
this._state = Object.assign( {}, oldState, newState ); |
|
|
|
dispatchObservers( this, this._observers.pre, newState, oldState ); |
|
if ( this._fragment ) this._fragment.update( newState, this._state ); |
|
dispatchObservers( this, this._observers.post, newState, oldState ); |
|
|
|
while ( this._renderHooks.length ) { |
|
var hook = this._renderHooks.pop(); |
|
hook.fn.call( hook.context ); |
|
} |
|
}; |
|
|
|
App.prototype.teardown = function teardown ( detach ) { |
|
this.fire( 'teardown' ); |
|
|
|
this._fragment.teardown( detach !== false ); |
|
this._fragment = null; |
|
|
|
this._state = {}; |
|
}; |
|
|
|
new App({ |
|
target: document.querySelector( 'main' ) |
|
}); |
|
|
|
}()); |