pressbooks aldine theme the theme used for the front page or default book
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

473 lines
17 KiB

/*
Copyright 2009 University of Toronto
Copyright 2010-2016 OCAD University
Copyright 2011 Lucendo Development Ltd.
Copyright 2012-2014 Raising the Floor - US
Copyright 2015 Raising the Floor - International
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/master/Infusion-LICENSE.txt
*/
var fluid_2_0_0 = fluid_2_0_0 || {};
(function ($, fluid) {
"use strict";
/*****************************
* Preferences Editor Loader *
*****************************/
/**
* An Preferences Editor top-level component that reflects the collaboration between prefsEditor, templateLoader and messageLoader.
* This component is the only Preferences Editor component that is intended to be called by the outside world.
*
* @param {Object} options
*/
fluid.defaults("fluid.prefs.prefsEditorLoader", {
gradeNames: ["fluid.prefs.settingsGetter", "fluid.prefs.initialModel", "fluid.viewComponent"],
defaultLocale: "en",
members: {
settings: {
expander: {
funcName: "fluid.prefs.prefsEditorLoader.getCompleteSettings",
args: ["{that}.initialModel", "{that}.getSettings"]
}
}
},
components: {
prefsEditor: {
priority: "last",
type: "fluid.prefs.prefsEditor",
createOnEvent: "onCreatePrefsEditorReady",
options: {
members: {
initialModel: "{prefsEditorLoader}.initialModel"
},
invokers: {
getSettings: "{prefsEditorLoader}.getSettings"
}
}
},
templateLoader: {
type: "fluid.resourceLoader",
options: {
events: {
onResourcesLoaded: "{prefsEditorLoader}.events.onPrefsEditorTemplatesLoaded"
}
}
},
messageLoader: {
type: "fluid.resourceLoader",
options: {
defaultLocale: "{prefsEditorLoader}.options.defaultLocale",
locale: "{prefsEditorLoader}.settings.locale",
resourceOptions: {
dataType: "json"
},
events: {
onResourcesLoaded: "{prefsEditorLoader}.events.onPrefsEditorMessagesLoaded"
}
}
}
},
events: {
onPrefsEditorTemplatesLoaded: null,
onPrefsEditorMessagesLoaded: null,
onCreatePrefsEditorReady: {
events: {
templateLoaded: "onPrefsEditorTemplatesLoaded",
prefsEditorMessagesLoaded: "onPrefsEditorMessagesLoaded"
}
}
},
distributeOptions: [{
source: "{that}.options.templateLoader",
removeSource: true,
target: "{that > templateLoader}.options"
}, {
source: "{that}.options.messageLoader",
removeSource: true,
target: "{that > messageLoader}.options"
}, {
source: "{that}.options.terms",
target: "{that > templateLoader}.options.terms"
}, {
source: "{that}.options.terms",
target: "{that > messageLoader}.options.terms"
}, {
source: "{that}.options.prefsEditor",
removeSource: true,
target: "{that > prefsEditor}.options"
}]
});
fluid.prefs.prefsEditorLoader.getCompleteSettings = function (initialModel, getSettingsFunc) {
var savedSettings = getSettingsFunc();
return $.extend(true, {}, initialModel, savedSettings);
};
// TODO: This mixin grade appears to be supplied manually by various test cases but no longer appears in
// the main configuration. We should remove the need for users to supply this - also the use of "defaultPanels" in fact
// refers to "starter panels"
fluid.defaults("fluid.prefs.transformDefaultPanelsOptions", {
// Do not supply "fluid.prefs.inline" here, since when this is used as a mixin for separatedPanel, it ends up displacing the
// more refined type of the prefsEditorLoader
gradeNames: ["fluid.viewComponent"],
distributeOptions: [{
source: "{that}.options.textSize",
removeSource: true,
target: "{that textSize}.options"
}, {
source: "{that}.options.lineSpace",
removeSource: true,
target: "{that lineSpace}.options"
}, {
source: "{that}.options.textFont",
removeSource: true,
target: "{that textFont}.options"
}, {
source: "{that}.options.contrast",
removeSource: true,
target: "{that contrast}.options"
}, {
source: "{that}.options.layoutControls",
removeSource: true,
target: "{that layoutControls}.options"
}, {
source: "{that}.options.linksControls",
removeSource: true,
target: "{that linksControls}.options"
}]
});
/**********************
* Preferences Editor *
**********************/
fluid.defaults("fluid.prefs.settingsGetter", {
gradeNames: ["fluid.component"],
members: {
getSettings: "{fluid.prefs.store}.get"
}
});
fluid.defaults("fluid.prefs.settingsSetter", {
gradeNames: ["fluid.component"],
invokers: {
setSettings: {
funcName: "fluid.prefs.settingsSetter.setSettings",
args: ["{arguments}.0", "{fluid.prefs.store}.set"]
}
}
});
fluid.prefs.settingsSetter.setSettings = function (model, set) {
var userSettings = fluid.copy(model);
set(userSettings);
};
fluid.defaults("fluid.prefs.uiEnhancerRelay", {
gradeNames: ["fluid.modelComponent"],
listeners: {
"onCreate.addListener": "{that}.addListener",
"onDestroy.removeListener": "{that}.removeListener"
},
events: {
updateEnhancerModel: "{fluid.prefs.prefsEditor}.events.onUpdateEnhancerModel"
},
invokers: {
addListener: {
funcName: "fluid.prefs.uiEnhancerRelay.addListener",
args: ["{that}.events.updateEnhancerModel", "{that}.updateEnhancerModel"]
},
removeListener: {
funcName: "fluid.prefs.uiEnhancerRelay.removeListener",
args: ["{that}.events.updateEnhancerModel", "{that}.updateEnhancerModel"]
},
updateEnhancerModel: {
funcName: "fluid.prefs.uiEnhancerRelay.updateEnhancerModel",
args: ["{uiEnhancer}", "{fluid.prefs.prefsEditor}.model.preferences"]
}
}
});
fluid.prefs.uiEnhancerRelay.addListener = function (modelChanged, listener) {
modelChanged.addListener(listener);
};
fluid.prefs.uiEnhancerRelay.removeListener = function (modelChanged, listener) {
modelChanged.removeListener(listener);
};
fluid.prefs.uiEnhancerRelay.updateEnhancerModel = function (uiEnhancer, newModel) {
uiEnhancer.updateModel(newModel);
};
/**
* A component that works in conjunction with the UI Enhancer component
* to allow users to set personal user interface preferences. The Preferences Editor component provides a user
* interface for setting and saving personal preferences, and the UI Enhancer component carries out the
* work of applying those preferences to the user interface.
*
* @param {Object} container
* @param {Object} options
*/
fluid.defaults("fluid.prefs.prefsEditor", {
gradeNames: ["fluid.prefs.settingsGetter", "fluid.prefs.settingsSetter", "fluid.prefs.initialModel", "fluid.viewComponent"],
invokers: {
/**
* Updates the change applier and fires modelChanged on subcomponent fluid.prefs.controls
*
* @param {Object} newModel
* @param {Object} source
*/
fetch: {
funcName: "fluid.prefs.prefsEditor.fetch",
args: ["{that}", "{arguments}.0"]
},
applyChanges: {
funcName: "fluid.prefs.prefsEditor.applyChanges",
args: ["{that}"]
},
save: {
funcName: "fluid.prefs.prefsEditor.save",
args: ["{that}"]
},
saveAndApply: {
funcName: "fluid.prefs.prefsEditor.saveAndApply",
args: ["{that}"]
},
reset: {
funcName: "fluid.prefs.prefsEditor.reset",
args: ["{that}"]
},
cancel: {
funcName: "fluid.prefs.prefsEditor.cancel",
args: ["{that}"]
}
},
selectors: {
cancel: ".flc-prefsEditor-cancel",
reset: ".flc-prefsEditor-reset",
save: ".flc-prefsEditor-save",
previewFrame : ".flc-prefsEditor-preview-frame"
},
events: {
onSave: null,
onCancel: null,
beforeReset: null,
afterReset: null,
onAutoSave: null,
modelChanged: null,
onPrefsEditorRefresh: null,
onUpdateEnhancerModel: null,
onPrefsEditorMarkupReady: null,
onReady: null
},
listeners: {
"onCreate.init": "fluid.prefs.prefsEditor.init",
"onAutoSave.save": "{that}.save"
},
modelListeners: {
"": [{
listener: "fluid.prefs.prefsEditor.handleAutoSave",
args: ["{that}"]
}, {
listener: "{that}.events.modelChanged.fire",
args: ["{change}.value"]
}]
},
resources: {
template: "{templateLoader}.resources.prefsEditor"
},
autoSave: false
});
/**
* Refresh PrefsEditor
*/
fluid.prefs.prefsEditor.applyChanges = function (that) {
that.events.onUpdateEnhancerModel.fire();
};
fluid.prefs.prefsEditor.fetch = function (that, eventName) {
var completeModel = that.getSettings();
completeModel = $.extend(true, {}, that.initialModel, completeModel);
// TODO: This may not be completely effective if the root model is smaller than
// the current one. Given our previous discoveries re "model shrinkage"
// (http://issues.fluidproject.org/browse/FLUID-5585 ), the proper thing to do here
// is to apply a DELETE to the root before putting in the new model. And this should
// be done within a transaction in order to avoid notifying the tree more than necessary.
// However, the transactional model of the changeApplier is going to change radically
// soon (http://wiki.fluidproject.org/display/fluid/New+New+Notes+on+the+ChangeApplier)
// and this implementation doesn't seem to be causing a problem at present so we had
// just better leave it the way it is for now.
that.applier.change("", completeModel);
if (eventName) {
that.events[eventName].fire(that);
}
that.events.onPrefsEditorRefresh.fire();
that.applyChanges();
};
/**
* Sends the prefsEditor.model to the store and fires onSave
* @param that: A fluid.prefs.prefsEditor instance
* @return the saved model
*/
fluid.prefs.prefsEditor.save = function (that) {
if (!that.model) { // Don't save a reset model
return;
}
var modelToSave = fluid.copy(that.model),
initialModel = that.initialModel,
stats = {changes: 0, unchanged: 0, changeMap: {}},
changedPrefs = {};
// To address https://issues.fluidproject.org/browse/FLUID-4686
fluid.model.diff(modelToSave.preferences, fluid.get(initialModel, ["preferences"]), stats);
if (stats.changes === 0) {
delete modelToSave.preferences;
} else {
fluid.each(stats.changeMap, function (state, pref) {
fluid.set(changedPrefs, pref, modelToSave.preferences[pref]);
});
modelToSave.preferences = changedPrefs;
}
that.events.onSave.fire(modelToSave);
that.setSettings(modelToSave);
return modelToSave;
};
fluid.prefs.prefsEditor.saveAndApply = function (that) {
var prevSettings = that.getSettings(),
changedSelections = that.save();
// Only when preferences are changed, re-render panels and trigger enactors to apply changes
if (!fluid.model.diff(fluid.get(changedSelections, "preferences"), fluid.get(prevSettings, "preferences"))) {
that.events.onPrefsEditorRefresh.fire();
that.applyChanges();
}
};
/**
* Resets the selections to the integrator's defaults and fires afterReset
*/
fluid.prefs.prefsEditor.reset = function (that) {
that.events.beforeReset.fire(that);
that.applier.fireChangeRequest({path: "", type: "DELETE"});
that.applier.change("", fluid.copy(that.initialModel));
that.events.onPrefsEditorRefresh.fire();
that.events.afterReset.fire(that);
};
/**
* Resets the selections to the last saved selections and fires onCancel
*/
fluid.prefs.prefsEditor.cancel = function (that) {
that.events.onCancel.fire();
that.fetch();
};
// called once markup is applied to the document containing tab component roots
fluid.prefs.prefsEditor.finishInit = function (that) {
var bindHandlers = function (that) {
var saveButton = that.locate("save");
if (saveButton.length > 0) {
saveButton.click(that.saveAndApply);
var form = fluid.findForm(saveButton);
$(form).submit(function () {
that.saveAndApply();
});
}
that.locate("reset").click(that.reset);
that.locate("cancel").click(that.cancel);
};
that.container.append(that.options.resources.template.resourceText);
bindHandlers(that);
that.fetch("onPrefsEditorMarkupReady");
that.events.onReady.fire(that);
};
fluid.prefs.prefsEditor.handleAutoSave = function (that) {
if (that.options.autoSave) {
that.events.onAutoSave.fire();
}
};
fluid.prefs.prefsEditor.init = function (that) {
// This setTimeout is to ensure that fetching of resources is asynchronous,
// and so that component construction does not run ahead of subcomponents for SeparatedPanel
// (FLUID-4453 - this may be a replacement for a branch removed for a FLUID-2248 fix)
setTimeout(function () {
if (!fluid.isDestroyed(that)) {
fluid.prefs.prefsEditor.finishInit(that);
}
}, 1);
};
/******************************
* Preferences Editor Preview *
******************************/
fluid.defaults("fluid.prefs.preview", {
gradeNames: ["fluid.viewComponent"],
components: {
enhancer: {
type: "fluid.uiEnhancer",
container: "{preview}.enhancerContainer",
createOnEvent: "onReady"
},
templateLoader: "{templateLoader}"
},
invokers: {
updateModel: {
funcName: "fluid.prefs.preview.updateModel",
args: [
"{preview}",
"{prefsEditor}.model.preferences"
]
}
},
events: {
onReady: null
},
listeners: {
"onCreate.startLoadingContainer": "fluid.prefs.preview.startLoadingContainer",
"{prefsEditor}.events.modelChanged": "{that}.updateModel",
"onReady.updateModel": "{that}.updateModel"
},
templateUrl: "%prefix/PrefsEditorPreview.html"
});
fluid.prefs.preview.updateModel = function (that, preferences) {
/**
* SetTimeout is temp fix for http://issues.fluidproject.org/browse/FLUID-2248
*/
setTimeout(function () {
if (that.enhancer) {
that.enhancer.updateModel(preferences);
}
}, 0);
};
fluid.prefs.preview.startLoadingContainer = function (that) {
var templateUrl = that.templateLoader.transformURL(that.options.templateUrl);
that.container.on("load", function () {
that.enhancerContainer = $("body", that.container.contents());
that.events.onReady.fire();
});
that.container.attr("src", templateUrl);
};
})(jQuery, fluid_2_0_0);