Source: menu/MenuProxy.js


const URI = require('uri-js');
const collect = require('collect.js');
const Menu = require('./Menu.js').Menu;
const Subject = require('../mvc/Subject.js').Subject;
const Event = require('../mvc/Event.js').Event;

/**
 * This class is the model for the menu system and contains the current state of the for it.
 * It hold the root for the menu hierarchy.
 */
class MenuProxy extends Subject {
	constructor() {
		super();
		this.eventOk = `proxyOk`;
		this._root = new Menu(0, '/');
		this.init(this._root);
		this.populate();
	}

	populate() {
		this.fire(new Event(this.constructor.name, this.eventOk, this._root));
	}

	/**
	 * Set a parameter on menu items by parameter names.
	 * Parameters can come from the query part or from the uri path.
	 * If the last segment is a number it will match parameters of uid and
	 * if more than 2 segments it will also match second last segment with ${segment}_uid
	 * It is only the first parameter from the query part which is used.
	 * @param {string} url
	 * 	A given url
	 */
	setParameter(url) {
		let parsedUri = URI.parse(url);
		let pathSegments = parsedUri.path.split('/');
		if (pathSegments.length <= 1) {
			return;
		}

		let args = collect({});
		let lastSegment = pathSegments[pathSegments.length - 1];
		if (!isNaN(lastSegment)) {
			let uid = parseInt(lastSegment);
			args.put('uid', uid);
			if (pathSegments.length >= 2) {
				let proxy = pathSegments[pathSegments.length - 2];
				args.put('proxy', proxy);
				args.put(`${proxy.toLowerCase()}_uid`, uid);
			}
		}

		if (parsedUri.query !== undefined) {
			parsedUri.query.split('&').forEach(elem => {
				let parts = elem.split('=');
				let name = parts[0];
				let value = isNaN(parts[1]) ? parts[1] : parseInt(parts[1]);
				args.put(name, value);
			});
		}

		if (args.keys().isNotEmpty()) {
			this._root.setParameter(args);
		}
	}

	/**
	 * Select an menu item and ensure it is visible
	 * @param {string} url
	 * 	A given url
	 */
	select(url) {
		// Don't do anytime if uri does not match
		if (!this._root.hasMatch(url)) {
			return;
		}
		// reset everything
		this._root.reset();
		// select the node
		this._root.select(url);
		// ensure visible
		this._root.ensureVisible();
	}

	/**
	 * Initialize the menu hierarchy. Eg:
	 * @param {Menu} root
	 * 	The root of the menu hierarchy
	 * @example
	 * let child = root.push(new Menu(1, '/some/url'));
	 * let grandChild = child.push(new Menu(5, '/some/url'));
	 * grandchild.push(new Menu(15, '/some/url'));
	 */
	init(root) {
		throw Error("You must override the init method");
	}
}
exports.MenuProxy = MenuProxy;