[Edit] Avoid rebuilding toolbar on edit

Avoid rebuilding the toolbar in Edit mode whenever
any change occurs to avoid losing the binding to the
current selection state; needed for color picker to
work properly for WTD-881.
This commit is contained in:
Victor Woeltjen 2015-02-23 15:57:45 -08:00
parent f894233182
commit 6c7dfb878b
3 changed files with 75 additions and 25 deletions

View File

@ -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);
}
};
}

View File

@ -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([]);
}

View File

@ -3,10 +3,12 @@
<div class="form">
<span ng-repeat="section in structure.sections"
class="control-group coordinates"
ng-if="!section.hidden"
title="{{section.description}}">
<ng-form ng-repeat="item in section.items"
ng-class="{ 'input-labeled': item.name }"
ng-hide="item.hidden"
class="inline"
title="{{item.description}}"
name="mctFormInner">