Skip to content

Commit 9d52f23

Browse files
committed
Updated navigation and model classes
1 parent 95bb660 commit 9d52f23

File tree

3 files changed

+50
-26
lines changed

3 files changed

+50
-26
lines changed

js/model.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ const REGEXP_NOTALIASED = /^()(\{\}|\[\])?(\w+)$/i;
1919
export default class Model {
2020
constructor(data) {
2121
// Get prototype
22-
const className = this.constructor.name;
23-
const proto = Model.models[className];
22+
const classKey = this.constructor.name;
23+
const proto = Model.models[classKey];
2424
if (!proto) {
25-
throw new Error(`Missing model definition for ${className}`);
25+
throw new Error(`Missing model definition for ${classKey}`);
2626
}
2727

2828
// Set prototype of instance prototype
@@ -36,33 +36,33 @@ export default class Model {
3636
if (typeof classConstructor !== 'function') {
3737
throw new Error('Called define without a class constructor');
3838
}
39-
const classKey = className || classConstructor.name;
39+
const classKey = classConstructor.name;
4040
if (Model.constructors[classKey]) {
41-
throw new Error(`Class already defined ${classKey}`);
41+
throw new Error(`Class already defined ${className || classKey}`);
4242
}
43-
const proto = Model.$newproto(classKey, classProps);
43+
const proto = Model.$newproto(classKey, classProps, className);
4444
if (!proto) {
45-
throw new Error(`No prototype for ${classKey}`);
45+
throw new Error(`No prototype for ${className || classKey}`);
4646
}
4747
Model.constructors[classKey] = classConstructor;
4848
Model.models[classKey] = proto;
4949
}
5050

51-
static $newproto(className, classProps) {
51+
static $newproto(classKey, classProps, className) {
5252
const proto = {};
5353

5454
// $className property
5555
Object.defineProperty(proto, '$className', {
56-
value: className,
56+
value: className || classKey,
5757
writable: false,
5858
enumerable: false,
5959
});
6060

6161
// $type property
62-
Model.types[className] = new Map();
62+
Model.types[classKey] = new Map();
6363
Object.defineProperty(proto, '$type', {
6464
get() {
65-
return Model.types[className];
65+
return Model.types[classKey];
6666
},
6767
enumerable: false,
6868
});
@@ -84,7 +84,7 @@ export default class Model {
8484
if (!type) {
8585
throw new Error(`Unable to parse declaration ${decl} for ${key}`);
8686
} else {
87-
Model.types[className].set(key, type);
87+
Model.types[classKey].set(key, type);
8888
}
8989
// Create getter and setter
9090
Object.defineProperty(proto, key, {

js/nav.js

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@ const EVENT_ROOT = 'mvc.nav';
99
const EVENT_CLICK = `${EVENT_ROOT}.click`;
1010
const CLASS_ACTIVE = 'active';
1111

12-
// ////////////////////////////////////////////////////////////////////////////
13-
// NAV
14-
12+
/**
13+
* Nav is the navgation view, which emits a mvc.nav.click event whenever
14+
* a navigational item is clicked which has an empty href in the navigation
15+
* item.
16+
* @class
17+
*/
1518
export default class Nav extends View {
1619
constructor(node) {
1720
super(node);
1821
this.$map = new Map();
1922

20-
// Set up nav items
21-
this.queryAll('.nav-item a.nav-link').forEach((elem) => {
22-
const navLink = new URL(elem.href).pathname.pathSplit().join('/');
23-
if (elem.parentNode.id) {
24-
this.$map.set(navLink, elem.parentNode.id);
25-
}
26-
elem.addEventListener('click', () => {
27-
this.dispatchEvent(EVENT_CLICK, this, elem.parentNode);
28-
});
23+
// Set up nav items - those with HREF # dispatch events
24+
this.queryAll('li a.nav-link').forEach((elem) => {
25+
this.$set(elem);
26+
});
27+
this.queryAll('li a.dropdown-item').forEach((elem) => {
28+
this.$set(elem);
2929
});
3030

3131
// Determine current path and set the active link
@@ -36,8 +36,32 @@ export default class Nav extends View {
3636
}
3737
}
3838

39+
/// @private
40+
$set(node) {
41+
const { href } = node;
42+
if (!href || href === '#') {
43+
node.addEventListener('click', (evt) => {
44+
evt.preventDefault();
45+
evt.cancelPropogation();
46+
this.dispatchEvent(EVENT_CLICK, this, node.parentNode);
47+
});
48+
} else {
49+
const navLink = new URL(href).pathname.pathSplit().join('/');
50+
if (node.parentNode.id) {
51+
this.$map.set(navLink, node.parentNode.id);
52+
}
53+
}
54+
}
55+
56+
/**
57+
* Set a class name on a specific navigational item and remove
58+
* that class from other navigational items. Usually this is used
59+
* to mark a specific dropdown item as active, for example.
60+
* @param {string} key - The id of the navigational item
61+
* @param {string} className - The class name which indicates
62+
*/
3963
setClassName(key, className) {
40-
this.queryAll('.nav-item a.nav-link').forEach((elem) => {
64+
this.queryAll('li a.nav-link').forEach((elem) => {
4165
if (elem.parentNode.id === key) {
4266
elem.classList.add(className);
4367
} else {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@djthorpe/js-framework",
3-
"version": "0.0.12",
3+
"version": "0.0.13",
44
"description": "Javascript UI Framework",
55
"main": "dist/js/index.js",
66
"scripts": {

0 commit comments

Comments
 (0)