d9cec545 by Adam Heath

First pass.

1 parent 155b7073
1 .*.sw?
2
3 /.grunt/
4 /node_modules/
5 /src/lib/bower/
6 /dist/
1 /* global module */
2
3 module.exports = function (grunt) {
4 /* global require */
5 'use strict';
6
7 var config = {};
8 config.base = 'src';
9 config.jshint = {
10 options: {
11 },
12 browserOptions: {
13 },
14 };
15 config.bower = {
16 directory: 'lib/bower',
17 };
18 config.jscs = {
19 options: {
20 validateIndentation: 4,
21 reporter: 'console',
22 maxErrors: -1,
23 },
24 };
25 config.jasmine = {
26 withCoverage: true,
27 };
28 var montyPython = require('grunt-monty-python')(grunt);
29 montyPython.createConfig(config);
30 };
1 {
2 "name": "rivets-bfeach-binder",
3 "version": "0.0.0",
4 "authors": [
5 "Adam Heath <doogie@brainfood.com>"
6 ],
7 "main": [
8 "src/scripts/rivets-bfeach-binder.js"
9 ],
10 "private": true,
11 "ignore": [
12 "**/.*",
13 "node_modules",
14 "src/lib"
15 ],
16 "dependencies": {
17 "backbone": "",
18 "backbone-validation": "",
19 "rivets-backbone-adapter-brainfood": "git@gitlab.brainfood.com:brainfood/rivets-backbone-adapter-brainfood.git#iterate-branch",
20 "jquery": "",
21 "requirejs": "",
22 "rivets": "",
23 "underscore": ""
24 }
25 }
1 {
2 "name": "rivets-bfeach-binder",
3 "version": "0.0.0",
4 "main": [
5 "src/scripts/rivets-bfeach-binder.js"
6 ],
7 "dependencies": {
8 "rivets": "",
9 "requirejs": ""
10 },
11 "devDependencies": {
12 "bower-requirejs": "~0.9.2",
13 "grunt": "~0",
14 "grunt-monty-python": "git+ssh://git@gitlab.brainfood.com:brainfood/grunt-monty-python.git"
15 },
16 "engines": {
17 "node": ">=0.8.0"
18 }
19 }
20
1 /* global require:true */
2 var require;
3 require = (function() {
4 'use strict';
5
6 var require = {
7 baseUrl: 'scripts',
8 config: {},
9 shim: {
10 rivets: {
11 deps: ['jquery'],
12 },
13 },
14 paths: {
15 backbone: '../lib/bower/backbone/backbone',
16 underscore: '../lib/bower/underscore/underscore',
17 sightglass: '../lib/bower/sightglass/index',
18 rivets: '../lib/bower/rivets/dist/rivets',
19 jquery: '../lib/bower/jquery/dist/jquery',
20 'rivets-backbone-adapter-brainfood': '../lib/bower/rivets-backbone-adapter-brainfood/src/scripts/rivets-backbone-adapter-brainfood',
21 },
22 };
23
24 return require;
25 })();
1 /* global require */
2 define(function() {
3 'use strict';
4 });
1 define(function(require) {
2 'use strict';
3 var Backbone = require('backbone');
4 var rivets = require('rivets');
5 var Sightglass = require('sightglass');
6
7 var setStack = (function(sightglassPrototype) {
8 var origSet = sightglassPrototype.set;
9 var setStack = [];
10 sightglassPrototype.set = function set(active, key, obj, callback) {
11 try {
12 setStack.push(arguments);
13 return origSet.apply(this, arguments);
14 } finally {
15 setSack.pop();
16 }
17 };
18 return setStack;
19 })(Sightglass.prototype);
20
21 var bfEachUtil = {
22 makeOverrideAdapters: function makeOverrideAdapters(parentAdapters, roData) {
23 function getStackPath() {
24 var currentStackPath = '';
25 _.each(setStack, function(stackFrame, stackFrameIndex) {
26 var key = stackFrame[1];
27 currentStackPath += key.i + key.path;
28 });
29 return currentStackPath;
30 currentStackPath += interfaceKey + leafKey;
31 if (currentStackPath in roData) {
32 givenObj = roData[currentStackPath];
33 }
34 return givenObj;
35 };
36 var subAdapters = {};
37 _.each(parentAdapters, function(adapterFunctions, interfaceKey) {
38 var subAdapter = {};
39 subAdapter.observe = function(obj, key, cb) {
40 var stackPath = getStackPath();
41 if (stackPath + interfaceKey + key in roData) {
42 return;
43 } else if (stackPath in roData) {
44 obj = roData[stackPath];
45 }
46 return adapterFunctions.observe(obj, key, cb);
47 };
48 subAdapter.unobserve = function(obj, key, cb) {
49 var stackPath = getStackPath();
50 if (stackPath in roData) {
51 obj = roData[stackPath];
52 }
53 if (stackPath + interfaceKey + key in roData) {
54 return;
55 } else if (stackPath in roData) {
56 obj = roData[stackPath];
57 }
58 return adapterFunctions.unobserve(obj, key, cb);
59 };
60 subAdapter.get = function(obj, key) {
61 var stackPath = getStackPath();
62 if (stackPath in roData) {
63 obj = roData[stackPath];
64 }
65 var fullKeyPath = stackPath + interfaceKey + key;
66 if (fullKeyPath in roData) {
67 return roData[fullKeyPath];
68 } else if (stackPath in roData) {
69 obj = roData[stackPath];
70 }
71 return adapterFunctions.get(obj, key);
72 };
73 subAdapter.set = function(obj, key, value) {
74 var stackPath = getStackPath();
75 if (stackPath in roData) {
76 obj = roData[stackPath];
77 }
78 var fullKeyPath = stackPath + interfaceKey + key;
79 if (fullKeyPath in roData) {
80 return roData[fullKeyPath];
81 } else if (stackPath in roData) {
82 obj = roData[stackPath];
83 }
84 return adapterFunctions.set(obj, key, value);
85 };
86 if (adapterFunctions.iterate) {
87 subAdapter.iterate = adapterFunctions.iterate;
88 }
89 subAdapters[interfaceKey] = subAdapter;
90 });
91 return subAdapters;
92 },
93 getIterator: function getIterator(adapter) {
94 return adapter.iterate || function iterate(obj, cb) {
95 obj = obj || [];
96 var i;
97 for (i = 0; i < obj.length; i++) {
98 cb(obj[i], i);
99 }
100 };
101 },
102 };
103
104 (function(rivetsBinders) {
105 rivetsBinders['bfeach-*'] = {
106 block: true,
107 bind: rivetsBinders['each-*'].bind,
108 unbind: rivetsBinders['each-*'].unbind,
109
110 routine: function(el, value) {
111 var parentView = this.view;
112 var observer = this.observer;
113 var adapters = observer.options.adapters;
114 var iterate = bfEachUtil.getIterator(adapters[observer.key.i]);
115
116 var rootInterface = observer.tokens.length ? observer.tokens[0].i : observer.key.i;
117 var modelName = this.args[0];
118 var iterationAlias = rivets.iterationAlias(modelName);
119 var iterated = this.iterated;
120 var previous = this.marker;
121 iterate(value, function(value, index) {
122 if (iterated[index] === undefined) {
123 var subData = {};
124 subData[rootInterface + 'index'] = index;
125 subData[rootInterface + modelName] = value;
126 subData[rootInterface + iterationAlias] = index;
127
128 var options = parentView.options();
129 options.preloadData = true;
130 options.adapters = bfEachUtil.makeOverrideAdapters(options.adapters, subData);
131 var template = el.cloneNode(true);
132 var childView = new rivets._.View(template, parentView.models, options);
133 childView.bind();
134 iterated.push(childView);
135 previous.parentNode.insertBefore(template, previous.nextSibling);
136 previous = template;
137 } else {
138 iterated[index].update(value);
139 }
140 });
141 },
142 };
143 })(rivets.binders);
144 return bfEachUtil;
145 });
1 define(function(require) {
2 'use strict';
3
4 var $ = require('jquery');
5 window.jQuery = $;
6 var RivetsBFEachUtil = require('rivets-bfeach-binder');
7 require('rivets-backbone-adapter-brainfood');
8 var _ = require('underscore');
9 var Backbone = require('backbone');
10 var rivets = require('rivets');
11
12 //rivets.config.rootInterface = ':';
13 /* global console:false */
14
15 describe('RivetsBFEachUtil', function() {
16 it('returns defined', function() {
17 expect(RivetsBFEachUtil).toBeDefined();
18 });
19 var rootScope, rootNode, rivetsView;
20 function makeTest(rootData, rootHtml, rootTests) {
21 beforeEach(function() {
22 rootScope = new Backbone.Model(rootData);
23 rootNode = $($.parseHTML(rootHtml));
24 rivetsView = rivets.bind(rootNode, rootScope);
25 });
26 rootTests();
27 }
28 makeTest({
29 sub: new Backbone.Model({
30 list: new Backbone.Collection([
31 {key: 'A'},
32 {key: 'B'},
33 {key: 'C'},
34 ], {parse: true}),
35 }),
36 list: new Backbone.Collection([
37 {key: 'A'},
38 {key: 'B'},
39 {key: 'C'},
40 ], {parse: true}),
41 constant: 'this-is-a-constant',
42 }, '<div>{:constant}<div rv-bfeach-item=":list">key:{:item:key} constant:{:constant}</div><div rv-bfeach-item=":sub:list">sub-key:{:item:key} constant:{:constant}</div</div>', function() {
43 it('foo', function() {
44 expect(rootNode.html()).toEqual(
45 'this-is-a-constant'
46 + '<!-- rivets: bfeach-item -->'
47 + '<div>key:A constant:this-is-a-constant</div>'
48 + '<div>key:B constant:this-is-a-constant</div>'
49 + '<div>key:C constant:this-is-a-constant</div>'
50 + '<!-- rivets: bfeach-item -->'
51 + '<div>sub-key:A constant:this-is-a-constant</div>'
52 + '<div>sub-key:B constant:this-is-a-constant</div>'
53 + '<div>sub-key:C constant:this-is-a-constant</div>'
54 );
55 });
56 describe('foo', function() {
57 beforeEach(function() {
58 //rootScope.set('constant', 'updated-constant');
59 rootScope.get('list').add({key: 'D'}, {at: -1, parse: true});
60 });
61 it('bar', function() {
62 expect(rootNode.html()).toEqual(
63 'updated-constant'
64 + '<!-- rivets: bfeach-item -->'
65 + '<div>key:A constant:updated-constant</div>'
66 + '<div>key:B constant:updated-constant</div>'
67 + '<div>key:C constant:updated-constant</div>'
68 + '<!-- rivets: bfeach-item -->'
69 + '<div>sub-key:A constant:updated-constant</div>'
70 + '<div>sub-key:B constant:updated-constant</div>'
71 + '<div>sub-key:C constant:updated-constant</div>'
72 );
73 });
74 });
75 });
76 });
77 });