oxidized-web 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
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) {
|