infusion
Version:
Infusion is an application framework for developing flexible stuff with JavaScript
332 lines (314 loc) • 12.1 kB
JavaScript
/*
Copyright The Infusion copyright holders
See the AUTHORS.md file at the top-level directory of this distribution and at
https://github.com/fluid-project/infusion/raw/main/AUTHORS.md.
Licensed under the Educational Community License (ECL), Version 2.0 or the New
BSD license. You may not use this file except in compliance with one these
Licenses.
You may obtain a copy of the ECL 2.0 License and BSD License at
https://github.com/fluid-project/infusion/raw/main/Infusion-LICENSE.txt
*/
"use strict";
fluid.registerNamespace("fluid.prefs.builder");
/**
* A merge policy where the items are not merged, but returned as a merge array to be handled by another
* function (e.g. by an expander). Similar merge policies are `fluid.membersMergePolicy` and
* `fluid.deferringMergePolicy`. These types of deferred merges are required to work around
* [FLUID-6457](https://issues.fluidproject.org/browse/FLUID-6457).
*
* @param {Object} target - A base for merging the options.
* @param {Object} source - Options being merged.
* @return {Object[]} - The merge array
*/
fluid.deferredMergePolicy = function (target, source) {
if (!target) {
target = new fluid.mergingArray();
}
if (source instanceof fluid.mergingArray) {
target.push.apply(target, source);
} else if (source !== undefined) {
target.push(source);
}
return target;
};
fluid.defaults("fluid.prefs.builder", {
gradeNames: [
"fluid.prefs.primaryBuilder",
"fluid.prefs.auxBuilder",
"{that}.applyAssemblerGrades"
],
mergePolicy: {
preferences: "replace",
prefsPrioritized: {
noexpand: true,
func: fluid.deferredMergePolicy
}
},
invokers: {
applyAssemblerGrades: {
funcName: "fluid.get",
args: ["{that}.options.assemblerGrades", "{that}.options.buildType"]
}
},
buildType: "prefsEditor",
assemblerGrades: {
store: "fluid.prefs.assembler.store",
prefsEditor: "fluid.prefs.assembler.prefsEd",
enhancer: "fluid.prefs.assembler.uie"
},
requestedPrefs: {
expander: {
funcName: "fluid.keys",
args: ["{that}.options.prefsMerged"]
}
},
prefsMerged: {
expander: {
funcName: "fluid.prefs.builder.mergePrefs",
args: ["{that}", "{that}.options.prefsPrioritized"]
}
},
// TODO: Due to https://issues.fluidproject.org/browse/FLUID-6438
// Context aware supplied preferences must be targeted at `prefsPrioritized` instead of `preferences` and
// be supplied as {PrioritizedPrefs} object.
prefsPrioritized: {
expander: {
funcName: "fluid.prefs.builder.prioritizePrefs",
args: ["{that}.options.preferences"]
}
},
componentGrades: {
expander: {
func: "fluid.prefs.builder.constructGrades",
args: [
"{that}.options.auxSchema",
[
"enactors",
"panels",
"initialModel",
"templateLoader",
"messageLoader",
"terms",
"aliases_prefsEditor",
"aliases_enhancer"
]
]
}
},
distributeOptions: {
generatePanelContainers: {
source: "{that}.options.auxiliarySchema.generatePanelContainers",
target: "{that prefsEditorLoader prefsEditor}.options.generatePanelContainers"
}
}
});
fluid.defaults("fluid.prefs.assembler.store", {
gradeNames: ["fluid.component"],
components: {
store: {
type: "fluid.prefs.globalSettingsStore",
options: {
distributeOptions: {
"uie.store.context.checkUser": {
target: "{that fluid.prefs.store}.options.contextAwareness.strategy.checks.user",
record: {
contextValue: "{fluid.prefs.assembler.store}.options.storeType",
gradeNames: "{fluid.prefs.assembler.store}.options.storeType"
}
}
}
}
}
},
distributeOptions: {
"uie.store": {
source: "{that}.options.store",
target: "{that fluid.prefs.store}.options"
}
}
});
fluid.defaults("fluid.prefs.assembler.uie", {
gradeNames: ["fluid.prefs.assembler.store", "fluid.viewComponent"],
enhancerType: "fluid.pageEnhancer",
components: {
store: {
type: "fluid.prefs.globalSettingsStore",
options: {
distributeOptions: {
"uie.store.context.checkUser": {
target: "{that fluid.prefs.store}.options.contextAwareness.strategy.checks.user",
record: {
contextValue: "{fluid.prefs.assembler.store}.options.storeType",
gradeNames: "{fluid.prefs.assembler.store}.options.storeType"
}
}
}
}
},
enhancer: {
type: "fluid.component",
options: {
gradeNames: "{that}.options.enhancerType",
components: {
uiEnhancer: {
options: {
gradeNames: [
"{fluid.prefs.assembler.uie}.options.componentGrades.enactors",
"{fluid.prefs.assembler.uie}.options.componentGrades.aliases_enhancer"
],
defaultLocale: "{fluid.prefs.assembler.uie}.options.auxSchema.defaultLocale"
}
}
}
}
}
},
distributeOptions: {
"uie.enhancer": {
source: "{that}.options.enhancer",
target: "{that uiEnhancer}.options",
removeSource: true
},
"uie.enhancer.enhancerType": {
source: "{that}.options.enhancerType",
target: "{that > enhancer}.options.enhancerType"
}
}
});
fluid.defaults("fluid.prefs.assembler.prefsEd", {
gradeNames: ["fluid.prefs.assembler.uie"],
components: {
prefsEditorLoader: {
type: "fluid.viewComponent",
container: "{fluid.prefs.assembler.prefsEd}.container",
options: {
gradeNames: [
"{fluid.prefs.assembler.prefsEd}.options.componentGrades.terms",
"{fluid.prefs.assembler.prefsEd}.options.componentGrades.messages",
"{fluid.prefs.assembler.prefsEd}.options.componentGrades.initialModel",
"{fluid.prefs.assembler.prefsEd}.options.auxSchema.loaderGrades"
],
defaultLocale: "{fluid.prefs.assembler.prefsEd}.options.auxSchema.defaultLocale",
templateLoader: {
gradeNames: ["{fluid.prefs.assembler.prefsEd}.options.componentGrades.templateLoader"]
},
messageLoader: {
gradeNames: ["{fluid.prefs.assembler.prefsEd}.options.componentGrades.messageLoader"]
},
prefsEditor: {
gradeNames: [
"{fluid.prefs.assembler.prefsEd}.options.componentGrades.panels",
"{fluid.prefs.assembler.prefsEd}.options.componentGrades.aliases_prefsEditor",
"fluid.prefs.uiEnhancerRelay"
]
},
events: {
onReady: "{fluid.prefs.assembler.prefsEd}.events.onPrefsEditorReady"
}
}
}
},
events: {
onPrefsEditorReady: null,
onReady: {
events: {
onPrefsEditorReady: "onPrefsEditorReady",
onCreate: "onCreate"
},
args: ["{that}"]
}
},
distributeOptions: {
"prefsEdAssembler.prefsEditor": {
source: "{that}.options.prefsEditor",
target: "{that prefsEditor}.options"
},
"prefsEdAssembler.prefsEditorPrefs": {
source: "{that}.options.prefsMerged",
target: "{that prefsEditor}.options.preferences"
},
"prefsEdAssembler.prefsEditorLoader": {
source: "{that}.options.prefsEditorLoader",
target: "{that prefsEditorLoader}.options"
}
}
});
/**
* Constructs a grade with the supplied options.
*
* @param {String} name - the "short" name of the grade
* @param {String} namespace - the namespace to use for the grade name.
* @param {Object} options - any options required for defining the grade
* @return {String} - the full grade name for the newly constructed grade
*/
fluid.prefs.builder.constructGrade = function (name, namespace, options) {
var gradeNameTemplate = "%namespace.%name";
var gradeName = fluid.stringTemplate(gradeNameTemplate, {name: name, namespace: namespace});
fluid.defaults(gradeName, options);
return gradeName;
};
/**
* Will attempt to construct grades for each supplied category if appropriate configuration can be found for the
* category in the supplied `auxSchema`. Categories refer to the top level properties of the {AuxSchema} which will
* be used to source the options for defining the related grades.
*
* @param {AuxSchema} auxSchema - A processed {AuxiliarySchema}
* @param {String[]} gradeCategories - an array of grade categories to construct
* @return {Object} - the grade names of the constructed grades
*/
fluid.prefs.builder.constructGrades = function (auxSchema, gradeCategories) {
var constructedGrades = {};
fluid.each(gradeCategories, function (category) {
var gradeOpts = auxSchema[category];
if (fluid.get(gradeOpts, "gradeNames")) {
constructedGrades[category] = fluid.prefs.builder.constructGrade(category, auxSchema.namespace, gradeOpts);
}
});
return constructedGrades;
};
/**
* A prioritized set of preferences where the keys are the {String} name of the preference and value in the form
* {priority: "optional.priority.definition"}. If the value is set to `null` the preference will be removed.
*
* @typedef {Object} PrioritizedPrefs
*/
/**
* Converts a list of preferences into a prioritized set. The preferences are prioritized based on their position
* in the array of preferences.
*
* @param {String[]} preferences - The list of preferences
* @return {PrioritizedPrefs} - The prioritized preferences
*/
fluid.prefs.builder.prioritizePrefs = function (preferences) {
var prioritized = {};
fluid.each(preferences, function (preference, index) {
var record = {};
if (index) {
record.priority = "after:" + preferences[index - 1];
}
prioritized[preference] = record;
});
return prioritized;
};
/**
* Handles the deferred merging of {PrioritizedPrefs} options. Each item in the mergingArray will be merged on top
* of the previous value. If a preference is supplied with a `null` value, the preference will be removed.
*
* @param {fluid.prefs.builder} that - The `fluid.prefs.builder` component
* @param {Object[]} mergingArray - The array of deferred merge objects
* @return {Object} - The fully merged option
*/
fluid.prefs.builder.mergePrefs = function (that, mergingArray) {
var merged = {};
fluid.each(mergingArray, function (mergeRecord) {
var expanded = fluid.expandImmediate(mergeRecord, that);
fluid.each(expanded, function (prefConfig, preference) {
if (prefConfig === null) {
delete merged[preference];
delete expanded[preference];
}
});
$.extend(true, merged, expanded);
});
return merged;
};