/extensions/SemanticResultFormats/Exhibit/exhibit/scripts/util/settings.js
JavaScript | 439 lines | 361 code | 56 blank | 22 comment | 130 complexity | 64d59882704bc2c6594bbb8119b4d176 MD5 | raw file
- /*==================================================
- * Exhibit.SettingsUtilities
- *
- * Utilities for various parts of Exhibit to
- * collect their settings.
- *==================================================
- */
- Exhibit.SettingsUtilities = new Object();
- /*--------------------------------------------------
- * Static settings
- *--------------------------------------------------
- */
- Exhibit.SettingsUtilities.collectSettings = function(config, specs, settings) {
- Exhibit.SettingsUtilities._internalCollectSettings(
- function(field) { return config[field]; },
- specs,
- settings
- );
- };
- Exhibit.SettingsUtilities.collectSettingsFromDOM = function(configElmt, specs, settings) {
- Exhibit.SettingsUtilities._internalCollectSettings(
- function(field) { return Exhibit.getAttribute(configElmt, field); },
- specs,
- settings
- );
- };
- Exhibit.SettingsUtilities._internalCollectSettings = function(f, specs, settings) {
- for (var field in specs) {
- var spec = specs[field];
- var name = field;
- if ("name" in spec) {
- name = spec.name;
- }
- if (!(name in settings) && "defaultValue" in spec) {
- settings[name] = spec.defaultValue;
- }
- var value = f(field);
- if (value == null) {
- continue;
- }
- if (typeof value == "string") {
- value = value.trim();
- if (value.length == 0) {
- continue;
- }
- }
- var type = "text";
- if ("type" in spec) {
- type = spec.type;
- }
- var dimensions = 1;
- if ("dimensions" in spec) {
- dimensions = spec.dimensions;
- }
- try {
- if (dimensions > 1) {
- var separator = ",";
- if ("separator" in spec) {
- separator = spec.separator;
- }
- var a = value.split(separator);
- if (a.length != dimensions) {
- throw new Error("Expected a tuple of " + dimensions + " dimensions separated with " + separator + " but got " + value);
- } else {
- for (var i = 0; i < a.length; i++) {
- a[i] = Exhibit.SettingsUtilities._parseSetting(a[i].trim(), type, spec);
- }
- settings[name] = a;
- }
- } else {
- settings[name] = Exhibit.SettingsUtilities._parseSetting(value, type, spec);
- }
- } catch (e) {
- SimileAjax.Debug.exception(e);
- }
- }
- };
- Exhibit.SettingsUtilities._parseSetting = function(s, type, spec) {
- var sType = typeof s;
- if (type == "text") {
- return s;
- } else if (type == "float") {
- if (sType == "number") {
- return s;
- } else if (sType == "string") {
- var f = parseFloat(s);
- if (!isNaN(f)) {
- return f;
- }
- }
- throw new Error("Expected a floating point number but got " + s);
- } else if (type == "int") {
- if (sType == "number") {
- return Math.round(s);
- } else if (sType == "string") {
- var n = parseInt(s);
- if (!isNaN(n)) {
- return n;
- }
- }
- throw new Error("Expected an integer but got " + s);
- } else if (type == "boolean") {
- if (sType == "boolean") {
- return s;
- } else if (sType == "string") {
- s = s.toLowerCase();
- if (s == "true") {
- return true;
- } else if (s == "false") {
- return false;
- }
- }
- throw new Error("Expected either 'true' or 'false' but got " + s);
- } else if (type == "function") {
- if (sType == "function") {
- return s;
- } else if (sType == "string") {
- try {
- var f = eval(s);
- if (typeof f == "function") {
- return f;
- }
- } catch (e) {
- // silent
- }
- }
- throw new Error("Expected a function or the name of a function but got " + s);
- } else if (type == "enum") {
- var choices = spec.choices;
- for (var i = 0; i < choices.length; i++) {
- if (choices[i] == s) {
- return s;
- }
- }
- throw new Error("Expected one of " + choices.join(", ") + " but got " + s);
- } else {
- throw new Error("Unknown setting type " + type);
- }
- };
- /*--------------------------------------------------
- * Accessors
- *--------------------------------------------------
- */
- Exhibit.SettingsUtilities.createAccessors = function(config, specs, accessors) {
- Exhibit.SettingsUtilities._internalCreateAccessors(
- function(field) { return config[field]; },
- specs,
- accessors
- );
- };
- Exhibit.SettingsUtilities.createAccessorsFromDOM = function(configElmt, specs, accessors) {
- Exhibit.SettingsUtilities._internalCreateAccessors(
- function(field) { return Exhibit.getAttribute(configElmt, field); },
- specs,
- accessors
- );
- };
- Exhibit.SettingsUtilities._internalCreateAccessors = function(f, specs, accessors) {
- for (var field in specs) {
- var spec = specs[field];
- var accessorName = spec.accessorName;
- var accessor = null;
- var isTuple = false;
- var createOneAccessor = function(spec2) {
- isTuple = false;
- if ("bindings" in spec2) {
- return Exhibit.SettingsUtilities._createBindingsAccessor(f, spec2.bindings);
- } else if ("bindingNames" in spec2) {
- isTuple = true;
- return Exhibit.SettingsUtilities._createTupleAccessor(f, spec2);
- } else {
- return Exhibit.SettingsUtilities._createElementalAccessor(f, spec2);
- }
- };
- if ("alternatives" in spec) {
- var alternatives = spec.alternatives;
- for (var i = 0; i < alternatives.length; i++) {
- accessor = createOneAccessor(alternatives[i]);
- if (accessor != null) {
- break;
- }
- }
- } else {
- accessor = createOneAccessor(spec);
- }
- if (accessor != null) {
- accessors[accessorName] = accessor;
- } else if (!(accessorName in accessors)) {
- accessors[accessorName] = function(value, database, visitor) {};
- }
- }
- };
- Exhibit.SettingsUtilities._createBindingsAccessor = function(f, bindingSpecs) {
- var bindings = [];
- for (var i = 0; i < bindingSpecs.length; i++) {
- var bindingSpec = bindingSpecs[i];
- var accessor = null;
- var isTuple = false;
- if ("bindingNames" in bindingSpec) {
- isTuple = true;
- accessor = Exhibit.SettingsUtilities._createTupleAccessor(f, bindingSpec);
- } else {
- accessor = Exhibit.SettingsUtilities._createElementalAccessor(f, bindingSpec);
- }
- if (accessor == null) {
- if (!("optional" in bindingSpec) || !bindingSpec.optional) {
- return null;
- }
- } else {
- bindings.push({
- bindingName: bindingSpec.bindingName,
- accessor: accessor,
- isTuple: isTuple
- });
- }
- }
- return function(value, database, visitor) {
- Exhibit.SettingsUtilities._evaluateBindings(value, database, visitor, bindings);
- };
- };
- Exhibit.SettingsUtilities._createTupleAccessor = function(f, spec) {
- var value = f(spec.attributeName);
- if (value == null) {
- return null;
- }
- if (typeof value == "string") {
- value = value.trim();
- if (value.length == 0) {
- return null;
- }
- }
- try {
- var expression = Exhibit.ExpressionParser.parse(value);
- var parsers = [];
- var bindingTypes = spec.types;
- for (var i = 0; i < bindingTypes.length; i++) {
- parsers.push(Exhibit.SettingsUtilities._typeToParser(bindingTypes[i]));
- }
- var bindingNames = spec.bindingNames;
- var separator = ",";
- if ("separator" in spec) {
- separator = spec.separator;
- }
- return function(itemID, database, visitor, tuple) {
- expression.evaluateOnItem(itemID, database).values.visit(
- function(v) {
- var a = v.split(separator);
- if (a.length == parsers.length) {
- var tuple2 = {};
- if (tuple) {
- for (var n in tuple) {
- tuple2[n] = tuple[n];
- }
- }
- for (var i = 0; i < bindingNames.length; i++) {
- tuple2[bindingNames[i]] = null;
- parsers[i](a[i], function(v) { tuple2[bindingNames[i]] = v; });
- }
- visitor(tuple2);
- }
- }
- );
- };
- } catch (e) {
- SimileAjax.Debug.exception(e);
- return null;
- }
- };
- Exhibit.SettingsUtilities._createElementalAccessor = function(f, spec) {
- var value = f(spec.attributeName);
- if (value == null) {
- return null;
- }
- if (typeof value == "string") {
- value = value.trim();
- if (value.length == 0) {
- return null;
- }
- }
- var bindingType = "text";
- if ("type" in spec) {
- bindingType = spec.type;
- }
- try {
- var expression = Exhibit.ExpressionParser.parse(value);
- var parser = Exhibit.SettingsUtilities._typeToParser(bindingType);
- return function(itemID, database, visitor) {
- expression.evaluateOnItem(itemID, database).values.visit(
- function(v) { return parser(v, visitor); }
- );
- };
- } catch (e) {
- SimileAjax.Debug.exception(e);
- return null;
- }
- }
- Exhibit.SettingsUtilities._typeToParser = function(type) {
- switch (type) {
- case "text": return Exhibit.SettingsUtilities._textParser;
- case "url": return Exhibit.SettingsUtilities._urlParser;
- case "float": return Exhibit.SettingsUtilities._floatParser;
- case "int": return Exhibit.SettingsUtilities._intParser;
- case "date": return Exhibit.SettingsUtilities._dateParser;
- case "boolean": return Exhibit.SettingsUtilities._booleanParser;
- default:
- throw new Error("Unknown setting type " + type);
- }
- }
- Exhibit.SettingsUtilities._textParser = function(v, f) {
- return f(v);
- };
- Exhibit.SettingsUtilities._floatParser = function(v, f) {
- var n = parseFloat(v);
- if (!isNaN(n)) {
- return f(n);
- }
- return false;
- };
- Exhibit.SettingsUtilities._intParser = function(v, f) {
- var n = parseInt(v);
- if (!isNaN(n)) {
- return f(n);
- }
- return false;
- };
- Exhibit.SettingsUtilities._dateParser = function(v, f) {
- if (v instanceof Date) {
- return f(v);
- } else if (typeof v == "number") {
- var d = new Date(0);
- d.setUTCFullYear(v);
- return f(d);
- } else {
- var d = SimileAjax.DateTime.parseIso8601DateTime(v.toString());
- if (d != null) {
- return f(d);
- }
- }
- return false;
- };
- Exhibit.SettingsUtilities._booleanParser = function(v, f) {
- v = v.toString().toLowerCase();
- if (v == "true") {
- return f(true);
- } else if (v == "false") {
- return f(false);
- }
- return false;
- };
- Exhibit.SettingsUtilities._urlParser = function(v, f) {
- return f(Exhibit.Persistence.resolveURL(v.toString()));
- };
- Exhibit.SettingsUtilities._evaluateBindings = function(value, database, visitor, bindings) {
- var maxIndex = bindings.length - 1;
- var f = function(tuple, index) {
- var binding = bindings[index];
- var visited = false;
- var recurse = index == maxIndex ? function() { visitor(tuple); } : function() { f(tuple, index + 1); };
- if (binding.isTuple) {
- /*
- The tuple accessor will copy existing fields out of "tuple" into a new
- object and then injects new fields into it before calling the visitor.
- This is so that the same tuple object is not reused for different
- tuple values, which would cause old tuples to be overwritten by new ones.
- */
- binding.accessor(
- value,
- database,
- function(tuple2) { visited = true; tuple = tuple2; recurse(); },
- tuple
- );
- } else {
- var bindingName = binding.bindingName;
- binding.accessor(
- value,
- database,
- function(v) { visited = true; tuple[bindingName] = v; recurse(); }
- );
- }
- if (!visited) { recurse(); }
- };
- f({}, 0);
- };