Last active
June 24, 2017 18:22
-
-
Save paulfalgout/95570a3a82141ff6a057164538371c78 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const _ = require('underscore'); | |
const Bb = require('backbone'); | |
const Mn = require('backbone.marionette'); | |
const morphdom = require('morphdom'); | |
const DomApi = { | |
// Returns a new HTML DOM node instance | |
createBuffer() { | |
return document.createDocumentFragment(); | |
}, | |
// Lookup the `selector` string | |
// Selector may also be a DOM element | |
// Returns an array-like object of nodes | |
getEl(selector) { | |
if (_.isObject(selector)) { | |
return [selector] | |
} else { | |
return document.querySelectorAll(selector); | |
} | |
}, | |
// Finds the `selector` string with the el | |
// Returns an array-like object of nodes | |
findEl(el, selector) { | |
return el.querySelectorAll(selector); | |
}, | |
// Detach `el` from the DOM without removing listeners | |
detachEl(el) { | |
if (el.parentNode) el.parentNode.removeChild(el); | |
}, | |
// Remove `oldEl` from the DOM and put `newEl` in its place | |
replaceEl(newEl, oldEl) { | |
if (newEl === oldEl) { | |
return; | |
} | |
const parent = oldEl.parentNode; | |
if (!parent) { | |
return; | |
} | |
parent.replaceChild(newEl, oldEl); | |
}, | |
// Replace the contents of `el` with the HTML string of `html` | |
setContents(el, html) { | |
if (html) el.innerHTML = html | |
}, | |
// Takes the DOM node `el` and appends the DOM node `contents` | |
// to the end of the element's contents. | |
appendContents(el, contents) { | |
el.appendChild(contents) | |
}, | |
// Remove the inner contents of `el` from the DOM while leaving | |
// `el` itself in the DOM. | |
detachContents(el) { | |
while (el.firstChild) { | |
el.removeChild(el.firstChild); | |
} | |
} | |
}; | |
Mn.setDomApi(DomApi); | |
const rowTemplate = function(data) { | |
const tr = document.createElement('tr'); | |
const td1 = document.createElement('td'); | |
td1.className = 'col-md-1'; | |
td1.innerText = data.id; | |
tr.appendChild(td1); | |
const td2 = document.createElement('td'); | |
td2.className = 'col-md-4'; | |
tr.appendChild(td2); | |
const a2 = document.createElement('a'); | |
a2.className = 'js-link'; | |
td2.appendChild(a2); | |
a2.innerText = data.label; | |
const td3 = document.createElement('td'); | |
td3.className = 'col-md-1'; | |
tr.appendChild(td3); | |
const a = document.createElement('a'); | |
a.className = 'js-del'; | |
a.dataset.id = data.id; | |
td3.appendChild(a); | |
const span = document.createElement('span'); | |
span.className = 'glyphicon glyphicon-remove'; | |
span.setAttribute('aria-hidden', 'true'); | |
a.appendChild(span); | |
const td4 = document.createElement('td'); | |
td4.className = 'col-md-6'; | |
tr.appendChild(td4); | |
return tr; | |
} | |
var startTime; | |
var lastMeasure; | |
var startMeasure = function(name) { | |
//console.profile(name); | |
startTime = performance.now(); | |
lastMeasure = name; | |
} | |
var stopMeasure = function() { | |
var last = lastMeasure; | |
if (lastMeasure) { | |
//console.profileEnd(lastMeasure); | |
window.setTimeout(function () { | |
lastMeasure = null; | |
var stop = performance.now(); | |
var duration = 0; | |
console.log(last+" took "+(stop-startTime)); | |
}, 0); | |
} | |
} | |
function _random(max) { | |
return Math.round(Math.random()*1000)%max; | |
} | |
const Store = Bb.Collection.extend({ | |
initialize() { | |
this.id = 1; | |
this.on('reset update', this.clearSelected); | |
}, | |
buildData(count = 1000) { | |
var adjectives = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; | |
var colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; | |
var nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; | |
var data = []; | |
for (var i = 0; i < count; i++) | |
data.push({id: this.id++, label: adjectives[_random(adjectives.length)] + " " + colours[_random(colours.length)] + " " + nouns[_random(nouns.length)] }); | |
return data; | |
}, | |
clearSelected() { | |
if(this.curSelected) { | |
this.curSelected.classList.remove('danger'); | |
this.curSelected = null; | |
} | |
}, | |
updateData(mod = 10) { | |
startMeasure("update"); | |
for (let i=0;i<this.models.length;i+=10) { | |
const label = this.models[i].get('label'); | |
this.models[i].set('label', label + ' !!!'); | |
} | |
stopMeasure(); | |
}, | |
delete(id) { | |
startMeasure("delete"); | |
this.trigger('removeRow', this.get(id)); | |
this.remove(id, { silent: true }); | |
stopMeasure(); | |
}, | |
run() { | |
startMeasure("run"); | |
this.trigger('clear'); | |
this.reset(this.buildData()); | |
stopMeasure(); | |
}, | |
addData() { | |
startMeasure("add"); | |
this.add(this.buildData(1000)); | |
stopMeasure(); | |
}, | |
select(target) { | |
startMeasure("select"); | |
if(this.curSelected) this.curSelected.classList.remove('danger'); | |
this.curSelected = target.parentNode.parentNode; | |
this.curSelected.classList.add('danger'); | |
stopMeasure(); | |
}, | |
runLots() { | |
startMeasure("runLots"); | |
this.trigger('clear'); | |
this.reset(this.buildData(10000)); | |
stopMeasure(); | |
}, | |
clear() { | |
startMeasure("clear"); | |
this.trigger('clear'); | |
this.reset(); | |
stopMeasure(); | |
}, | |
swapRows() { | |
startMeasure("swapRows"); | |
if (this.length > 10) { | |
const a = this.models[4]; | |
this.models[4] = this.models[9]; | |
this.models[9] = a; | |
this.trigger('swapRows', this.models[4], this.models[9]); | |
} | |
stopMeasure(); | |
} | |
}); | |
const store = new Store(); | |
const ChildView = Mn.View.extend({ | |
monitorViewEvents: false, | |
setElement() {}, | |
_setAttributes() {}, | |
template: rowTemplate, | |
serializeData() { | |
return this.model.attributes; | |
}, | |
attachElContent(el) { | |
if(this.isRendered()) morphdom(this.el, el, { onlyChildren: true }); | |
else this.el = el; | |
}, | |
destroy() { | |
this.stopListening(); | |
} | |
}); | |
const CollectionView = Mn.NextCollectionView.extend({ | |
monitorViewEvents: false, | |
viewComparator: false, | |
el: '#tbody', | |
childView: ChildView, | |
initialize() { | |
this.listenTo(this.collection, { | |
'clear': this.onClear, | |
'swapRows': this.onSwapRows, | |
'removeRow': this.onRemoveRow, | |
'change:label': this.onChangeLabel | |
}); | |
}, | |
events: { | |
'click .js-link'(e) { | |
this.collection.select(e.currentTarget); | |
}, | |
'click .js-del'(e) { | |
this.collection.delete(e.currentTarget.dataset.id); | |
} | |
}, | |
childViewEventPrefix: false, | |
onClear() { | |
this.el.textContent = ''; | |
}, | |
onSwapRows(model1, model2) { | |
const el1 = this.children.findByModel(model1).el; | |
const el2 = this.children.findByModel(model2).el; | |
const parent1 = el1.parentNode; | |
const next1 = el1.nextSibling; | |
const parent2 = el2.parentNode; | |
const next2 = el2.nextSibling; | |
parent1.insertBefore(el2, next1); | |
parent2.insertBefore(el1, next2); | |
}, | |
onRemoveRow(model) { | |
const view = this.children.findByModel(model); | |
this.el.removeChild(view.el); | |
this.removeChildView(view); | |
}, | |
onChangeLabel(model) { | |
const view = this.children.findByModel(model); | |
view.render(); | |
} | |
}); | |
const collectionView = new CollectionView({ | |
collection: store | |
}); | |
collectionView.render(); | |
const MainView = Mn.View.extend({ | |
el : '.jumbotron', | |
triggers: { | |
'click #run': 'run', | |
'click #runlots': 'runLots', | |
'click #add': 'add', | |
'click #update': 'update', | |
'click #clear': 'clear', | |
'click #swaprows': 'swapRows' | |
}, | |
onRun() { | |
store.run(); | |
}, | |
onRunLots() { | |
store.runLots(); | |
}, | |
onAdd() { | |
store.addData(); | |
}, | |
onUpdate() { | |
store.updateData(); | |
}, | |
onClear() { | |
store.clear(); | |
}, | |
onSwapRows() { | |
store.swapRows(); | |
} | |
}); | |
new MainView(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment