diff --git a/src/js/core/fluidNewRenderer.js b/src/js/core/fluidNewRenderer.js
index ab2b44e..7cc2d5a 100644
--- a/src/js/core/fluidNewRenderer.js
+++ b/src/js/core/fluidNewRenderer.js
@@ -51,10 +51,13 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
includeTemplateRoot: false,
workflows: {
global: {
+ bindMarkup: {
+ funcName: "fluid.renderer.workflow.bindMarkup",
+ priority: "after:fetchTemplates",
+ waitIO: true
+ },
renderMarkup: {
- funcName: "fluid.renderer.renderMarkup",
- // TODO: Should really be able to specify that this depends on BOTH resolveResourceModel AND fetchTemplates
- // But then what becomes of our "positional" priority scheme!
+ funcName: "fluid.renderer.workflow.renderMarkup",
priority: "after:resolveResourceModel",
waitIO: true
}
@@ -154,6 +157,16 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
target.classList.add.apply(target.classList, source.classList);
};
+ /** Render the template for the supplied component, given a representation of the parent container. If the parent
+ * is a renderer DOM range, the new container will be appended to the end of the range. If the parent is a
+ * DocumentFragment for a fresh DOM section, the template will be appended as the first (and expected only) child.
+ * If the parent is a conventional (single) DOM node, the template root node will be fused with it.
+ * @param {fluid.newRendererComponent} that - The renderer component for which the template is to be rendered
+ * @param {DomRange} outerContainer - A jQuery-like wrapper for the parent DOM range. Either a return from
+ * a renderer DOM binder or a conventional wrapped node
+ * @return {Element} The template root node which was cloned from the component's template. In case 3 where the
+ * template was fused to an existing DOM node, this will not be the upcoming component's container.
+ */
fluid.renderer.renderTemplate = function (that, outerContainer) {
var $b = fluid.renderer.binderSymbol;
var templateContainer = that.resources.template.parsed.node.cloneNode(true);
@@ -210,10 +223,11 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
}
// We do this here otherwise there is nothing we could initialise "container" with - and also in this case
// we know there must be a parent rendererComponent and hence we are not in "split mode"
- innerContainer = fluid.renderer.renderTemplate(that, outerContainer);
+ innerContainer = $(fluid.renderer.renderTemplate(that, outerContainer));
}
}
- return $(innerContainer);
+ fluid.allocateSimpleId(innerContainer);
+ return innerContainer;
};
// Modifies supplied argument
@@ -320,7 +334,11 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
var innerContainer = dom.containerFragment || dom.locate("container");
// TODO: Resolve "elideParent" option to fuse inner and outer containers
// TODO: Extract some kind of base class out of "fluid.containerRenderingView" so that we could expose a path via override of renderMarkup and that.options.markup.container
- fluid.renderer.renderTemplate(that, innerContainer);
+ var templateContainer = fluid.renderer.renderTemplate(that, innerContainer);
+ if (dom.containerFragment) {
+ // Copy the upcoming id in so that self-based selectors will work
+ templateContainer.id = dom.locate("container")[0].id;
+ }
}
};
@@ -417,11 +435,14 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
}
},
events: {
+ bindMarkup: null,
render: null
},
- members: {
- },
listeners: {
+ "bindMarkup.bindMarkup": {
+ funcName: "fluid.renderer.bindMarkup",
+ args: ["{that}", "{arguments}.0"]
+ },
"render.render": {
funcName: "fluid.renderer.render",
args: ["{that}", "{arguments}.0"]
@@ -429,9 +450,9 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
}
});
- /** Main listener to the fluid.renderer's "render" event */
+ /** Main listener to the fluid.renderer's "bindMarkup" event */
- fluid.renderer.render = function (renderer, shadows) {
+ fluid.renderer.bindMarkup = function (renderer, shadows) {
// First phase of render workflow after resource resolution - first listener to renderer.events.render
console.log("About to render " + shadows.length + " components to renderer " + fluid.dumpComponentPath(renderer));
@@ -440,17 +461,14 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
// Evaluating the container of each component will force it to evaluate and render into it
fluid.getForComponent(that, "container");
fluid.getForComponent(that, "dom");
- that.events.onDomBind.fire(that);
});
+ };
+ fluid.renderer.render = function (renderer, shadows) {
+ // Final call for model-driven DOM modifications before we are attached
shadows.forEach(function (shadow) {
- // TODO: Will eventually be "Late materialised model relay" which is possible since transaction is not closed
- // until notifyInitModel
- // Note that leaf components will probably be abolished - this work will be done during onDomBind through materialisation
var that = shadow.that;
- if (fluid.componentHasGrade(that, "fluid.leafRendererComponent")) {
- fluid.getForComponent(that, "updateTemplateMarkup")(that.container[0], that.model);
- }
+ that.events.onDomBind.fire(that);
});
// Final pass to render all accumulate documentFragments into the real dom
shadows.forEach(function (shadow) {
@@ -461,12 +479,22 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
});
};
+ fluid.registerNamespace("fluid.renderer.workflow");
+
+ fluid.renderer.workflow.bindMarkup = function (shadows) {
+ fluid.renderer.workflow.toEvent(shadows, "bindMarkup");
+ };
+
+ fluid.renderer.workflow.render = function (shadows) {
+ fluid.renderer.workflow.toEvent(shadows, "render");
+ };
+
/** Main workflow function for fluid.newRendererComponent's global workflow.
* Assembles map of rendererComponent's to corresponding renderer, and then fires the "render"
* event on each renderer
*/
- fluid.renderer.renderMarkup = function (shadows) {
+ fluid.renderer.workflow.toEvent = function (shadows, eventKey) {
// Map of parent renderer's id to list of nested renderer components
var rendererToShadows = {};
shadows.forEach(function (shadow) {
@@ -479,11 +507,9 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
fluid.pushArray(rendererToShadows, parentRenderer.id, shadow);
}
});
- // var renderId = fluid.allocateGuid();
fluid.each(rendererToShadows, function (shadows, key) {
var renderer = fluid.globalInstantiator.idToShadow[key].that;
- fluid.getForComponent(renderer, "events.render");
- renderer.events.render.fire(shadows);
+ renderer.events[eventKey].fire(renderer, shadows);
});
};
diff --git a/src/js/core/fluidNewRendererComponents.js b/src/js/core/fluidNewRendererComponents.js
index 7db432a..e633869 100644
--- a/src/js/core/fluidNewRendererComponents.js
+++ b/src/js/core/fluidNewRendererComponents.js
@@ -12,76 +12,103 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
(function ($, fluid) {
"use strict";
- // Mix this in to any fluid.leafRendererComponent under a fluid.renderer.template in order to keep it live
- fluid.defaults("fluid.templateLeafRendererComponent", {
- modelListeners: {
- updateTemplateMarkup: {
- path: "",
- func: "{that}.updateTemplateMarkup",
- args: ["{that}.container.0", "{change}.value"]
+ fluid.defaults("fluid.polyMarkupComponent", {
+ gradeNames: "fluid.newRendererComponent",
+ listeners: {
+ "onDomBind.checkMarkup": {
+ listener: "fluid.polyMarkupComponent.check",
+ args: "{that}"
}
}
});
- fluid.defaults("fluid.leafRendererComponent", {
- gradeNames: "fluid.newRendererComponent",
- invokers: {
- updateTemplateMarkup: {
- // signature: container node, model contents
- funcName: "fluid.notImplemented"
+ fluid.polyMarkupComponent.check = function (that) {
+ var checks = fluid.getForComponent(that, ["options", "markupChecks"]);
+ var grade = fluid.find(checks, function (grade, value) {
+ if (value.selector !== undefined) {
+ var container = that.dom.container;
+ var fullSelector = "#" + container.id + " " + value.selector;
+ var nodes = that.dom.doQuery(fullSelector, "*");
+ if (nodes[0].tagName === value.tagName) {
+ return grade;
+ }
+ } else {
+ return grade;
}
- },
- parentMarkup: true
- });
+ });
+ if (grade !== undefined) {
+ var shadow = fluid.shadowForComponent(that);
+ // Cheapskate strategy - grade content will be wrong since we can't be bothered to hack into computeDynamicGrades and its malignly hidden "rec" structure
+ shadow.mergeBlocks.push(fluid.generateExpandBlock({
+ options: fluid.defaults(grade),
+ recordType: "polyMarkupBindings",
+ priority: fluid.mergeRecordTypes.distribution
+ }, that, {}));
+ shadow.mergeOptions.updateBlocks();
+ }
+ };
fluid.defaults("fluid.uiValue", {
- gradeNames: "fluid.leafRendererComponent",
+ gradeNames: "fluid.polyMarkupComponent",
model: {
// value: any
},
- invokers: {
- updateTemplateMarkup: {
- funcName: "fluid.uiValue.updateTemplateMarkup",
- // container node, new model
- args: ["{arguments}.0", "{that}.options.verbatim", "{arguments}.1"]
+ markupChecks: {
+ "fluid.uiInputValue": {
+ selector: "",
+ tagName: "input"
+ },
+ "fluid.uiTextValue": {}
+ }
+ });
+
+ fluid.defaults("fluid.uiTextValue", {
+ modelRelay: {
+ value: {
+ target: "dom.container.text",
+ source: "{that}.model.value"
}
},
resources: {
template: {
resourceText: ""
}
- },
- verbatim: false
+ }
});
- // See old fluidRenderer.js renderComponent
-
- fluid.registerNamespace("fluid.uiValue.template");
-
- fluid.uiValue.updateTemplateMarkup = function (node, verbatim, model) {
- if (typeof(model.value) !== "string") {
- fluid.fail("uiValue component is missing required model field \"value\": model contents are ", model);
- }
- var encodedValue = verbatim ? model.value : fluid.XMLEncode(model.value);
- var tagName = node.tagName;
- if (tagName === "input") {
- fluid.setImmediate(node, ["attrs", "value"], encodedValue);
- } else {
- node.children = [{text: encodedValue}];
+ fluid.defaults("fluid.uiInputValue", {
+ gradeNames: "fluid.polyMarkupComponent",
+ model: {
+ // value: any
+ },
+ modelRelay: {
+ value: {
+ target: "dom.container.value",
+ source: "{that}.model.value"
+ }
+ },
+ resources: {
+ template: {
+ resourceText: ""
+ }
}
- };
+ });
fluid.defaults("fluid.uiLink", {
- gradeNames: "fluid.leafRendererComponent",
+ gradeNames: "fluid.newRendererComponent",
+ parentMarkup: true,
model: {
// target: string
- // linktext: string (optional)
+ // linkText: string (optional)
},
- invokers: {
- updateTemplateMarkup: {
- funcName: "fluid.uiLink.updateTemplateMarkup",
- // container node, new model
- args: ["{arguments}.0", "{that}.options.verbatim", "{arguments}.1"]
+ modelRelay: {
+ linkTarget: {
+ target: "dom.container.attrs.href",
+ source: "{that}.model.target"
+ },
+ linkText: {
+ target: "dom.container.text",
+ source: "{that}.model.linkText"
}
},
resources: {
@@ -91,6 +118,10 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
}
});
+ /** Could be supported some day via some variety of AFFERENT POLYMORPHISM but the reusability value seems low -
+ * the user is far more likely to simply specify the relay rule onto the relevant attribute inline as above
+ */
+ /*
fluid.uiLink.attributeMap = { // From old fluidRenderer.js
a: "href",
link: "href",
@@ -119,5 +150,6 @@ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
}];
}
};
+ */
})(jQuery, fluid_3_0_0);