2015-04-12 20:03:17 +00:00
|
|
|
// Utility functions used elsewhere in the codebase. Most JavaScript files on
|
|
|
|
// the site use some functions defined in this file.
|
|
|
|
|
2014-12-19 17:06:21 +00:00
|
|
|
import _ from 'lodash';
|
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Generate an `Event` object for triggering a custom event.
|
|
|
|
//
|
|
|
|
// - __name__ - Name of the custom event. This should be a String.
|
|
|
|
// - __detail__ - Event details. The event details are provided to the event
|
|
|
|
// handler.
|
2014-12-20 15:25:32 +00:00
|
|
|
function customEvent(name, detail) {
|
2014-12-19 15:24:45 +00:00
|
|
|
var evt = document.createEvent('Event');
|
|
|
|
evt.initEvent(name, true, true);
|
|
|
|
evt.detail = detail;
|
|
|
|
return evt;
|
|
|
|
}
|
2014-12-19 17:06:21 +00:00
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Add extra fields to a bounding box returned by `getBBox`. Specifically adds
|
|
|
|
// details about the box's axis points (used when positioning elements for
|
|
|
|
// display).
|
|
|
|
//
|
|
|
|
// - __box__ - Bounding box object to update. Attributes `ax`, `ax2`, and `ay`
|
|
|
|
// will be added if they are not already defined.
|
2014-12-20 15:25:32 +00:00
|
|
|
function normalizeBBox(box) {
|
2015-04-16 21:10:30 +00:00
|
|
|
return _.defaults(box, {
|
2014-12-19 17:06:21 +00:00
|
|
|
ax: box.x,
|
|
|
|
ax2: box.x2,
|
|
|
|
ay: box.cy
|
2015-04-16 21:10:30 +00:00
|
|
|
});
|
2014-12-19 17:06:21 +00:00
|
|
|
}
|
2014-12-19 17:11:44 +00:00
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Positions a collection of items with their axis points aligned along a
|
|
|
|
// horizontal line. This leads to the items being spaced horizontally and
|
|
|
|
// effectively centered vertically.
|
|
|
|
//
|
|
|
|
// - __items__ - Array of items to be positioned
|
|
|
|
// - __options.padding__ - Number of pixels to leave between items
|
2014-12-20 15:25:32 +00:00
|
|
|
function spaceHorizontally(items, options) {
|
2015-04-15 01:46:14 +00:00
|
|
|
var verticalCenter,
|
|
|
|
values;
|
2014-12-19 17:11:44 +00:00
|
|
|
|
|
|
|
options = _.defaults(options || {}, {
|
|
|
|
padding: 0
|
|
|
|
});
|
|
|
|
|
2015-04-15 01:46:14 +00:00
|
|
|
values = _.map(items, item => {
|
|
|
|
return {
|
|
|
|
box: normalizeBBox(item.getBBox()),
|
|
|
|
item
|
|
|
|
};
|
|
|
|
});
|
2014-12-19 17:11:44 +00:00
|
|
|
|
2015-04-15 01:46:14 +00:00
|
|
|
// Calculate where the axis points should be positioned vertically.
|
|
|
|
verticalCenter = _.reduce(values, (center, { box }) => {
|
|
|
|
return Math.max(center, box.ay);
|
|
|
|
}, 0);
|
2014-12-19 17:11:44 +00:00
|
|
|
|
2015-04-15 01:46:14 +00:00
|
|
|
// Position items with padding between them and aligned their axis points.
|
|
|
|
_.reduce(values, (offset, { item, box }) => {
|
|
|
|
item.transform(Snap.matrix()
|
|
|
|
.translate(offset, verticalCenter - box.ay));
|
2014-12-19 17:11:44 +00:00
|
|
|
|
|
|
|
return offset + options.padding + box.width;
|
|
|
|
}, 0);
|
|
|
|
}
|
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Positions a collection of items centered horizontally in a vertical stack.
|
|
|
|
//
|
|
|
|
// - __items__ - Array of items to be positioned
|
|
|
|
// - __options.padding__ - Number of pixels to leave between items
|
2014-12-20 15:25:32 +00:00
|
|
|
function spaceVertically(items, options) {
|
2015-04-15 01:46:14 +00:00
|
|
|
var horizontalCenter,
|
|
|
|
values;
|
2014-12-19 17:11:44 +00:00
|
|
|
|
|
|
|
options = _.defaults(options || {}, {
|
|
|
|
padding: 0
|
|
|
|
});
|
|
|
|
|
2015-04-15 01:46:14 +00:00
|
|
|
values = _.map(items, item => {
|
|
|
|
return {
|
|
|
|
box: item.getBBox(),
|
|
|
|
item
|
|
|
|
};
|
|
|
|
});
|
2014-12-19 17:11:44 +00:00
|
|
|
|
2015-04-15 01:46:14 +00:00
|
|
|
// Calculate where the center of each item should be positioned horizontally.
|
|
|
|
horizontalCenter = _.reduce(values, (center, { box }) => {
|
|
|
|
return Math.max(center, box.cx);
|
|
|
|
}, 0);
|
2014-12-19 17:11:44 +00:00
|
|
|
|
2015-04-15 01:46:14 +00:00
|
|
|
// Position items with padding between them and align their centers.
|
|
|
|
_.reduce(values, (offset, { item, box }) => {
|
|
|
|
item.transform(Snap.matrix()
|
|
|
|
.translate(horizontalCenter - box.cx, offset));
|
2014-12-19 17:11:44 +00:00
|
|
|
|
|
|
|
return offset + options.padding + box.height;
|
|
|
|
}, 0);
|
|
|
|
}
|
2014-12-20 15:18:00 +00:00
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Creates a Promise that will be resolved after a specified delay.
|
|
|
|
//
|
|
|
|
// - __delay__ - Time in milliseconds to wait before resolving promise.
|
2015-03-14 21:27:59 +00:00
|
|
|
function wait(delay) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
setTimeout(resolve, delay);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Creates a Promise that will be resolved after 0 milliseconds. This is used
|
|
|
|
// to create a short delay that allows the browser to address any pending tasks
|
|
|
|
// while the JavaScript VM is not active.
|
2015-03-14 21:27:59 +00:00
|
|
|
function tick() {
|
|
|
|
return wait(0);
|
|
|
|
}
|
|
|
|
|
2015-04-12 20:03:17 +00:00
|
|
|
// Re-throws an exception asynchronously. This is used to expose an exception
|
|
|
|
// that was created during a Promise operation to be handled by global error
|
|
|
|
// handlers (and to be displayed in the browser's debug console).
|
|
|
|
//
|
|
|
|
// - __error__ - Error/exception object to be re-thrown to the browser.
|
2015-03-14 21:27:59 +00:00
|
|
|
function exposeError(error) {
|
2015-09-02 10:41:21 +00:00
|
|
|
setTimeout(() => {
|
2015-03-14 21:27:59 +00:00
|
|
|
throw error;
|
2015-09-02 10:41:21 +00:00
|
|
|
}, 0);
|
2015-03-14 21:27:59 +00:00
|
|
|
}
|
|
|
|
|
2014-12-20 15:18:00 +00:00
|
|
|
export default {
|
|
|
|
customEvent,
|
|
|
|
normalizeBBox,
|
|
|
|
spaceHorizontally,
|
2015-03-14 21:27:59 +00:00
|
|
|
spaceVertically,
|
|
|
|
wait,
|
|
|
|
tick,
|
|
|
|
exposeError
|
2014-12-20 15:18:00 +00:00
|
|
|
};
|