Пример #1
0
export default function Element$unrender ( shouldDestroy ) {
	var binding, bindings;

	// Detach as soon as we can
	if ( this.name === 'option' ) {
		// <option> elements detach immediately, so that
		// their parent <select> element syncs correctly, and
		// since option elements can't have transitions anyway
		this.detach();
	} else if ( shouldDestroy ) {
		runloop.detachWhenReady( this );
	}

	// Children first. that way, any transitions on child elements will be
	// handled by the current transitionManager
	if ( this.fragment ) {
		this.fragment.unrender( false );
	}

	if ( binding = this.binding ) {
		this.binding.unrender();

		this.node._ractive.binding = null;
		bindings = this.root._twowayBindings[ binding.keypath ];
		bindings.splice( bindings.indexOf( binding ), 1 );
	}

	// Remove event handlers
	if ( this.eventHandlers ) {
		this.eventHandlers.forEach( h => h.unrender() );
	}

	if ( this.decorator ) {
		this.decorator.teardown();
	}

	// trigger outro transition if necessary
	if ( this.root.transitionsEnabled && this.outro ) {
		let transition = new Transition ( this, this.outro, false );
		runloop.registerTransition( transition );
		runloop.scheduleTask( () => transition.start() );
	}

	// Remove this node from any live queries
	if ( this.liveQueries ) {
		removeFromLiveQueries( this );
	}

	// Remove from nodes
	if ( this.node.id ) {
		delete this.root.nodes[ this.node.id ];
	}
}
Пример #2
0
export default function Element$render () {
	var root = this.root, namespace, node;

	namespace = getNamespace( this );
	node = this.node = createElement( this.name, namespace );

	// Is this a top-level node of a component? If so, we may need to add
	// a data-rvcguid attribute, for CSS encapsulation
	// NOTE: css no longer copied to instance, so we check constructor.css -
	// we can enhance to handle instance, but this is more "correct" with current
	// functionality
	if ( root.constructor.css && this.parentFragment.getNode() === root.el ) {
		this.node.setAttribute( 'data-rvcguid', root.constructor._guid /*|| root._guid*/ );
	}

	// Add _ractive property to the node - we use this object to store stuff
	// related to proxy events, two-way bindings etc
	defineProperty( this.node, '_ractive', {
		value: {
			proxy: this,
			keypath: getInnerContext( this.parentFragment ),
			index: this.parentFragment.indexRefs,
			events: create( null ),
			root: root
		}
	});

	// Render attributes
	this.attributes.forEach( a => a.render( node ) );
	this.conditionalAttributes.forEach( a => a.render( node ) );

	// Render children
	if ( this.fragment ) {
		// Special case - <script> element
		if ( this.name === 'script' ) {
			this.bubble = updateScript;
			this.node.text = this.fragment.toString( false ); // bypass warning initially
			this.fragment.unrender = noop; // TODO this is a kludge
		}

		// Special case - <style> element
		else if ( this.name === 'style' ) {
			this.bubble = updateCss;
			this.bubble();
			this.fragment.unrender = noop;
		}

		// Special case - contenteditable
		else if ( this.binding && this.getAttribute( 'contenteditable' ) ) {
			this.fragment.unrender = noop;
		}

		else {
			this.node.appendChild( this.fragment.render() );
		}
	}

	// Add proxy event handlers
	if ( this.eventHandlers ) {
		this.eventHandlers.forEach( h => h.render() );
	}

	// deal with two-way bindings
	if ( this.binding ) {
		this.binding.render();
		this.node._ractive.binding = this.binding;
	}

	// Special case: if this is an <img>, and we're in a crap browser, we may
	// need to prevent it from overriding width and height when it loads the src
	if ( this.name === 'img' ) {
		renderImage( this );
	}

	// apply decorator(s)
	if ( this.decorator && this.decorator.fn ) {
		runloop.scheduleTask( () => this.decorator.init(), true );
	}

	// trigger intro transition
	if ( root.transitionsEnabled && this.intro ) {
		let transition = new Transition ( this, this.intro, true );
		runloop.registerTransition( transition );
		runloop.scheduleTask( () => transition.start(), true );

		this.transition = transition;
	}

	if ( this.name === 'option' ) {
		processOption( this );
	}

	if ( this.node.autofocus ) {
		// Special case. Some browsers (*cough* Firefix *cough*) have a problem
		// with dynamically-generated elements having autofocus, and they won't
		// allow you to programmatically focus the element until it's in the DOM
		runloop.scheduleTask( () => this.node.focus(), true );
	}

	updateLiveQueries( this );
	return this.node;
}