Initial work to reorder zoom fields.

This commit is contained in:
orangemug 2017-11-08 13:45:34 +00:00
parent 3aae2e976f
commit 40235fe473
3 changed files with 98 additions and 4 deletions

View file

@ -17,6 +17,9 @@ import MdInsertChart from 'react-icons/lib/md/insert-chart'
import PropTypes from 'prop-types'
import capitalize from 'lodash.capitalize'
import docUid from '../../libs/document-uid'
import sortNumerically from '../../libs/sort-numerically'
function isZoomField(value) {
return typeof value === 'object' && value.stops && typeof value.property === 'undefined'
}
@ -43,6 +46,70 @@ export default class FunctionSpecProperty extends React.Component {
]),
}
constructor() {
super()
this.state = {
refs: {}
}
}
/**
* We cache a reference for each stop by its index.
*
* When the stops are reordered the references are also updated (see this.orderStops) this allows React to use the same key for the element and keep keyboard focus.
*/
setStopRefs(props) {
// This is initialsed below only if required to improved performance.
let newRefs;
if(props.value && props.value.stops) {
props.value.stops.forEach((val, idx) => {
if(!this.state.refs.hasOwnProperty(idx)) {
if(!newRefs) {
newRefs = {...this.state.refs};
}
newRefs[idx] = docUid("stop-");
}
})
}
if(newRefs) {
this.setState({
refs: newRefs
})
}
}
componentWillReceiveProps(nextProps) {
this.setStopRefs(nextProps);
}
// Order the stops altering the refs to reflect their new position.
orderStopsByZoom(stops) {
const mappedWithRef = stops
.map((stop, idx) => {
return {
ref: this.state.refs[idx],
data: stop
}
})
// Sort by zoom
.sort((a, b) => sortNumerically(a.data[0], b.data[0]));
// Fetch the new position of the stops
const newRefs = {};
mappedWithRef
.forEach((stop, idx) =>{
newRefs[idx] = stop.ref;
})
this.setState({
refs: newRefs
});
return mappedWithRef.map((item) => item.data);
}
addStop() {
const stops = this.props.value.stops.slice(0)
const lastStop = stops[stops.length - 1]
@ -122,11 +189,14 @@ export default class FunctionSpecProperty extends React.Component {
}
changeStop(changeIdx, stopData, value) {
const stops = this.props.value.stops.slice(0)
stops[changeIdx] = [stopData, value]
const stops = this.props.value.stops.slice(0);
stops[changeIdx] = [stopData, value];
const orderedStops = this.orderStopsByZoom(stops);
const changedValue = {
...this.props.value,
stops: stops,
stops: orderedStops
}
this.props.onChange(this.props.fieldName, changedValue)
}
@ -241,11 +311,12 @@ export default class FunctionSpecProperty extends React.Component {
renderZoomProperty() {
const zoomFields = this.props.value.stops.map((stop, idx) => {
const zoomLevel = stop[0]
const key = this.state.refs[idx];
const value = stop[1]
const deleteStopBtn= <DeleteStopButton onClick={this.deleteStop.bind(this, idx)} />
return <InputBlock
key={zoomLevel}
key={key}
doc={this.props.fieldSpec.doc}
label={labelFromFieldName(this.props.fieldName)}
action={deleteStopBtn}

9
src/libs/document-uid.js Normal file
View file

@ -0,0 +1,9 @@
/**
* A unique id for the current document.
*/
let REF = 0;
export default function(prefix="") {
REF++;
return prefix+REF;
}

View file

@ -0,0 +1,14 @@
export default function(a, b) {
a = parseFloat(a, 10);
b = parseFloat(b, 10);
if(a < b) {
return -1
}
else if(a > b) {
return 1
}
else {
return 0;
}
}