desy-html 5.0.1 → 5.2.1

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.
Files changed (30) hide show
  1. package/docs/_include.template-header.njk +8 -0
  2. package/docs/_macro.example-render.njk +8 -0
  3. package/docs/componentes.html +6 -0
  4. package/docs/ds/_ds.example.menu-vertical.njk +3 -3
  5. package/docs/ds/_ds.example.toggle.njk +56 -0
  6. package/docs/ds/_ds.example.tree.njk +457 -0
  7. package/docs/ds/_ds.section.forms.njk +5 -0
  8. package/docs/ds/_ds.section.mostrar-ocultar.njk +5 -0
  9. package/docs/examples-toggle.html +5 -0
  10. package/docs/examples-tree.html +5 -0
  11. package/docs/index.html +20 -1
  12. package/package.json +1 -1
  13. package/src/css/styles.css +1 -0
  14. package/src/js/aria/tree.js +245 -0
  15. package/src/js/aria/treeitem.js +260 -0
  16. package/src/js/desy-html.js +28 -0
  17. package/src/js/index.js +3 -1
  18. package/src/templates/components/checkboxes/_template.checkboxes.njk +1 -2
  19. package/src/templates/components/menubar/_examples.menubar.njk +169 -0
  20. package/src/templates/components/pagination/_examples.pagination.njk +32 -0
  21. package/src/templates/components/pagination/_template.pagination.njk +1 -0
  22. package/src/templates/components/toggle/_examples.toggle.njk +52 -0
  23. package/src/templates/components/toggle/_macro.toggle.njk +3 -0
  24. package/src/templates/components/toggle/_template.toggle.njk +37 -0
  25. package/src/templates/components/toggle/params.toggle.yaml +57 -0
  26. package/src/templates/components/tree/_examples.tree.njk +1171 -0
  27. package/src/templates/components/tree/_macro.tree.njk +3 -0
  28. package/src/templates/components/tree/_styles.tree.css +45 -0
  29. package/src/templates/components/tree/_template.tree.njk +178 -0
  30. package/src/templates/components/tree/params.tree.yaml +163 -0
@@ -35,6 +35,7 @@
35
35
  @import "../templates/components/skip-link/_styles.skip-link.css";
36
36
  @import "../templates/components/table-advanced/_styles.table-advanced.css";
37
37
  @import "../templates/components/tabs/_styles.tabs.css";
38
+ @import "../templates/components/tree/_styles.tree.css";
38
39
  @import "./component.form-group.css";
39
40
  @import "./component.tippy-box.css";
40
41
 
@@ -0,0 +1,245 @@
1
+ export function Tree(aria) {
2
+ /*
3
+ * This content is licensed according to the W3C Software License at
4
+ * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
5
+ *
6
+ * File: Tree.js
7
+ *
8
+ * Desc: Tree widget that implements ARIA Authoring Practices
9
+ * for a tree being used as a file viewer
10
+ */
11
+
12
+ /*
13
+ * @constructor
14
+ *
15
+ * @desc
16
+ * Tree item object for representing the state and user interactions for a
17
+ * tree widget
18
+ *
19
+ * @param node
20
+ * An element with the role=tree attribute
21
+ */
22
+ aria.Tree = function (node) {
23
+ // Check whether node is a DOM element
24
+ if (typeof node !== 'object') {
25
+ return;
26
+ }
27
+
28
+ this.domNode = node;
29
+
30
+ this.treeitems = [];
31
+ this.firstChars = [];
32
+
33
+ this.firstTreeitem = null;
34
+ this.lastTreeitem = null;
35
+
36
+ };
37
+
38
+ aria.Tree.prototype.init = function () {
39
+
40
+ function findTreeitems (node, tree, group) {
41
+
42
+ var elem = node.firstElementChild;
43
+ var ti = group;
44
+
45
+ while (elem) {
46
+
47
+ if (elem.tagName.toLowerCase() === 'li') {
48
+ ti = new aria.Treeitem(elem, tree, group);
49
+ ti.init();
50
+ tree.treeitems.push(ti);
51
+ tree.firstChars.push(ti.label.substring(0, 1).toLowerCase());
52
+ }
53
+
54
+ if (elem.firstElementChild) {
55
+ findTreeitems(elem, tree, ti);
56
+ }
57
+
58
+ elem = elem.nextElementSibling;
59
+ }
60
+ }
61
+
62
+ // initialize pop up menus
63
+ if (!this.domNode.getAttribute('role')) {
64
+ this.domNode.setAttribute('role', 'tree');
65
+ }
66
+
67
+ findTreeitems(this.domNode, this, false);
68
+
69
+ this.updateVisibleTreeitems();
70
+
71
+ this.firstTreeitem.domNode.tabIndex = 0;
72
+
73
+ };
74
+
75
+ aria.Tree.prototype.setFocusToItem = function (treeitem) {
76
+
77
+ for (var i = 0; i < this.treeitems.length; i++) {
78
+ var ti = this.treeitems[i];
79
+
80
+ if (ti === treeitem) {
81
+ ti.domNode.tabIndex = 0;
82
+ ti.domNode.focus();
83
+ }
84
+ else {
85
+ ti.domNode.tabIndex = -1;
86
+ }
87
+ }
88
+
89
+ };
90
+
91
+ aria.Tree.prototype.setFocusToNextItem = function (currentItem) {
92
+
93
+ var nextItem = false;
94
+
95
+ for (var i = (this.treeitems.length - 1); i >= 0; i--) {
96
+ var ti = this.treeitems[i];
97
+ if (ti === currentItem) {
98
+ break;
99
+ }
100
+ if (ti.isVisible) {
101
+ nextItem = ti;
102
+ }
103
+ }
104
+
105
+ if (nextItem) {
106
+ this.setFocusToItem(nextItem);
107
+ }
108
+
109
+ };
110
+
111
+ aria.Tree.prototype.setFocusToPreviousItem = function (currentItem) {
112
+
113
+ var prevItem = false;
114
+
115
+ for (var i = 0; i < this.treeitems.length; i++) {
116
+ var ti = this.treeitems[i];
117
+ if (ti === currentItem) {
118
+ break;
119
+ }
120
+ if (ti.isVisible) {
121
+ prevItem = ti;
122
+ }
123
+ }
124
+
125
+ if (prevItem) {
126
+ this.setFocusToItem(prevItem);
127
+ }
128
+ };
129
+
130
+ aria.Tree.prototype.setFocusToParentItem = function (currentItem) {
131
+
132
+ if (currentItem.groupTreeitem) {
133
+ this.setFocusToItem(currentItem.groupTreeitem);
134
+ }
135
+ };
136
+
137
+ aria.Tree.prototype.setFocusToFirstItem = function () {
138
+ this.setFocusToItem(this.firstTreeitem);
139
+ };
140
+
141
+ aria.Tree.prototype.setFocusToLastItem = function () {
142
+ this.setFocusToItem(this.lastTreeitem);
143
+ };
144
+
145
+ aria.Tree.prototype.expandTreeitem = function (currentItem) {
146
+
147
+ if (currentItem.isExpandable) {
148
+ currentItem.domNode.setAttribute('aria-expanded', true);
149
+ this.updateVisibleTreeitems();
150
+ }
151
+
152
+ };
153
+
154
+ aria.Tree.prototype.expandAllSiblingItems = function (currentItem) {
155
+ for (var i = 0; i < this.treeitems.length; i++) {
156
+ var ti = this.treeitems[i];
157
+
158
+ if ((ti.groupTreeitem === currentItem.groupTreeitem) && ti.isExpandable) {
159
+ this.expandTreeitem(ti);
160
+ }
161
+ }
162
+
163
+ };
164
+
165
+ aria.Tree.prototype.collapseTreeitem = function (currentItem) {
166
+
167
+ var groupTreeitem = false;
168
+
169
+ if (currentItem.isExpanded()) {
170
+ groupTreeitem = currentItem;
171
+ }
172
+ else {
173
+ groupTreeitem = currentItem.groupTreeitem;
174
+ }
175
+
176
+ if (groupTreeitem) {
177
+ groupTreeitem.domNode.setAttribute('aria-expanded', false);
178
+ this.updateVisibleTreeitems();
179
+ this.setFocusToItem(groupTreeitem);
180
+ }
181
+
182
+ };
183
+
184
+ aria.Tree.prototype.updateVisibleTreeitems = function () {
185
+
186
+ this.firstTreeitem = this.treeitems[0];
187
+
188
+ for (var i = 0; i < this.treeitems.length; i++) {
189
+ var ti = this.treeitems[i];
190
+
191
+ var parent = ti.domNode.parentNode;
192
+
193
+ ti.isVisible = true;
194
+
195
+ while (parent && (parent !== this.domNode)) {
196
+
197
+ if (parent.getAttribute('aria-expanded') == 'false') {
198
+ ti.isVisible = false;
199
+ }
200
+ parent = parent.parentNode;
201
+ }
202
+
203
+ if (ti.isVisible) {
204
+ this.lastTreeitem = ti;
205
+ }
206
+ }
207
+
208
+ };
209
+
210
+ aria.Tree.prototype.setFocusByFirstCharacter = function (currentItem, char) {
211
+ var start, index, char = char.toLowerCase();
212
+
213
+ // Get start index for search based on position of currentItem
214
+ start = this.treeitems.indexOf(currentItem) + 1;
215
+ if (start === this.treeitems.length) {
216
+ start = 0;
217
+ }
218
+
219
+ // Check remaining slots in the menu
220
+ index = this.getIndexFirstChars(start, char);
221
+
222
+ // If not found in remaining slots, check from beginning
223
+ if (index === -1) {
224
+ index = this.getIndexFirstChars(0, char);
225
+ }
226
+
227
+ // If match was found...
228
+ if (index > -1) {
229
+ this.setFocusToItem(this.treeitems[index]);
230
+ }
231
+ };
232
+
233
+ aria.Tree.prototype.getIndexFirstChars = function (startIndex, char) {
234
+ for (var i = startIndex; i < this.firstChars.length; i++) {
235
+ if (this.treeitems[i].isVisible) {
236
+ if (char === this.firstChars[i]) {
237
+ return i;
238
+ }
239
+ }
240
+ }
241
+ return -1;
242
+ };
243
+
244
+ return aria;
245
+ }
@@ -0,0 +1,260 @@
1
+ export function Treeitem(aria) {
2
+ /*
3
+ * This content is licensed according to the W3C Software License at
4
+ * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
5
+ *
6
+ * File: Treeitem.js
7
+ *
8
+ * Desc: Treeitem widget that implements ARIA Authoring Practices
9
+ * for a tree being used as a file viewer
10
+ */
11
+
12
+ /*
13
+ * @constructor
14
+ *
15
+ * @desc
16
+ * Treeitem object for representing the state and user interactions for a
17
+ * treeItem widget
18
+ *
19
+ * @param node
20
+ * An element with the role=tree attribute
21
+ */
22
+
23
+ aria.Treeitem = function (node, treeObj, group) {
24
+
25
+ // Check whether node is a DOM element
26
+ if (typeof node !== 'object') {
27
+ return;
28
+ }
29
+
30
+ node.tabIndex = -1;
31
+ this.tree = treeObj;
32
+ this.groupTreeitem = group;
33
+ this.domNode = node;
34
+ this.label = node.textContent.trim();
35
+
36
+ if (node.getAttribute('aria-label')) {
37
+ this.label = node.getAttribute('aria-label').trim();
38
+ }
39
+
40
+ this.isExpandable = false;
41
+ this.isVisible = false;
42
+ this.inGroup = false;
43
+
44
+ if (group) {
45
+ this.inGroup = true;
46
+ }
47
+
48
+ var elem = node.firstElementChild;
49
+
50
+ while (elem) {
51
+
52
+ if (elem.tagName.toLowerCase() == 'ul') {
53
+ elem.setAttribute('role', 'group');
54
+ this.isExpandable = true;
55
+ break;
56
+ }
57
+
58
+ elem = elem.nextElementSibling;
59
+ }
60
+
61
+ this.keyCode = Object.freeze({
62
+ RETURN: 13,
63
+ SPACE: 32,
64
+ PAGEUP: 33,
65
+ PAGEDOWN: 34,
66
+ END: 35,
67
+ HOME: 36,
68
+ LEFT: 37,
69
+ UP: 38,
70
+ RIGHT: 39,
71
+ DOWN: 40
72
+ });
73
+ };
74
+
75
+ aria.Treeitem.prototype.init = function () {
76
+ this.domNode.tabIndex = -1;
77
+
78
+ if (!this.domNode.getAttribute('role')) {
79
+ this.domNode.setAttribute('role', 'treeitem');
80
+ }
81
+
82
+ this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
83
+ this.domNode.addEventListener('click', this.handleClick.bind(this));
84
+ this.domNode.addEventListener('focus', this.handleFocus.bind(this));
85
+ this.domNode.addEventListener('blur', this.handleBlur.bind(this));
86
+
87
+ if (!this.isExpandable) {
88
+ this.domNode.addEventListener('mouseover', this.handleMouseOver.bind(this));
89
+ this.domNode.addEventListener('mouseout', this.handleMouseOut.bind(this));
90
+ }
91
+ };
92
+
93
+ aria.Treeitem.prototype.isExpanded = function () {
94
+
95
+ if (this.isExpandable) {
96
+ return this.domNode.getAttribute('aria-expanded') === 'true';
97
+ }
98
+
99
+ return false;
100
+
101
+ };
102
+
103
+ /* EVENT HANDLERS */
104
+
105
+ aria.Treeitem.prototype.handleKeydown = function (event) {
106
+
107
+ var tgt = event.currentTarget,
108
+ flag = false,
109
+ char = event.key,
110
+ clickEvent;
111
+
112
+ function isPrintableCharacter (str) {
113
+ return str.length === 1 && str.match(/\S/);
114
+ }
115
+
116
+ function printableCharacter (item) {
117
+ if (char == '*') {
118
+ item.tree.expandAllSiblingItems(item);
119
+ flag = true;
120
+ }
121
+ else {
122
+ if (isPrintableCharacter(char)) {
123
+ item.tree.setFocusByFirstCharacter(item, char);
124
+ flag = true;
125
+ }
126
+ }
127
+ }
128
+
129
+ if (event.altKey || event.ctrlKey || event.metaKey) {
130
+ return;
131
+ }
132
+
133
+ if (event.shift) {
134
+ if (isPrintableCharacter(char)) {
135
+ printableCharacter(this);
136
+ }
137
+ }
138
+ else {
139
+ switch (event.keyCode) {
140
+ case this.keyCode.SPACE:
141
+ case this.keyCode.RETURN:
142
+ // Create simulated mouse event to mimic the behavior of ATs
143
+ // and let the event handler handleClick do the housekeeping.
144
+ try {
145
+ clickEvent = new MouseEvent('click', {
146
+ 'view': window,
147
+ 'bubbles': true,
148
+ 'cancelable': true
149
+ });
150
+ }
151
+ catch (err) {
152
+ if (document.createEvent) {
153
+ // DOM Level 3 for IE 9+
154
+ clickEvent = document.createEvent('MouseEvents');
155
+ clickEvent.initEvent('click', true, true);
156
+ }
157
+ }
158
+ tgt.dispatchEvent(clickEvent);
159
+ flag = true;
160
+ break;
161
+
162
+ case this.keyCode.UP:
163
+ this.tree.setFocusToPreviousItem(this);
164
+ flag = true;
165
+ break;
166
+
167
+ case this.keyCode.DOWN:
168
+ this.tree.setFocusToNextItem(this);
169
+ flag = true;
170
+ break;
171
+
172
+ case this.keyCode.RIGHT:
173
+ if (this.isExpandable) {
174
+ if (this.isExpanded()) {
175
+ this.tree.setFocusToNextItem(this);
176
+ }
177
+ else {
178
+ this.tree.expandTreeitem(this);
179
+ }
180
+ }
181
+ flag = true;
182
+ break;
183
+
184
+ case this.keyCode.LEFT:
185
+ if (this.isExpandable && this.isExpanded()) {
186
+ this.tree.collapseTreeitem(this);
187
+ flag = true;
188
+ }
189
+ else {
190
+ if (this.inGroup) {
191
+ this.tree.setFocusToParentItem(this);
192
+ flag = true;
193
+ }
194
+ }
195
+ break;
196
+
197
+ case this.keyCode.HOME:
198
+ this.tree.setFocusToFirstItem();
199
+ flag = true;
200
+ break;
201
+
202
+ case this.keyCode.END:
203
+ this.tree.setFocusToLastItem();
204
+ flag = true;
205
+ break;
206
+
207
+ default:
208
+ if (isPrintableCharacter(char)) {
209
+ printableCharacter(this);
210
+ }
211
+ break;
212
+ }
213
+
214
+ }
215
+
216
+ if (flag) {
217
+ event.stopPropagation();
218
+ event.preventDefault();
219
+ }
220
+ };
221
+
222
+ aria.Treeitem.prototype.handleClick = function (event) {
223
+ if (this.isExpandable) {
224
+ if (this.isExpanded()) {
225
+ this.tree.collapseTreeitem(this);
226
+ }
227
+ else {
228
+ this.tree.expandTreeitem(this);
229
+ }
230
+ event.stopPropagation();
231
+ }
232
+ else {
233
+ this.tree.setFocusToItem(this);
234
+ }
235
+ };
236
+
237
+ aria.Treeitem.prototype.handleFocus = function (event) {
238
+ var node = this.domNode;
239
+ if (this.isExpandable) {
240
+ node = node.firstElementChild;
241
+ }
242
+ node.classList.add('c-tree__item--focus');
243
+ };
244
+
245
+ aria.Treeitem.prototype.handleBlur = function (event) {
246
+ var node = this.domNode;
247
+ if (this.isExpandable) {
248
+ node = node.firstElementChild;
249
+ }
250
+ node.classList.remove('c-tree__item--focus');
251
+ };
252
+
253
+ aria.Treeitem.prototype.handleMouseOver = function (event) {
254
+ event.currentTarget.classList.add('c-tree__item--hover');
255
+ };
256
+
257
+ aria.Treeitem.prototype.handleMouseOut = function (event) {
258
+ event.currentTarget.classList.remove('c-tree__item--hover');
259
+ };
260
+ }
@@ -9,6 +9,8 @@ import { MenubarItemAction } from './aria/MenubarItemAction.js';
9
9
  import { MenubarAction } from './aria/MenubarAction.js';
10
10
  import { listbox } from './aria/listbox.js';
11
11
  import { alert } from './aria/alert.js';
12
+ import { Treeitem } from './aria/treeitem.js';
13
+ import { Tree } from './aria/tree.js';
12
14
 
13
15
 
14
16
  export function accordionComponent(aria) {
@@ -311,3 +313,29 @@ export function tooltipComponent(aria) {
311
313
  }
312
314
  }
313
315
 
316
+ export function treeComponent(aria) {
317
+ Treeitem(aria);
318
+ Tree(aria);
319
+ const modules = document.querySelectorAll('[data-module]');
320
+ for (const item in modules) if (modules.hasOwnProperty(item)) {
321
+ const moduleValue = modules[item].getAttribute('data-module');
322
+
323
+ if (moduleValue == 'c-tree'){
324
+ const tree = new aria.Tree(modules[item]);
325
+ tree.init();
326
+ }
327
+
328
+ if (moduleValue == 'c-tree__item'){
329
+ modules[item].addEventListener('click', function (event) {
330
+ const current = event.target;
331
+ if ((current.tagName == 'INPUT')||(current.tagName == 'LABEL')) {
332
+ event.stopPropagation();
333
+ } else {
334
+ event.stopPropagation();
335
+ event.preventDefault();
336
+ }
337
+ });
338
+ }
339
+ }
340
+ }
341
+
package/src/js/index.js CHANGED
@@ -12,7 +12,8 @@ import {
12
12
  menubarComponent,
13
13
  tableAdvancedComponent,
14
14
  tabsComponent,
15
- tooltipComponent
15
+ tooltipComponent,
16
+ treeComponent
16
17
  } from './desy-html.js';
17
18
 
18
19
  var aria = aria || {};
@@ -26,3 +27,4 @@ menubarComponent(aria);
26
27
  tableAdvancedComponent(aria);
27
28
  tabsComponent(aria);
28
29
  tooltipComponent(aria);
30
+ treeComponent(aria);
@@ -80,8 +80,7 @@
80
80
  {%- if itemDescribedBy %} aria-describedby="{{ itemDescribedBy }}"{% endif -%}
81
81
  {%- if params.errorMessage %} aria-invalid="true"{% endif -%}
82
82
  {%- for attribute, value in item.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}
83
- {%- if item.isIndeterminate %} onclick="if (this.readOnly) this.checked=this.readOnly=false; else if (!this.checked) this.readOnly=this.indeterminate=true;"{% endif %}
84
- {%- if item.indeterminateChecked %} onclick="if (this.readOnly) this.checked=this.readOnly=false; else if (!this.checked) this.readOnly=this.indeterminate=true;"{% endif %}>
83
+ {%- if item.isIndeterminate or item.indeterminateChecked %} onclick="if (this.readOnly) this.checked=this.readOnly=false; else if (!this.checked) this.readOnly=this.indeterminate=true;"{% endif %}>
85
84
  </div>
86
85
  <div class="pt-0.5 leading-5">
87
86
  {{ componentLabel({