diff --git a/platform/commonUI/edit/src/representers/EditToolbar.js b/platform/commonUI/edit/src/representers/EditToolbar.js index 4b2a925019..0fd916d561 100644 --- a/platform/commonUI/edit/src/representers/EditToolbar.js +++ b/platform/commonUI/edit/src/representers/EditToolbar.js @@ -20,9 +20,10 @@ define( * @param {Function} commit callback to invoke after changes * @constructor */ - function EditToolbar(structure, selection, commit) { + function EditToolbar(structure, commit) { var toolbarStructure = Object.create(structure || {}), toolbarState, + selection, properties = []; // Generate a new key for an item's property @@ -155,35 +156,79 @@ define( return section && section.items && section.items.length > 0; } - // Prepare a toolbar section based on current selection + // Prepare a toolbar section function convertSection(section) { var converted = Object.create(section || {}); converted.items = ((section || {}).items || []) - .map(convertItem) - .filter(isApplicable); + .map(convertItem); return converted; } + // Show/hide controls in this section per applicability + function refreshSectionApplicability(section) { + var count = 0; + // Show/hide each item + (section.items || []).forEach(function (item) { + item.hidden = !isApplicable(item); + count += item.hidden ? 0 : 1; + }); + // Hide this section if there are no applicable items + section.hidden = !count; + } + + // Show/hide controls if they are applicable + function refreshApplicability() { + toolbarStructure.sections.forEach(refreshSectionApplicability); + } + + // Refresh toolbar state to match selection + function refreshState() { + toolbarState = properties.map(initializeState); + } + toolbarStructure.sections = ((structure || {}).sections || []) .map(convertSection) .filter(nonEmpty); - toolbarState = properties.map(initializeState); + toolbarState = []; return { /** - * + * Set the current selection. Visisbility of sections + * and items in the toolbar will be updated to match this. + * @param {Array} s the new selection + */ + setSelection: function (s) { + selection = s; + refreshApplicability(); + refreshState(); + }, + /** + * Get the structure of the toolbar, as appropriate to + * pass to `mct-toolbar`. + * @returns the toolbar structure */ getStructure: function () { return toolbarStructure; }, + /** + * Get the current state of the toolbar, as appropriate + * to two-way bind to the state handled by `mct-toolbar`. + * @returns {Array} state of the toolbar + */ getState: function () { return toolbarState; }, - updateState: function (key, value) { - updateProperties(properties[key], value); + /** + * Update state within the current selection. + * @param {number} index the index of the corresponding + * element in the state array + * @param value the new value to convey to the selection + */ + updateState: function (index, value) { + updateProperties(properties[index], value); } }; } diff --git a/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js b/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js index 0c5cd772d4..5f2b740b72 100644 --- a/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js +++ b/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js @@ -15,9 +15,7 @@ define( * @constructor */ function EditToolbarRepresenter(scope, element, attrs) { - var definition, - unwatch, - toolbar, + var toolbar, toolbarObject = {}; // Mark changes as ready to persist @@ -29,17 +27,20 @@ define( // Handle changes to the current selection function updateSelection(selection) { - // Make sure selection is array-like - selection = Array.isArray(selection) ? - selection : - (selection ? [selection] : []); + // Only update if there is a toolbar to update + if (toolbar) { + // Make sure selection is array-like + selection = Array.isArray(selection) ? + selection : + (selection ? [selection] : []); - // Instantiate a new toolbar... - toolbar = new EditToolbar(definition, selection, commit); + // Update the toolbar's selection + toolbar.setSelection(selection); - // ...and expose its structure/state - toolbarObject.structure = toolbar.getStructure(); - toolbarObject.state = toolbar.getState(); + // ...and expose its structure/state + toolbarObject.structure = toolbar.getStructure(); + toolbarObject.state = toolbar.getState(); + } } // Get state (to watch it) @@ -50,7 +51,7 @@ define( // Update selection models to match changed toolbar state function updateState(state) { // Update underlying state based on toolbar changes - state.forEach(function (value, index) { + (state || []).forEach(function (value, index) { toolbar.updateState(index, value); }); // Commit the changes. @@ -58,9 +59,11 @@ define( } // Initialize toolbar (expose object to parent scope) - function initialize() { + function initialize(definition) { // If we have been asked to expose toolbar state... if (attrs.toolbar) { + // Initialize toolbar object + toolbar = new EditToolbar(definition, commit); // Expose toolbar state under that name scope.$parent[attrs.toolbar] = toolbarObject; } @@ -68,12 +71,12 @@ define( // Represent a domain object using this definition function represent(representation) { + // Get the newest toolbar definition from the view + var definition = (representation || {}).toolbar || {}; // Expose the toolbar object to the parent scope - initialize(); + initialize(definition); // Clear any existing selection scope.selection = []; - // Get the newest toolbar definition from the view - definition = (representation || {}).toolbar || {}; // Initialize toolbar to an empty selection updateSelection([]); } diff --git a/platform/forms/res/templates/toolbar.html b/platform/forms/res/templates/toolbar.html index 17602268d8..aa61bc3911 100644 --- a/platform/forms/res/templates/toolbar.html +++ b/platform/forms/res/templates/toolbar.html @@ -3,10 +3,12 @@