Skip to content

Instantly share code, notes, and snippets.

@foofoodog
Last active December 16, 2015 21:09
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 foofoodog/5497235 to your computer and use it in GitHub Desktop.
Save foofoodog/5497235 to your computer and use it in GitHub Desktop.
Library of some stuff
// Aguments for init and update are the same.
// element, valueAccessor, allBindingsAccessor, viewModel, bindingContext
// See http://knockoutjs.com/documentation/custom-bindings.html
ko.bindingHandlers.dirty = {
// bind dom element change event to dirty flag observable
init: function (el, va, ba, vm, bc) {
$(el).change(function () {
if (bc.$parent.flag.dirty) (bc.$parent.flag.dirty(va())); // might check if dirty is actually an observable
});
},
update: function (el, va, ba, vm, bc) {
// TODO try to use this instead of jq event binding
}
};
ko.bindingHandlers.required = {
init: function (el, va, ba, vm, bc) {
$("<span>*</span>").insertAfter(el);
bc.$data.valid = ko.observable(false);
},
update: function (el, va, ba, vm, bc) {
bc.$data.valid(!(ba().value().trim() == ""));
}
};
Library of some stuff
function Storage(type, converter) {
// TODO create a default converter if argument is missing.
return {
load: load,
save: save
};
function load(items) {
var data = localStorage.getItem(type.name) || "[]";
JSON.parse(data).forEach(
function (item) {
items.push(converter.from(extend(new type(), item)));
}
);
}
function save(items) {
var data = [];
items.forEach(function (item) {
data.push(converter.to(item));
});
localStorage.setItem(type.name, JSON.stringify(data));
}
function extend(target, source) { // poor mans extend
for (var prop in source) {
target[prop] = source[prop];
}
return target;
}
}
function ViewModel(type) {
// Need serilaized objects properties to be observable on load, non-observable on save.
var converter = {
to: ko.mapping.toJS,
from: ko.mapping.fromJS
};
// Create type specific storage that uses converter.
var storage = new Storage(type, converter);
// Working variables.
var item = ko.observable(newItem());
var items = ko.observableArray();
var dirty = ko.observable(false);
var valid = ko.observable(false);
var message = ko.observable("");
load(); // see what we have laying around
// Retun this interface.
return {
data: {
item: item,
items: items,
message: message,
},
flag: {
dirty: dirty,
valid: valid
},
event: {
add: add,
remove: remove
},
call: {
save: save,
load: load
}
};
// privates
function newItem() {
return converter.from(new type()); // use coverter to create new item
}
function validate(data) {
var ret = data.valid ? data.valid() : true;
message(ret ? "" : "*required");
return ret;
}
function validateAll() {
var ret = true;
items().forEach(function(data) {
if (!validate(data)) {
ret = false;
throw {}; // break
}
});
return ret;
}
// publics
function save() {
if (!validateAll()) return;
storage.save(items()); // !important call it with the values().
dirty(false);
}
function load() {
items.removeAll();
storage.load(items);
dirty(false);
}
function add(data) {
if (!validate(data)) return;
items.push(data);
dirty(true);
item(newItem());
}
function remove(data) {
items.remove(data);
dirty(true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment