alchemymvc 1.3.7 → 1.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,156 @@
1
+ /**
2
+ * The Breadcrumb class
3
+ *
4
+ * @constructor
5
+ *
6
+ * @author Jelle De Loecker <jelle@elevenways.be>
7
+ * @since 1.3.8
8
+ * @version 1.3.8
9
+ *
10
+ * @param {String} input
11
+ */
12
+ const Breadcrumb = Function.inherits('Alchemy.Base', function Breadcrumb(input) {
13
+
14
+ this.trails = [];
15
+
16
+ if (input) {
17
+ this.addTrail(input);
18
+ }
19
+ });
20
+
21
+ /**
22
+ * Get the number of trails
23
+ *
24
+ * @author Jelle De Loecker <jelle@elevenways.be>
25
+ * @since 1.3.8
26
+ * @version 1.3.8
27
+ *
28
+ * @return {Number}
29
+ */
30
+ Breadcrumb.setProperty(function length() {
31
+ return this.trails.length;
32
+ });
33
+
34
+ /**
35
+ * Add a breadcrumb trail
36
+ *
37
+ * @author Jelle De Loecker <jelle@elevenways.be>
38
+ * @since 1.3.8
39
+ * @version 1.3.8
40
+ *
41
+ * @param {String} input
42
+ */
43
+ Breadcrumb.setMethod(function addTrail(input) {
44
+
45
+ let trails;
46
+
47
+ if (!input) {
48
+ input = '';
49
+ } else if (typeof input == 'object') {
50
+ if (input instanceof Breadcrumb) {
51
+ trails = input.trails;
52
+ } else if (input.nodeType === 1) {
53
+ // Simple way to see if it's an HTMLElement
54
+
55
+ let element = input;
56
+ input = '';
57
+
58
+ let crumb = element.getAttribute('data-breadcrumb');
59
+
60
+ if (crumb) {
61
+ input = crumb;
62
+ }
63
+
64
+ crumb = element.getAttribute('data-breadcrumbs');
65
+
66
+ if (crumb) {
67
+ input += ' ' + crumb;
68
+ }
69
+ }
70
+ }
71
+
72
+ if (!trails) {
73
+ // Split the string why whitespaces
74
+ trails = input.trim().split(/\s+|\|+/);
75
+ }
76
+
77
+ if (trails?.length) {
78
+ for (let trail of trails) {
79
+
80
+ if (!trail) {
81
+ continue;
82
+ }
83
+
84
+ // The trail has to end with a dot
85
+ if (!trail.endsWith('.')) {
86
+ trail += '.';
87
+ }
88
+
89
+ this.trails.push(trail);
90
+ }
91
+ }
92
+ });
93
+
94
+ /**
95
+ * Do these 2 breadcrumbs match loosely?
96
+ *
97
+ * @author Jelle De Loecker <jelle@elevenways.be>
98
+ * @since 1.3.8
99
+ * @version 1.3.8
100
+ *
101
+ * @param {Alchemy.Breadcrumb} other
102
+ */
103
+ Breadcrumb.setMethod(function matches(other) {
104
+ return this.matchLevel(other) > 0;
105
+ });
106
+
107
+ /**
108
+ * What leven of match is there between these 2 breadcrumbs?
109
+ *
110
+ * @author Jelle De Loecker <jelle@elevenways.be>
111
+ * @since 1.3.8
112
+ * @version 1.3.8
113
+ *
114
+ * @param {Alchemy.Breadcrumb} other
115
+ *
116
+ * @return {Number} 1 for a strict match, 2 for a loose match
117
+ */
118
+ Breadcrumb.setMethod(function matchLevel(other) {
119
+
120
+ if (!other || !this.trails.length) {
121
+ return 0;
122
+ }
123
+
124
+ if (!(other instanceof Breadcrumb)) {
125
+ other = new Breadcrumb(other);
126
+ }
127
+
128
+ let their_trail,
129
+ our_trail;
130
+
131
+ for (our_trail of this.trails) {
132
+ for (their_trail of other.trails) {
133
+ // Strict matches are always true
134
+ if (our_trail == their_trail) {
135
+ return 1;
136
+ }
137
+
138
+ if (our_trail.startsWith(their_trail)) {
139
+ return 2;
140
+ }
141
+ }
142
+ }
143
+
144
+ return 0;
145
+ });
146
+
147
+ /**
148
+ * Turn it into a string
149
+ *
150
+ * @author Jelle De Loecker <jelle@elevenways.be>
151
+ * @since 1.3.8
152
+ * @version 1.3.8
153
+ */
154
+ Breadcrumb.setMethod(function toString() {
155
+ return this.trails.join(' ');
156
+ });
@@ -147,14 +147,24 @@ Router.setMethod(function applyDirective(element, name, options) {
147
147
  }
148
148
  }
149
149
 
150
- if (config.breadcrumb) {
151
- let link_breadcrumb = this.getTrail(name, params);
150
+ let breadcrumb = config.breadcrumb;
151
+
152
+ if (options.breadcrumb) {
153
+ if (!breadcrumb) {
154
+ breadcrumb = options.breadcrumb;
155
+ } else {
156
+ breadcrumb += ' ' + options.breadcrumb;
157
+ }
158
+ }
159
+
160
+ if (config.breadcrumb || options.breadcrumb) {
161
+ let link_breadcrumb = this.getTrail(name, {...params}, options);
152
162
  element.setAttribute('data-breadcrumb', link_breadcrumb);
153
163
 
154
164
  if (this.renderer && link_breadcrumb) {
155
- let page_breadcrumb = this.renderer.internal('breadcrumb');
165
+ let page_breadcrumb = new Classes.Alchemy.Breadcrumb(this.renderer.internal('breadcrumb'));
156
166
 
157
- if (page_breadcrumb && page_breadcrumb.startsWith(link_breadcrumb)) {
167
+ if (page_breadcrumb.matches(link_breadcrumb)) {
158
168
 
159
169
  if (element.parentElement) {
160
170
  // @TODO: We need to make sure the options (classnames & such)
@@ -326,7 +336,7 @@ Router.setMethod(function routeConfig(name, socket_route) {
326
336
  *
327
337
  * @author Jelle De Loecker <jelle@elevenways.be>
328
338
  * @since 0.2.0
329
- * @version 1.3.7
339
+ * @version 1.3.9
330
340
  *
331
341
  * @param {String} name
332
342
  * @param {Object} parameters
@@ -335,8 +345,7 @@ Router.setMethod(function routeConfig(name, socket_route) {
335
345
  */
336
346
  Router.setMethod(function routeUrl(name, parameters, options) {
337
347
 
338
- var parameters,
339
- base_url,
348
+ var base_url,
340
349
  locales,
341
350
  config,
342
351
  url,
@@ -360,6 +369,10 @@ Router.setMethod(function routeUrl(name, parameters, options) {
360
369
  locales = [];
361
370
  }
362
371
 
372
+ if (parameters) {
373
+ parameters = {...parameters};
374
+ }
375
+
363
376
  let chosen_prefix;
364
377
 
365
378
  if (config != null) {
@@ -492,28 +505,72 @@ Router.setMethod(function routeUrl(name, parameters, options) {
492
505
  *
493
506
  * @author Jelle De Loecker <jelle@develry.be>
494
507
  * @since 0.3.0
495
- * @version 0.3.0
508
+ * @version 1.3.8
496
509
  *
497
510
  * @param {String} name
498
511
  * @param {Object} parameters
512
+ * @param {Object} options
499
513
  *
500
- * @return {String}
514
+ * @return {Alchemy.Breadcrumb}
501
515
  */
502
- Router.setMethod(function getTrail(name, parameters) {
516
+ Router.setMethod(function getTrail(name, parameters, options) {
503
517
 
504
- var breadcrumb,
518
+ let can_have_assignments,
519
+ trails = [],
505
520
  config;
521
+
522
+ if (options?.breadcrumb) {
523
+ can_have_assignments = true;
524
+ trails.push(options.breadcrumb);
525
+ }
506
526
 
507
527
  config = this.routeConfig(name);
508
528
 
509
- if (!config || !config.breadcrumb) {
529
+ if (!trails.length && (!config || !config.breadcrumb)) {
510
530
  return;
511
531
  }
512
532
 
513
- breadcrumb = config.breadcrumb;
533
+ let breadcrumb = new Classes.Alchemy.Breadcrumb();
534
+
535
+ if (config?.breadcrumb) {
536
+ trails.push(config.breadcrumb);
537
+ }
514
538
 
515
- if (config.has_breadcrumb_assignments) {
516
- breadcrumb = Blast.Bound.String.assign(breadcrumb, parameters).toLowerCase();
539
+ if (!can_have_assignments) {
540
+ can_have_assignments = config?.has_breadcrumb_assignments;
541
+ }
542
+
543
+ if (can_have_assignments) {
544
+ let key;
545
+ parameters = {...parameters};
546
+
547
+ for (key in parameters) {
548
+ if (key[0] == key[0].toUpperCase()) {
549
+ let value = parameters[key];
550
+
551
+ if (value && typeof value == 'object') {
552
+ let subkey;
553
+
554
+ let context = value?.$main || value;
555
+
556
+ for (subkey in context) {
557
+ if (parameters[subkey] == null) {
558
+ parameters[subkey] = context[subkey];
559
+ }
560
+ }
561
+ }
562
+ }
563
+ }
564
+ }
565
+
566
+ let trail;
567
+
568
+ for (trail of trails) {
569
+ if (can_have_assignments) {
570
+ trail = Blast.Bound.String.assign(trail, parameters).toLowerCase();
571
+ }
572
+
573
+ breadcrumb.addTrail(trail);
517
574
  }
518
575
 
519
576
  return breadcrumb;
@@ -527,9 +584,6 @@ Router.setMethod(function getTrail(name, parameters) {
527
584
  * @version 0.3.0
528
585
  */
529
586
  Router.setMethod(function printBreadcrumb() {
530
-
531
- var that = this;
532
-
533
587
  this.view.print_partial('breadcrumb/wrapper');
534
588
  });
535
589
 
@@ -693,7 +747,7 @@ Router.setMethod(function getRouteVariables() {
693
747
  let params,
694
748
  route,
695
749
  url;
696
-
750
+
697
751
  if (this.view_render?.variables?.__route) {
698
752
  route = this.view_render.variables.__route;
699
753
  params = this.view_render.variables.__urlparams;
@@ -739,7 +793,7 @@ Router.setMethod(function updateLanguageSwitcher(element, variables) {
739
793
  *
740
794
  * @author Jelle De Loecker <jelle@elevenways.be>
741
795
  * @since 1.2.5
742
- * @version 1.3.7
796
+ * @version 1.3.8
743
797
  *
744
798
  * @param {String} prefix The prefix to use
745
799
  * @param {Object} variables
@@ -761,6 +815,15 @@ Router.setMethod(function translateCurrentRoute(prefix, variables) {
761
815
  return;
762
816
  }
763
817
 
818
+ // Don't just translate the last rendered route, make sure it's the current one
819
+ if (info.url && Blast.isBrowser) {
820
+ let url = RURL.parse(info.url);
821
+
822
+ if (url && !url.matchesPath(window.location)) {
823
+ return;
824
+ }
825
+ }
826
+
764
827
  let config = this.routeConfig(info.route);
765
828
 
766
829
  if (!config) {
@@ -597,9 +597,9 @@ Model.setMethod(function getAliasModel(alias) {
597
597
  /**
598
598
  * Query the database
599
599
  *
600
- * @author Jelle De Loecker <jelle@develry.be>
600
+ * @author Jelle De Loecker <jelle@elevenways.be>
601
601
  * @since 0.0.1
602
- * @version 1.3.4
602
+ * @version 1.3.8
603
603
  *
604
604
  * @param {String} type The type of find (first, all)
605
605
  * @param {Criteria} criteria The criteria object
@@ -660,7 +660,7 @@ Model.setMethod(function find(type, criteria, callback) {
660
660
  }
661
661
 
662
662
  if (!criteria.options.locale && this.conduit) {
663
- criteria.setOption('locale', this.conduit.prefix);
663
+ criteria.setOption('locale', this.conduit.active_prefix);
664
664
  }
665
665
 
666
666
  let that = this,
@@ -519,6 +519,59 @@ Alchemy.setMethod(function routeConfig(name) {
519
519
 
520
520
  const markLinkElement = Alchemy.prototype.markLinkElement;
521
521
 
522
+ /**
523
+ * Get a live map of all the routes
524
+ *
525
+ * @author Jelle De Loecker <jelle@elevenways.be>
526
+ * @since 1.3.8
527
+ * @version 1.3.8
528
+ *
529
+ * @return {Develry.BackedMap}
530
+ */
531
+ Alchemy.setMethod(function getRoutes() {
532
+ return new Classes.Develry.BackedMap(getRoutesDict);
533
+ });
534
+
535
+ /**
536
+ * The live-map dictionary creator
537
+ *
538
+ * @author Jelle De Loecker <jelle@elevenways.be>
539
+ * @since 1.3.8
540
+ * @version 1.3.8
541
+ *
542
+ * @return {Object}
543
+ */
544
+ function getRoutesDict() {
545
+ let routes;
546
+
547
+ if (Blast.isNode) {
548
+ routes = {};
549
+
550
+ let roots = Router.getRoutes();
551
+
552
+ for (let key in roots) {
553
+ let root = roots[key];
554
+
555
+ for (let name in root) {
556
+ routes[name] = root[name];
557
+ }
558
+ }
559
+
560
+ } else {
561
+ routes = {};
562
+
563
+ for (let root in hawkejs.scene.exposed.routes) {
564
+ let section = hawkejs.scene.exposed.routes[root];
565
+
566
+ for (let key in section) {
567
+ routes[key] = section[key];
568
+ }
569
+ }
570
+ }
571
+
572
+ return routes;
573
+ }
574
+
522
575
  // From here on, only client-side code is added
523
576
  if (Blast.isBrowser) {
524
577
  window.alchemy = new Alchemy();
@@ -582,21 +635,18 @@ Alchemy.setMethod(function linkup(type, data, cb) {
582
635
  *
583
636
  * @author Jelle De Loecker <jelle@develry.be>
584
637
  * @since 0.3.0
585
- * @version 1.3.0
638
+ * @version 1.3.8
586
639
  *
587
640
  * @param {Object} variables
588
641
  * @param {Object} render_data
589
642
  */
590
643
  Alchemy.setMethod(function markLinks(variables, render_data) {
591
644
 
592
- var page_breadcrumb,
593
- el_breadcrumbs,
594
- el_breadcrumb,
645
+ let page_breadcrumb,
595
646
  placeholder,
596
647
  href_val,
597
648
  elements,
598
649
  element,
599
- temp,
600
650
  url,
601
651
  i;
602
652
 
@@ -607,7 +657,7 @@ Alchemy.setMethod(function markLinks(variables, render_data) {
607
657
  }
608
658
 
609
659
  // Get the newly set breadcrumb
610
- page_breadcrumb = variables.__breadcrumb;
660
+ page_breadcrumb = new Classes.Alchemy.Breadcrumb(variables.__breadcrumb);
611
661
 
612
662
  // Get all the language switcher anchors
613
663
  elements = document.querySelectorAll('[data-alchemy-language-switch]');
@@ -621,30 +671,7 @@ Alchemy.setMethod(function markLinks(variables, render_data) {
621
671
 
622
672
  for (i = 0; i < elements.length; i++) {
623
673
  element = elements[i];
624
-
625
- // Create the breadcrumbs array
626
- el_breadcrumbs = [];
627
-
628
- // Get the element's set breadcrumb
629
- el_breadcrumb = element.getAttribute('data-breadcrumb');
630
-
631
- if (el_breadcrumb) {
632
- el_breadcrumbs.push(el_breadcrumb);
633
- }
634
-
635
- el_breadcrumb = element.getAttribute('data-breadcrumbs');
636
-
637
- if (el_breadcrumb) {
638
- el_breadcrumbs.include(el_breadcrumb.split('|'));
639
- }
640
-
641
- if (el_breadcrumbs.indexOf(page_breadcrumb) > -1) {
642
- markLinkElement(element, 1);
643
- } else if (page_breadcrumb && page_breadcrumb.startsWithAny(el_breadcrumbs)) {
644
- markLinkElement(element, 2);
645
- } else {
646
- markLinkElement(element, false);
647
- }
674
+ markLinkElement(element, page_breadcrumb.matchLevel(element));
648
675
  }
649
676
 
650
677
  // Get all anchors without breadcrumbs
@@ -702,9 +729,9 @@ Alchemy.setMethod(function markLinks(variables, render_data) {
702
729
  /**
703
730
  * Reload all stylesheets
704
731
  *
705
- * @author Jelle De Loecker <jelle@develry.be>
732
+ * @author Jelle De Loecker <jelle@elevenways.be>
706
733
  * @since 1.0.0
707
- * @version 1.2.5
734
+ * @version 1.3.8
708
735
  */
709
736
  Alchemy.setMethod(function reloadStylesheets() {
710
737
 
@@ -718,15 +745,15 @@ Alchemy.setMethod(function reloadStylesheets() {
718
745
  let url = new RURL(sheet.href);
719
746
  url.param('last_reload', Date.now());
720
747
 
721
- //sheet.ownerNode.href = String(url);
722
-
723
748
  let new_element = alchemy.hawkejs.createElement('link');
724
749
  new_element.setAttribute('rel', 'stylesheet');
725
750
  new_element.setAttribute('href', String(url));
726
751
  document.head.append(new_element);
727
752
 
728
753
  new_element.addEventListener('load', e => {
729
- sheet.ownerNode.remove();
754
+ if (sheet.ownerNode) {
755
+ sheet.ownerNode.remove();
756
+ }
730
757
  });
731
758
  }
732
759
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemymvc",
3
3
  "description": "MVC framework for Node.js",
4
- "version": "1.3.7",
4
+ "version": "1.3.9",
5
5
  "author": "Jelle De Loecker <jelle@elevenways.be>",
6
6
  "keywords": [
7
7
  "alchemy",