Created
November 20, 2017 16:03
-
-
Save efreed/5c327d75638cbe83c08c88193a16f407 to your computer and use it in GitHub Desktop.
Knockout Helpers
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
/** | |
* Lookup the observable object or value of a field safely no matter if it is static or observable or even exists | |
* @syntax kov([scope,]period_delimited_lookup_string[,ifmissing]) | |
* @returns value or ifmissing | |
* @author Eric Freed | |
*/ | |
function kov(a, b, c, orig_f, orig_scope) { | |
try { | |
var ifmissing, f, _scope = "init"; | |
if (typeof a == "string") { | |
_scope = (ko.contextFor(document.body)||{}).$data; | |
f = a+""; | |
ifmissing = b; | |
} else { | |
_scope = a; | |
f = b+""; | |
ifmissing = c; | |
} | |
// Grab first element in a dot-notation field | |
var path = f.split("."); | |
f = path.shift(); | |
if (typeof _scope === undefined) | |
throw "scope is empty"; | |
if ( !(_scope.hasOwnProperty(f) || f in _scope) ) | |
throw "property is undefined"; | |
if (typeof _scope === "string" && !isNaN(f)) | |
throw "you didn't mean to ask for a character in a string, right?"; | |
var field_found = _scope[f]; | |
if (path.length) { | |
// Drill in to next level | |
if (typeof field_found == "function") | |
field_found = field_found(); | |
return kov(field_found, path.join("."), ifmissing, orig_f || (f+"."+(path.join('.'))), orig_scope || _scope); | |
} else { | |
if (field_found === undefined) | |
return ifmissing; | |
return field_found; | |
} | |
} catch(e) { | |
if (f === undefined) | |
console.log("error loading kov", a, b, c); | |
if (ifmissing === undefined) { | |
if (orig_f) { | |
console.log("error in kov("+f+")", e, _scope, "_orig_", orig_f, orig_scope); | |
} else { | |
console.log("error in kov("+f+")", e, _scope); | |
} | |
if (typeof window.Error == "function") { | |
var err = new Error(); | |
console.log('stack from above error: ', err.stack); | |
} | |
if (window.Rollbar) { | |
Rollbar.warning("error in kov("+f+")", { | |
js_error: e, | |
scope: _scope, | |
orig_search: orig_f, | |
orig_scope: orig_scope | |
}); | |
} | |
} | |
return ifmissing; | |
} | |
} | |
// Safe shorthand for kov(...)() | |
function v(a, b, c) { | |
var v = this.kov(a, b, c); | |
if (typeof v === "function") | |
return v(); | |
return v; | |
} | |
// Numeric extender from KO's Documentation | |
ko.extenders.numeric = function(target, precision) { | |
//create a writable computed observable to intercept writes to our observable | |
var result = ko.pureComputed({ | |
read: target, //always return the original observables value | |
write: function(newValue) { | |
var current = target(), | |
roundingMultiplier = Math.pow(10, precision), | |
newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue), | |
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier; | |
//only write if it changed | |
if (valueToWrite !== current) { | |
target(valueToWrite); | |
} else { | |
//if the rounded value is the same, but a different value was written, force a notification for the current field | |
if (newValue !== current) { | |
target.notifySubscribers(valueToWrite); | |
} | |
} | |
} | |
}).extend({ notify: 'always' }); | |
//initialize with current value to make sure it is rounded appropriately | |
result(target()); | |
//return the new computed observable | |
return result; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment