Index: fluid-engage-core/framework/js/engageClientUtils.js =================================================================== --- fluid-engage-core/framework/js/engageClientUtils.js (revision 9131) +++ fluid-engage-core/framework/js/engageClientUtils.js (working copy) @@ -306,63 +306,60 @@ fluid.engage.renderUtils = fluid.engage.renderUtils || {}; fluid.engage.renderUtils.createRendererFunction = function (container, selectors, options) { - var that = fluid.merge("merge", {container: container, selectors: selectors}, options); - that.container = $(that.container); + options = options || {}; + container = $(container); + var rendererOptions = options.rendererOptions || {}; + var templates = null; - var renderFunc = function (tree, options) { - if (that.template) { - fluid.reRender(that.template, that.container, tree, options); + return function (tree) { + var cutpointFn = options.cutpointGenerator || "fluid.engage.renderUtils.selectorsToCutpoints"; + rendererOptions.cutpoints = rendererOptions.cutpoints || fluid.invokeGlobalFunction(cutpointFn, [selectors, options]); + + if (templates) { + fluid.reRender(templates, container, tree, rendererOptions); } else { - that.template = fluid.selfRender(that.container, tree, options); + templates = fluid.selfRender(container, tree, rendererOptions); } }; - - var render = function (tree) { - var mapFunc = "fluid.engage.renderUtils.selectorMapper"; - - that.selectorMap = that.selectorMap || fluid.invokeGlobalFunction(that.selectorMapper || mapFunc, [that.selectors, that]); - renderFunc(tree, fluid.merge("merge", {cutpoints: that.selectorMap}, that.rendererOptions)); - }; - - return function (tree) { - render(tree); - }; }; - fluid.engage.renderUtils.removeSelectors = function (selectors, ignore) { - $.each(ignore || [], function (index, selectorToIgnore) { - delete selectors[selectorToIgnore]; - }); + fluid.engage.renderUtils.removeSelectors = function (selectors, selectorsToIgnore) { + if (selectorsToIgnore) { + $.each(selectorsToIgnore, function (index, selectorToIgnore) { + delete selectors[selectorToIgnore]; + }); + } return selectors; }; - fluid.engage.renderUtils.markRepeated = function (selector, repeat) { - $.each(repeat || [], function (index, repeatingSelector) { - if (selector === repeatingSelector) { - selector = selector + ":"; - } - }); + fluid.engage.renderUtils.markRepeated = function (selector, repeatingSelectors) { + if (repeatingSelectors) { + $.each(repeatingSelectors, function (index, repeatingSelector) { + if (selector === repeatingSelector) { + selector = selector + ":"; + } + }); + } return selector; }; - fluid.engage.renderUtils.selectorMapper = function (selectors, options) { - var map = []; + fluid.engage.renderUtils.selectorsToCutpoints = function (selectors, options) { + var cutpoints = []; options = options || {}; + selectors = fluid.copy(selectors); // Make a copy before potentially destructively changing someone's selectors. if (options.selectorsToIgnore) { selectors = fluid.engage.renderUtils.removeSelectors(selectors, options.selectorsToIgnore); } - for (var key in selectors) { - if (selectors.hasOwnProperty(key)) { - map.push({ - id: fluid.engage.renderUtils.markRepeated(key, options.repeatingSelectors), - selector: selectors[key] - }); - } + for (var selector in selectors) { + cutpoints.push({ + id: fluid.engage.renderUtils.markRepeated(selector, options.repeatingSelectors), + selector: selectors[selector] + }); } - return map; + return cutpoints; }; /** A special "shallow copy" operation suitable for nondestructively Index: fluid-engage-core/tests/framework-tests/engageClientUtils/js/EngageClientUtilsTests.js =================================================================== --- fluid-engage-core/tests/framework-tests/engageClientUtils/js/EngageClientUtilsTests.js (revision 9131) +++ fluid-engage-core/tests/framework-tests/engageClientUtils/js/EngageClientUtilsTests.js (working copy) @@ -121,11 +121,35 @@ jqUnit.assertDeepEq("Proper uiBound with an attr decorator created, no value passed", {ID: id, decorators: [{attrs: attrObj}]}, fluid.engage.renderUtils.attrDecoratedUIBound(id, attrName, attrValue)); }); - tests.test("Renderer Utilities Test: selector mapper", function () { - jqUnit.assertDeepEq("Selector Map generation", [{id: "selector", selector: ".className"}], fluid.engage.renderUtils.selectorMapper({selector: ".className"})); - jqUnit.assertDeepEq("Selector Map generation, with repeating items", [{id: "selector1", selector: ".class1"}, {id: "selector2:", selector: ".class2"}], fluid.engage.renderUtils.selectorMapper({selector1: ".class1", selector2: ".class2"}, {repeatingSelectors: ["selector2"]})); - jqUnit.assertDeepEq("Selector Map generation, with ignored selectors", [{id: "selector1", selector: ".class1"}], fluid.engage.renderUtils.selectorMapper({selector1: ".class1", selector2: ".class2"}, {selectorsToIgnore: ["selector2"]})); - jqUnit.assertDeepEq("Selector Map generation, with repeating items and ignored selectors", [{id: "selector1:", selector: ".class1"}], fluid.engage.renderUtils.selectorMapper({selector1: ".class1", selector2: ".class2"}, {repeatingSelectors: ["selector1"], selectorsToIgnore: ["selector2"]})); + tests.test("Renderer Utilities Test: selectorsToCutpoints", function () { + // Single class name, simple cutpoints generation. + var selectors = {selector1: ".class1"}; + var expected = [{id: "selector1", selector: ".class1"}]; + jqUnit.assertDeepEq("Selector Map generation", expected, fluid.engage.renderUtils.selectorsToCutpoints(selectors)); + + selectors.selector2 = ".class2"; + + // Multiple selectors with one repeating. + expected = [{id: "selector1", selector: ".class1"}, {id: "selector2:", selector: ".class2"}]; + var actual = fluid.engage.renderUtils.selectorsToCutpoints(selectors, {repeatingSelectors: ["selector2"]}); + jqUnit.assertDeepEq("Selector Map generation, with repeating items", expected, actual); + + // Ignoring selectors. + expected = [{id: "selector1", selector: ".class1"}]; + actual = fluid.engage.renderUtils.selectorsToCutpoints(selectors, { + selectorsToIgnore: ["selector2"] + }); + jqUnit.assertDeepEq("Selector Map generation, with ignored selectors", expected, actual); + jqUnit.assertNotUndefined("selectorsToCutpoints should not eat other people's selectors", selectors.selector2); + + // Repeating and ignored selectors. + expected = [{id: "selector1:", selector: ".class1"}]; + actual = fluid.engage.renderUtils.selectorsToCutpoints(selectors, { + repeatingSelectors: ["selector1"], + selectorsToIgnore: ["selector2"] + }); + jqUnit.assertDeepEq("Selector Map generation, with repeating items and ignored selectors", expected, actual); + jqUnit.assertNotUndefined("selectorsToCutpoints should not eat other people's selectors", selectors.selector2); }); tests.test("Renderer Utilities Test: Renderer Init Helper", function () {