pixl-xyapp 2.1.11 → 2.1.14
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/README.md +3 -3
- package/css/base.css +26 -2
- package/js/base.js +6 -0
- package/js/page.js +7 -160
- package/js/select.js +173 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -293,7 +293,7 @@ The library provides CSS styles and JavaScript functions for creating data table
|
|
|
293
293
|
</table>
|
|
294
294
|
```
|
|
295
295
|
|
|
296
|
-
In addition to the CSS, a pagination system is provided, to assist you with generating tables from a large dataset that have pagination links built-in. The function to call is `this.
|
|
296
|
+
In addition to the CSS, a pagination system is provided, to assist you with generating tables from a large dataset that have pagination links built-in. The function to call is `this.getPaginatedGrid()` and is available in the `Page` base class. It returns the final rendered HTML for the page.
|
|
297
297
|
|
|
298
298
|
To use it, you'll need to provide an object containing the following pieces of information:
|
|
299
299
|
|
|
@@ -322,7 +322,7 @@ Here is an example:
|
|
|
322
322
|
{ name: 'Rhubarb', color: 'Purple', size: '2ft', quantity: 190, price: '$3.99', created: 1441724876 }
|
|
323
323
|
];
|
|
324
324
|
|
|
325
|
-
var html = this.
|
|
325
|
+
var html = this.getPaginatedGrid({
|
|
326
326
|
cols: cols,
|
|
327
327
|
rows: rows,
|
|
328
328
|
data_type: 'vegetable',
|
|
@@ -343,7 +343,7 @@ Here is an example:
|
|
|
343
343
|
});
|
|
344
344
|
```
|
|
345
345
|
|
|
346
|
-
So the idea here is, we have a dataset of 10 items total, but we are only showing 5 items per page. So we have an array of 5 items in `rows`, but we're specifying the `total` as 10, and `offset` as 0 (first page). Based on this, the `
|
|
346
|
+
So the idea here is, we have a dataset of 10 items total, but we are only showing 5 items per page. So we have an array of 5 items in `rows`, but we're specifying the `total` as 10, and `offset` as 0 (first page). Based on this, the `getPaginatedGrid()` will generate the proper pagination links.
|
|
347
347
|
|
|
348
348
|
Your callback is fired once per row, and is passed the current row (array element from `rows`), and the localized index in `idx` (starts from `0` regardless of `offset`). Your function should return an array of values which should match up with the `cols`, and each will be stuffed into a `<TD>` element.
|
|
349
349
|
|
package/css/base.css
CHANGED
|
@@ -185,6 +185,9 @@ button.link {
|
|
|
185
185
|
margin: 0;
|
|
186
186
|
font: inherit;
|
|
187
187
|
}
|
|
188
|
+
button.link.icon_pad i.mdi {
|
|
189
|
+
padding-right: 5px;
|
|
190
|
+
}
|
|
188
191
|
|
|
189
192
|
a, .link {
|
|
190
193
|
color: var(--link-color);
|
|
@@ -1311,9 +1314,27 @@ body.dark .dialog .multiselect > .item {
|
|
|
1311
1314
|
background: rgba(255, 255, 255, 0.1);
|
|
1312
1315
|
}
|
|
1313
1316
|
|
|
1314
|
-
.multiselect > .item >
|
|
1317
|
+
.multiselect > .item > button.mdi {
|
|
1318
|
+
background: none;
|
|
1319
|
+
border: none;
|
|
1320
|
+
padding: 0;
|
|
1321
|
+
margin: 0;
|
|
1322
|
+
font: inherit;
|
|
1323
|
+
cursor: pointer;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
.multiselect > .item > button.mdi:before {
|
|
1327
|
+
transform: scale(1.20);
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
.multiselect > .item > button.mdi:focus-visible {
|
|
1331
|
+
outline: 2px solid var(--theme-color);
|
|
1332
|
+
outline-offset: -2px;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
.multiselect > .item > button.mdi-close:hover:before {
|
|
1315
1336
|
content: "\F0159"; /* mdi-close-circle */
|
|
1316
|
-
color: var(--
|
|
1337
|
+
color: var(--red);
|
|
1317
1338
|
}
|
|
1318
1339
|
|
|
1319
1340
|
.multiselect > .item.inherited {
|
|
@@ -2535,6 +2556,9 @@ div.dropzone.drag > div.dz_bar {
|
|
|
2535
2556
|
overflow: hidden;
|
|
2536
2557
|
text-overflow: ellipsis;
|
|
2537
2558
|
}
|
|
2559
|
+
.data_grid_pagination button.link {
|
|
2560
|
+
text-transform: uppercase;
|
|
2561
|
+
}
|
|
2538
2562
|
.data_grid_pagination i.mdi:before {
|
|
2539
2563
|
transform: scale(1.5);
|
|
2540
2564
|
}
|
package/js/base.js
CHANGED
|
@@ -8,6 +8,11 @@ var app = {
|
|
|
8
8
|
secure: !!location.protocol.match(/^https/i),
|
|
9
9
|
retina: (window.devicePixelRatio > 1),
|
|
10
10
|
mobile: !!navigator.userAgent.match(/(iOS|iPhone|iPad|Android)/),
|
|
11
|
+
os: {
|
|
12
|
+
mac: !!navigator.userAgent.match(/(Macintosh|Mac OS X|macOS)/),
|
|
13
|
+
win: !!navigator.userAgent.match(/(Windows)/),
|
|
14
|
+
linux: !!navigator.userAgent.match(/(Linux)/)
|
|
15
|
+
},
|
|
11
16
|
base_api_url: '/api',
|
|
12
17
|
plain_text_post: false,
|
|
13
18
|
prefs: {},
|
|
@@ -163,6 +168,7 @@ var app = {
|
|
|
163
168
|
var id = this.page_manager.current_page_id;
|
|
164
169
|
var page = this.page_manager.find(id);
|
|
165
170
|
if (page && page.onKeyDown) page.onKeyDown(event);
|
|
171
|
+
else if (app.onKeyDown) app.onKeyDown(event);
|
|
166
172
|
}
|
|
167
173
|
else if (app.onKeyDown) app.onKeyDown(event);
|
|
168
174
|
},
|
package/js/page.js
CHANGED
|
@@ -493,161 +493,6 @@ window.Page = class Page {
|
|
|
493
493
|
$(elem).closest('.form_row_range').find('input').val(value);
|
|
494
494
|
}
|
|
495
495
|
|
|
496
|
-
getPaginatedTable() {
|
|
497
|
-
// get html for paginated table
|
|
498
|
-
// dual-calling convention: (resp, cols, data_type, callback) or (args)
|
|
499
|
-
var args = null;
|
|
500
|
-
if (arguments.length == 1) {
|
|
501
|
-
// custom args calling convention
|
|
502
|
-
args = arguments[0];
|
|
503
|
-
|
|
504
|
-
// V2 API
|
|
505
|
-
if (!args.resp && args.rows && args.total) {
|
|
506
|
-
args.resp = {
|
|
507
|
-
rows: args.rows,
|
|
508
|
-
list: { length: args.total }
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
// classic calling convention
|
|
514
|
-
args = {
|
|
515
|
-
resp: arguments[0],
|
|
516
|
-
cols: arguments[1],
|
|
517
|
-
data_type: arguments[2],
|
|
518
|
-
callback: arguments[3],
|
|
519
|
-
limit: this.args.limit,
|
|
520
|
-
offset: this.args.offset || 0
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
var resp = args.resp;
|
|
525
|
-
var cols = args.cols;
|
|
526
|
-
var data_type = args.data_type;
|
|
527
|
-
var callback = args.callback;
|
|
528
|
-
var cpl = args.pagination_link || '';
|
|
529
|
-
var html = '';
|
|
530
|
-
|
|
531
|
-
// pagination header
|
|
532
|
-
html += '<div class="pagination">';
|
|
533
|
-
html += '<table cellspacing="0" cellpadding="0" border="0" width="100%"><tr>';
|
|
534
|
-
|
|
535
|
-
var results = {
|
|
536
|
-
limit: args.limit,
|
|
537
|
-
offset: args.offset || 0,
|
|
538
|
-
total: resp.list.length
|
|
539
|
-
};
|
|
540
|
-
|
|
541
|
-
var num_pages = Math.floor( results.total / results.limit ) + 1;
|
|
542
|
-
if (results.total % results.limit == 0) num_pages--;
|
|
543
|
-
var current_page = Math.floor( results.offset / results.limit ) + 1;
|
|
544
|
-
|
|
545
|
-
html += '<td align="left" width="33%">';
|
|
546
|
-
html += commify(results.total) + ' ' + pluralize(data_type, results.total) + ' found';
|
|
547
|
-
html += '</td>';
|
|
548
|
-
|
|
549
|
-
html += '<td align="center" width="34%">';
|
|
550
|
-
if (num_pages > 1) html += 'Page ' + commify(current_page) + ' of ' + commify(num_pages);
|
|
551
|
-
else html += ' ';
|
|
552
|
-
html += '</td>';
|
|
553
|
-
|
|
554
|
-
html += '<td align="right" width="33%">';
|
|
555
|
-
|
|
556
|
-
if (num_pages > 1) {
|
|
557
|
-
// html += 'Page: ';
|
|
558
|
-
if (current_page > 1) {
|
|
559
|
-
if (cpl) {
|
|
560
|
-
html += '<span class="link" onClick="'+cpl+'('+Math.floor((current_page - 2) * results.limit)+')">« Prev</span>';
|
|
561
|
-
}
|
|
562
|
-
else {
|
|
563
|
-
html += '<a href="#' + this.ID + compose_query_string(merge_objects(this.args, {
|
|
564
|
-
offset: (current_page - 2) * results.limit
|
|
565
|
-
})) + '">« Prev</a>';
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
html += ' ';
|
|
569
|
-
|
|
570
|
-
var start_page = current_page - 4;
|
|
571
|
-
var end_page = current_page + 5;
|
|
572
|
-
|
|
573
|
-
if (start_page < 1) {
|
|
574
|
-
end_page += (1 - start_page);
|
|
575
|
-
start_page = 1;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
if (end_page > num_pages) {
|
|
579
|
-
start_page -= (end_page - num_pages);
|
|
580
|
-
if (start_page < 1) start_page = 1;
|
|
581
|
-
end_page = num_pages;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
for (var idx = start_page; idx <= end_page; idx++) {
|
|
585
|
-
if (idx == current_page) {
|
|
586
|
-
html += '<b>' + commify(idx) + '</b>';
|
|
587
|
-
}
|
|
588
|
-
else {
|
|
589
|
-
if (cpl) {
|
|
590
|
-
html += '<span class="link" onClick="'+cpl+'('+Math.floor((idx - 1) * results.limit)+')">' + commify(idx) + '</span>';
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
html += '<a href="#' + this.ID + compose_query_string(merge_objects(this.args, {
|
|
594
|
-
offset: (idx - 1) * results.limit
|
|
595
|
-
})) + '">' + commify(idx) + '</a>';
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
html += ' ';
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
html += ' ';
|
|
602
|
-
if (current_page < num_pages) {
|
|
603
|
-
if (cpl) {
|
|
604
|
-
html += '<span class="link" onClick="'+cpl+'('+Math.floor((current_page + 0) * results.limit)+')">Next »</span>';
|
|
605
|
-
}
|
|
606
|
-
else {
|
|
607
|
-
html += '<a href="#' + this.ID + compose_query_string(merge_objects(this.args, {
|
|
608
|
-
offset: (current_page + 0) * results.limit
|
|
609
|
-
})) + '">Next »</a>';
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
} // more than one page
|
|
613
|
-
else {
|
|
614
|
-
html += 'Page 1 of 1';
|
|
615
|
-
}
|
|
616
|
-
html += '</td>';
|
|
617
|
-
html += '</tr></table>';
|
|
618
|
-
html += '</div>';
|
|
619
|
-
|
|
620
|
-
html += '<div style="margin-top:5px; overflow-x:auto;">';
|
|
621
|
-
|
|
622
|
-
var tattrs = args.attribs || {};
|
|
623
|
-
if (!tattrs.class) tattrs.class = 'data_table ellip';
|
|
624
|
-
if (!tattrs.width) tattrs.width = '100%';
|
|
625
|
-
html += '<table ' + compose_attribs(tattrs) + '>';
|
|
626
|
-
|
|
627
|
-
html += '<tr><th>' + cols.join('</th><th>').replace(/\s+/g, ' ') + '</th></tr>';
|
|
628
|
-
|
|
629
|
-
for (var idx = 0, len = resp.rows.length; idx < len; idx++) {
|
|
630
|
-
var row = resp.rows[idx];
|
|
631
|
-
var tds = callback(row, idx);
|
|
632
|
-
if (tds) {
|
|
633
|
-
html += '<tr' + (tds.className ? (' class="'+tds.className+'"') : '') + '>';
|
|
634
|
-
html += '<td>' + tds.join('</td><td>') + '</td>';
|
|
635
|
-
html += '</tr>';
|
|
636
|
-
}
|
|
637
|
-
} // foreach row
|
|
638
|
-
|
|
639
|
-
if (!resp.rows.length) {
|
|
640
|
-
html += '<tr><td colspan="'+cols.length+'" align="center" style="padding-top:10px; padding-bottom:10px; font-weight:bold;">';
|
|
641
|
-
html += 'No '+pluralize(data_type)+' found.';
|
|
642
|
-
html += '</td></tr>';
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
html += '</table>';
|
|
646
|
-
html += '</div>';
|
|
647
|
-
|
|
648
|
-
return html;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
496
|
getPaginatedGrid() {
|
|
652
497
|
// get html for paginated grid
|
|
653
498
|
// multi-calling convention: (resp, cols, data_type, callback), or (args, callback), or (args)
|
|
@@ -717,12 +562,13 @@ window.Page = class Page {
|
|
|
717
562
|
// html += 'Page: ';
|
|
718
563
|
if (current_page > 1) {
|
|
719
564
|
if (cpl) {
|
|
720
|
-
|
|
565
|
+
var click = cpl + '(' + Math.floor((current_page - 2) * results.limit) + ')';
|
|
566
|
+
html += '<button class="link" ' + (args.primary ? 'id="btn_nav_prev"' : '') + ' onClick="' + click + '"><i class="mdi mdi-chevron-left"></i> Prev</button>';
|
|
721
567
|
}
|
|
722
568
|
else {
|
|
723
569
|
html += '<a href="#' + this.ID + compose_query_string(merge_objects(this.args, {
|
|
724
570
|
offset: (current_page - 2) * results.limit
|
|
725
|
-
})) + '">&
|
|
571
|
+
})) + '" ' + (args.primary ? 'id="btn_nav_prev"' : '') + '><i class="mdi mdi-chevron-left"></i> Prev</a>';
|
|
726
572
|
}
|
|
727
573
|
}
|
|
728
574
|
html += ' ';
|
|
@@ -748,7 +594,7 @@ window.Page = class Page {
|
|
|
748
594
|
}
|
|
749
595
|
else {
|
|
750
596
|
if (cpl) {
|
|
751
|
-
html += '<
|
|
597
|
+
html += '<button class="link" onClick="'+cpl+'('+Math.floor((idx - 1) * results.limit)+')">' + commify(idx) + '</button>';
|
|
752
598
|
}
|
|
753
599
|
else {
|
|
754
600
|
html += '<a href="#' + this.ID + compose_query_string(merge_objects(this.args, {
|
|
@@ -763,12 +609,13 @@ window.Page = class Page {
|
|
|
763
609
|
|
|
764
610
|
if (current_page < num_pages) {
|
|
765
611
|
if (cpl) {
|
|
766
|
-
|
|
612
|
+
var click = cpl + '(' + Math.floor((current_page + 0) * results.limit) + ')';
|
|
613
|
+
html += '<button class="link" ' + (args.primary ? 'id="btn_nav_next"' : '') + ' onClick="' + click + '">Next <i class="mdi mdi-chevron-right"></i></button>';
|
|
767
614
|
}
|
|
768
615
|
else {
|
|
769
616
|
html += '<a href="#' + this.ID + compose_query_string(merge_objects(this.args, {
|
|
770
617
|
offset: (current_page + 0) * results.limit
|
|
771
|
-
})) + '">Next
|
|
618
|
+
})) + '" ' + (args.primary ? 'id="btn_nav_next"' : '') + '>Next <i class="mdi mdi-chevron-right"></i></a>';
|
|
772
619
|
}
|
|
773
620
|
}
|
|
774
621
|
} // more than one page
|
package/js/select.js
CHANGED
|
@@ -358,7 +358,7 @@ var MultiSelect = {
|
|
|
358
358
|
}
|
|
359
359
|
else if (opt.selected) {
|
|
360
360
|
// item is selected
|
|
361
|
-
var html = '<
|
|
361
|
+
var html = '<button class="mdi mdi-close" aria-label="Remove Item: ' + encode_attrib_entities(opt.label) + '"> </button>';
|
|
362
362
|
if (opt.getAttribute && opt.getAttribute('data-icon')) {
|
|
363
363
|
html += '<i class="mdi mdi-' + opt.getAttribute('data-icon') + '"> </i>';
|
|
364
364
|
}
|
|
@@ -372,8 +372,10 @@ var MultiSelect = {
|
|
|
372
372
|
if (num_sel) $ms.append( '<div class="clear"></div>' );
|
|
373
373
|
else $ms.append( '<div class="placeholder">' + ($this.attr('placeholder') || 'Click to select...') + '</div>' );
|
|
374
374
|
|
|
375
|
-
$ms.find('div.item >
|
|
375
|
+
$ms.find('div.item > button.mdi-close').on('click keydown', function(e) {
|
|
376
376
|
// user clicked on the 'X' -- remove this item and redraw
|
|
377
|
+
if (e.key && (e.key != 'Enter') && (e.key != ' ')) return;
|
|
378
|
+
|
|
377
379
|
var $item = $(this).parent();
|
|
378
380
|
var value = $item.data('value');
|
|
379
381
|
for (var idx = 0, len = self.options.length; idx < len; idx++) {
|
|
@@ -411,7 +413,7 @@ var MultiSelect = {
|
|
|
411
413
|
$this.on('redraw', redraw);
|
|
412
414
|
|
|
413
415
|
// allow keyboard to open menu
|
|
414
|
-
$ms.on('
|
|
416
|
+
$ms.on('keypress', function(event) {
|
|
415
417
|
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
416
418
|
$ms.click();
|
|
417
419
|
event.preventDefault();
|
|
@@ -776,7 +778,7 @@ var TextSelect = {
|
|
|
776
778
|
for (var idx = 0, len = self.options.length; idx < len; idx++) {
|
|
777
779
|
var opt = self.options[idx];
|
|
778
780
|
var $item = $('<div class="item"></div>').data('value', opt.value).html(
|
|
779
|
-
'<
|
|
781
|
+
'<button class="mdi mdi-close" aria-label="Remove Item: ' + encode_attrib_entities(opt.label) + '"> </button>' + opt.label
|
|
780
782
|
);
|
|
781
783
|
$ms.append( $item );
|
|
782
784
|
num_sel++;
|
|
@@ -785,8 +787,10 @@ var TextSelect = {
|
|
|
785
787
|
if (num_sel) $ms.append( '<div class="clear"></div>' );
|
|
786
788
|
else $ms.append( '<div class="placeholder">' + ($this.attr('placeholder') || 'Click to add...') + '</div>' );
|
|
787
789
|
|
|
788
|
-
$ms.find('div.item >
|
|
790
|
+
$ms.find('div.item > button.mdi').on('click keydown', function(e) {
|
|
789
791
|
// user clicked on the 'X' -- remove this item and redraw
|
|
792
|
+
if (e.key && (e.key != 'Enter') && (e.key != ' ')) return;
|
|
793
|
+
|
|
790
794
|
var $item = $(this).parent();
|
|
791
795
|
var value = $item.data('value');
|
|
792
796
|
|
|
@@ -809,7 +813,7 @@ var TextSelect = {
|
|
|
809
813
|
$this.on('redraw', redraw);
|
|
810
814
|
|
|
811
815
|
// allow keyboard to open menu
|
|
812
|
-
$ms.on('
|
|
816
|
+
$ms.on('keypress', function(event) {
|
|
813
817
|
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
814
818
|
$ms.click();
|
|
815
819
|
event.preventDefault();
|
|
@@ -946,3 +950,166 @@ var TextSelect = {
|
|
|
946
950
|
}
|
|
947
951
|
|
|
948
952
|
}; // TextSelect
|
|
953
|
+
|
|
954
|
+
var KeySelect = {
|
|
955
|
+
|
|
956
|
+
init: function(sel) {
|
|
957
|
+
// initialize all key-selects based on selector
|
|
958
|
+
$(sel).each( function() {
|
|
959
|
+
var self = this;
|
|
960
|
+
var $this = $(this);
|
|
961
|
+
$this.css('display', 'none').attr({ 'aria-hidden': true, 'tabindex': '-1' });
|
|
962
|
+
|
|
963
|
+
var $ms = $('<div class="multiselect text" role="button" tabindex="0"></div>');
|
|
964
|
+
$this.after( $ms );
|
|
965
|
+
|
|
966
|
+
var redraw = function() {
|
|
967
|
+
// render contents of visible multiselect div
|
|
968
|
+
var num_sel = 0;
|
|
969
|
+
$ms.empty();
|
|
970
|
+
$ms.append('<div class="select_chevron mdi mdi-plus"></div>');
|
|
971
|
+
|
|
972
|
+
for (var idx = 0, len = self.options.length; idx < len; idx++) {
|
|
973
|
+
var opt = self.options[idx];
|
|
974
|
+
var $item = $('<div class="item"></div>').data('value', opt.value).html(
|
|
975
|
+
'<button class="mdi mdi-close" aria-label="Remove Key: ' + encode_attrib_entities(opt.label) + '"> </button>' + opt.label
|
|
976
|
+
);
|
|
977
|
+
$ms.append( $item );
|
|
978
|
+
num_sel++;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
if (num_sel) $ms.append( '<div class="clear"></div>' );
|
|
982
|
+
else $ms.append( '<div class="placeholder">' + ($this.attr('placeholder') || 'Click to add...') + '</div>' );
|
|
983
|
+
|
|
984
|
+
$ms.find('div.item > button.mdi').on('click keydown', function(e) {
|
|
985
|
+
// user clicked on the 'X' -- remove this item and redraw
|
|
986
|
+
if (e.key && (e.key != 'Enter') && (e.key != ' ')) return;
|
|
987
|
+
|
|
988
|
+
var $item = $(this).parent();
|
|
989
|
+
var value = $item.data('value');
|
|
990
|
+
|
|
991
|
+
var idx = find_object_idx( self.options, { value: value } );
|
|
992
|
+
self.options.remove( idx );
|
|
993
|
+
|
|
994
|
+
$this.trigger('change');
|
|
995
|
+
e.stopPropagation();
|
|
996
|
+
e.preventDefault();
|
|
997
|
+
return false;
|
|
998
|
+
});
|
|
999
|
+
}; // redraw
|
|
1000
|
+
|
|
1001
|
+
redraw();
|
|
1002
|
+
|
|
1003
|
+
// also trigger a redraw if the underlying hidden select changes
|
|
1004
|
+
$this.on('change', redraw);
|
|
1005
|
+
|
|
1006
|
+
// also expose redraw as a custom event that can be triggered
|
|
1007
|
+
$this.on('redraw', redraw);
|
|
1008
|
+
|
|
1009
|
+
// allow keyboard to open menu
|
|
1010
|
+
$ms.on('keypress', function(event) {
|
|
1011
|
+
if ((event.key == 'Enter') || (event.key == ' ')) {
|
|
1012
|
+
$ms.click();
|
|
1013
|
+
event.preventDefault();
|
|
1014
|
+
}
|
|
1015
|
+
} );
|
|
1016
|
+
|
|
1017
|
+
$ms.on('click', function() {
|
|
1018
|
+
// create popover dialog for adding new items
|
|
1019
|
+
var html = '';
|
|
1020
|
+
if ($ms.hasClass('disabled')) return;
|
|
1021
|
+
|
|
1022
|
+
html += '<div class="sel_dialog_label">' + ($this.attr('title') || 'Add New Item') + '</div>';
|
|
1023
|
+
html += '<div class="sel_dialog_search_container">';
|
|
1024
|
+
html += '<input type="hidden" id="fe_sel_dialog_key" value=""/>';
|
|
1025
|
+
html += '<input type="text" id="fe_sel_dialog_text" class="sel_dialog_search" style="border-radius:2px;" autocomplete="off" value=""/>';
|
|
1026
|
+
html += '<div class="sel_dialog_search_icon"><i class="mdi mdi-' + ($this.attr('icon') || 'plus') + '"></i></div>';
|
|
1027
|
+
html += '</div>';
|
|
1028
|
+
|
|
1029
|
+
if ($this.attr('description')) {
|
|
1030
|
+
html += '<div class="sel_dialog_caption">' + $this.attr('description') + '</div>';
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
html += '<div class="sel_dialog_button_container">';
|
|
1034
|
+
html += '<div class="button" id="btn_sel_dialog_cancel">Cancel</div>';
|
|
1035
|
+
html += '<div class="button primary" id="btn_sel_dialog_add">' + ($this.attr('confirm') || 'Add Hot Key') + '</div>';
|
|
1036
|
+
html += '</div>';
|
|
1037
|
+
|
|
1038
|
+
Popover.attach( $ms, '<div style="padding:15px;">' + html + '</div>', $this.data('shrinkwrap') || false );
|
|
1039
|
+
|
|
1040
|
+
var doAdd = function() {
|
|
1041
|
+
app.clearError();
|
|
1042
|
+
|
|
1043
|
+
var value = $('#fe_sel_dialog_key').val();
|
|
1044
|
+
var label = $('#fe_sel_dialog_text').val();
|
|
1045
|
+
|
|
1046
|
+
if (!value.length || find_object(self.options, { value: value })) {
|
|
1047
|
+
Popover.detach();
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// add new item
|
|
1052
|
+
var opt = new Option( label, value );
|
|
1053
|
+
opt.selected = true;
|
|
1054
|
+
self.options[ self.options.length ] = opt;
|
|
1055
|
+
|
|
1056
|
+
Popover.detach();
|
|
1057
|
+
$this.trigger('change');
|
|
1058
|
+
}; // doAdd
|
|
1059
|
+
|
|
1060
|
+
$('#btn_sel_dialog_cancel').on('click', function() { Popover.detach(); });
|
|
1061
|
+
$('#btn_sel_dialog_add').on('click', function() { doAdd(); });
|
|
1062
|
+
|
|
1063
|
+
var $input = $('#fe_sel_dialog_text').focus().on('keydown', function(event) {
|
|
1064
|
+
// capture keydown
|
|
1065
|
+
if ((event.keyCode == 13) && this.value.length) {
|
|
1066
|
+
event.preventDefault();
|
|
1067
|
+
event.stopPropagation();
|
|
1068
|
+
doAdd();
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
var key_id = KeySelect.getKeyID(event);
|
|
1072
|
+
if (!key_id) return;
|
|
1073
|
+
|
|
1074
|
+
event.preventDefault();
|
|
1075
|
+
event.stopPropagation();
|
|
1076
|
+
|
|
1077
|
+
$('#fe_sel_dialog_key').val( key_id );
|
|
1078
|
+
$('#fe_sel_dialog_text').val( KeySelect.getkeyLabel(key_id) );
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
// highlight multiselect field under us
|
|
1082
|
+
$ms.addClass('selected');
|
|
1083
|
+
Popover.onDetach = function() {
|
|
1084
|
+
$ms.removeClass('selected').focus();
|
|
1085
|
+
};
|
|
1086
|
+
}); // click
|
|
1087
|
+
|
|
1088
|
+
}); // forach elem
|
|
1089
|
+
},
|
|
1090
|
+
|
|
1091
|
+
getKeyID(event) {
|
|
1092
|
+
// get get ID based on event
|
|
1093
|
+
// ignore modifiers by themselves
|
|
1094
|
+
if (event.key.match(/^(Shift|Control|Alt|Meta)$/)) return '';
|
|
1095
|
+
|
|
1096
|
+
var parts = [];
|
|
1097
|
+
if (event.shiftKey) parts.push('Shift');
|
|
1098
|
+
if (event.ctrlKey) parts.push('Control');
|
|
1099
|
+
if (event.altKey) parts.push('Alt');
|
|
1100
|
+
if (event.metaKey) parts.push('Meta');
|
|
1101
|
+
if (!parts.includes(event.code)) parts.push( event.code );
|
|
1102
|
+
|
|
1103
|
+
return parts.join('+');
|
|
1104
|
+
},
|
|
1105
|
+
|
|
1106
|
+
getkeyLabel(key_id, glue = '+') {
|
|
1107
|
+
// get formatted label based on key id
|
|
1108
|
+
var os = app.os;
|
|
1109
|
+
return key_id.split(/\+/).map( function(key) {
|
|
1110
|
+
if (key == 'Meta') return os.mac ? 'Command' : (os.win ? 'Windows' : 'Super');
|
|
1111
|
+
else return key.replace(/^(Key|Digit)/, '');
|
|
1112
|
+
} ).join(glue);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
}; // KeySelect
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-xyapp",
|
|
3
|
-
"version": "2.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.1.14",
|
|
4
|
+
"description": "Front-end web application and theme for xyOps.",
|
|
5
5
|
"author": "Joseph Huckaby <jhuckaby@pixlcore.com>",
|
|
6
6
|
"homepage": "https://github.com/pixlcore/pixl-xyapp",
|
|
7
7
|
"license": "BSD-3-Clause",
|