compago-list
Advanced tools
Comparing version 1.0.0 to 1.0.1
{ | ||
"name": "compago-list", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "", | ||
@@ -33,2 +33,18 @@ "keywords": [ | ||
}, | ||
"eslintConfig": { | ||
"extends": "airbnb", | ||
"rules": { | ||
"no-nested-ternary": 1, | ||
"eqeqeq": [ | ||
2, | ||
"smart" | ||
], | ||
"no-param-reassign": [ | ||
2, | ||
{ | ||
"props": false | ||
} | ||
] | ||
} | ||
}, | ||
"babel": { | ||
@@ -45,2 +61,5 @@ "presets": [ | ||
"compago-model": "^1.0.1", | ||
"eslint": "^1.10.3", | ||
"eslint-config-airbnb": "^3.0.0", | ||
"eslint-plugin-react": "^3.14.0", | ||
"expect": "^1.13.4", | ||
@@ -47,0 +66,0 @@ "istanbul": "^1.0.0-alpha.2", |
150
src/index.js
import View from 'compago-view'; | ||
/* eslint default-case: 1 */ | ||
export default class List extends View { | ||
@@ -14,7 +15,7 @@ | ||
super(options); | ||
const {collection, childView, container, unsync} = options; | ||
const { collection, childView, container, unsync } = options; | ||
this.views = []; | ||
this._elMap = new WeakMap(); | ||
this.collection = collection; | ||
this.childView = childView; | ||
this.ChildView = childView; | ||
this._modelMap = new WeakMap(); | ||
@@ -31,32 +32,29 @@ this.container = container || this.el; | ||
* | ||
* @param {Array.<View>|View} [views] A view or an array of views to add to the list. | ||
* @param {Object} [options] The options are sent to `List#set`. | ||
* @param {Array.<View>|View} [views] A view or an array of views to be added to the list. | ||
* @param {Object} [options] | ||
* @param {number} [options.at] The position at which the new view(s) should be added. | ||
* @param {boolean} [options.silent] to avoid firing any event. | ||
* @param {boolean} [options.avoidRender] to avoid rendering the list. | ||
* @param {boolean} [options.insert] to only render and attach new views to the list | ||
* avoiding re-rendering the entire list. //todo change to defalt to `false` | ||
* @param {boolean} [options.replace] to re-render the entire list instead of just rendering and | ||
* appending only newly added views as it's done by default. | ||
* @returns {List} | ||
*/ | ||
add(views, options = {}) { | ||
let {at, silent, avoidRender, insert} = options; | ||
if (!Array.isArray(views)) views = [views]; | ||
const { silent, avoidRender, replace } = options; | ||
const add = []; | ||
at = options.at = this.views[at] ? at : this.views.length; | ||
for (let i = 0, l = views.length; i < l; i++) { | ||
const view = views[i]; | ||
const viewsArray = [].concat(views); | ||
const at = this.views[options.at] ? options.at : this.views.length; | ||
let index = at; | ||
for (const view of viewsArray) { | ||
if (!(view instanceof View) || (~this.views.indexOf(view))) continue; | ||
this.views.splice(at, 0, view); | ||
this.views.splice(index, 0, view); | ||
this._addReference(view); | ||
view.render(); | ||
if (!silent) { | ||
options.at = at; | ||
view.emit('add', options); | ||
view.emit('add', { index, avoidRender, replace }); | ||
} | ||
at++; | ||
index++; | ||
add.push(view); | ||
} | ||
options.add = add; | ||
if (insert !== false) options.insert = true; | ||
if (!avoidRender) this.render(options); | ||
if (!avoidRender) this.render({ silent, at, insert: !replace ? add : undefined }); | ||
return this; | ||
@@ -75,6 +73,5 @@ } | ||
remove(views, options = {}) { | ||
const {silent, save} = options; | ||
if (!Array.isArray(views)) views = [views]; | ||
for (let i = 0, l = views.length; i < l; i++) { | ||
const view = views[i]; | ||
const { silent, save } = options; | ||
const viewsArray = [].concat(views); | ||
for (const view of viewsArray) { | ||
const index = this.views.indexOf(view); | ||
@@ -85,4 +82,3 @@ if (!~index) continue; | ||
if (!silent) { | ||
options.at = index; | ||
view.emit('remove', options); | ||
view.emit('remove', { save, index }); | ||
} | ||
@@ -104,7 +100,7 @@ this._removeReference(view); | ||
clear(options = {}) { | ||
const {silent, save} = options; | ||
const { silent, save } = options; | ||
const views = this.views; | ||
for (let i = views.length - 1; i >= 0; i--) { | ||
this._removeReference(views[i]); | ||
if (!save) views[i].dispose(); | ||
for (const view of views) { | ||
this._removeReference(view); | ||
if (!save) view.dispose(); | ||
} | ||
@@ -116,3 +112,3 @@ this.views = []; | ||
options.previousViews = views; | ||
this.emit('clear', options) | ||
this.emit('clear', { save, previousViews: views }); | ||
} | ||
@@ -134,12 +130,7 @@ this.render(); | ||
sort(options = {}) { | ||
const {comparator, silent, avoidRender} = options; | ||
const { comparator, silent, avoidRender } = options; | ||
if (comparator) { | ||
this.views.sort(comparator); | ||
} else if (this.collection) { | ||
const views = []; | ||
for (let i = 0, l = this.collection.models.length; i < l; i++) { | ||
const model = this.collection.models[i]; | ||
views.push(this._modelMap.get(model)); | ||
} | ||
this.views = views; | ||
this.views = this.collection.models.map(model => this._modelMap.get(model)); | ||
} else { | ||
@@ -149,3 +140,3 @@ return this; | ||
if (!avoidRender) this.render(); | ||
if (!silent) this.emit('sort', options); | ||
if (!silent) this.emit('sort', { comparator, avoidRender }); | ||
return this; | ||
@@ -158,5 +149,6 @@ } | ||
* @param {Object} [options] | ||
* @param {Array.<View>} [options.add] New views to be added to the list. | ||
* @param {boolean} [options.renderALL] to re-render all views in the list. | ||
* @param {boolean} [options.insert] to insert new views without re-rendering the entire list. | ||
* @param {Array.<View>} [options.insert] A list of views to be inserted in the list without | ||
* re-rendering it. | ||
* @param {number} [options.at] The position at which the inserted view should be added. | ||
* @param {boolean} [options.renderALL] to re-render each view in the list. | ||
* @param {boolean} [options.silent] to avoid firing any event. | ||
@@ -166,3 +158,3 @@ * @returns {HTMLElement} | ||
render(options = {}) { | ||
const {add, renderAll, insert, silent} = options; | ||
const { insert, renderAll, silent } = options; | ||
if (!silent) this.emit('before:render', options); | ||
@@ -174,3 +166,3 @@ if (renderAll) { | ||
} | ||
const views = insert ? add : this.views; | ||
const views = insert || this.views; | ||
if (views) { | ||
@@ -181,3 +173,7 @@ const list = document.createDocumentFragment(); | ||
} | ||
insert ? this.insertHTML(list, options) : this.replaceHTML(list, options); | ||
if (insert) { | ||
this.insertHTML(list, options); | ||
} else { | ||
this.replaceHTML(list, options); | ||
} | ||
} | ||
@@ -201,5 +197,6 @@ this._linkUI(); | ||
* | ||
* @param {DocumentFragment} list The DocumentFragment containing rendered view(s) to be added to the list. | ||
* @param {DocumentFragment} list The DocumentFragment containing rendered view(s) | ||
* to be added to the list. | ||
* @param {Object} [options] | ||
* @param {number} [options.at] The position at which the new view(s) is to be added. | ||
* @param {number} [options.at] The position at which the new views are to be added. | ||
*/ | ||
@@ -214,7 +211,8 @@ insertHTML(list, options) { | ||
} | ||
/* eslint no-unused-vars: 1 */ | ||
/** | ||
* Implements replacing the content of list's DOM element. | ||
* | ||
* @param {DocumentFragment} list The DocumentFragment to replace the content of the current container of the list. | ||
* @param {DocumentFragment} list The DocumentFragment to replace the content of | ||
* the current container of the list. | ||
* @param {Object} [options] | ||
@@ -237,2 +235,3 @@ */ | ||
if (!this.collection) return this; | ||
const { save, silent } = options; | ||
const models = this.collection.models; | ||
@@ -242,14 +241,13 @@ const views = []; | ||
const viewSet = new Set(); | ||
let view; | ||
for (let i = 0, l = models.length; i < l; i++) { | ||
const model = models[i]; | ||
if (view = this._modelMap.get(model)) { | ||
for (const model of models) { | ||
let view = this._modelMap.get(model); | ||
if (view) { | ||
views.push(view); | ||
} else { | ||
view = new this.childView({model}); | ||
view = new this.ChildView({ model }); | ||
views.push(view); | ||
this._addReference(view); | ||
view.render(); | ||
if (!options.silent) view.emit('add', options); | ||
if (!silent) view.emit('add', { save }); | ||
} | ||
@@ -259,6 +257,6 @@ viewSet.add(view); | ||
for (let i = 0, l = this.views.length; i < l; i++) { | ||
if (!viewSet.has(view = this.views[i])) toRemove.push(view); | ||
for (const view of this.views) { | ||
if (!viewSet.has(view)) toRemove.push(view); | ||
} | ||
if (toRemove.length) this.remove(toRemove, options); | ||
if (toRemove.length) this.remove(toRemove, { save }); | ||
@@ -279,6 +277,6 @@ this.views = views; | ||
dispose(options = {}) { | ||
const {silent, save} = options; | ||
if (!silent) this.emit('dispose', options); | ||
this.clear({silent: true, save}); | ||
super.dispose({silent: true}); | ||
const { silent, save } = options; | ||
if (!silent) this.emit('dispose', { save }); | ||
this.clear({ silent: true, save }); | ||
super.dispose({ silent: true }); | ||
return this; | ||
@@ -290,4 +288,4 @@ } | ||
* Overrides `View._handler` allowing for handler functions to know to which view | ||
* belongs the event target. Thus, the list can handle all events on all of its views without the need | ||
* to attach them on every view individually. | ||
* belongs the event target. Thus, the list can handle all events on all of its views | ||
* without the need to attach them on every view individually. | ||
* | ||
@@ -301,13 +299,13 @@ * @param {Event} event The DOM Event. | ||
if (!handlers) return; | ||
let selector, callback, match, view; | ||
for (let i = 0, l = handlers.length; i < l; i++) { | ||
callback = handlers[i]; | ||
for (const callback of handlers) { | ||
let selector; | ||
let cb = callback; | ||
if (Array.isArray(callback)) { | ||
[callback, selector] = callback; | ||
[cb, selector] = callback; | ||
} | ||
if (!selector) { | ||
callback.call(this, event); | ||
cb.call(this, event); | ||
} else { | ||
match = undefined; | ||
view = undefined; | ||
let match = undefined; | ||
let view = undefined; | ||
for (let el = event.target; el && el !== this.el; el = el.parentElement) { | ||
@@ -322,3 +320,3 @@ if (!match) { | ||
} | ||
if (match) callback.call(this, event, view, match); | ||
if (match) cb.call(this, event, view, match); | ||
} | ||
@@ -362,5 +360,5 @@ } | ||
_onViewEvent(event) { | ||
const {event:eventName, emitter:view} = event; | ||
const { event: eventName, emitter: view } = event; | ||
if ((eventName === 'dispose') || view.list !== this) { | ||
this.remove(view, {save: true}); | ||
this.remove(view, { save: true }); | ||
return; | ||
@@ -378,8 +376,8 @@ } | ||
_onCollectionEvent(event) { | ||
const {event:eventName, emitter:model} = event; | ||
const { event: eventName, emitter: model } = event; | ||
let view; | ||
switch (eventName) { | ||
case 'add': | ||
view = new this.childView({model}); | ||
this.add(view, {at: event.at, avoidRender: event.sort}); | ||
view = new this.ChildView({ model }); | ||
this.add(view, { at: event.at, avoidRender: event.sort }); | ||
break; | ||
@@ -406,2 +404,2 @@ case 'remove': | ||
} | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
/* eslint-env node, mocha */ | ||
import List from '../src/index'; | ||
@@ -16,5 +17,8 @@ import View from 'compago-view'; | ||
describe('List', ()=> { | ||
let list, v1, v2, v3; | ||
beforeEach(()=> { | ||
describe('List', () => { | ||
let list; | ||
let v1; | ||
let v2; | ||
let v3; | ||
beforeEach(() => { | ||
list = new List(); | ||
@@ -28,4 +32,4 @@ v1 = new View(); | ||
describe('constructor', ()=> { | ||
it('creates a list', ()=> { | ||
describe('constructor', () => { | ||
it('creates a list', () => { | ||
expect(list instanceof List).toBe(true); | ||
@@ -40,5 +44,4 @@ expect(list instanceof View).toBe(true); | ||
describe('add', ()=> { | ||
it('adds views to the list', ()=> { | ||
describe('add', () => { | ||
it('adds views to the list', () => { | ||
list.add(v1); | ||
@@ -53,5 +56,5 @@ expect(list.views[0]).toBe(v1); | ||
it('puts views at the specified index', ()=> { | ||
it('puts views at the specified index', () => { | ||
list.add([v1, v3]); | ||
list.add([v2], {at: 1}); | ||
list.add([v2], { at: 1 }); | ||
expect(list.views.length).toBe(3); | ||
@@ -63,3 +66,3 @@ expect(list.views[0]).toBe(v1); | ||
it('emits `add` events on added views', ()=> { | ||
it('emits `add` events on added views', () => { | ||
list.on(v1, 'add', list.someMethod); | ||
@@ -72,8 +75,8 @@ list.add(v1); | ||
expect(list.someMethod.calls[0].arguments[0].emitter).toBe(v1); | ||
expect(list.someMethod.calls[0].arguments[0].at).toBe(0); | ||
expect(list.someMethod.calls[0].arguments[0].index).toBe(0); | ||
}); | ||
it('avoids rendering the list if `avoidRender:true`', ()=> { | ||
it('avoids rendering the list if `avoidRender:true`', () => { | ||
list.render = expect.createSpy(); | ||
list.add(v1, {avoidRender: true}); | ||
list.add(v1, { avoidRender: true }); | ||
expect(list.views[0]).toBe(v1); | ||
@@ -83,11 +86,21 @@ expect(list.el.children.length).toBe(0); | ||
}); | ||
it('re-renders the entire list if `replace:true`', () => { | ||
list.add(v1); | ||
expect(list.views.length).toBe(1); | ||
expect.spyOn(list, 'replaceHTML').andCallThrough(); | ||
list.add(v2, { replace: true }); | ||
expect(list.views[1]).toBe(v2); | ||
expect(list.el.children.length).toBe(2); | ||
expect(list.el.children[1]).toBe(v2.el); | ||
expect(list.replaceHTML).toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('remove', ()=> { | ||
beforeEach(()=> { | ||
describe('remove', () => { | ||
beforeEach(() => { | ||
list.add([v1, v2]); | ||
}); | ||
it('removes views from the list', ()=> { | ||
it('removes views from the list', () => { | ||
list.remove(v1); | ||
@@ -100,3 +113,3 @@ expect(list.views.length).toBe(1); | ||
it('skips views that are not on the list', ()=> { | ||
it('skips views that are not on the list', () => { | ||
list.remove(v1); | ||
@@ -110,3 +123,3 @@ expect(list.views.length).toBe(1); | ||
it('emits `remove` events unless `silent:true`', ()=> { | ||
it('emits `remove` events unless `silent:true`', () => { | ||
list.on(v1, 'remove', list.someMethod); | ||
@@ -116,12 +129,17 @@ list.on(v2, 'remove', list.otherMethod); | ||
expect(list.someMethod.calls.length).toBe(1); | ||
expect(list.someMethod.calls[0].arguments[0]).toEqual({event: 'remove', emitter: v1, at: 0}); | ||
expect(list.someMethod.calls[0].arguments[0]).toEqual({ | ||
event: 'remove', | ||
emitter: v1, | ||
index: 0, | ||
save: undefined, | ||
}); | ||
list.remove(v2, {silent: true}); | ||
list.remove(v2, { silent: true }); | ||
expect(list.otherMethod).toNotHaveBeenCalled(); | ||
}); | ||
it('disposes removed views unless `save:true`', ()=> { | ||
it('disposes removed views unless `save:true`', () => { | ||
v1.dispose = expect.createSpy(); | ||
v2.dispose = expect.createSpy(); | ||
list.remove(v1, {save: true}); | ||
list.remove(v1, { save: true }); | ||
expect(v1.dispose).toNotHaveBeenCalled(); | ||
@@ -131,12 +149,10 @@ list.remove(v2); | ||
}); | ||
}); | ||
describe('clear', ()=> { | ||
beforeEach(()=> { | ||
describe('clear', () => { | ||
beforeEach(() => { | ||
list.add([v1, v2]); | ||
}); | ||
it('empties the list', ()=> { | ||
it('empties the list', () => { | ||
list.clear(); | ||
@@ -147,7 +163,7 @@ expect(list.views.length).toBe(0); | ||
it('emits a single `clear` event unless `silence:true`', ()=> { | ||
it('emits a single `clear` event unless `silence:true`', () => { | ||
list.on(list, 'remove', list.otherMethod); | ||
list.on(list, 'clear', list.someMethod); | ||
list.clear({silent: true}); | ||
list.clear({ silent: true }); | ||
expect(list.someMethod).toNotHaveBeenCalled(); | ||
@@ -162,3 +178,4 @@ expect(list.otherMethod).toNotHaveBeenCalled(); | ||
emitter: list, | ||
previousViews: preViews | ||
previousViews: preViews, | ||
save: undefined, | ||
}); | ||
@@ -168,6 +185,6 @@ expect(list.otherMethod).toNotHaveBeenCalled(); | ||
it('disposes removed views unless `save:true`', ()=> { | ||
it('disposes removed views unless `save:true`', () => { | ||
v1.dispose = expect.createSpy(); | ||
v2.dispose = expect.createSpy(); | ||
list.clear({save: true}); | ||
list.clear({ save: true }); | ||
expect(v1.dispose).toNotHaveBeenCalled(); | ||
@@ -180,6 +197,5 @@ expect(v2.dispose).toNotHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('sort', ()=> { | ||
describe('sort', () => { | ||
class ItemView extends View { | ||
@@ -192,3 +208,3 @@ constructor(options) { | ||
it('sorts the list according to the provided comparator', ()=> { | ||
it('sorts the list according to the provided comparator', () => { | ||
v1.cid = '1'; | ||
@@ -200,3 +216,3 @@ v2.cid = '2'; | ||
list.sort({ | ||
comparator: function(a, b) { | ||
comparator: (a, b) => { | ||
if (a.cid !== b.cid) { | ||
@@ -211,3 +227,3 @@ if (a.cid > b.cid || a.cid === undefined) { | ||
return 0; | ||
} | ||
}, | ||
}); | ||
@@ -217,9 +233,9 @@ expect(list.views[0]).toBe(v1); | ||
it("attempts to sort according to the collection if no comparator is provided", ()=> { | ||
const m1 = new Model({order: 1}); | ||
const m2 = new Model({order: 2}); | ||
const m3 = new Model({order: 3}); | ||
const col = new Collection([m3, m2, m1], {model: Model}); | ||
const colList = new List({collection: col, childView: ItemView}); | ||
col.sort({comparator: 'order', silent: true}); | ||
it('attempts to sort according to the collection if no comparator is provided', () => { | ||
const m1 = new Model({ order: 1 }); | ||
const m2 = new Model({ order: 2 }); | ||
const m3 = new Model({ order: 3 }); | ||
const col = new Collection([m3, m2, m1], { model: Model }); | ||
const colList = new List({ collection: col, childView: ItemView }); | ||
col.sort({ comparator: 'order', silent: true }); | ||
expect(col.models[0]).toBe(m1); | ||
@@ -232,3 +248,3 @@ expect(colList.views[0].model).toBe(m3); | ||
it('does not sort if neither comparator nor collection are available', ()=> { | ||
it('does not sort if neither comparator nor collection are available', () => { | ||
const nl = new List(); | ||
@@ -239,12 +255,10 @@ list.on(nl, 'sort', list.someMethod); | ||
}); | ||
}); | ||
describe('render', ()=> { | ||
beforeEach(()=> { | ||
list.add([v1, v2], {avoidRender: true}); | ||
describe('render', () => { | ||
beforeEach(() => { | ||
list.add([v1, v2], { avoidRender: true }); | ||
}); | ||
it("renders the views in the list into the DOM", ()=> { | ||
it('renders the views in the list into the DOM', () => { | ||
expect(list.views.length).toBe(2); | ||
@@ -258,3 +272,3 @@ expect(list.el.children.length).toBe(0); | ||
it('re-renders every view in the list if `renderAll:true`', ()=> { | ||
it('re-renders every view in the list if `renderAll:true`', () => { | ||
v1.render = expect.createSpy(); | ||
@@ -265,3 +279,3 @@ v2.render = expect.createSpy(); | ||
expect(v2.render).toNotHaveBeenCalled(); | ||
list.render({renderAll: true}); | ||
list.render({ renderAll: true }); | ||
expect(v1.render).toHaveBeenCalled(); | ||
@@ -271,11 +285,13 @@ expect(v2.render).toHaveBeenCalled(); | ||
it('inserts new views without rendering all views if `insert:true`', ()=> { | ||
list.render({add: [v3], insert: true}); | ||
it('inserts new views without rendering all views', () => { | ||
expect.spyOn(list, 'insertHTML').andCallThrough(); | ||
list.render({ insert: [v3] }); | ||
expect(list.el.children[0]).toBe(v3.el); | ||
expect(list.insertHTML).toHaveBeenCalled(); | ||
}); | ||
it('emits `before:render` and `render` events unless `silent:true`', ()=> { | ||
it('emits `before:render` and `render` events unless `silent:true`', () => { | ||
list.on(list, 'before:render', list.someMethod); | ||
list.on(list, 'render', list.otherMethod); | ||
list.render({silent: true}); | ||
list.render({ silent: true }); | ||
expect(list.someMethod).toNotHaveBeenCalled(); | ||
@@ -287,7 +303,6 @@ expect(list.otherMethod).toNotHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('removeHTML', ()=> { | ||
it('removes a view from the DOM', ()=> { | ||
describe('removeHTML', () => { | ||
it('removes a view from the DOM', () => { | ||
list.add(v1); | ||
@@ -301,4 +316,4 @@ expect(list.el.children.length).toBe(1); | ||
describe('insertHTML', ()=> { | ||
it('inserts views into the container element of the list', ()=> { | ||
describe('insertHTML', () => { | ||
it('inserts views into the container element of the list', () => { | ||
const fragment = document.createDocumentFragment(); | ||
@@ -309,3 +324,3 @@ fragment.appendChild(v1.el); | ||
expect(list.el.children.length).toBe(1); | ||
list.insertHTML(fragment, {at: 0}); | ||
list.insertHTML(fragment, { at: 0 }); | ||
expect(list.el.children.length).toBe(3); | ||
@@ -318,4 +333,4 @@ expect(list.el.children[0]).toBe(v1.el); | ||
describe('replaceHTML', ()=> { | ||
it("replaces the inner content of the list's container", ()=> { | ||
describe('replaceHTML', () => { | ||
it("replaces the inner content of the list's container", () => { | ||
const fragment = document.createDocumentFragment(); | ||
@@ -333,4 +348,7 @@ fragment.appendChild(v1.el); | ||
describe('sync', ()=> { | ||
let m1, m2, m3, col; | ||
describe('sync', () => { | ||
let m1; | ||
let m2; | ||
let m3; | ||
let col; | ||
class ItemView extends View { | ||
@@ -342,16 +360,16 @@ constructor(options) { | ||
} | ||
beforeEach(()=> { | ||
beforeEach(() => { | ||
m1 = new Model(); | ||
m2 = new Model(); | ||
m3 = new Model(); | ||
col = new Collection([m1, m2, m3], {model: Model}); | ||
col = new Collection([m1, m2, m3], { model: Model }); | ||
}); | ||
it("synchronizes the list with it's collection", ()=> { | ||
it("synchronizes the list with it's collection", () => { | ||
const colList = new List(); | ||
colList.collection = col; | ||
colList.childView = ItemView; | ||
colList.ChildView = ItemView; | ||
colList.sync(); | ||
expect(colList.collection).toBe(col); | ||
expect(colList.childView).toBe(ItemView); | ||
expect(colList.ChildView).toBe(ItemView); | ||
expect(colList.views.length).toBe(3); | ||
@@ -363,3 +381,3 @@ expect(colList._modelMap.get(m1)).toBe(colList.views[0]); | ||
it('returns if no collection is available', ()=> { | ||
it('returns if no collection is available', () => { | ||
const nl = new List(); | ||
@@ -370,5 +388,4 @@ expect(nl.sync()).toBe(nl); | ||
describe('dispose', ()=> { | ||
it('prepares the list to be disposed', ()=> { | ||
describe('dispose', () => { | ||
it('prepares the list to be disposed', () => { | ||
list.add([v1, v2]); | ||
@@ -381,5 +398,5 @@ list.dispose(); | ||
it('emits `dispose` event unless `silent:true`', ()=> { | ||
it('emits `dispose` event unless `silent:true`', () => { | ||
list.on(list, 'dispose', list.someMethod); | ||
list.dispose({silent: true}); | ||
list.dispose({ silent: true }); | ||
expect(list.someMethod).toNotHaveBeenCalled(); | ||
@@ -391,6 +408,6 @@ list.on(list, 'dispose', list.someMethod); | ||
it('disposes views unless `save:true`', ()=> { | ||
it('disposes views unless `save:true`', () => { | ||
v1.dispose = expect.createSpy(); | ||
list.add(v1); | ||
list.dispose({save: true}); | ||
list.dispose({ save: true }); | ||
expect(v1.dispose).toNotHaveBeenCalled(); | ||
@@ -403,5 +420,4 @@ list.add(v1); | ||
describe('_handler', ()=> { | ||
it('dispatches an event to proper handlers', ()=> { | ||
describe('_handler', () => { | ||
it('dispatches an event to proper handlers', () => { | ||
const eventObject = document.createElement('div'); | ||
@@ -411,5 +427,5 @@ eventObject.setAttribute('id', 'submit'); | ||
type: 'click', | ||
target: eventObject | ||
target: eventObject, | ||
}; | ||
//no handler for the event | ||
// no handler for the event | ||
expect(list._handler(event)).toBe(undefined); | ||
@@ -421,5 +437,5 @@ | ||
list.handlers = list._prepareHandlers({ | ||
'click': list.otherMethod, | ||
click: list.otherMethod, | ||
'click #submit': list.someMethod, | ||
'click #header': list.yetAnother | ||
'click #header': list.yetAnother, | ||
}); | ||
@@ -434,7 +450,6 @@ list._setEventHandlers(); | ||
}); | ||
}); | ||
describe('_addReferece', ()=> { | ||
it('ties a view to the list', ()=> { | ||
describe('_addReferece', () => { | ||
it('ties a view to the list', () => { | ||
const m = v1.model = new Model(); | ||
@@ -449,4 +464,4 @@ list._addReference(v1); | ||
describe('_removeReferece', ()=> { | ||
it("severs a view's ties to the list", ()=> { | ||
describe('_removeReferece', () => { | ||
it("severs a view's ties to the list", () => { | ||
const m = v1.model = new Model(); | ||
@@ -462,6 +477,5 @@ list._addReference(v1); | ||
describe('_onViewEvent', ()=> { | ||
it("re-translates events from the list's views", ()=> { | ||
const options = {number: 1}; | ||
describe('_onViewEvent', () => { | ||
it("re-translates events from the list's views", () => { | ||
const options = { number: 1 }; | ||
list.add(v1); | ||
@@ -471,3 +485,7 @@ expect.spyOn(list, 'emit'); | ||
expect(list.emit.calls[0].arguments[0]).toBe('someEvent'); | ||
expect(list.emit.calls[0].arguments[1]).toEqual({event: 'someEvent', emitter: v1, number: 1}); | ||
expect(list.emit.calls[0].arguments[1]).toEqual({ | ||
event: 'someEvent', | ||
emitter: v1, | ||
number: 1, | ||
}); | ||
v1.emit('dispose', options); | ||
@@ -477,3 +495,3 @@ expect(list.views.length).toBe(0); | ||
it('removes a view from the list if the view emits dispose event', ()=> { | ||
it('removes a view from the list if the view emits dispose event', () => { | ||
list.add(v1); | ||
@@ -485,3 +503,3 @@ expect(list.views[0]).toBe(v1); | ||
it("removes a view from the list if the view changes it's list", ()=> { | ||
it("removes a view from the list if the view changes it's list", () => { | ||
const nList = new List(); | ||
@@ -494,7 +512,10 @@ list.add(v1); | ||
}); | ||
}); | ||
describe('_onCollectionEvent', ()=> { | ||
let m1, m2, m3, col, colList; | ||
describe('_onCollectionEvent', () => { | ||
let m1; | ||
let m2; | ||
let m3; | ||
let col; | ||
let colList; | ||
class ItemView extends View { | ||
@@ -506,11 +527,11 @@ constructor(options) { | ||
} | ||
beforeEach(()=> { | ||
m1 = new Model({order: 1}); | ||
m2 = new Model({order: 2}); | ||
m3 = new Model({order: 3}); | ||
col = new Collection([], {model: Model}); | ||
colList = new List({collection: col, childView: ItemView}); | ||
beforeEach(() => { | ||
m1 = new Model({ order: 1 }); | ||
m2 = new Model({ order: 2 }); | ||
m3 = new Model({ order: 3 }); | ||
col = new Collection([], { model: Model }); | ||
colList = new List({ collection: col, childView: ItemView }); | ||
}); | ||
it("adds a view in response to the `add` event", ()=> { | ||
it('adds a view in response to the `add` event', () => { | ||
col.add(m1); | ||
@@ -526,3 +547,3 @@ expect(colList.views.length).toBe(1); | ||
expect(colList.el.children.length).toBe(2); | ||
col.add(m3, {at: 1}); | ||
col.add(m3, { at: 1 }); | ||
expect(colList.views.length).toBe(3); | ||
@@ -537,3 +558,3 @@ expect(colList._modelMap.get(m3)).toBe(colList.views[1]); | ||
it('removes a view in response to the `remove` event', ()=> { | ||
it('removes a view in response to the `remove` event', () => { | ||
col.add([m1, m2, m3]); | ||
@@ -547,3 +568,3 @@ expect(colList.views.length).toBe(3); | ||
it('clears the list in response to the `clear` event', ()=> { | ||
it('clears the list in response to the `clear` event', () => { | ||
col.add([m1, m2, m3]); | ||
@@ -556,10 +577,10 @@ expect(colList.views.length).toBe(3); | ||
it('sorts the list in response to the `sort` event', ()=> { | ||
it('sorts the list in response to the `sort` event', () => { | ||
col.add([m3, m2, m1]); | ||
expect(colList.views[0].model).toBe(m3); | ||
col.sort({comparator: 'order'}); | ||
col.sort({ comparator: 'order' }); | ||
expect(colList.views[0].model).toBe(m1); | ||
}); | ||
it('resets the list in response to the `reset` event', ()=> { | ||
it('resets the list in response to the `reset` event', () => { | ||
col.add([m1, m2, m3]); | ||
@@ -574,3 +595,3 @@ expect(colList.views.length).toBe(3); | ||
it('clears the list and removes the collection in response to the `dispose` event', ()=> { | ||
it('clears the list and removes the collection in response to the `dispose` event', () => { | ||
col.add([m1, m2, m3]); | ||
@@ -583,2 +604,2 @@ expect(colList.views.length).toBe(3); | ||
}); | ||
}); | ||
}); |
33697
8
860
12