pixl-xyapp 2.1.7 → 2.1.10
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.
- package/LICENSE.md +23 -6
- package/css/base.css +21 -11
- package/js/base.js +46 -2
- package/js/datetime.js +2 -2
- package/js/dialog.js +32 -2
- package/js/page.js +13 -26
- package/js/popover.js +3 -0
- package/js/select.js +154 -60
- package/js/tools.js +2 -2
- package/package.json +2 -2
package/LICENSE.md
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
BSD 3-Clause License
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Copyright (c) 2019 - 2026 PixlCore LLC & CONTRIBUTORS.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/css/base.css
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* xyOps Base Theme */
|
|
2
|
-
/* Copyright (c) 2019 Joseph Huckaby -
|
|
2
|
+
/* Copyright (c) 2019 - 2026 Joseph Huckaby - BSD 3-Clause License */
|
|
3
3
|
|
|
4
4
|
* {
|
|
5
5
|
box-sizing: border-box;
|
|
@@ -178,6 +178,14 @@ body.dark fieldset input {
|
|
|
178
178
|
background: var(--box-background-color);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
button.link {
|
|
182
|
+
background: none;
|
|
183
|
+
border: none;
|
|
184
|
+
padding: 0;
|
|
185
|
+
margin: 0;
|
|
186
|
+
font: inherit;
|
|
187
|
+
}
|
|
188
|
+
|
|
181
189
|
a, .link {
|
|
182
190
|
color: var(--link-color);
|
|
183
191
|
}
|
|
@@ -197,6 +205,12 @@ a, .link {
|
|
|
197
205
|
text-decoration: none;
|
|
198
206
|
}
|
|
199
207
|
|
|
208
|
+
.link {
|
|
209
|
+
user-select: none;
|
|
210
|
+
-moz-user-select: none;
|
|
211
|
+
-webkit-user-select: none;
|
|
212
|
+
}
|
|
213
|
+
|
|
200
214
|
a.danger:hover, .link.danger:hover {
|
|
201
215
|
color: var(--red) !important;
|
|
202
216
|
}
|
|
@@ -1490,9 +1504,6 @@ body.dark fieldset .checkbox_container > label:before {
|
|
|
1490
1504
|
transform: scale(.2);
|
|
1491
1505
|
}
|
|
1492
1506
|
|
|
1493
|
-
/* .checkbox_container > input:hover ~ label:before {
|
|
1494
|
-
border-color: var(--theme-color);
|
|
1495
|
-
} */
|
|
1496
1507
|
.checkbox_container > input:hover ~ label {
|
|
1497
1508
|
color: var(--theme-color);
|
|
1498
1509
|
}
|
|
@@ -1517,13 +1528,11 @@ body.dark fieldset .checkbox_container > label:before {
|
|
|
1517
1528
|
.checkbox_container:hover {
|
|
1518
1529
|
color: var(--body-text-color);
|
|
1519
1530
|
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
background-color: var(--theme-color-half) !important;
|
|
1526
|
-
} */
|
|
1531
|
+
|
|
1532
|
+
.checkbox_container > input:focus-visible ~ label::before {
|
|
1533
|
+
outline: 2px solid var(--theme-color);
|
|
1534
|
+
outline-offset: 2px;
|
|
1535
|
+
}
|
|
1527
1536
|
|
|
1528
1537
|
div.info_label {
|
|
1529
1538
|
font-size: 11px;
|
|
@@ -2398,6 +2407,7 @@ table.data_table.compact th:first-child, table.data_table.compact td:first-child
|
|
|
2398
2407
|
}
|
|
2399
2408
|
|
|
2400
2409
|
div.data_table_compact > div.data_grid > ul.grid_row_header > div {
|
|
2410
|
+
border-top: none;
|
|
2401
2411
|
margin-bottom: 5px;
|
|
2402
2412
|
}
|
|
2403
2413
|
|
package/js/base.js
CHANGED
|
@@ -41,7 +41,7 @@ var app = {
|
|
|
41
41
|
|
|
42
42
|
setHeaderNav: function(items) {
|
|
43
43
|
// populate header with multiple nav elements
|
|
44
|
-
var html = '<div class="header_nav_cont">';
|
|
44
|
+
var html = '<div class="header_nav_cont" role="navigation">';
|
|
45
45
|
|
|
46
46
|
items.forEach( function(item, idx) {
|
|
47
47
|
if (!item) return;
|
|
@@ -247,8 +247,11 @@ var app = {
|
|
|
247
247
|
// show toast notification given raw html
|
|
248
248
|
var { type, icon, msg, lifetime, loc } = args;
|
|
249
249
|
|
|
250
|
+
var role = 'alert';
|
|
251
|
+
if ((type == 'success') || (type == 'info')) role = 'status';
|
|
252
|
+
|
|
250
253
|
var html = '';
|
|
251
|
-
html += '<div class="toast ' + type + '" style="display:none">';
|
|
254
|
+
html += '<div class="toast ' + type + '" style="display:none" role="' + role + '" aria-atomic="true">';
|
|
252
255
|
html += '<i class="mdi mdi-' + icon + '"></i>';
|
|
253
256
|
html += '<span>' + msg + '</span>';
|
|
254
257
|
html += '</div>';
|
|
@@ -536,6 +539,47 @@ var app = {
|
|
|
536
539
|
notifyUserNav: function(loc) {
|
|
537
540
|
// override in app
|
|
538
541
|
// called by each page nav operation
|
|
542
|
+
},
|
|
543
|
+
|
|
544
|
+
focusNext($cur, $cont) {
|
|
545
|
+
// focus the next focusable element
|
|
546
|
+
if (!$cur) $cur = $(document.activeElement);
|
|
547
|
+
if (!$cont) $cont = $(document);
|
|
548
|
+
|
|
549
|
+
const $elems = $cont.find(
|
|
550
|
+
'a[href], button, input, textarea, select, details, summary, [tabindex]:not([tabindex="-1"])'
|
|
551
|
+
).filter(function() {
|
|
552
|
+
const $el = $(this);
|
|
553
|
+
if ($el.is(':disabled') || !$el.is(':visible')) return false;
|
|
554
|
+
if ($el.attr('tabindex') === "-1") return false;
|
|
555
|
+
return true;
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
// Find current element in list
|
|
559
|
+
const idx = $elems.index($cur);
|
|
560
|
+
|
|
561
|
+
// Focus the next tabbable element
|
|
562
|
+
if (idx !== -1 && idx < $elems.length - 1) {
|
|
563
|
+
const $next = $elems.eq(idx + 1);
|
|
564
|
+
$next.focus();
|
|
565
|
+
return $next;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return null;
|
|
569
|
+
},
|
|
570
|
+
|
|
571
|
+
buttonize: function($sel) {
|
|
572
|
+
// add aria roles and keyboard handlers to all buttons inside container
|
|
573
|
+
$sel.find('.button').attr({ role: 'button', tabindex: '0', onkeypress: 'app.buttonKey(this,event)' });
|
|
574
|
+
},
|
|
575
|
+
|
|
576
|
+
buttonKey: function(elem, event) {
|
|
577
|
+
// key pressed while button is focused -- click if space or enter
|
|
578
|
+
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
579
|
+
event.preventDefault();
|
|
580
|
+
event.stopPropagation();
|
|
581
|
+
$(elem).click();
|
|
582
|
+
}
|
|
539
583
|
}
|
|
540
584
|
|
|
541
585
|
}; // app object
|
package/js/datetime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Joe's Date/Time Tools
|
|
2
|
-
// Copyright (c) 2004 -
|
|
3
|
-
// Released under the
|
|
2
|
+
// Copyright (c) 2004 - 2026 Joseph Huckaby
|
|
3
|
+
// Released under the BSD 3-Clause License
|
|
4
4
|
|
|
5
5
|
var _months = [
|
|
6
6
|
[ 1, 'January' ], [ 2, 'February' ], [ 3, 'March' ], [ 4, 'April' ],
|
package/js/dialog.js
CHANGED
|
@@ -45,7 +45,7 @@ var Dialog = {
|
|
|
45
45
|
$('#dialog').stop().remove();
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
var $dialog = $('<div id="dialog" class="dialog"></div>').css({
|
|
48
|
+
var $dialog = $('<div id="dialog" class="dialog" role="dialog" aria-modal="true"></div>').css({
|
|
49
49
|
opacity: 0,
|
|
50
50
|
left: '' + x + 'px',
|
|
51
51
|
top: '' + y + 'px'
|
|
@@ -56,6 +56,12 @@ var Dialog = {
|
|
|
56
56
|
|
|
57
57
|
this.active = true;
|
|
58
58
|
unscroll();
|
|
59
|
+
|
|
60
|
+
// buttonize all buttons
|
|
61
|
+
app.buttonize( $dialog );
|
|
62
|
+
|
|
63
|
+
// make everything behind us inert, for accessibility
|
|
64
|
+
$('div.sidebar, div.header, div.main, div.footer').attr('inert', 'true');
|
|
59
65
|
},
|
|
60
66
|
|
|
61
67
|
autoResize: function() {
|
|
@@ -83,6 +89,7 @@ var Dialog = {
|
|
|
83
89
|
if (this.active) {
|
|
84
90
|
$('#dialog').stop().fadeOut( 250, function() { $(this).remove(); } );
|
|
85
91
|
$('#dialog_overlay').stop().fadeOut( 300, function() { $(this).remove(); } );
|
|
92
|
+
$('div.sidebar, div.header, div.main, div.footer').removeAttr('inert');
|
|
86
93
|
this.active = false;
|
|
87
94
|
unscroll.reset();
|
|
88
95
|
|
|
@@ -221,6 +228,9 @@ var Dialog = {
|
|
|
221
228
|
Dialog.active = 'confirmation';
|
|
222
229
|
|
|
223
230
|
setTimeout( function() {
|
|
231
|
+
// change aria role for danger type
|
|
232
|
+
$('#dialog').attr('role', 'alertdialog');
|
|
233
|
+
|
|
224
234
|
// hold alt/opt key to immediately click default button
|
|
225
235
|
if (app.lastClick.altKey) return Dialog.confirm_click(true);
|
|
226
236
|
}, 1 );
|
|
@@ -300,7 +310,7 @@ var CodeEditor = {
|
|
|
300
310
|
$('#ceditor').stop().remove();
|
|
301
311
|
}
|
|
302
312
|
|
|
303
|
-
var $dialog = $('<div class="dialog" id="ceditor"></div>').css({
|
|
313
|
+
var $dialog = $('<div class="dialog" id="ceditor" role="dialog" aria-modal="true"></div>').css({
|
|
304
314
|
opacity: 0,
|
|
305
315
|
left: '' + x + 'px',
|
|
306
316
|
top: '' + y + 'px'
|
|
@@ -313,6 +323,17 @@ var CodeEditor = {
|
|
|
313
323
|
|
|
314
324
|
// only do the unscroll thing if another dialog isn't active under us
|
|
315
325
|
if (!Dialog.active) unscroll();
|
|
326
|
+
|
|
327
|
+
// if dialog is active under us, remove its modal role and make it inert
|
|
328
|
+
if (Dialog.active) {
|
|
329
|
+
$('#dialog').removeAttr('aria-modal').attr({ 'aria-hidden': 'true', 'inert': 'true' });
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
$('div.sidebar, div.header, div.main, div.footer').attr('inert', 'true');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// buttonize all buttons
|
|
336
|
+
app.buttonize( $dialog );
|
|
316
337
|
},
|
|
317
338
|
|
|
318
339
|
autoResize: function() {
|
|
@@ -345,6 +366,14 @@ var CodeEditor = {
|
|
|
345
366
|
// only release scroll lock if another dialog isn't active under us
|
|
346
367
|
if (!Dialog.active) unscroll.reset();
|
|
347
368
|
|
|
369
|
+
// if dialog is active under us, restore its modal role
|
|
370
|
+
if (Dialog.active) {
|
|
371
|
+
$('#dialog').attr('aria-modal', 'true').removeAttr('aria-hidden').removeAttr('inert');
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
$('div.sidebar, div.header, div.main, div.footer').removeAttr('inert');
|
|
375
|
+
}
|
|
376
|
+
|
|
348
377
|
if (this.onHide) {
|
|
349
378
|
// one time hook for hide
|
|
350
379
|
var callback = this.onHide;
|
|
@@ -353,6 +382,7 @@ var CodeEditor = {
|
|
|
353
382
|
}
|
|
354
383
|
|
|
355
384
|
this.onDragDrop = null;
|
|
385
|
+
this.onKeyDown = null;
|
|
356
386
|
}
|
|
357
387
|
},
|
|
358
388
|
|
package/js/page.js
CHANGED
|
@@ -88,7 +88,7 @@ window.Page = class Page {
|
|
|
88
88
|
|
|
89
89
|
html += '<div class="form_row ' + extra_classes + '" ' + compose_attribs(args) + '>';
|
|
90
90
|
if (label) html += '<div class="fr_label">' + label + '</div>';
|
|
91
|
-
if (content) html += '<div class="fr_content">' + content + '</div>';
|
|
91
|
+
if (content) html += '<div class="fr_content" aria-label="' + strip_html(label).replace(/\&\w+\;/g, '').trim() + '">' + content + '</div>';
|
|
92
92
|
if (suffix) html += '<div class="fr_suffix">' + suffix + '</div>';
|
|
93
93
|
if (caption) html += '<div class="fr_caption"><span>' + inline_marked(caption) + '</span></div>'; // markdown
|
|
94
94
|
html += '</div>';
|
|
@@ -161,7 +161,7 @@ window.Page = class Page {
|
|
|
161
161
|
|
|
162
162
|
html += '<div class="checkbox_container">';
|
|
163
163
|
html += '<input type="checkbox" ' + compose_attribs(args) + '/>';
|
|
164
|
-
html += '<label>' + label + '</label>';
|
|
164
|
+
html += '<label for="' + (args.id || '') + '">' + label + '</label>';
|
|
165
165
|
html += '</div>';
|
|
166
166
|
|
|
167
167
|
return html;
|
|
@@ -1250,26 +1250,17 @@ window.Page = class Page {
|
|
|
1250
1250
|
var $elem = $field.closest('.form_row').find('.fr_suffix .checker');
|
|
1251
1251
|
|
|
1252
1252
|
if (username.match(/^[\w\-\.]+$/)) {
|
|
1253
|
-
// check with
|
|
1254
|
-
app.
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
$elem.css('color', 'red').html('<span class="mdi mdi-alert-decagram"></span>').attr('title', "Username is malformed.");
|
|
1265
|
-
$field.addClass('warning');
|
|
1266
|
-
}
|
|
1267
|
-
else {
|
|
1268
|
-
// username is valid and available!
|
|
1269
|
-
$elem.css('color','green').html('<span class="mdi mdi-check-circle"></span>').attr('title', "Username available!");
|
|
1270
|
-
$field.removeClass('warning');
|
|
1271
|
-
}
|
|
1272
|
-
} );
|
|
1253
|
+
// check with user list
|
|
1254
|
+
if (find_object( app.users, { username })) {
|
|
1255
|
+
// username taken
|
|
1256
|
+
$elem.css('color','red').html('<span class="mdi mdi-alert-circle"></span>').attr('title', "Username is taken.");
|
|
1257
|
+
$field.addClass('warning');
|
|
1258
|
+
}
|
|
1259
|
+
else {
|
|
1260
|
+
// username is valid and available!
|
|
1261
|
+
$elem.css('color','green').html('<span class="mdi mdi-check-circle"></span>').attr('title', "Username available!");
|
|
1262
|
+
$field.removeClass('warning');
|
|
1263
|
+
}
|
|
1273
1264
|
}
|
|
1274
1265
|
else if (username.length) {
|
|
1275
1266
|
// bad username
|
|
@@ -1726,10 +1717,6 @@ window.PageManager = class PageManager {
|
|
|
1726
1717
|
var result = page.onActivate.apply(page, [args]);
|
|
1727
1718
|
if (typeof(result) == 'boolean') return result;
|
|
1728
1719
|
else throw("Page " + id + " onActivate did not return a boolean!");
|
|
1729
|
-
|
|
1730
|
-
// expand section if applicable -- TODO: unreachable code:
|
|
1731
|
-
var $sect = $('#tab_'+id).parent().prev();
|
|
1732
|
-
if ($sect.length && $sect.hasClass('section_title')) this.expandSidebarGroup( $sect );
|
|
1733
1720
|
}
|
|
1734
1721
|
|
|
1735
1722
|
deactivate(id, new_id) {
|
package/js/popover.js
CHANGED
package/js/select.js
CHANGED
|
@@ -9,9 +9,9 @@ var SingleSelect = {
|
|
|
9
9
|
$(sel).each( function() {
|
|
10
10
|
var self = this;
|
|
11
11
|
var $this = $(this);
|
|
12
|
-
$this.css('display', 'none');
|
|
12
|
+
$this.css('display', 'none').attr({ 'aria-hidden': true, tabindex: '-1' });
|
|
13
13
|
|
|
14
|
-
var $ms = $('<div class="multiselect single"></div>');
|
|
14
|
+
var $ms = $('<div class="multiselect single" role="button" tabindex="0" aria-haspopup="listbox" aria-expanded="false"></div>');
|
|
15
15
|
if ($this.data('private')) $ms.attr('data-private', 1);
|
|
16
16
|
$this.after( $ms );
|
|
17
17
|
|
|
@@ -50,16 +50,25 @@ var SingleSelect = {
|
|
|
50
50
|
// also expose redraw as a custom event that can be triggered
|
|
51
51
|
$this.on('redraw', redraw);
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
// allow keyboard to open menu
|
|
54
|
+
$ms.on('keydown', function(event) {
|
|
55
|
+
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
56
|
+
$ms.click();
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
}
|
|
59
|
+
} );
|
|
60
|
+
|
|
61
|
+
$ms.on('click', function() {
|
|
54
62
|
// create popover dialog for selecting and filtering
|
|
55
63
|
var html = '';
|
|
56
64
|
var is_private = $this.data('private');
|
|
57
65
|
if ($ms.hasClass('disabled')) return;
|
|
66
|
+
$ms.attr('aria-expanded', 'true');
|
|
58
67
|
|
|
59
68
|
html += '<div class="sel_dialog_label">' + ($this.attr('title') || 'Select Item') + '</div>';
|
|
60
69
|
|
|
61
70
|
if (!$this.data('compact')) {
|
|
62
|
-
html += '<div class="sel_dialog_search_container">';
|
|
71
|
+
html += '<div class="sel_dialog_search_container" role="search">';
|
|
63
72
|
html += '<input type="text" id="fe_sel_dialog_search" class="sel_dialog_search" autocomplete="off" value=""/>';
|
|
64
73
|
html += '<div class="sel_dialog_search_icon"><i class="mdi mdi-magnify"></i></div>';
|
|
65
74
|
html += '</div>';
|
|
@@ -67,7 +76,7 @@ var SingleSelect = {
|
|
|
67
76
|
|
|
68
77
|
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea';
|
|
69
78
|
if ($this.data('nudgeheight')) html += ' nudgeheight';
|
|
70
|
-
html += '">';
|
|
79
|
+
html += '" role="listbox">';
|
|
71
80
|
|
|
72
81
|
for (var idx = 0, len = self.options.length; idx < len; idx++) {
|
|
73
82
|
var opt = self.options[idx];
|
|
@@ -83,7 +92,8 @@ var SingleSelect = {
|
|
|
83
92
|
}
|
|
84
93
|
if ($this.data('shrinkwrap')) html += ' shrinkwrap';
|
|
85
94
|
|
|
86
|
-
html += '" ' + ((idx >= SingleSelect.maxMenuItems) ? 'style="display:none"' : '') + ' data-value="' + opt.value + '"
|
|
95
|
+
html += '" ' + ((idx >= SingleSelect.maxMenuItems) ? 'style="display:none"' : '') + ' data-value="' + opt.value + '"';
|
|
96
|
+
html += ' role="option" aria-selected="' + (opt.selected ? 'true' : 'false') + '" tabindex="-1">';
|
|
87
97
|
|
|
88
98
|
if (opt.getAttribute && opt.getAttribute('data-icon')) {
|
|
89
99
|
html += '<i class="mdi mdi-' + opt.getAttribute('data-icon') + '"> </i>';
|
|
@@ -100,11 +110,11 @@ var SingleSelect = {
|
|
|
100
110
|
}
|
|
101
111
|
html += '</div>';
|
|
102
112
|
|
|
103
|
-
html += '</div>';
|
|
113
|
+
html += '</div>'; // scrollarea
|
|
104
114
|
|
|
105
115
|
Popover.attach( $ms, '<div style="padding:15px;">' + html + '</div>', $this.data('shrinkwrap') || false );
|
|
106
116
|
|
|
107
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('
|
|
117
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('click', function() {
|
|
108
118
|
// select item, close dialog and update multi-select
|
|
109
119
|
var $item = $(this);
|
|
110
120
|
$this.val( $item.data('value') );
|
|
@@ -154,19 +164,64 @@ var SingleSelect = {
|
|
|
154
164
|
if ((event.keyCode == 13) && value.length) {
|
|
155
165
|
event.preventDefault();
|
|
156
166
|
event.stopPropagation();
|
|
157
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item.match').slice(0, 1).trigger('
|
|
167
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item.match').slice(0, 1).trigger('click');
|
|
158
168
|
}
|
|
159
169
|
});
|
|
160
170
|
}
|
|
161
171
|
|
|
172
|
+
// handle keyboard focus
|
|
173
|
+
Popover.onKeyDown = SingleSelect.handleKeyDown;
|
|
174
|
+
|
|
162
175
|
// highlight select field under us
|
|
163
176
|
$ms.addClass('selected');
|
|
164
|
-
Popover.onDetach = function() {
|
|
165
|
-
|
|
177
|
+
Popover.onDetach = function() {
|
|
178
|
+
$ms.removeClass('selected').attr('aria-expanded', 'false').focus();
|
|
179
|
+
};
|
|
180
|
+
}); // click
|
|
166
181
|
|
|
167
182
|
}); // forach elem
|
|
168
183
|
},
|
|
169
184
|
|
|
185
|
+
handleKeyDown: function(event) {
|
|
186
|
+
var $options = $('#d_sel_dialog_scrollarea > div.sel_dialog_item');
|
|
187
|
+
var $active = $(document.activeElement).closest('.sel_dialog_item');
|
|
188
|
+
|
|
189
|
+
var focusItem = function($item) {
|
|
190
|
+
if (!$item.length) return;
|
|
191
|
+
$options.attr({ 'tabindex':'-1', 'aria-selected':'false' });
|
|
192
|
+
$item.attr({ 'tabindex':'0', 'aria-selected':'true' }).focus();
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
switch (event.key) {
|
|
196
|
+
case 'ArrowDown':
|
|
197
|
+
focusItem( $options.eq( $active.length ? ($active.index('.sel_dialog_item') + 1) : 0 ) );
|
|
198
|
+
event.preventDefault();
|
|
199
|
+
event.stopPropagation();
|
|
200
|
+
break;
|
|
201
|
+
|
|
202
|
+
case 'ArrowUp':
|
|
203
|
+
focusItem( $options.eq( $active.length ? Math.max(0, $active.index('.sel_dialog_item') - 1) : 0 ) );
|
|
204
|
+
event.preventDefault();
|
|
205
|
+
event.stopPropagation();
|
|
206
|
+
break;
|
|
207
|
+
|
|
208
|
+
case 'Enter':
|
|
209
|
+
case ' ':
|
|
210
|
+
if ($active.length) {
|
|
211
|
+
$active.click();
|
|
212
|
+
event.preventDefault();
|
|
213
|
+
event.stopPropagation();
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
|
|
217
|
+
case 'Escape':
|
|
218
|
+
Popover.detach();
|
|
219
|
+
event.preventDefault();
|
|
220
|
+
event.stopPropagation();
|
|
221
|
+
break;
|
|
222
|
+
} // switch key
|
|
223
|
+
}, // onKeyDown
|
|
224
|
+
|
|
170
225
|
popupQuickMenu: function(opts) {
|
|
171
226
|
// show popup menu on custom element
|
|
172
227
|
// opts: { elem, title, items, value, callback, nocheck?, onCancel? }
|
|
@@ -179,17 +234,20 @@ var SingleSelect = {
|
|
|
179
234
|
|
|
180
235
|
html += '<div class="sel_dialog_label">' + opts.title + '</div>';
|
|
181
236
|
if (opts.search) {
|
|
182
|
-
html += '<div class="sel_dialog_search_container">';
|
|
237
|
+
html += '<div class="sel_dialog_search_container" role="search">';
|
|
183
238
|
html += '<input type="text" id="fe_sel_dialog_search" class="sel_dialog_search" autocomplete="off" value=""/>';
|
|
184
239
|
html += '<div class="sel_dialog_search_icon"><i class="mdi mdi-magnify"></i></div>';
|
|
185
240
|
html += '</div>';
|
|
186
241
|
}
|
|
187
|
-
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea">';
|
|
242
|
+
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea" role="listbox">';
|
|
188
243
|
for (var idy = 0, ley = items.length; idy < ley; idy++) {
|
|
189
244
|
var item = items[idy];
|
|
190
245
|
var sel = (item.id == opts.value);
|
|
191
246
|
if (item.group) html += '<div class="sel_dialog_group">' + item.group + '</div>';
|
|
192
|
-
|
|
247
|
+
|
|
248
|
+
html += '<div class="sel_dialog_item ' + check + ' ' + (sel ? 'selected' : '') + ' shrinkwrap" data-value="' + item.id + '"';
|
|
249
|
+
html += ' role="option" aria-selected="' + (sel ? 'true' : 'false') + '" tabindex="-1">';
|
|
250
|
+
|
|
193
251
|
if (item.icon) html += '<i class="mdi mdi-' + item.icon + '"> </i>';
|
|
194
252
|
html += '<span>' + item.title + '</span>';
|
|
195
253
|
if (!opts.nocheck) html += '<div class="sel_dialog_item_check"><i class="mdi mdi-check"></i></div>';
|
|
@@ -199,7 +257,7 @@ var SingleSelect = {
|
|
|
199
257
|
|
|
200
258
|
Popover.attach( $elem, '<div style="padding:15px;">' + html + '</div>', true );
|
|
201
259
|
|
|
202
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('
|
|
260
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('click', function() {
|
|
203
261
|
// select item, close dialog and update state
|
|
204
262
|
var $item = $(this);
|
|
205
263
|
var value = $item.data('value');
|
|
@@ -207,10 +265,13 @@ var SingleSelect = {
|
|
|
207
265
|
delete opts.onCancel;
|
|
208
266
|
Popover.detach();
|
|
209
267
|
callback(value);
|
|
210
|
-
}); //
|
|
268
|
+
}); // click
|
|
269
|
+
|
|
270
|
+
// handle keyboard focus
|
|
271
|
+
Popover.onKeyDown = SingleSelect.handleKeyDown;
|
|
211
272
|
|
|
212
273
|
Popover.onDetach = function() {
|
|
213
|
-
$elem.removeClass('popped');
|
|
274
|
+
$elem.removeClass('popped').focus();
|
|
214
275
|
if (opts.onCancel) opts.onCancel();
|
|
215
276
|
};
|
|
216
277
|
|
|
@@ -249,7 +310,7 @@ var SingleSelect = {
|
|
|
249
310
|
event.preventDefault();
|
|
250
311
|
event.stopPropagation();
|
|
251
312
|
|
|
252
|
-
var mup = jQuery.Event( "
|
|
313
|
+
var mup = jQuery.Event( "click" );
|
|
253
314
|
mup.metaKey = true; // bypass `hold` feature
|
|
254
315
|
$('#d_sel_dialog_scrollarea > div.sel_dialog_item.match').slice(0, 1).trigger(mup);
|
|
255
316
|
}
|
|
@@ -266,9 +327,9 @@ var MultiSelect = {
|
|
|
266
327
|
$(sel).each( function() {
|
|
267
328
|
var self = this;
|
|
268
329
|
var $this = $(this);
|
|
269
|
-
$this.css('display', 'none');
|
|
330
|
+
$this.css('display', 'none').attr({ 'aria-hidden': true, 'tabindex': '-1' });
|
|
270
331
|
|
|
271
|
-
var $ms = $('<div class="multiselect multi"></div>');
|
|
332
|
+
var $ms = $('<div class="multiselect multi" role="button" tabindex="0" aria-haspopup="listbox" aria-expanded="false"></div>');
|
|
272
333
|
if ($this.data('compact')) $ms.addClass('compact');
|
|
273
334
|
if ($this.data('private')) $ms.attr('data-private', 1);
|
|
274
335
|
$this.after( $ms );
|
|
@@ -311,7 +372,7 @@ var MultiSelect = {
|
|
|
311
372
|
if (num_sel) $ms.append( '<div class="clear"></div>' );
|
|
312
373
|
else $ms.append( '<div class="placeholder">' + ($this.attr('placeholder') || 'Click to select...') + '</div>' );
|
|
313
374
|
|
|
314
|
-
$ms.find('div.item > i.mdi-close').on('
|
|
375
|
+
$ms.find('div.item > i.mdi-close').on('click', function(e) {
|
|
315
376
|
// user clicked on the 'X' -- remove this item and redraw
|
|
316
377
|
var $item = $(this).parent();
|
|
317
378
|
var value = $item.data('value');
|
|
@@ -335,8 +396,8 @@ var MultiSelect = {
|
|
|
335
396
|
|
|
336
397
|
if ($this.data('hold') && $this.data('volatile') && Popover.enabled && (Popover.$anchor.prop('id') == $this.prop('id'))) {
|
|
337
398
|
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').each( function(idx) {
|
|
338
|
-
if (self.options[idx].selected) $(this).addClass('selected');
|
|
339
|
-
else $(this).removeClass('selected');
|
|
399
|
+
if (self.options[idx].selected) $(this).addClass('selected').attr('aria-selected', 'true');
|
|
400
|
+
else $(this).removeClass('selected').attr('aria-selected', 'false');
|
|
340
401
|
} );
|
|
341
402
|
}
|
|
342
403
|
}; // redraw
|
|
@@ -349,7 +410,15 @@ var MultiSelect = {
|
|
|
349
410
|
// also expose redraw as a custom event that can be triggered
|
|
350
411
|
$this.on('redraw', redraw);
|
|
351
412
|
|
|
352
|
-
|
|
413
|
+
// allow keyboard to open menu
|
|
414
|
+
$ms.on('keydown', function(event) {
|
|
415
|
+
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
416
|
+
$ms.click();
|
|
417
|
+
event.preventDefault();
|
|
418
|
+
}
|
|
419
|
+
} );
|
|
420
|
+
|
|
421
|
+
$ms.on('click', function() {
|
|
353
422
|
// create popover dialog for selecting and filtering
|
|
354
423
|
var html = '';
|
|
355
424
|
var orig_sel_state = [];
|
|
@@ -357,6 +426,7 @@ var MultiSelect = {
|
|
|
357
426
|
var inherited = $this.data('inherited') ? ($this.data('inherited') || '').split(/\,\s*/) : [];
|
|
358
427
|
var is_private = $this.data('private');
|
|
359
428
|
if ($ms.hasClass('disabled')) return;
|
|
429
|
+
$ms.attr('aria-expanded', 'true');
|
|
360
430
|
|
|
361
431
|
html += '<div class="sel_dialog_label">' + ($this.attr('title') || 'Select Items');
|
|
362
432
|
if ($this.data('select-all')) {
|
|
@@ -365,11 +435,11 @@ var MultiSelect = {
|
|
|
365
435
|
}
|
|
366
436
|
html += '</div>';
|
|
367
437
|
|
|
368
|
-
html += '<div class="sel_dialog_search_container">';
|
|
438
|
+
html += '<div class="sel_dialog_search_container" role="search">';
|
|
369
439
|
html += '<input type="text" id="fe_sel_dialog_search" class="sel_dialog_search" autocomplete="off" value=""/>';
|
|
370
440
|
html += '<div class="sel_dialog_search_icon"><i class="mdi mdi-magnify"></i></div>';
|
|
371
441
|
html += '</div>';
|
|
372
|
-
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea">';
|
|
442
|
+
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea" role="listbox">';
|
|
373
443
|
|
|
374
444
|
for (var idx = 0, len = self.options.length; idx < len; idx++) {
|
|
375
445
|
var opt = self.options[idx];
|
|
@@ -387,7 +457,9 @@ var MultiSelect = {
|
|
|
387
457
|
if ($this.data('shrinkwrap')) html += ' shrinkwrap';
|
|
388
458
|
if (is_inherited) html += ' inherited';
|
|
389
459
|
|
|
390
|
-
html += '" data-value="' + opt.value + '" title="' + (is_inherited ? ($this.data('itooltip') || '(Inherited Item)') : '') + '"
|
|
460
|
+
html += '" data-value="' + opt.value + '" title="' + (is_inherited ? ($this.data('itooltip') || '(Inherited Item)') : '') + '"';
|
|
461
|
+
html += ' role="option" aria-selected="' + (opt.selected ? 'true' : 'false') + '" tabindex="-1">';
|
|
462
|
+
|
|
391
463
|
if (opt.getAttribute && opt.getAttribute('data-icon')) {
|
|
392
464
|
html += '<i class="mdi mdi-' + opt.getAttribute('data-icon') + '"> </i>';
|
|
393
465
|
}
|
|
@@ -409,7 +481,7 @@ var MultiSelect = {
|
|
|
409
481
|
|
|
410
482
|
Popover.attach( $ms, '<div style="padding:15px;">' + html + '</div>', $this.data('shrinkwrap') || false );
|
|
411
483
|
|
|
412
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('
|
|
484
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('click', function(event) {
|
|
413
485
|
// select item, close dialog and update multi-select
|
|
414
486
|
var $item = $(this);
|
|
415
487
|
if ($item.hasClass('inherited')) return; // no clicky on inherited items
|
|
@@ -422,7 +494,7 @@ var MultiSelect = {
|
|
|
422
494
|
var opt = self.options[idx];
|
|
423
495
|
if (opt.value == value) {
|
|
424
496
|
opt.selected = new_sel_state;
|
|
425
|
-
if (new_sel_state) $item.addClass('selected'); else $item.removeClass('selected');
|
|
497
|
+
if (new_sel_state) $item.addClass('selected').attr('aria-selected', 'true'); else $item.removeClass('selected').attr('aria-selected', 'false');
|
|
426
498
|
if (new_sel_state) new_sel_idx = idx;
|
|
427
499
|
idx = len;
|
|
428
500
|
}
|
|
@@ -436,7 +508,7 @@ var MultiSelect = {
|
|
|
436
508
|
// select range
|
|
437
509
|
if (last_sel_idx > new_sel_idx) { var temp = last_sel_idx; last_sel_idx = new_sel_idx; new_sel_idx = temp; }
|
|
438
510
|
for (var idx = last_sel_idx; idx <= new_sel_idx; idx++) { self.options[idx].selected = true; }
|
|
439
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').slice(last_sel_idx, new_sel_idx + 1).addClass('selected');
|
|
511
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').slice(last_sel_idx, new_sel_idx + 1).addClass('selected').attr('aria-selected', 'true');
|
|
440
512
|
}
|
|
441
513
|
else if ($this.data('hold') && event.altKey && (new_sel_idx > -1) && (last_sel_idx > -1) && (new_sel_idx != last_sel_idx)) {
|
|
442
514
|
// select pattern
|
|
@@ -445,7 +517,7 @@ var MultiSelect = {
|
|
|
445
517
|
for (var idx = last_sel_idx, len = self.options.length; idx < len; idx += dist) {
|
|
446
518
|
var opt = self.options[idx];
|
|
447
519
|
opt.selected = true;
|
|
448
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').slice(idx, idx + 1).addClass('selected');
|
|
520
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').slice(idx, idx + 1).addClass('selected').attr('aria-selected', 'true');
|
|
449
521
|
}
|
|
450
522
|
}
|
|
451
523
|
else if ($this.data('hold') && !new_sel_state) {
|
|
@@ -461,10 +533,10 @@ var MultiSelect = {
|
|
|
461
533
|
var is_all_sel = !!(find_objects(self.options, { selected: true }).length == self.options.length);
|
|
462
534
|
$('div.arrow_box div.sel_all_none').html( is_all_sel ? 'Select None' : 'Select All' );
|
|
463
535
|
}
|
|
464
|
-
}); //
|
|
536
|
+
}); // click
|
|
465
537
|
|
|
466
538
|
if ($this.data('hold')) {
|
|
467
|
-
$('#btn_sel_dialog_cancel').on('
|
|
539
|
+
$('#btn_sel_dialog_cancel').on('click', function() {
|
|
468
540
|
Popover.detach();
|
|
469
541
|
|
|
470
542
|
// restore original opts and redraw
|
|
@@ -476,11 +548,11 @@ var MultiSelect = {
|
|
|
476
548
|
redraw();
|
|
477
549
|
$this.trigger('change');
|
|
478
550
|
});
|
|
479
|
-
$('#btn_sel_dialog_add').on('
|
|
551
|
+
$('#btn_sel_dialog_add').on('click', function() { Popover.detach(); $ms.focus(); });
|
|
480
552
|
} // hold
|
|
481
553
|
|
|
482
554
|
// attach click handler for select-all-none
|
|
483
|
-
$('div.arrow_box div.sel_all_none').on('
|
|
555
|
+
$('div.arrow_box div.sel_all_none').on('click', function(event) {
|
|
484
556
|
var is_all_sel = !!(find_objects(self.options, { selected: true }).length == self.options.length);
|
|
485
557
|
var new_sel_state = !is_all_sel;
|
|
486
558
|
|
|
@@ -490,7 +562,7 @@ var MultiSelect = {
|
|
|
490
562
|
|
|
491
563
|
var opt = self.options[idx];
|
|
492
564
|
opt.selected = new_sel_state;
|
|
493
|
-
if (new_sel_state) $item.addClass('selected'); else $item.removeClass('selected');
|
|
565
|
+
if (new_sel_state) $item.addClass('selected').attr('aria-selected', 'true'); else $item.removeClass('selected').attr('aria-selected', 'false');
|
|
494
566
|
} );
|
|
495
567
|
|
|
496
568
|
$this.trigger('change');
|
|
@@ -535,7 +607,7 @@ var MultiSelect = {
|
|
|
535
607
|
event.preventDefault();
|
|
536
608
|
event.stopPropagation();
|
|
537
609
|
|
|
538
|
-
var mup = jQuery.Event( "
|
|
610
|
+
var mup = jQuery.Event( "click" );
|
|
539
611
|
mup.metaKey = true; // bypass `hold` feature
|
|
540
612
|
$('#d_sel_dialog_scrollarea > div.sel_dialog_item.match').slice(0, 1).trigger(mup);
|
|
541
613
|
}
|
|
@@ -543,13 +615,13 @@ var MultiSelect = {
|
|
|
543
615
|
// enter key WITHOUT value typed into search box + hold mode
|
|
544
616
|
event.preventDefault();
|
|
545
617
|
event.stopPropagation();
|
|
546
|
-
$('#btn_sel_dialog_add').trigger( jQuery.Event("
|
|
618
|
+
$('#btn_sel_dialog_add').trigger( jQuery.Event("click") );
|
|
547
619
|
}
|
|
548
620
|
else if ((event.keyCode == 27) && $this.data('hold')) {
|
|
549
621
|
// esc key WITHOUT value typed into search box + hold mode
|
|
550
622
|
event.preventDefault();
|
|
551
623
|
event.stopPropagation();
|
|
552
|
-
$('#btn_sel_dialog_cancel').trigger( jQuery.Event("
|
|
624
|
+
$('#btn_sel_dialog_cancel').trigger( jQuery.Event("click") );
|
|
553
625
|
}
|
|
554
626
|
});
|
|
555
627
|
|
|
@@ -559,23 +631,26 @@ var MultiSelect = {
|
|
|
559
631
|
// enter key
|
|
560
632
|
event.preventDefault();
|
|
561
633
|
event.stopPropagation();
|
|
562
|
-
$('#btn_sel_dialog_add').trigger( jQuery.Event("
|
|
634
|
+
$('#btn_sel_dialog_add').trigger( jQuery.Event("click") );
|
|
563
635
|
}
|
|
564
636
|
else if ((event.keyCode == 27) && !$input.is(':focus') && $this.data('hold')) {
|
|
565
637
|
// esc key
|
|
566
638
|
event.preventDefault();
|
|
567
639
|
event.stopPropagation();
|
|
568
|
-
$('#btn_sel_dialog_cancel').trigger( jQuery.Event("
|
|
640
|
+
$('#btn_sel_dialog_cancel').trigger( jQuery.Event("click") );
|
|
569
641
|
}
|
|
570
642
|
};
|
|
571
643
|
|
|
644
|
+
// handle keyboard focus
|
|
645
|
+
Popover.onKeyDown = SingleSelect.handleKeyDown;
|
|
646
|
+
|
|
572
647
|
// highlight multiselect field under us
|
|
573
648
|
$ms.addClass('selected');
|
|
574
649
|
Popover.onDetach = function() {
|
|
575
|
-
$ms.removeClass('selected');
|
|
650
|
+
$ms.removeClass('selected').attr('aria-expanded', 'false').focus();
|
|
576
651
|
if (Dialog.active) Dialog.autoResize();
|
|
577
652
|
};
|
|
578
|
-
}); //
|
|
653
|
+
}); // click
|
|
579
654
|
|
|
580
655
|
}); // foreach elem
|
|
581
656
|
},
|
|
@@ -591,16 +666,19 @@ var MultiSelect = {
|
|
|
591
666
|
|
|
592
667
|
html += '<div class="sel_dialog_label">' + opts.title + '</div>';
|
|
593
668
|
if (opts.search) {
|
|
594
|
-
html += '<div class="sel_dialog_search_container">';
|
|
669
|
+
html += '<div class="sel_dialog_search_container" role="search">';
|
|
595
670
|
html += '<input type="text" id="fe_sel_dialog_search" class="sel_dialog_search" autocomplete="off" value=""/>';
|
|
596
671
|
html += '<div class="sel_dialog_search_icon"><i class="mdi mdi-magnify"></i></div>';
|
|
597
672
|
html += '</div>';
|
|
598
673
|
}
|
|
599
|
-
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea">';
|
|
674
|
+
html += '<div id="d_sel_dialog_scrollarea" class="sel_dialog_scrollarea" role="listbox">';
|
|
600
675
|
for (var idy = 0, ley = items.length; idy < ley; idy++) {
|
|
601
676
|
var item = items[idy];
|
|
602
677
|
var sel = opts.values.includes(item.id);
|
|
603
|
-
|
|
678
|
+
|
|
679
|
+
html += '<div class="sel_dialog_item check ' + (sel ? 'selected' : '') + ' shrinkwrap" data-value="' + item.id + '"';
|
|
680
|
+
html += ' role="option" aria-selected="' + (sel ? 'true' : 'false') + '" tabindex="-1">';
|
|
681
|
+
|
|
604
682
|
if (item.icon) html += '<i class="mdi mdi-' + item.icon + '"> </i>';
|
|
605
683
|
html += '<span>' + item.title + '</span>';
|
|
606
684
|
html += '<div class="sel_dialog_item_check"><i class="mdi mdi-check"></i></div>';
|
|
@@ -610,7 +688,7 @@ var MultiSelect = {
|
|
|
610
688
|
|
|
611
689
|
Popover.attach( $elem, '<div style="padding:15px;">' + html + '</div>', true );
|
|
612
690
|
|
|
613
|
-
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('
|
|
691
|
+
$('#d_sel_dialog_scrollarea > div.sel_dialog_item').on('click', function() {
|
|
614
692
|
// select item, close dialog and update state
|
|
615
693
|
var $item = $(this);
|
|
616
694
|
if ($item.hasClass('selected')) $item.removeClass('selected');
|
|
@@ -623,10 +701,13 @@ var MultiSelect = {
|
|
|
623
701
|
|
|
624
702
|
Popover.detach();
|
|
625
703
|
callback(values);
|
|
626
|
-
}); //
|
|
704
|
+
}); // click
|
|
705
|
+
|
|
706
|
+
// handle keyboard focus
|
|
707
|
+
Popover.onKeyDown = SingleSelect.handleKeyDown;
|
|
627
708
|
|
|
628
709
|
Popover.onDetach = function() {
|
|
629
|
-
$elem.removeClass('popped');
|
|
710
|
+
$elem.removeClass('popped').focus();
|
|
630
711
|
};
|
|
631
712
|
|
|
632
713
|
$elem.addClass('popped');
|
|
@@ -664,7 +745,7 @@ var MultiSelect = {
|
|
|
664
745
|
event.preventDefault();
|
|
665
746
|
event.stopPropagation();
|
|
666
747
|
|
|
667
|
-
var mup = jQuery.Event( "
|
|
748
|
+
var mup = jQuery.Event( "click" );
|
|
668
749
|
mup.metaKey = true; // bypass `hold` feature
|
|
669
750
|
$('#d_sel_dialog_scrollarea > div.sel_dialog_item.match').slice(0, 1).trigger(mup);
|
|
670
751
|
}
|
|
@@ -681,8 +762,9 @@ var TextSelect = {
|
|
|
681
762
|
$(sel).each( function() {
|
|
682
763
|
var self = this;
|
|
683
764
|
var $this = $(this);
|
|
765
|
+
$this.css('display', 'none').attr({ 'aria-hidden': true, 'tabindex': '-1' });
|
|
684
766
|
|
|
685
|
-
var $ms = $('<div class="multiselect text"></div>');
|
|
767
|
+
var $ms = $('<div class="multiselect text" role="button" tabindex="0"></div>');
|
|
686
768
|
$this.after( $ms );
|
|
687
769
|
|
|
688
770
|
var redraw = function() {
|
|
@@ -703,7 +785,7 @@ var TextSelect = {
|
|
|
703
785
|
if (num_sel) $ms.append( '<div class="clear"></div>' );
|
|
704
786
|
else $ms.append( '<div class="placeholder">' + ($this.attr('placeholder') || 'Click to add...') + '</div>' );
|
|
705
787
|
|
|
706
|
-
$ms.find('div.item > i').on('
|
|
788
|
+
$ms.find('div.item > i').on('click', function(e) {
|
|
707
789
|
// user clicked on the 'X' -- remove this item and redraw
|
|
708
790
|
var $item = $(this).parent();
|
|
709
791
|
var value = $item.data('value');
|
|
@@ -726,7 +808,15 @@ var TextSelect = {
|
|
|
726
808
|
// also expose redraw as a custom event that can be triggered
|
|
727
809
|
$this.on('redraw', redraw);
|
|
728
810
|
|
|
729
|
-
|
|
811
|
+
// allow keyboard to open menu
|
|
812
|
+
$ms.on('keydown', function(event) {
|
|
813
|
+
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
814
|
+
$ms.click();
|
|
815
|
+
event.preventDefault();
|
|
816
|
+
}
|
|
817
|
+
} );
|
|
818
|
+
|
|
819
|
+
$ms.on('click', function() {
|
|
730
820
|
// create popover dialog for adding new items
|
|
731
821
|
var html = '';
|
|
732
822
|
if ($ms.hasClass('disabled')) return;
|
|
@@ -772,8 +862,8 @@ var TextSelect = {
|
|
|
772
862
|
$this.trigger('change');
|
|
773
863
|
}; // doAdd
|
|
774
864
|
|
|
775
|
-
$('#btn_sel_dialog_cancel').on('
|
|
776
|
-
$('#btn_sel_dialog_add').on('
|
|
865
|
+
$('#btn_sel_dialog_cancel').on('click', function() { Popover.detach(); });
|
|
866
|
+
$('#btn_sel_dialog_add').on('click', function() { doAdd(); });
|
|
777
867
|
|
|
778
868
|
var $input = $('#fe_sel_dialog_text').focus().on('keydown', function(event) {
|
|
779
869
|
// capture enter key
|
|
@@ -786,8 +876,10 @@ var TextSelect = {
|
|
|
786
876
|
|
|
787
877
|
// highlight multiselect field under us
|
|
788
878
|
$ms.addClass('selected');
|
|
789
|
-
Popover.onDetach = function() {
|
|
790
|
-
|
|
879
|
+
Popover.onDetach = function() {
|
|
880
|
+
$ms.removeClass('selected').focus();
|
|
881
|
+
};
|
|
882
|
+
}); // click
|
|
791
883
|
|
|
792
884
|
}); // forach elem
|
|
793
885
|
},
|
|
@@ -835,8 +927,8 @@ var TextSelect = {
|
|
|
835
927
|
callback(value);
|
|
836
928
|
}; // doAdd
|
|
837
929
|
|
|
838
|
-
$('#btn_sel_dialog_cancel').on('
|
|
839
|
-
$('#btn_sel_dialog_add').on('
|
|
930
|
+
$('#btn_sel_dialog_cancel').on('click', function() { Popover.detach(); });
|
|
931
|
+
$('#btn_sel_dialog_add').on('click', function() { doAdd(); });
|
|
840
932
|
|
|
841
933
|
var $input = $('#fe_sel_dialog_text').focus().on('keydown', function(event) {
|
|
842
934
|
// capture enter key
|
|
@@ -848,7 +940,9 @@ var TextSelect = {
|
|
|
848
940
|
});
|
|
849
941
|
|
|
850
942
|
$elem.addClass('popped');
|
|
851
|
-
Popover.onDetach = function() {
|
|
943
|
+
Popover.onDetach = function() {
|
|
944
|
+
$elem.removeClass('popped').focus();
|
|
945
|
+
};
|
|
852
946
|
}
|
|
853
947
|
|
|
854
948
|
}; // TextSelect
|
package/js/tools.js
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-xyapp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.10",
|
|
4
4
|
"description": "A theme for xyOps.",
|
|
5
5
|
"author": "Joseph Huckaby <jhuckaby@pixlcore.com>",
|
|
6
6
|
"homepage": "https://github.com/pixlcore/pixl-xyapp",
|
|
7
|
-
"license": "
|
|
7
|
+
"license": "BSD-3-Clause",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/pixlcore/pixl-xyapp.git"
|