ui-router
Version:
State-based routing for Javascript
52 lines (41 loc) • 1.64 kB
text/typescript
/** @module state */ /** for typedoc */
import {isString} from "../common/predicates";
import {StateOrName} from "./interface";
import {State} from "./module";
export class StateMatcher {
constructor (private _states: { [key: string]: State }) { }
isRelative(stateName: string) {
stateName = stateName || "";
return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0;
}
find(stateOrName: StateOrName, base?: StateOrName): State {
if (!stateOrName && stateOrName !== "") return undefined;
let isStr = isString(stateOrName);
let name: string = isStr ? stateOrName : (<any>stateOrName).name;
if (this.isRelative(name)) name = this.resolvePath(name, base);
let state = this._states[name];
if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) {
return state;
}
return undefined;
}
resolvePath(name: string, base: StateOrName) {
if (!base) throw new Error(`No reference point given for path '${name}'`);
let baseState: State = this.find(base);
let splitName = name.split("."), i = 0, pathLength = splitName.length, current = baseState;
for (; i < pathLength; i++) {
if (splitName[i] === "" && i === 0) {
current = baseState;
continue;
}
if (splitName[i] === "^") {
if (!current.parent) throw new Error(`Path '${name}' not valid for state '${baseState.name}'`);
current = current.parent;
continue;
}
break;
}
let relName = splitName.slice(i).join(".");
return current.name + (current.name && relName ? "." : "") + relName;
}
}