Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ncortines/5a79727cd0f086d0abb2 to your computer and use it in GitHub Desktop.
Save ncortines/5a79727cd0f086d0abb2 to your computer and use it in GitHub Desktop.
IndexedDB + Backbone + Knockout + Knockback
<div id="example">
<div class="box" data-bind="visible: preparingData">
Preparing data...
</div>
<div class="box">
<div>
<span>Text filter:</span>
<input type="text" data-bind="value: textFilter, valueUpdate: 'input', disable: preparingData">
</div>
<div>
<span>Sort by:</span>
<select data-bind="value: sortCriteria, options: sortCriteriaOptions, disable: preparingData"></select>
</div>
</div>
<div class="box">
<span>Movies (<!-- ko text: movies().length --><!-- /ko -->):</span>
<div data-bind="foreach: movies">
<div class="box">
<div>
<span>Title:</span>
<!-- ko text: name --><!-- /ko -->
</div>
<div>
<span>Year:</span>
<!-- ko text: year --><!-- /ko -->
</div>
</div>
</div>
<div data-bind="visible: loadingData">
Loading...
</div>
</div>
</div>

IndexedDB + Backbone + Knockout + Knockback

This explains how to load sorted and filtered data on a responsive way thanks to indexeddb

A Pen by Juan Cortines on CodePen.

License.

var database = {
id: 'example',
description: 'example',
migrations: [
{
version: '1.0',
migrate: function (transaction, next) {
var movies = transaction.db.createObjectStore('movies', {keyPath: 'id'});
movies.createIndex('name', 'name', {
unique: true
});
movies.createIndex('year', 'year', {
unique: false
});
next();
}
}
]
};
var Movie = Backbone.Model.extend({
storeName: 'movies',
database: database,
defaults: {
name: '',
year: undefined
}
});
var Movies = Backbone.Collection.extend({
storeName: 'movies',
database: database,
model: Movie
});
var getRandomString = function () {
var i,
text = '',
possible = 'AB CDEFGH IJKLMNOPQ RSTUVWXY Zabcdefgh ijklmnopq rstuvwxyz 123';
for (i = 0; i < 10; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
};
var getRandomDate = function () {
return Math.round(Math.random() * Date.now());
};
var prepareData = function (oncomplete) {
var movies = new Movies();
movies.once('sync', function () {
var count,
request = indexedDB.open('example', '1.0');
request.onsuccess = function () {
var db = request.result,
transaction = db.transaction(['movies'], 'readwrite'),
store = transaction.objectStore('movies');
transaction.oncomplete = function (event) {
oncomplete();
};
for (count = 1; count < 100000; count++) {
store.put({
id: count,
name: getRandomString(),
year: getRandomDate()
});
}
};
});
movies.create({
id: 0,
name: getRandomString(),
year: getRandomDate()
});
};
var ViewModel = function () {
var promise,
movies = new Movies(),
loadMoviesCollection = function (textFilter, sortCriteria) {
if (promise) {
promise.abort();
}
movies.reset();
this.loadingData(true);
promise = movies.fetch({
indexName: sortCriteria,
addIndividually: true,
filter: function (movie) {
return movie.name.indexOf(textFilter) !== -1;
}
}).done(function () {
this.loadingData(false);
}.bind(this));
}.bind(this);
this.movies = kb.collectionObservable(movies, {
view_model: function (movie) {
this.name = movie.get('name');
this.year = new Date(movie.get('year')).getFullYear();
},
auto_compact: true
});
this.preparingData = ko.observable(true);
this.loadingData = ko.observable(false);
this.textFilter = ko.observable('');
this.sortCriteria = ko.observable();
this.sortCriteriaOptions = ko.observableArray(['name', 'year']);
this.textFilter.subscribe(function (text) {
loadMoviesCollection(text, this.sortCriteria());
}.bind(this));
this.sortCriteria.subscribe(function (criteria) {
loadMoviesCollection(this.textFilter(), criteria);
}.bind(this));
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel, $('#example')[0]);
prepareData(function () {
viewModel.preparingData(false);
});
.box {
border-style: solid;
border-width: 1px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment