Skip to content

Commit

Permalink
feat(model): Support for children of items.
Browse files Browse the repository at this point in the history
  • Loading branch information
QuentinRoy committed Jul 20, 2017
1 parent 205247b commit 2895f30
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 20 deletions.
5 changes: 4 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
<script src="./Rx.min.js"></script>
<script src="../marking-menu.js"></script>
<script>
var items = Array.from({ length: 8 }).map((_, i) => `item ${i}`);
var items = Array.from({ length: 8 })
.map((_, i) => ({ name: `item ${i}` }));
items[2].children = Array.from({ length: 4 })
.map((_, i) => ({ name: `item 2${i}` }))
var main = document.getElementById('main');
var mm = MarkingMenu(items, main);
mm.subscribe(selection => { console.log('selection', selection) })
Expand Down
54 changes: 35 additions & 19 deletions src/model.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,52 @@
import { deltaAngle } from './utils';

const getAngleRange = items => (items.length > 4 ? 45 : 90);

// Create the model item from a list of items.
const createModelItems = (items, idPrefix = undefined) => {
// Calculate the angle range for each items.
const angleRange = getAngleRange(items);
// Create the frozen list of model items.
return Object.freeze(
items.map((item, i) => {
// Standard item id.
const stdId = idPrefix ? [idPrefix, i].join('-') : i.toString();
// Create the item without the children property.
const base = {
name: typeof item === 'string' ? item : item.name,
angle: i * angleRange,
id: item.id == null ? stdId : item.id
};
// Add the children property if the item has children.
if (item.children) {
base.children = createModelItems(item.children, stdId);
}
return Object.freeze(base);
})
);
};

/**
* Create the marking menu model.
*
* @param {List<String>} itemList the list of item names.
* @param {List<String|{name,children}>} itemList the list of item names.
* @return {{items, get, getNearest}}
*/
const createModel = itemNames => {
const itemGap = itemNames.length > 4 ? 45 : 90;

const itemList = itemNames.map((itemName, i) =>
Object.freeze({
name: itemName,
angle: i * itemGap,
id: i
})
const createModel = itemList => {
const modelItemList = createModelItems(itemList);
const modelItems = Object.freeze(
Object.assign(...modelItemList.map(it => ({ [it.id]: it })))
);

const items = Object.freeze(
Object.assign(...itemList.map(it => ({ [it.id]: it })))
);

return {
items,
items: modelItems,
get(itemId) {
return items[itemId];
return modelItems[itemId];
},
getByName(itemName) {
return itemList.find(it => it.name === itemName);
return modelItemList.find(it => it.name === itemName);
},
getNearest(angle) {
return itemList.reduce((a, b) => {
return modelItemList.reduce((a, b) => {
const deltaA = Math.abs(deltaAngle(a.angle, angle));
const deltaB = Math.abs(deltaAngle(b.angle, angle));
return deltaA > deltaB ? b : a;
Expand Down

0 comments on commit 2895f30

Please sign in to comment.