Wrap an existing DOM element in an enyo kind

Is it possible to wrap an existing DOM element into an enyo kind? For example, I have a div in html, and I want to use that div as if it were an enyo.kind of 'SpecialDiv'. Is there a way to create a SpecialDiv instance and tell it to occupy/use/wrap the existing div?

The application of this question, and I am open to alternate suggestions, is to pre-render html on the server, but still use enyo for functionality on the client. In other words, we want to skip the render part and instead tell enyo to use an already rendered element.

Comments

  • It's not possible now, but it seems like an interesting extension of the enyo code... maybe instead of render() it would be assume() and would take a DOM node as the parameter.

    There's already some practical code doing this kind of thing in enyo.FlyweightRepeater -- that handles mapping existing enyo kind instances back to DOM nodes in prepareRow.
  • Well, I found I am halfway there. My fiddle is here: http://jsfiddle.net/dposin/grCUT/

    You can force an existing node into the node property of a kind instance. The enyo instance works with the node as if it rendered it, which is very cool. But it doesn't load initial state. Although, you can pass them in manually through the createComponent.

    assume() would be awesome..I might try that with my createComponent trick
    Thanks for the lead. I will check out the Flyweight Repeater

    As always, thanks for the response and help
  • edited October 2013
    If anyone is curious, this is what I have settled on for now:
    enyo.DomToEnyoNode = {
    	name: 'DomToEnyoNode',
    	loadNode: function (node, parent, enyoOptions) {
    		var props = {},
    			map = {
    				id: 'id',
    				name: 'name',
    				classList: 'classes',
    				type: 'type'
    			},
    			result = {},
    			kind = '';
    
    		enyo.forEach(Object.keys(map), function (key) {
    			if (node[key]) {
    				if (typeof map[key] === 'string'){ 
    					if (node[key]) {
    						props[map[key]] = node[key];
    					}
    				}else{
    					enyo.forEach(map[key], function (propertyName) {
    						if (node[key]) {
    							props[propertyName] = node[key];
    						}
    					});
    				}				
    			}
    		});
    
    		props.node = node;
    		props.owner = parent;
    		props.generated = true;
    		props._needsRender = false;
    
    		if (enyoOptions) {
    			enyo.mixin(props, enyoOptions, true);
    		}
    
    		if (enyoOptions) {
    			kind = enyoOptions.kindName || 'Control'
    		}
    
    		result = parent.createComponent({ kind: kind || 'Control' }, props);
    		return result;
    	}
    };
    
    So html like:
    <input id="signin_username" type="text" name="username" tabindex="1" class="enyo-input " style="">
    
    Gets enyo-nized like:
    enyo.DomToEnyoNode.loadNode(enyo.dom.byId('signin_username'), form, {
    			kindName: 'Input',
    			handlers: { onchange: 'onChange' },
    			onChange: function (inSender) {
    				var isValid = (inSender.getValue().length > 0);
    				$(inSender.node).toggleClass('k-invalid', !isValid);
    			}
    		});
    
  • One Enyo naming convention is that only constructors have capitalized names... that's why "enyo", "onyx", and "enyo.dom" aren't capitalized, but kinds, which you can invoke via new, are. While enyo.DomToEnyoNode is a namespace, if you can't say "new enyo.DomToEnyoNode()", then it should be lower-case at the start.
  • the fiddle now properly shows lower-case enyo.domToEnyoNode.

    Thanks Ben.
  • Will assume be added to enyo release?
Sign In or Register to comment.