oxidized-web 0.14.0 → 0.15.0
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.
Potentially problematic release.
This version of oxidized-web might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -3
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +1 -6
- data/CHANGELOG.md +18 -0
- data/Rakefile +1 -0
- data/docs/development.md +16 -4
- data/lib/oxidized/web/public/scripts/oxidized.js +0 -36
- data/lib/oxidized/web/public/weblibs/buttons.bootstrap5.css +77 -80
- data/lib/oxidized/web/public/weblibs/buttons.bootstrap5.js +4 -7
- data/lib/oxidized/web/public/weblibs/dataTables.bootstrap5.css +45 -15
- data/lib/oxidized/web/public/weblibs/dataTables.bootstrap5.js +12 -37
- data/lib/oxidized/web/public/weblibs/dataTables.buttons.js +139 -23
- data/lib/oxidized/web/public/weblibs/dataTables.js +1190 -518
- data/lib/oxidized/web/version.rb +1 -1
- data/lib/oxidized/web/views/layout.haml +0 -4
- data/lib/oxidized/web/webapp.rb +20 -35
- data/oxidized-web.gemspec +16 -15
- data/package-lock.json +14 -14
- data/spec/node_spec.rb +3 -47
- data/spec/node_version_spec.rb +102 -0
- data/spec/nodes_spec.rb +57 -0
- data/spec/spec_helper.rb +3 -0
- metadata +30 -35
- data/lib/oxidized/web/mig.rb +0 -140
- data/lib/oxidized/web/public/scripts/script-migration.js +0 -15
- data/lib/oxidized/web/views/migration.haml +0 -53
@@ -74,6 +74,14 @@ $.extend( true, DataTable.ext.classes, {
|
|
74
74
|
},
|
75
75
|
processing: {
|
76
76
|
container: "dt-processing card"
|
77
|
+
},
|
78
|
+
layout: {
|
79
|
+
row: 'row mt-2 justify-content-between',
|
80
|
+
cell: 'd-md-flex justify-content-between align-items-center',
|
81
|
+
tableCell: 'col-12',
|
82
|
+
start: 'dt-layout-start col-md-auto me-auto',
|
83
|
+
end: 'dt-layout-end col-md-auto ms-auto',
|
84
|
+
full: 'dt-layout-full col-md'
|
77
85
|
}
|
78
86
|
} );
|
79
87
|
|
@@ -91,9 +99,10 @@ DataTable.ext.renderer.pagingButton.bootstrap = function (settings, buttonType,
|
|
91
99
|
}
|
92
100
|
|
93
101
|
var li = $('<li>').addClass(btnClasses.join(' '));
|
94
|
-
var a = $('<
|
95
|
-
'
|
96
|
-
|
102
|
+
var a = $('<button>', {
|
103
|
+
'class': 'page-link',
|
104
|
+
role: 'link',
|
105
|
+
type: 'button'
|
97
106
|
})
|
98
107
|
.html(content)
|
99
108
|
.appendTo(li);
|
@@ -108,40 +117,6 @@ DataTable.ext.renderer.pagingContainer.bootstrap = function (settings, buttonEls
|
|
108
117
|
return $('<ul/>').addClass('pagination').append(buttonEls);
|
109
118
|
};
|
110
119
|
|
111
|
-
DataTable.ext.renderer.layout.bootstrap = function ( settings, container, items ) {
|
112
|
-
var row = $( '<div/>', {
|
113
|
-
"class": items.full ?
|
114
|
-
'row mt-2 justify-content-md-center' :
|
115
|
-
'row mt-2 justify-content-between'
|
116
|
-
} )
|
117
|
-
.appendTo( container );
|
118
|
-
|
119
|
-
$.each( items, function (key, val) {
|
120
|
-
var klass;
|
121
|
-
|
122
|
-
// Apply start / end (left / right when ltr) margins
|
123
|
-
if (val.table) {
|
124
|
-
klass = 'col-12';
|
125
|
-
}
|
126
|
-
else if (key === 'start') {
|
127
|
-
klass = 'col-md-auto me-auto';
|
128
|
-
}
|
129
|
-
else if (key === 'end') {
|
130
|
-
klass = 'col-md-auto ms-auto';
|
131
|
-
}
|
132
|
-
else {
|
133
|
-
klass = 'col-md';
|
134
|
-
}
|
135
|
-
|
136
|
-
$( '<div/>', {
|
137
|
-
id: val.id || null,
|
138
|
-
"class": klass + ' ' + (val.className || '')
|
139
|
-
} )
|
140
|
-
.append( val.contents )
|
141
|
-
.appendTo( row );
|
142
|
-
} );
|
143
|
-
};
|
144
|
-
|
145
120
|
|
146
121
|
return DataTable;
|
147
122
|
}));
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! Buttons for DataTables 3.
|
1
|
+
/*! Buttons for DataTables 3.2.2
|
2
2
|
* © SpryMedia Ltd - datatables.net/license
|
3
3
|
*/
|
4
4
|
|
@@ -302,9 +302,20 @@ $.extend(Buttons.prototype, {
|
|
302
302
|
disable: function (node) {
|
303
303
|
var button = this._nodeToButton(node);
|
304
304
|
|
305
|
-
|
306
|
-
|
307
|
-
|
305
|
+
if (button.isSplit) {
|
306
|
+
$(button.node.childNodes[0])
|
307
|
+
.addClass(this.c.dom.button.disabled)
|
308
|
+
.prop('disabled', true);
|
309
|
+
}
|
310
|
+
else {
|
311
|
+
$(button.node)
|
312
|
+
.addClass(this.c.dom.button.disabled)
|
313
|
+
.prop('disabled', true);
|
314
|
+
}
|
315
|
+
|
316
|
+
button.disabled = true;
|
317
|
+
|
318
|
+
this._checkSplitEnable();
|
308
319
|
|
309
320
|
return this;
|
310
321
|
},
|
@@ -355,9 +366,21 @@ $.extend(Buttons.prototype, {
|
|
355
366
|
}
|
356
367
|
|
357
368
|
var button = this._nodeToButton(node);
|
358
|
-
|
359
|
-
|
360
|
-
.
|
369
|
+
|
370
|
+
if (button.isSplit) {
|
371
|
+
$(button.node.childNodes[0])
|
372
|
+
.removeClass(this.c.dom.button.disabled)
|
373
|
+
.prop('disabled', false);
|
374
|
+
}
|
375
|
+
else {
|
376
|
+
$(button.node)
|
377
|
+
.removeClass(this.c.dom.button.disabled)
|
378
|
+
.prop('disabled', false);
|
379
|
+
}
|
380
|
+
|
381
|
+
button.disabled = false;
|
382
|
+
|
383
|
+
this._checkSplitEnable();
|
361
384
|
|
362
385
|
return this;
|
363
386
|
},
|
@@ -670,6 +693,13 @@ $.extend(Buttons.prototype, {
|
|
670
693
|
attachTo.push(built);
|
671
694
|
}
|
672
695
|
|
696
|
+
// Any button type can have a drop icon set
|
697
|
+
if (built.conf.dropIcon && ! built.conf.split) {
|
698
|
+
$(built.node)
|
699
|
+
.addClass(this.c.dom.button.dropClass)
|
700
|
+
.append(this.c.dom.button.dropHtml);
|
701
|
+
}
|
702
|
+
|
673
703
|
// Create the dropdown for a collection
|
674
704
|
if (built.conf.buttons) {
|
675
705
|
built.collection = $(
|
@@ -677,8 +707,6 @@ $.extend(Buttons.prototype, {
|
|
677
707
|
);
|
678
708
|
built.conf._collection = built.collection;
|
679
709
|
|
680
|
-
$(built.node).append(domCollection.action.dropHtml);
|
681
|
-
|
682
710
|
this._expandButton(
|
683
711
|
built.buttons,
|
684
712
|
built.conf.buttons,
|
@@ -827,7 +855,7 @@ $.extend(Buttons.prototype, {
|
|
827
855
|
else {
|
828
856
|
run(e, dt, button, config, function () {});
|
829
857
|
}
|
830
|
-
}
|
858
|
+
};
|
831
859
|
|
832
860
|
var tag = config.tag || dom.tag;
|
833
861
|
var clickBlurs =
|
@@ -946,6 +974,7 @@ $.extend(Buttons.prototype, {
|
|
946
974
|
.append(button);
|
947
975
|
|
948
976
|
var dropButtonConfig = $.extend(config, {
|
977
|
+
autoClose: true,
|
949
978
|
align: dropdownConf.dropdown.align,
|
950
979
|
attr: {
|
951
980
|
'aria-haspopup': 'dialog',
|
@@ -982,7 +1011,8 @@ $.extend(Buttons.prototype, {
|
|
982
1011
|
dropdownConf.dropdown.className +
|
983
1012
|
' dt-button"></button>'
|
984
1013
|
)
|
985
|
-
.html(
|
1014
|
+
.html(this.c.dom.button.dropHtml)
|
1015
|
+
.addClass(this.c.dom.button.dropClass)
|
986
1016
|
.on('click.dtb', function (e) {
|
987
1017
|
e.preventDefault();
|
988
1018
|
e.stopPropagation();
|
@@ -1024,6 +1054,57 @@ $.extend(Buttons.prototype, {
|
|
1024
1054
|
};
|
1025
1055
|
},
|
1026
1056
|
|
1057
|
+
/**
|
1058
|
+
* Spin over buttons checking if splits should be enabled or not.
|
1059
|
+
* @param {*} buttons Array of buttons to check
|
1060
|
+
*/
|
1061
|
+
_checkSplitEnable: function (buttons) {
|
1062
|
+
if (! buttons) {
|
1063
|
+
buttons = this.s.buttons;
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
for (var i=0 ; i<buttons.length ; i++) {
|
1067
|
+
var button = buttons[i];
|
1068
|
+
|
1069
|
+
// Check if the button is a split one and if so, determine
|
1070
|
+
// its state
|
1071
|
+
if (button.isSplit) {
|
1072
|
+
var splitBtn = button.node.childNodes[1];
|
1073
|
+
|
1074
|
+
if (this._checkAnyEnabled(button.buttons)) {
|
1075
|
+
// Enable the split
|
1076
|
+
$(splitBtn)
|
1077
|
+
.removeClass(this.c.dom.button.disabled)
|
1078
|
+
.prop('disabled', false);
|
1079
|
+
}
|
1080
|
+
else {
|
1081
|
+
$(splitBtn)
|
1082
|
+
.addClass(this.c.dom.button.disabled)
|
1083
|
+
.prop('disabled', false);
|
1084
|
+
}
|
1085
|
+
}
|
1086
|
+
else if (button.isCollection) {
|
1087
|
+
// Nest down into collections
|
1088
|
+
this._checkSplitEnable(button.buttons);
|
1089
|
+
}
|
1090
|
+
}
|
1091
|
+
},
|
1092
|
+
|
1093
|
+
/**
|
1094
|
+
* Check an array of buttons and see if any are enabled in it
|
1095
|
+
* @param {*} buttons Button array
|
1096
|
+
* @returns true if a button is enabled, false otherwise
|
1097
|
+
*/
|
1098
|
+
_checkAnyEnabled: function (buttons) {
|
1099
|
+
for (var i=0 ; i<buttons.length ; i++) {
|
1100
|
+
if (! buttons[i].disabled) {
|
1101
|
+
return true;
|
1102
|
+
}
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
return false;
|
1106
|
+
},
|
1107
|
+
|
1027
1108
|
/**
|
1028
1109
|
* Get the button object from a node (recursive)
|
1029
1110
|
* @param {node} node Button node
|
@@ -1037,7 +1118,7 @@ $.extend(Buttons.prototype, {
|
|
1037
1118
|
}
|
1038
1119
|
|
1039
1120
|
for (var i = 0, ien = buttons.length; i < ien; i++) {
|
1040
|
-
if (buttons[i].node === node) {
|
1121
|
+
if (buttons[i].node === node || $(buttons[i].node).children().eq(0).get(0) === node) {
|
1041
1122
|
return buttons[i];
|
1042
1123
|
}
|
1043
1124
|
|
@@ -1306,7 +1387,8 @@ $.extend(Buttons.prototype, {
|
|
1306
1387
|
|
1307
1388
|
var containerSelector =
|
1308
1389
|
options.tag + '.' + options.containerClassName.replace(/ /g, '.');
|
1309
|
-
var
|
1390
|
+
var hostButtonNode = hostButton.node();
|
1391
|
+
var hostNode = options.collectionLayout.includes('fixed') ? $('body') : hostButton.node();
|
1310
1392
|
|
1311
1393
|
var close = function () {
|
1312
1394
|
closed = true;
|
@@ -1333,6 +1415,8 @@ $.extend(Buttons.prototype, {
|
|
1333
1415
|
$('body').off('.dtb-collection');
|
1334
1416
|
dt.off('buttons-action.b-internal');
|
1335
1417
|
dt.off('destroy');
|
1418
|
+
|
1419
|
+
$('body').trigger('buttons-popover-hide.dt');
|
1336
1420
|
};
|
1337
1421
|
|
1338
1422
|
if (content === false) {
|
@@ -1352,6 +1436,26 @@ $.extend(Buttons.prototype, {
|
|
1352
1436
|
close();
|
1353
1437
|
}
|
1354
1438
|
|
1439
|
+
// Sort buttons if defined
|
1440
|
+
if (options.sort) {
|
1441
|
+
var elements = $('button', content)
|
1442
|
+
.map(function (idx, el) {
|
1443
|
+
return {
|
1444
|
+
text: $(el).text(),
|
1445
|
+
el: el
|
1446
|
+
};
|
1447
|
+
})
|
1448
|
+
.toArray();
|
1449
|
+
|
1450
|
+
elements.sort(function (a, b) {
|
1451
|
+
return a.text.localeCompare(b.text);
|
1452
|
+
});
|
1453
|
+
|
1454
|
+
$(content).append(elements.map(function (v) {
|
1455
|
+
return v.el;
|
1456
|
+
}));
|
1457
|
+
}
|
1458
|
+
|
1355
1459
|
// Try to be smart about the layout
|
1356
1460
|
var cnt = $('.dt-button', content).length;
|
1357
1461
|
var mod = '';
|
@@ -1382,10 +1486,10 @@ $.extend(Buttons.prototype, {
|
|
1382
1486
|
.attr('role', 'menu')
|
1383
1487
|
.appendTo(display);
|
1384
1488
|
|
1385
|
-
|
1489
|
+
hostButtonNode.attr('aria-expanded', 'true');
|
1386
1490
|
|
1387
1491
|
if (hostNode.parents('body')[0] !== document.body) {
|
1388
|
-
hostNode = document.body.
|
1492
|
+
hostNode = $(document.body).children('div, section, p').last();
|
1389
1493
|
}
|
1390
1494
|
|
1391
1495
|
if (options.popoverTitle) {
|
@@ -1514,7 +1618,7 @@ $.extend(Buttons.prototype, {
|
|
1514
1618
|
popoverSizes.marginBottom;
|
1515
1619
|
}
|
1516
1620
|
|
1517
|
-
if (
|
1621
|
+
if (offsetParent.offset().top + top < $(window).scrollTop()) {
|
1518
1622
|
// Correction for when the top is beyond the top of the page
|
1519
1623
|
top = buttonPosition.top + hostNode.outerHeight();
|
1520
1624
|
}
|
@@ -1882,6 +1986,11 @@ Buttons.buttonSelector = function (insts, selector) {
|
|
1882
1986
|
* @param {*} str Data to strip
|
1883
1987
|
*/
|
1884
1988
|
Buttons.stripData = function (str, config) {
|
1989
|
+
// If the input is an HTML element, we can use the HTML from it (HTML might be stripped below).
|
1990
|
+
if (str !== null && typeof str === 'object' && str.nodeName && str.nodeType) {
|
1991
|
+
str = str.innerHTML;
|
1992
|
+
}
|
1993
|
+
|
1885
1994
|
if (typeof str !== 'string') {
|
1886
1995
|
return str;
|
1887
1996
|
}
|
@@ -1914,6 +2023,14 @@ Buttons.stripData = function (str, config) {
|
|
1914
2023
|
}
|
1915
2024
|
}
|
1916
2025
|
|
2026
|
+
// Prevent Excel from running a formula
|
2027
|
+
if (!config || config.escapeExcelFormula) {
|
2028
|
+
if (str.match(/^[=+\-@\t\r]/)) {
|
2029
|
+
console.log('matching and updateing');
|
2030
|
+
str = "'" + str;
|
2031
|
+
}
|
2032
|
+
}
|
2033
|
+
|
1917
2034
|
return str;
|
1918
2035
|
};
|
1919
2036
|
|
@@ -1976,10 +2093,6 @@ Buttons.defaults = {
|
|
1976
2093
|
className: 'dt-buttons'
|
1977
2094
|
},
|
1978
2095
|
collection: {
|
1979
|
-
action: {
|
1980
|
-
// action button
|
1981
|
-
dropHtml: '<span class="dt-button-down-arrow">▼</span>'
|
1982
|
-
},
|
1983
2096
|
container: {
|
1984
2097
|
// The element used for the dropdown
|
1985
2098
|
className: 'dt-button-collection',
|
@@ -2005,7 +2118,9 @@ Buttons.defaults = {
|
|
2005
2118
|
liner: {
|
2006
2119
|
tag: 'span',
|
2007
2120
|
className: ''
|
2008
|
-
}
|
2121
|
+
},
|
2122
|
+
dropClass: '',
|
2123
|
+
dropHtml: '<span class="dt-button-down-arrow">▼</span>'
|
2009
2124
|
},
|
2010
2125
|
split: {
|
2011
2126
|
action: {
|
@@ -2017,7 +2132,6 @@ Buttons.defaults = {
|
|
2017
2132
|
// button to trigger the dropdown
|
2018
2133
|
align: 'split-right',
|
2019
2134
|
className: 'dt-button-split-drop',
|
2020
|
-
dropHtml: '<span class="dt-button-down-arrow">▼</span>',
|
2021
2135
|
splitAlignClass: 'dt-button-split-left',
|
2022
2136
|
tag: 'button'
|
2023
2137
|
},
|
@@ -2035,7 +2149,7 @@ Buttons.defaults = {
|
|
2035
2149
|
* @type {string}
|
2036
2150
|
* @static
|
2037
2151
|
*/
|
2038
|
-
Buttons.version = '3.
|
2152
|
+
Buttons.version = '3.2.2';
|
2039
2153
|
|
2040
2154
|
$.extend(_dtButtons, {
|
2041
2155
|
collection: {
|
@@ -2044,6 +2158,7 @@ $.extend(_dtButtons, {
|
|
2044
2158
|
},
|
2045
2159
|
className: 'buttons-collection',
|
2046
2160
|
closeButton: false,
|
2161
|
+
dropIcon: true,
|
2047
2162
|
init: function (dt, button) {
|
2048
2163
|
button.attr('aria-expanded', false);
|
2049
2164
|
},
|
@@ -2638,6 +2753,7 @@ var _exportData = function (dt, inOpts) {
|
|
2638
2753
|
stripHtml: true,
|
2639
2754
|
stripNewlines: true,
|
2640
2755
|
decodeEntities: true,
|
2756
|
+
escapeExcelFormula: false,
|
2641
2757
|
trim: true,
|
2642
2758
|
format: {
|
2643
2759
|
header: function (d) {
|