Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to convert real dom to virtual-dom #49

Closed
Swatinem opened this issue Apr 7, 2014 · 21 comments
Closed

Ability to convert real dom to virtual-dom #49

Swatinem opened this issue Apr 7, 2014 · 21 comments

Comments

@Swatinem
Copy link

Swatinem commented Apr 7, 2014

In my project, I have a fromDOM method that takes a real dom element (or DocumentFragment) and converts it into a virtualdom node or array.

Would be nice to have that ability here as well.

@Matt-Esch
Copy link
Owner

See: #1

@Swatinem
Copy link
Author

Swatinem commented Apr 7, 2014

Hm, I should really take a look also at the closed tickets, haha.
So its really hard to do because of the properties vs attributes discussion.

@neonstalwart
Copy link
Collaborator

a similar but different feature would allow attaching a vtree to some existing DOM. the scenario would be that vdom would be used to render the initial contents of the page on the server and then the client would attach to that when the page loads. because the server could only set attributes but the vtree would describe properties, it's necessary to do some initial work to get the properties in the right state when the page loads.

the client and the server would presumably both be able to generate the same vtree for the initial contents of the page and so this should be much easier than actually serializing an existing DOM without a matching vtree.

@Matt-Esch
Copy link
Owner

We need a project that can turn DOM properties into attributes reliably. One option is of course to use a browser (like phantomjs) then you can just retrieve the html of the resulting document, but it seems overkill to me. A dom property/attribute module on it's own would be pretty useful, but the mapping is not very clean at all.

@Raynos
Copy link
Collaborator

Raynos commented Apr 7, 2014

+1 for DOM properties -> attributes.

min-document has a properties -> attributes serializer but may not be complete.

Also note to convert a real DOM into a virtual DOM is easy. a real dom already has properties. You dont need any kind of properties attributes serializer.

You only need properties -> attributes serializer for converting vdom to html.

@Swatinem
Copy link
Author

Swatinem commented Apr 8, 2014

Yes, the real DOM has properties already. But it has hundreds of those, only a few of which are useful in the context of virtual-dom.

@marcelklehr
Copy link

fyi, I just started https://github.com/marcelklehr/vdom-virtualize

The property list is probably not complete yet.

@Matt-Esch
Copy link
Owner

👍 I've had a quick look over it but I'm busy at the moment. I'll post some feedback as soon as I get the chance :)

@Raynos
Copy link
Collaborator

Raynos commented May 1, 2014

@neonstalwart
Copy link
Collaborator

i'm wondering what the use cases are for doing this. the main one i can think of is for attaching to DOM that was already rendered when the page loads. for this case, since markup can only set attributes, you can ignore properties and only need to walk the element tree and collect their attributes.

a rough sketch for the code to recursively walk the DOM might be something like this

function processNode(node) {
    if (node.nodeType === Node.ELEMENT_NODE) {
        var i, child, attributes = {}, children = [];
        for (i = 0; (child = node.attributes[i]); ++i) {
            attributes[child.nodeName] = child.nodeValue;
        }
        for (i = 0; (child = node.childNodes[i]); ++i) {
            children.push(processNode(child));
        }
        return new VNode(node.tagName, { attributes: attributes }, children);
    }
    if (node.nodeType === Node.TEXT_NODE) {
        return new VText(node.nodeValue);
    }
}

// scan the existing DOM to get a vtree
var vnode = processNode(document.body);

// produce a richer vtree which should result in the same DOM structure as the existing
// one but will need hooks, widgets, properties, etc to be applied when we patch.
// `initialData` should be the same data used by the server to generate the
// initial markup.
var next = render(initialData);

var patches = diff(vnode, next);
patch(document.body, patches);

i'm not sure if i've oversimplified it but i would hope it could be made about as simple as that.

the only time i can think of when you would want to know about properties is when you've got other JS that has interacted with the DOM before you attached to it. if that's happening though, i think you're already in a dangerous spot because at a later time vdom may pull nodes out from under the other JS and cause it to break - you probably don't want to mix the streams like that - either vdom is the boss or the other JS is the boss but i wouldn't think it's a good idea for both of them to interact with the same nodes with each one expecting that they are the boss.

@neonstalwart
Copy link
Collaborator

actually... i think the initial attributes would need to be in some kind of hook that used node.setAttribute to set them - not too hard to do though. wish i had some time to work it out properly 😄

@neonstalwart
Copy link
Collaborator

hmm... nevermind - i did oversimplify it and i realize now that what needs to happen is to use the attributes as the whitelist to tell you which properties you need to look at. so, rather than using a known whitelist of properties, the attributes on the node are your whitelist and then you need to know how those translate to properties so you can build the properties for your vnode.

@Raynos
Copy link
Collaborator

Raynos commented May 1, 2014

the idea is that there is a bijection.

Purity says virtualize(createElement(vnode)) === vnode.

Personally I think this is a dangerous thing to do correctly and there is no use case for it.

There are a couple of debugging use cases. Say you have an existing application that you want to upgrade, you may want to virtualize the DOM or create a vnode from a html string so that you dont have to do this step manually.

@marcelklehr
Copy link

Thanks for the link!

@Raynos
Copy link
Collaborator

Raynos commented May 31, 2014

@marcelklehr I'll probably use vdom-virtualize to implement server side rendering this weekend :)

I might send some PRs in your direction!

@necolas
Copy link

necolas commented Aug 2, 2014

I was thinking of using a virtualizer to work with HTML rendered from a non-javascript server. We have several apps at Twitter that have Scala backends and use Flight to attach to the DOM on the client-side.

@Raynos
Copy link
Collaborator

Raynos commented Aug 2, 2014

@necolas there are two implementations of this https://github.com/Matt-Esch/virtual-dom/wiki

@necolas
Copy link

necolas commented Aug 2, 2014

thanks i've seen those. merely mentioning a relevant use case since use cases were doubted.

@gsf
Copy link
Contributor

gsf commented Aug 2, 2014

Can this be closed, then, since it's being handled outside of virtual-dom?

Also @Raynos regarding server-side rendering see marcelklehr/vdom-virtualize#7.

@Swatinem
Copy link
Author

Swatinem commented Aug 3, 2014

Yes sure.

@Swatinem Swatinem closed this as completed Aug 3, 2014
@marcelklehr
Copy link

@neonstalwart Feel free to open a pull request over on vdom-virtualize for restricting the property white-list with actual attributes :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants