Skip to content

Instantly share code, notes, and snippets.

@lahmatiy
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lahmatiy/e499e76be22140648cb9 to your computer and use it in GitHub Desktop.
Save lahmatiy/e499e76be22140648cb9 to your computer and use it in GitHub Desktop.
Example of persistent user preferences using basis.js
//
// Enum class is proposed future citizen of basis.js
//
var Value = require('basis.data').Value;
var Enum = Value.subclass({
className: 'Enum',
init: function(){
var values = basis.array.from(this.values);
/** @cut */if (this.proxy)
/** @cut */ basis.dev.warn('Setting `proxy` for Enum instances is prohibited');
this.proxy = function(value){
if (values.indexOf(value) != -1)
return value;
/** @cut */basis.dev.warn('Trying to set wrong value for Enum instance.' +
/** @cut */ '\nVariants: ', values,
/** @cut */ '\nIgnored value: ', value);
return this.value;
};
if (values.indexOf(this.value) == -1)
this.value = values[0];
Value.prototype.init.call(this);
},
toggle: function(){
var idx = (this.values.indexOf(this.value) + 1) % this.values.length;
this.set(this.values[idx]);
}
});
module.exports = Enum;
// Example of persistent user preferencies.
// Probably common class based on this solution will be added to basis.js.
var SETTINGS = 'user-preferences';
var Value = require('basis.data').Value;
var ObjectSet = require('basis.data.value').ObjectSet;
var Enum = require('./enum.js');
var initValues = {};
var storage = (function(){
var testKey = '__localStorageTest' + Math.random();
var localStorage = global.localStorage;
var supported = false;
// test localStorage as it can produce exceptions in some cases
try {
localStorage.setItem(testKey, testKey);
supported = localStorage.getItem(testKey) === testKey;
localStorage.removeItem(testKey);
} catch (e) {
// if exception don't use localStorage
}
return supported ? localStorage : {};
})();
// try fetch settings from storage
try {
initValues = basis.json.parse(storage[SETTINGS]);
} catch (e) {}
// preference map and default values
var preferences = {
sidebarSize: ['normal', 'short'],
viewMode: ['list', 'table'],
lastLogin: ''
};
// convert to Value instances
for (var name in preferences)
preferences[name] = Array.isArray(preferences[name])
? new Enum({
value: initValues[name],
values: preferences[name]
})
: new Value({
value: name in initValues ? initValues[name] : preferences[name]
});
// sync with local storage
var changesWatcher = new ObjectSet({
objects: basis.object.values(preferences),
calculateValue: function(){
return JSON.stringify(basis.object.keys(preferences).sort().reduce(function(res, name){
res[name] = preferences[name].value;
return res;
}, {}));
},
handler: {
change: function(){
storage[SETTINGS] = this.value;
}
}
});
// make copy of preferences object, to avoid overrides
module.exports = basis.object.slice(preferences);
var Value = require('basis.data').Value;
var Node = require('basis.ui').Node;
var preferences = require('./preferences.js');
console.log(preferences.sidebarSize);
// > Enum { .. }
// if no value in localStorage than default value used
// for enums it's a first item
console.log(preferences.sidebarSize.value);
// > "normal"
preferences.sidebarSize.set('xxx');
// > Trying to set wrong value for Enum instance.
// Variants: ["normal", "short"]
// Ignored value: xxx
preferences.sidebarSize.set('short');
console.log(preferences.sidebarSize.value);
// > "short"
// if setting is enum, we could switch value by toggle method
preferences.sidebarSize.toggle();
console.log(preferences.sidebarSize.value);
// > "normal"
var view = new Node({
binding: {
size: preferences.sidebarSize,
// of cause it's anti-pattern and sizes should live in template/css land
// but it shows how value could be transformed
width: preferences.sidebarSize.as(function(value){
return value == 'normal' ? 300 : 50;
})
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment