infusion
Version:
Infusion is an application framework for developing flexible stuff with JavaScript
178 lines (164 loc) • 7.25 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
*/
/*
The contents of this file were adapted from ViewComponentSupport.js and ComponentGraph.js in fluid-authoring
See: https://github.com/fluid-project/fluid-authoring/blob/FLUID-4884/src/js/ViewComponentSupport.js
https://github.com/fluid-project/fluid-authoring/blob/FLUID-4884/src/js/ComponentGraph.js
*/
"use strict";
// This grade only exists to signal for FLUID-6584 that a view component by some means uses the "new workflow" of
// firing onDomBind before onCreate - the exact mechanism is left up to the component but will likely be a workflow function
fluid.defaults("fluid.newViewComponent", {
gradeNames: "fluid.viewComponent",
listeners: {
// Override this definition from fluid.viewComponent
"onCreate.onDomBind": null
}
});
/**
* A viewComponent which renders its own markup including its container, into a
* specified parent container.
*/
fluid.defaults("fluid.containerRenderingView", {
gradeNames: ["fluid.newViewComponent"],
members: {
container: "@expand:{that}.renderContainer()"
},
// The DOM element which this component should inject its markup into on startup
parentContainer: "{that}.options.container",
injectionType: "append",
invokers: {
renderMarkup: "fluid.identity({that}.options.markup.container)",
renderContainer: "fluid.containerRenderingView.renderContainer({that}, {that}.renderMarkup, {that}.addToParent)",
addToParent: {
funcName: "fluid.containerRenderingView.addToParent",
args: ["{that}.options.parentContainer", "{arguments}.0", "{that}.options.injectionType"]
}
},
workflows: {
global: {
// This workflow function is necessary since otherwise the natural evaluation order of lensed components
// during local workflow will evaluate them in reverse order
evaluateContainers: {
funcName: "fluid.renderer.evaluateContainers",
priority: "last",
waitIO: true
}
}
},
listeners: {
"onDestroy.clearInjectedMarkup": {
"this": "{that}.container",
method: "remove",
args: []
}
}
});
fluid.registerNamespace("fluid.renderer");
/** A component depending on template markup resources during startup. Shared between fluid.templateRenderingView
* and the new renderer
*/
fluid.defaults("fluid.templateResourceFetcher", {
gradeNames: "fluid.resourceLoader",
// Configure a map here of all templates which should be pre-fetched during fetchTemplates so that they are
// ready for renderMarkup
rendererTemplateResources: {
template: true
},
// Set to true to defeat template fetching during startup
skipTemplateFetch: false,
workflows: {
global: {
fetchTemplates: {
funcName: "fluid.renderer.fetchTemplates",
priority: "after:resolveResourceModel" // Resolve FLUID-6705 by allowing localised resources
}
}
}
});
fluid.renderer.fetchTemplates = function (shadows) {
shadows.forEach(function (shadow) {
var that = shadow.that;
if (fluid.componentHasGrade(that, "fluid.templateResourceFetcher")) {
var skipTemplateFetch = fluid.getForComponent(that, ["options", "skipTemplateFetch"]);
if (!skipTemplateFetch) {
var rendererTemplateResources = fluid.getForComponent(that, ["options", "rendererTemplateResources"]);
fluid.each(rendererTemplateResources, function (value, key) {
if (value) {
fluid.getForComponent(that, ["resources", key]);
}
});
}
}
});
};
/**
* Used to add an element to a parent container. Internally it can use either of jQuery's prepend or append methods.
*
* @param {jQuery|DOMElement|Selector} parentContainer - any jQueryable selector representing the parent element to
* inject the `elm` into.
* @param {DOMElement|jQuery} elm - a DOM element or jQuery element to be added to the parent.
* @param {String} method - (optional) a string representing the method to use to add the `elm` to the
* `parentContainer`. The method can be "append" (default), "prepend", or "html" (will
* replace the contents).
*/
fluid.containerRenderingView.addToParent = function (parentContainer, elm, method) {
if (!parentContainer) {
fluid.fail("fluid.containerRenderingView needs to have \"parentContainer\" or \"container\" option supplied");
}
method = method || "append";
$(parentContainer)[method](elm);
};
fluid.renderer.evaluateContainers = function (shadows) {
shadows.forEach(function (shadow) {
fluid.getForComponent(shadow.that, "container");
});
shadows.forEach(function (shadow) {
shadow.that.events.onDomBind.fire(shadow.that);
});
};
/**
* Renders the components markup and inserts it into the parent container based on the addToParent method
*
* @param {Component} that - the component
* @param {Function} renderMarkup - a function returning the components container markup to be inserted into the
* parentContainer element
* @param {Function} addToParent - a function that inserts the container into the DOM
* @return {DOMElement} - the container
*/
fluid.containerRenderingView.renderContainer = function (that, renderMarkup, addToParent) {
fluid.log("Rendering container for " + that.id);
var containerMarkup = renderMarkup();
var container = $(containerMarkup);
addToParent(container);
return container;
};
/**
* A fluid.containerRenderingView which fetches a template and renders it into the container.
*
* The template path must be supplied either via a top level `templateUrl` option or directly to the
* `resources.template` option. The path may optionally include "terms" to use as tokens which will be resolved
* from values specified in the `resourceOptions.terms` option --- see fluid.resourceLoader for further details.
*
* The template is fetched on creation and rendered into the container after it has been fetched.
*/
fluid.defaults("fluid.templateRenderingView", {
gradeNames: ["fluid.containerRenderingView", "fluid.templateResourceFetcher"],
invokers: {
renderMarkup: "fluid.identity({that}.resources.template.parsed)"
},
distributeOptions: {
"mapTemplateUrl": {
source: "{that}.options.templateUrl",
target: "{that}.options.resources.template.url"
}
}
});