mirror of
https://github.com/Febbweiss/filebrowser-durandal-widget.git
synced 2026-03-05 06:35:49 +00:00
97 lines
3.7 KiB
JavaScript
97 lines
3.7 KiB
JavaScript
|
|
(function() {
|
|
var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
|
|
|
|
ko.toJS = function(rootObject) {
|
|
if (arguments.length == 0)
|
|
throw new Error("When calling ko.toJS, pass the object you want to convert.");
|
|
|
|
// We just unwrap everything at every level in the object graph
|
|
return mapJsObjectGraph(rootObject, function(valueToMap) {
|
|
// Loop because an observable's value might in turn be another observable wrapper
|
|
for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
|
|
valueToMap = valueToMap();
|
|
return valueToMap;
|
|
});
|
|
};
|
|
|
|
ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
|
|
var plainJavaScriptObject = ko.toJS(rootObject);
|
|
return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
|
|
};
|
|
|
|
function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
|
|
visitedObjects = visitedObjects || new objectLookup();
|
|
|
|
rootObject = mapInputCallback(rootObject);
|
|
var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date)) && (!(rootObject instanceof String)) && (!(rootObject instanceof Number)) && (!(rootObject instanceof Boolean));
|
|
if (!canHaveProperties)
|
|
return rootObject;
|
|
|
|
var outputProperties = rootObject instanceof Array ? [] : {};
|
|
visitedObjects.save(rootObject, outputProperties);
|
|
|
|
visitPropertiesOrArrayEntries(rootObject, function(indexer) {
|
|
var propertyValue = mapInputCallback(rootObject[indexer]);
|
|
|
|
switch (typeof propertyValue) {
|
|
case "boolean":
|
|
case "number":
|
|
case "string":
|
|
case "function":
|
|
outputProperties[indexer] = propertyValue;
|
|
break;
|
|
case "object":
|
|
case "undefined":
|
|
var previouslyMappedValue = visitedObjects.get(propertyValue);
|
|
outputProperties[indexer] = (previouslyMappedValue !== undefined)
|
|
? previouslyMappedValue
|
|
: mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
|
|
break;
|
|
}
|
|
});
|
|
|
|
return outputProperties;
|
|
}
|
|
|
|
function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
|
|
if (rootObject instanceof Array) {
|
|
for (var i = 0; i < rootObject.length; i++)
|
|
visitorCallback(i);
|
|
|
|
// For arrays, also respect toJSON property for custom mappings (fixes #278)
|
|
if (typeof rootObject['toJSON'] == 'function')
|
|
visitorCallback('toJSON');
|
|
} else {
|
|
for (var propertyName in rootObject) {
|
|
visitorCallback(propertyName);
|
|
}
|
|
}
|
|
};
|
|
|
|
function objectLookup() {
|
|
this.keys = [];
|
|
this.values = [];
|
|
};
|
|
|
|
objectLookup.prototype = {
|
|
constructor: objectLookup,
|
|
save: function(key, value) {
|
|
var existingIndex = ko.utils.arrayIndexOf(this.keys, key);
|
|
if (existingIndex >= 0)
|
|
this.values[existingIndex] = value;
|
|
else {
|
|
this.keys.push(key);
|
|
this.values.push(value);
|
|
}
|
|
},
|
|
get: function(key) {
|
|
var existingIndex = ko.utils.arrayIndexOf(this.keys, key);
|
|
return (existingIndex >= 0) ? this.values[existingIndex] : undefined;
|
|
}
|
|
};
|
|
})();
|
|
|
|
ko.exportSymbol('toJS', ko.toJS);
|
|
ko.exportSymbol('toJSON', ko.toJSON);
|