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

Nodes per element #51

Merged

Conversation

revengineering
Copy link
Contributor

Fixes Issue #50, allowing the body of the foreachInit to have multiple HTML nodes per array element.

Also fixes a couple of minor browser compatibility issues with older versions of IE.

   * Changed how `<tr>` elements are read from a named template (original code did not work in IE<10).
   * Do not use cloneNode or delete script tag based templates. This breaks the templates in IE<9.
   * Used `ko.utils.arrayMap` instead of `.map` since the latter is unsupported in IE<9.
   * Removed hanging commas that cause syntax errors in IE<8.

These changes allow the ko-pre-rendered bindings to support the same browser versions as knockout itself.
…es should be associated with a single element in the array.

   * If unspecified, the default nodesPerElement is 1
   * Modified "makeTemplateNode" to support multiple nodes in the template.
   * Modified the "existing" method so it correctly applies bindings when nodesPerElement > 1.
   * Modified the "createElements" method so it creates the correct number of array elements for the number of existing HTML nodes.
Tested:
   * Initialization of the observable array based on existing markup.
   * Proper rendering of multi-node templates when adding new items to the observable array.
   * Proper removal of markup when removing items from the observable array.
@coveralls
Copy link

coveralls commented Jun 6, 2018

Coverage Status

Coverage increased (+0.4%) to 93.659% when pulling 9eef8eb on revengineering:NodesPerElement into ed687b2 on ErikSchierboom:master.

Copy link
Owner

@ErikSchierboom ErikSchierboom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very nice PR! Really like the code quality.

I've requested some styling changes, but other than that it looks great!

@@ -78,20 +78,34 @@
// For e.g. <template> tags
parentNode = sourceNode.content;
} else if (sourceNode.tagName === 'SCRIPT') {
parentNode = sourceNode.innerHTML.match(/<tr[\s\S]*?<\/tr>/g) ? document.createElement('tbody') : document.createElement('div');
parentNode.innerHTML = sourceNode.innerHTML;
if(sourceNode.innerHTML.match(/<tr[\s\S]*?<\/tr>/g)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very small nit: there should be a space after the if.


for(var i = 0, node = template; i < nodesPerElement; i++) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a space after the for.

var currentNode = node;
container.insertBefore(node.cloneNode(true), null);
// Find next element sibling. (Some older browsers don't support nextElementSibling).
do { node = node.nextElementSibling || node.nextSibling; } while(node && node.nodeType !== 1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to put this on multiple lines:

do {
  node = node.nextElementSibling || node.nextSibling; 
} while (node && node.nodeType !== 1); 

// Remove current template node
if(deleteTemplateNodes) {
ko.removeNode(currentNode);
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There appears to be some indentation problem here

@revengineering
Copy link
Contributor Author

Should be all set.

@ErikSchierboom ErikSchierboom merged commit 9d30ab5 into ErikSchierboom:master Jun 7, 2018
@ErikSchierboom
Copy link
Owner

Merged! Thanks a lot @revengineering. I'll put out a new release tonight.

@revengineering
Copy link
Contributor Author

My pleasure. Thanks for making this library! It has completely changed my perspective on knockout, and put it back in the running for my current and future projects.

@ErikSchierboom
Copy link
Owner

@revengineering That's great to hear!

I've just published version 0.9.2 to NPM and GitHub, which includes your changes. Again, thanks a lot!

@penguinstampede
Copy link
Contributor

This update seems to break foreachInit if your looped elements (if that's the right term) are tables, so something like:

<div data-bind="foreachInit: { name: 'theTemplate', data: myData }">
<table data-init>
[usual table-y stuff here]
</table>
</div>

nets you the error Cannot read property 'cloneNode' of null

I wrote a test for this, and I fixed it by changing line 81:

if (sourceNode.innerHTML.match(/<tr[\s\S]*?<\/tr>/g)) {

to

if (sourceNode.innerHTML.match(/<tr[\s\S]*?<\/tr>/g) && !sourceNode.innerHTML.match(/<table[\s\S]*?<\/table>/g)) {

but I'm not sure if this is the best way to fix this? I can make a new PR with the test/fix if you'd like, though.

@ErikSchierboom
Copy link
Owner

I can make a new PR with the test/fix if you'd like, though.

That would be great!

@revengineering
Copy link
Contributor Author

revengineering commented Nov 6, 2018

The fix you proposed would work except if the tr elements contain any nested tables

I suggest an alternate regex of:

if (sourceNode.innerHTML.match(/^\s*<tr[\s\S]*?<\/tr>\s*$/i)

This way, it would only concern itself with templates where the first child is a tr element, regardless of whatever else might be inside them. (Also ignoring case, because browsers still understand uppercase tag names.)

@ErikSchierboom
Copy link
Owner

@penguinstampede The suggestion by @revengineering is probably good to follow, as the internals are better understood by @revengineering than by me currently :D

@revengineering revengineering deleted the NodesPerElement branch January 9, 2019 15:14
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

Successfully merging this pull request may close these issues.

None yet

4 participants