Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

Commit

Permalink
allow re-binding by internally cloning before re-use
Browse files Browse the repository at this point in the history
  • Loading branch information
0x8890 committed Jul 9, 2016
1 parent 4262af8 commit 4dcedd0
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog


### 1.2.1 (2016-07-10)
- Fix: allow re-use of bindings again, by internally cloning binding before re-use.


### 1.2.0 (2016-07-10)
- Feature: shorthand for binding to parent node is now just defining a change function or definition object, no CSS selector string or DOM Node required.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ var node = simulacra(data, bindings)
var initialData = clone(data)

// Do some mutations, and then reset to initial state.
node = simulacra(initialData, clone(bindings))
node = simulacra(initialData, bindings)
```

This is just one way to implement time travel, but not the most efficient.
Expand Down
32 changes: 30 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ function simulacra (obj, def) {
if (!isArray(def))
throw new TypeError('Second argument must be an array.')

if (isProcessedKey in def)
throw new Error('Can not re-use binding.')
// Need to clone bindings before re-using them, due to the marker mappings
// being coupled to the definitions.
if (isProcessedKey in def) def = clone(def)

if (typeof def[0] === 'string') {
query = def[0]
Expand Down Expand Up @@ -240,3 +241,30 @@ function featureCheck (globalScope) {
}
}
}


/**
* A fast deep clone function, which should work for the use case of cloning
* bindings before re-use.
*
* @param {*}
* @return {*}
*/
function clone (input) {
var output, key, value, isArray

if (Array.isArray(input)) isArray = true
else if (input == null || Object.getPrototypeOf(input) !== Object.prototype)
return input

output = isArray ? [] : {}

for (key in input) {
value = input[key]
output[key] = value != null &&
Object.getPrototypeOf(value) === Object.prototype ||
Array.isArray(value) ? clone(value) : value
}

return output
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "simulacra",
"description": "One-way data binding for web applications.",
"version": "1.2.0",
"version": "1.2.1",
"license": "MIT",
"author": {
"email": "0x8890@airmail.cc",
Expand Down
24 changes: 12 additions & 12 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
var tapdance = require('tapdance')
var comment = tapdance.comment
var ok = tapdance.ok
var pass = tapdance.pass
var fail = tapdance.fail
var run = tapdance.run

var simulacra = require('../lib')
Expand Down Expand Up @@ -35,6 +33,7 @@ run(function () {

run(function () {
var template, fragment, data, bindings, outlet, i = 0
var isRebinding = false

comment('test main use case')

Expand All @@ -61,8 +60,11 @@ run(function () {
bindings = [ fragment, {
name: [ '.name', function (node, value, previousValue, path) {
ok(path.length === 1, 'path length is correct')
ok(path.root === data, 'root is correct')
ok(path.target === data, 'target is correct')
if (!isRebinding) {
isRebinding = true
ok(path.root === data, 'root is correct')
ok(path.target === data, 'target is correct')
}
ok(path[0] === 'name', 'path is correct')
return value + '!'
} ],
Expand Down Expand Up @@ -127,14 +129,12 @@ run(function () {
ok(outlet.querySelector('.size').textContent === 'XXL',
'continues to work after error')

comment('rebinding should fail')
try {
simulacra({}, bindings)
fail('should have failed')
}
catch (error) {
pass('rebinding does not work')
}
comment('test rebinding')
outlet.innerHTML = ''
outlet.appendChild(simulacra({
name: 'babby'
}, bindings))
ok(outlet.textContent === 'babby!', 'rebinding works')
})


Expand Down

0 comments on commit 4dcedd0

Please sign in to comment.