Skip to content

Commit

Permalink
Changed the clone method, which is used for data-bind_each loops, t…
Browse files Browse the repository at this point in the history
…o also clone the internal index of attribute templates.

There was a syncrinization issue where - as cloned elements in a loop shared the same internal ID - the result of template compilation was usually applied to the subsequent element. This fixes issues #10
  • Loading branch information
chrismichaelscott committed Aug 10, 2013
1 parent 0e847e7 commit 4ef3a6e
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 17 deletions.
34 changes: 29 additions & 5 deletions iugo-bind_to_dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
// Create a metadata store
$iugo['store']['bind_to_dom'] = {
tags: [],
namespacedTagIndex: {}
namespacedTagIndex: {},
idCounter: 0
};

// This initializer swaps ${var} for <spans> with attributes for use with the VC below
$iugo['initializers'].push(function(view) {
var idCounter = 0;

$iugo['initializers'].push(function(view) {
var innerHTMLRegex = /(>[^<]*)\$\{([^:.}<]+:)?([^}<]*)\}([^<]*<)/g;
// it is important to repeat the regex as it will only match one ${var} per tag innerHTML
while (view.innerHTML.match(innerHTMLRegex)) {
Expand All @@ -40,7 +39,7 @@ $iugo['initializers'].push(function(view) {
// First find tags that use a variable syntax in an attribute
var tagRegex = /<[^>]+ [^ =]+="[^"]*\$\{[^}<"]+\}[^"]*"[^>]*>/g;
view.innerHTML = view.innerHTML.replace(tagRegex, function(tag) {
var tagId = idCounter++;
var tagId = $iugo['store']['bind_to_dom'].idCounter++;

$iugo['store']['bind_to_dom'].tags[tagId] = {
bindAttributes: [],
Expand Down Expand Up @@ -130,6 +129,20 @@ $iugo['defaultViewcontrollers'].push(function(property, value, view, path) {
}
}

function cloneTagIndex(view) {
var oldId = view.getAttribute("data-iugo_id");
var newId = $iugo['store']['bind_to_dom'].idCounter++;

var oldIndex = $iugo['store']['bind_to_dom'].tags[oldId];
$iugo['store']['bind_to_dom'].tags[newId] = {
bindAttributes: oldIndex.bindAttributes,
attributeTemplates: oldIndex.attributeTemplates,
replacements: {}
};

view.setAttribute("data-iugo_id", newId);
}

/**
* Recursively scan the given view looking for replacements to variables and
* marked tag's innerHTML.
Expand Down Expand Up @@ -169,6 +182,17 @@ $iugo['defaultViewcontrollers'].push(function(property, value, view, path) {
if (y >= 1) {
duplicateElement = elementView.cloneNode(true);
duplicateElement.classList.add("iugo_cloned");

// Look for cloned elements further down the hierarchy which have attributes with variables...
// ...and unlink from the clone-template's ID
if (duplicateElement.hasAttribute("data-iugo_id")) {
cloneTagIndex(duplicateElement);
}
var clonedTagsWithAttributeReplacements = duplicateElement.querySelectorAll('[data-iugo_id]');
for (var z = 0; z < clonedTagsWithAttributeReplacements.length; z++) {
cloneTagIndex(clonedTagsWithAttributeReplacements[z]);
}

view.appendChild(duplicateElement);
} else {
duplicateElement = elementView;
Expand Down
2 changes: 1 addition & 1 deletion iugo-bind_to_dom.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 33 additions & 6 deletions iugo.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,18 @@ $iugo["store"] = {};
window["Iugo"] = function(model, view, viewcontroller) {
return new $iugo.$internals.MVVC(model, view, viewcontroller);
};

// ** START BIND_TO_DOM controller ** //

// Create a metadata store
$iugo['store']['bind_to_dom'] = {
tags: [],
namespacedTagIndex: {}
namespacedTagIndex: {},
idCounter: 0
};

// This initializer swaps ${var} for <spans> with attributes for use with the VC below
$iugo['initializers'].push(function(view) {
var idCounter = 0;

$iugo['initializers'].push(function(view) {
var innerHTMLRegex = /(>[^<]*)\$\{([^:.}<]+:)?([^}<]*)\}([^<]*<)/g;
// it is important to repeat the regex as it will only match one ${var} per tag innerHTML
while (view.innerHTML.match(innerHTMLRegex)) {
Expand All @@ -268,7 +270,7 @@ $iugo['initializers'].push(function(view) {
// First find tags that use a variable syntax in an attribute
var tagRegex = /<[^>]+ [^ =]+="[^"]*\$\{[^}<"]+\}[^"]*"[^>]*>/g;
view.innerHTML = view.innerHTML.replace(tagRegex, function(tag) {
var tagId = idCounter++;
var tagId = $iugo['store']['bind_to_dom'].idCounter++;

$iugo['store']['bind_to_dom'].tags[tagId] = {
bindAttributes: [],
Expand Down Expand Up @@ -358,6 +360,20 @@ $iugo['defaultViewcontrollers'].push(function(property, value, view, path) {
}
}

function cloneTagIndex(view) {
var oldId = view.getAttribute("data-iugo_id");
var newId = $iugo['store']['bind_to_dom'].idCounter++;

var oldIndex = $iugo['store']['bind_to_dom'].tags[oldId];
$iugo['store']['bind_to_dom'].tags[newId] = {
bindAttributes: oldIndex.bindAttributes,
attributeTemplates: oldIndex.attributeTemplates,
replacements: {}
};

view.setAttribute("data-iugo_id", newId);
}

/**
* Recursively scan the given view looking for replacements to variables and
* marked tag's innerHTML.
Expand Down Expand Up @@ -397,6 +413,17 @@ $iugo['defaultViewcontrollers'].push(function(property, value, view, path) {
if (y >= 1) {
duplicateElement = elementView.cloneNode(true);
duplicateElement.classList.add("iugo_cloned");

// Look for cloned elements further down the hierarchy which have attributes with variables...
// ...and unlink from the clone-template's ID
if (duplicateElement.hasAttribute("data-iugo_id")) {
cloneTagIndex(duplicateElement);
}
var clonedTagsWithAttributeReplacements = duplicateElement.querySelectorAll('[data-iugo_id]');
for (var z = 0; z < clonedTagsWithAttributeReplacements.length; z++) {
cloneTagIndex(clonedTagsWithAttributeReplacements[z]);
}

view.appendChild(duplicateElement);
} else {
duplicateElement = elementView;
Expand Down Expand Up @@ -451,4 +478,4 @@ $iugo['defaultViewcontrollers'].push(function(property, value, view, path) {
for (var x = 0; x < elements.length; x++ ) {
process(value, elements[x]);
}
});
});
2 changes: 1 addition & 1 deletion iugo.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4ef3a6e

Please sign in to comment.