wai-website-theme 1.3.1 → 1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/different.html +2 -1
  3. data/_includes/external.html +2 -1
  4. data/_includes/header.html +2 -1
  5. data/_includes/menuitem.html +6 -2
  6. data/_includes/peoplelist.html +21 -0
  7. data/_includes/prevnext-navigation.html +56 -0
  8. data/_includes/{prevnext.html → prevnext-order.html} +9 -0
  9. data/_includes/translation-note-msg.html +5 -3
  10. data/_includes/video-player.html +2 -2
  11. data/_layouts/default.html +8 -1
  12. data/_layouts/news.html +7 -1
  13. data/_layouts/policy.html +7 -1
  14. data/_layouts/sidenav.html +8 -1
  15. data/_layouts/sidenavsidebar.html +8 -1
  16. data/assets/ableplayer/Gruntfile.js +2 -1
  17. data/assets/ableplayer/README.md +158 -85
  18. data/assets/ableplayer/build/ableplayer.dist.js +15445 -13823
  19. data/assets/ableplayer/build/ableplayer.js +15445 -13823
  20. data/assets/ableplayer/build/ableplayer.min.css +1 -2
  21. data/assets/ableplayer/build/ableplayer.min.js +3 -10
  22. data/assets/ableplayer/package-lock.json +944 -346
  23. data/assets/ableplayer/package.json +8 -8
  24. data/assets/ableplayer/scripts/ableplayer-base.js +515 -524
  25. data/assets/ableplayer/scripts/browser.js +158 -158
  26. data/assets/ableplayer/scripts/buildplayer.js +1750 -1682
  27. data/assets/ableplayer/scripts/caption.js +424 -401
  28. data/assets/ableplayer/scripts/chapters.js +259 -259
  29. data/assets/ableplayer/scripts/control.js +1831 -1594
  30. data/assets/ableplayer/scripts/description.js +333 -256
  31. data/assets/ableplayer/scripts/dialog.js +145 -145
  32. data/assets/ableplayer/scripts/dragdrop.js +746 -749
  33. data/assets/ableplayer/scripts/event.js +875 -696
  34. data/assets/ableplayer/scripts/initialize.js +819 -912
  35. data/assets/ableplayer/scripts/langs.js +979 -743
  36. data/assets/ableplayer/scripts/metadata.js +124 -124
  37. data/assets/ableplayer/scripts/misc.js +170 -137
  38. data/assets/ableplayer/scripts/preference.js +904 -904
  39. data/assets/ableplayer/scripts/search.js +172 -172
  40. data/assets/ableplayer/scripts/sign.js +82 -78
  41. data/assets/ableplayer/scripts/slider.js +449 -448
  42. data/assets/ableplayer/scripts/track.js +409 -309
  43. data/assets/ableplayer/scripts/transcript.js +684 -595
  44. data/assets/ableplayer/scripts/translation.js +63 -67
  45. data/assets/ableplayer/scripts/ttml2webvtt.js +85 -85
  46. data/assets/ableplayer/scripts/vimeo.js +448 -0
  47. data/assets/ableplayer/scripts/volume.js +395 -380
  48. data/assets/ableplayer/scripts/vts.js +1077 -1077
  49. data/assets/ableplayer/scripts/webvtt.js +766 -763
  50. data/assets/ableplayer/scripts/youtube.js +695 -478
  51. data/assets/ableplayer/styles/ableplayer.css +54 -46
  52. data/assets/ableplayer/translations/nl.js +54 -54
  53. data/assets/ableplayer/translations/pt-br.js +311 -0
  54. data/assets/ableplayer/translations/tr.js +311 -0
  55. data/assets/ableplayer/translations/zh-tw.js +1 -1
  56. data/assets/css/style.css +1 -1
  57. data/assets/css/style.css.map +1 -1
  58. data/assets/images/icons.svg +5 -5
  59. data/assets/scripts/main.js +7 -0
  60. data/assets/search/tipuesearch.js +3 -3
  61. metadata +8 -3
@@ -1,134 +1,134 @@
1
1
  (function ($) {
2
- AblePlayer.prototype.updateMeta = function (time) {
3
- if (this.hasMeta) {
4
- if (this.metaType === 'text') {
5
- this.$metaDiv.show();
6
- this.showMeta(time || this.getElapsed());
7
- }
8
- else {
9
- this.showMeta(time || this.getElapsed());
10
- }
11
- }
12
- };
2
+ AblePlayer.prototype.updateMeta = function (time) {
3
+ if (this.hasMeta) {
4
+ if (this.metaType === 'text') {
5
+ this.$metaDiv.show();
6
+ this.showMeta(time || this.elapsed);
7
+ }
8
+ else {
9
+ this.showMeta(time || this.elapsed);
10
+ }
11
+ }
12
+ };
13
13
 
14
- AblePlayer.prototype.showMeta = function(now) {
15
- var tempSelectors, m, thisMeta,
16
- cues, cueText, cueLines, i, line,
17
- showDuration, focusTarget;
14
+ AblePlayer.prototype.showMeta = function(now) {
15
+ var tempSelectors, m, thisMeta,
16
+ cues, cueText, cueLines, i, line,
17
+ showDuration, focusTarget;
18
18
 
19
- tempSelectors = [];
20
- if (this.meta.length >= 1) {
21
- cues = this.meta;
22
- }
23
- else {
24
- cues = [];
25
- }
26
- for (m = 0; m < cues.length; m++) {
27
- if ((cues[m].start <= now) && (cues[m].end > now)) {
28
- thisMeta = m;
29
- break;
30
- }
31
- }
32
- if (typeof thisMeta !== 'undefined') {
33
- if (this.currentMeta !== thisMeta) {
34
- if (this.metaType === 'text') {
35
- // it's time to load the new metadata cue into the container div
36
- this.$metaDiv.html(this.flattenCueForMeta(cues[thisMeta]).replace('\n', '<br>'));
37
- }
38
- else if (this.metaType === 'selector') {
39
- // it's time to show content referenced by the designated selector(s)
40
- cueText = this.flattenCueForMeta(cues[thisMeta]);
41
- cueLines = cueText.split('\n');
42
- for (i=0; i<cueLines.length; i++) {
43
- line = $.trim(cueLines[i]);
44
- if (line.toLowerCase().trim() === 'pause') {
45
- // don't show big play button when pausing via metadata
46
- this.hideBigPlayButton = true;
47
- this.pauseMedia();
48
- }
49
- else if (line.toLowerCase().substring(0,6) == 'focus:') {
50
- focusTarget = line.substring(6).trim();
51
- if ($(focusTarget).length) {
52
- $(focusTarget).focus();
53
- }
54
- }
55
- else {
56
- if ($(line).length) {
57
- // selector exists
58
- showDuration = parseInt($(line).attr('data-duration'));
59
- if (typeof showDuration !== 'undefined' && !isNaN(showDuration)) {
60
- $(line).show().delay(showDuration).fadeOut();
61
- }
62
- else {
63
- // no duration specified. Just show the element until end time specified in VTT file
64
- $(line).show();
65
- }
66
- // add to array of visible selectors so it can be hidden at end time
67
- this.visibleSelectors.push(line);
68
- tempSelectors.push(line);
69
- }
70
- }
71
- }
72
- // now step through this.visibleSelectors and remove anything that's stale
73
- if (this.visibleSelectors && this.visibleSelectors.length) {
74
- if (this.visibleSelectors.length !== tempSelectors.length) {
75
- for (i=this.visibleSelectors.length-1; i>=0; i--) {
76
- if ($.inArray(this.visibleSelectors[i],tempSelectors) == -1) {
77
- $(this.visibleSelectors[i]).hide();
78
- this.visibleSelectors.splice(i,1);
79
- }
80
- }
81
- }
82
- }
19
+ tempSelectors = [];
20
+ if (this.meta.length >= 1) {
21
+ cues = this.meta;
22
+ }
23
+ else {
24
+ cues = [];
25
+ }
26
+ for (m = 0; m < cues.length; m++) {
27
+ if ((cues[m].start <= now) && (cues[m].end > now)) {
28
+ thisMeta = m;
29
+ break;
30
+ }
31
+ }
32
+ if (typeof thisMeta !== 'undefined') {
33
+ if (this.currentMeta !== thisMeta) {
34
+ if (this.metaType === 'text') {
35
+ // it's time to load the new metadata cue into the container div
36
+ this.$metaDiv.html(this.flattenCueForMeta(cues[thisMeta]).replace('\n', '<br>'));
37
+ }
38
+ else if (this.metaType === 'selector') {
39
+ // it's time to show content referenced by the designated selector(s)
40
+ cueText = this.flattenCueForMeta(cues[thisMeta]);
41
+ cueLines = cueText.split('\n');
42
+ for (i=0; i<cueLines.length; i++) {
43
+ line = $.trim(cueLines[i]);
44
+ if (line.toLowerCase().trim() === 'pause') {
45
+ // don't show big play button when pausing via metadata
46
+ this.hideBigPlayButton = true;
47
+ this.pauseMedia();
48
+ }
49
+ else if (line.toLowerCase().substring(0,6) == 'focus:') {
50
+ focusTarget = line.substring(6).trim();
51
+ if ($(focusTarget).length) {
52
+ $(focusTarget).focus();
53
+ }
54
+ }
55
+ else {
56
+ if ($(line).length) {
57
+ // selector exists
58
+ showDuration = parseInt($(line).attr('data-duration'));
59
+ if (typeof showDuration !== 'undefined' && !isNaN(showDuration)) {
60
+ $(line).show().delay(showDuration).fadeOut();
61
+ }
62
+ else {
63
+ // no duration specified. Just show the element until end time specified in VTT file
64
+ $(line).show();
65
+ }
66
+ // add to array of visible selectors so it can be hidden at end time
67
+ this.visibleSelectors.push(line);
68
+ tempSelectors.push(line);
69
+ }
70
+ }
71
+ }
72
+ // now step through this.visibleSelectors and remove anything that's stale
73
+ if (this.visibleSelectors && this.visibleSelectors.length) {
74
+ if (this.visibleSelectors.length !== tempSelectors.length) {
75
+ for (i=this.visibleSelectors.length-1; i>=0; i--) {
76
+ if ($.inArray(this.visibleSelectors[i],tempSelectors) == -1) {
77
+ $(this.visibleSelectors[i]).hide();
78
+ this.visibleSelectors.splice(i,1);
79
+ }
80
+ }
81
+ }
82
+ }
83
83
 
84
- }
85
- this.currentMeta = thisMeta;
86
- }
87
- }
88
- else {
89
- // there is currently no metadata. Empty stale content
90
- if (typeof this.$metaDiv !== 'undefined') {
91
- this.$metaDiv.html('');
92
- }
93
- if (this.visibleSelectors && this.visibleSelectors.length) {
94
- for (i=0; i<this.visibleSelectors.length; i++) {
95
- $(this.visibleSelectors[i]).hide();
96
- }
97
- // reset array
98
- this.visibleSelectors = [];
99
- }
100
- this.currentMeta = -1;
101
- }
102
- };
84
+ }
85
+ this.currentMeta = thisMeta;
86
+ }
87
+ }
88
+ else {
89
+ // there is currently no metadata. Empty stale content
90
+ if (typeof this.$metaDiv !== 'undefined') {
91
+ this.$metaDiv.html('');
92
+ }
93
+ if (this.visibleSelectors && this.visibleSelectors.length) {
94
+ for (i=0; i<this.visibleSelectors.length; i++) {
95
+ $(this.visibleSelectors[i]).hide();
96
+ }
97
+ // reset array
98
+ this.visibleSelectors = [];
99
+ }
100
+ this.currentMeta = -1;
101
+ }
102
+ };
103
103
 
104
- // Takes a cue and returns the metadata text to display for it.
105
- AblePlayer.prototype.flattenCueForMeta = function (cue) {
106
- var result = [];
104
+ // Takes a cue and returns the metadata text to display for it.
105
+ AblePlayer.prototype.flattenCueForMeta = function (cue) {
106
+ var result = [];
107
107
 
108
- var flattenComponent = function (component) {
109
- var result = [], ii;
110
- if (component.type === 'string') {
111
- result.push(component.value);
112
- }
113
- else if (component.type === 'v') {
114
- result.push('[' + component.value + ']');
115
- for (ii = 0; ii < component.children.length; ii++) {
116
- result.push(flattenComponent(component.children[ii]));
117
- }
118
- }
119
- else {
120
- for (ii = 0; ii < component.children.length; ii++) {
121
- result.push(flattenComponent(component.children[ii]));
122
- }
123
- }
124
- return result.join('');
125
- }
108
+ var flattenComponent = function (component) {
109
+ var result = [], ii;
110
+ if (component.type === 'string') {
111
+ result.push(component.value);
112
+ }
113
+ else if (component.type === 'v') {
114
+ result.push('[' + component.value + ']');
115
+ for (ii = 0; ii < component.children.length; ii++) {
116
+ result.push(flattenComponent(component.children[ii]));
117
+ }
118
+ }
119
+ else {
120
+ for (ii = 0; ii < component.children.length; ii++) {
121
+ result.push(flattenComponent(component.children[ii]));
122
+ }
123
+ }
124
+ return result.join('');
125
+ }
126
126
 
127
- for (var ii = 0; ii < cue.components.children.length; ii++) {
128
- result.push(flattenComponent(cue.components.children[ii]));
129
- }
127
+ for (var ii = 0; ii < cue.components.children.length; ii++) {
128
+ result.push(flattenComponent(cue.components.children[ii]));
129
+ }
130
130
 
131
- return result.join('');
132
- };
131
+ return result.join('');
132
+ };
133
133
 
134
134
  })(jQuery);
@@ -1,141 +1,174 @@
1
1
  (function ($) {
2
2
 
3
- AblePlayer.prototype.getNextHeadingLevel = function($element) {
4
-
5
- // Finds the nearest heading in the ancestor tree
6
- // Loops over each parent of the current element until a heading is found
7
- // If multiple headings are found beneath a given parent, get the closest
8
- // Returns an integer (1-6) representing the next available heading level
9
-
10
- var $parents, $foundHeadings, numHeadings, headingType, headingNumber;
11
-
12
- $parents = $element.parents();
13
- $parents.each(function(){
14
- $foundHeadings = $(this).children(':header');
15
- numHeadings = $foundHeadings.length;
16
- if (numHeadings) {
17
- headingType = $foundHeadings.eq(numHeadings-1).prop('tagName');
18
- return false;
19
- }
20
- });
21
- if (typeof headingType === 'undefined') {
22
- // page has no headings
23
- headingNumber = 1;
24
- }
25
- else {
26
- // Increment closest heading by one if less than 6.
27
- headingNumber = parseInt(headingType[1]);
28
- headingNumber += 1;
29
- if (headingNumber > 6) {
30
- headingNumber = 6;
31
- }
32
- }
33
- return headingNumber;
34
- };
35
-
36
- AblePlayer.prototype.countProperties = function(obj) {
37
-
38
- // returns the number of properties in an object
39
- var count, prop;
40
- count = 0;
41
- for (prop in obj) {
42
- if (obj.hasOwnProperty(prop)) {
43
- ++count;
44
- }
45
- }
46
- return count;
47
- };
48
-
49
- AblePlayer.prototype.formatSecondsAsColonTime = function (seconds, showFullTime) {
50
-
51
- // Takes seconds and converts to string of form hh:mm:ss
52
- // If showFullTime is true, shows 00 for hours if time is less than an hour
53
- // and show milliseconds (e.g., 00:00:04.123 as in Video Track Sorter)
54
- // Otherwise, omits empty hours and milliseconds (e.g., 00:04 as in timer on controller)
55
-
56
- var dHours, dMinutes, dSeconds,
57
- parts, milliSeconds, numShort, i;
58
-
59
- if (showFullTime) {
60
- // preserve milliseconds, if included in seconds
61
- parts = seconds.toString().split('.');
62
- if (parts.length === 2) {
63
- milliSeconds = parts[1];
64
- if (milliSeconds.length < 3) {
65
- numShort = 3 - milliSeconds.length;
66
- for (i=1; i <= numShort; i++) {
67
- milliSeconds += '0';
68
- }
69
- }
70
- }
71
- else {
72
- milliSeconds = '000';
73
- }
74
- }
75
- dHours = Math.floor(seconds / 3600);
76
- dMinutes = Math.floor(seconds / 60) % 60;
77
- dSeconds = Math.floor(seconds % 60);
78
- if (dSeconds < 10) {
79
- dSeconds = '0' + dSeconds;
80
- }
81
- if (dHours > 0) {
82
- if (dMinutes < 10) {
83
- dMinutes = '0' + dMinutes;
84
- }
85
- if (showFullTime) {
86
- return dHours + ':' + dMinutes + ':' + dSeconds + '.' + milliSeconds;
87
- }
88
- else {
89
- return dHours + ':' + dMinutes + ':' + dSeconds;
90
- }
91
- }
92
- else {
93
- if (showFullTime) {
94
- if (dHours < 1) {
95
- dHours = '00';
96
- }
97
- else if (dHours < 10) {
98
- dHours = '0' + dHours;
99
- }
100
- if (dMinutes < 1) {
101
- dMinutes = '00';
102
- }
103
- else if (dMinutes < 10) {
104
- dMinutes = '0' + dMinutes;
105
- }
106
- return dHours + ':' + dMinutes + ':' + dSeconds + '.' + milliSeconds;
107
- }
108
- else {
109
- return dMinutes + ':' + dSeconds;
110
- }
111
- }
112
- };
113
-
114
- AblePlayer.prototype.getSecondsFromColonTime = function (timeStr) {
115
-
116
- // Converts string of form hh:mm:ss to seconds
117
- var timeParts, hours, minutes, seconds, newTime;
118
-
119
- timeParts = timeStr.split(':');
120
- if (timeParts.length === 3) {
121
- hours = parseInt(timeParts[0]);
122
- minutes = parseInt(timeParts[1]);
123
- seconds = parseFloat(timeParts[2]);
124
- return ((hours * 3600) + (minutes * 60) + (seconds));
125
- }
126
- else if (timeParts.length === 2) {
127
- minutes = parseInt(timeParts[0]);
128
- seconds = parseFloat(timeParts[1]);
129
- return ((minutes * 60) + (seconds));
130
- }
131
- else if (timeParts.length === 1) {
132
- seconds = parseFloat(timeParts[0]);
133
- return seconds;
134
- }
135
- };
136
-
137
- AblePlayer.prototype.capitalizeFirstLetter = function (string) {
138
- return string.charAt(0).toUpperCase() + string.slice(1);
139
- }
3
+ AblePlayer.prototype.getNextHeadingLevel = function($element) {
4
+
5
+ // Finds the nearest heading in the ancestor tree
6
+ // Loops over each parent of the current element until a heading is found
7
+ // If multiple headings are found beneath a given parent, get the closest
8
+ // Returns an integer (1-6) representing the next available heading level
9
+
10
+ var $parents, $foundHeadings, numHeadings, headingType, headingNumber;
11
+
12
+ $parents = $element.parents();
13
+ $parents.each(function(){
14
+ $foundHeadings = $(this).children(':header');
15
+ numHeadings = $foundHeadings.length;
16
+ if (numHeadings) {
17
+ headingType = $foundHeadings.eq(numHeadings-1).prop('tagName');
18
+ return false;
19
+ }
20
+ });
21
+ if (typeof headingType === 'undefined') {
22
+ // page has no headings
23
+ headingNumber = 1;
24
+ }
25
+ else {
26
+ // Increment closest heading by one if less than 6.
27
+ headingNumber = parseInt(headingType[1]);
28
+ headingNumber += 1;
29
+ if (headingNumber > 6) {
30
+ headingNumber = 6;
31
+ }
32
+ }
33
+ return headingNumber;
34
+ };
35
+
36
+ AblePlayer.prototype.countProperties = function(obj) {
37
+
38
+ // returns the number of properties in an object
39
+ var count, prop;
40
+ count = 0;
41
+ for (prop in obj) {
42
+ if (obj.hasOwnProperty(prop)) {
43
+ ++count;
44
+ }
45
+ }
46
+ return count;
47
+ };
48
+
49
+ AblePlayer.prototype.formatSecondsAsColonTime = function (seconds, showFullTime) {
50
+
51
+ // Takes seconds and converts to string of form hh:mm:ss
52
+ // If showFullTime is true, shows 00 for hours if time is less than an hour
53
+ // and show milliseconds (e.g., 00:00:04.123 as in Video Track Sorter)
54
+ // Otherwise, omits empty hours and milliseconds (e.g., 00:04 as in timer on controller)
55
+
56
+ var dHours, dMinutes, dSeconds,
57
+ parts, milliSeconds, numShort, i;
58
+
59
+ if (showFullTime) {
60
+ // preserve milliseconds, if included in seconds
61
+ parts = seconds.toString().split('.');
62
+ if (parts.length === 2) {
63
+ milliSeconds = parts[1];
64
+ if (milliSeconds.length < 3) {
65
+ numShort = 3 - milliSeconds.length;
66
+ for (i=1; i <= numShort; i++) {
67
+ milliSeconds += '0';
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ milliSeconds = '000';
73
+ }
74
+ }
75
+ dHours = Math.floor(seconds / 3600);
76
+ dMinutes = Math.floor(seconds / 60) % 60;
77
+ dSeconds = Math.floor(seconds % 60);
78
+ if (dSeconds < 10) {
79
+ dSeconds = '0' + dSeconds;
80
+ }
81
+ if (dHours > 0) {
82
+ if (dMinutes < 10) {
83
+ dMinutes = '0' + dMinutes;
84
+ }
85
+ if (showFullTime) {
86
+ return dHours + ':' + dMinutes + ':' + dSeconds + '.' + milliSeconds;
87
+ }
88
+ else {
89
+ return dHours + ':' + dMinutes + ':' + dSeconds;
90
+ }
91
+ }
92
+ else {
93
+ if (showFullTime) {
94
+ if (dHours < 1) {
95
+ dHours = '00';
96
+ }
97
+ else if (dHours < 10) {
98
+ dHours = '0' + dHours;
99
+ }
100
+ if (dMinutes < 1) {
101
+ dMinutes = '00';
102
+ }
103
+ else if (dMinutes < 10) {
104
+ dMinutes = '0' + dMinutes;
105
+ }
106
+ return dHours + ':' + dMinutes + ':' + dSeconds + '.' + milliSeconds;
107
+ }
108
+ else {
109
+ return dMinutes + ':' + dSeconds;
110
+ }
111
+ }
112
+ };
113
+
114
+ AblePlayer.prototype.getSecondsFromColonTime = function (timeStr) {
115
+
116
+ // Converts string of form hh:mm:ss to seconds
117
+ var timeParts, hours, minutes, seconds, newTime;
118
+
119
+ timeParts = timeStr.split(':');
120
+ if (timeParts.length === 3) {
121
+ hours = parseInt(timeParts[0]);
122
+ minutes = parseInt(timeParts[1]);
123
+ seconds = parseFloat(timeParts[2]);
124
+ return ((hours * 3600) + (minutes * 60) + (seconds));
125
+ }
126
+ else if (timeParts.length === 2) {
127
+ minutes = parseInt(timeParts[0]);
128
+ seconds = parseFloat(timeParts[1]);
129
+ return ((minutes * 60) + (seconds));
130
+ }
131
+ else if (timeParts.length === 1) {
132
+ seconds = parseFloat(timeParts[0]);
133
+ return seconds;
134
+ }
135
+ };
136
+
137
+ AblePlayer.prototype.capitalizeFirstLetter = function (string) {
138
+ return string.charAt(0).toUpperCase() + string.slice(1);
139
+ };
140
+
141
+ AblePlayer.prototype.roundDown = function (value, decimals) {
142
+
143
+ // round value down to the nearest X decimal points
144
+ // where X is the value of the decimals parameter
145
+ return Number(Math.floor(value+'e'+decimals)+'e-'+decimals);
146
+ };
147
+
148
+ AblePlayer.prototype.hasAttr = function (object, attribute) {
149
+
150
+ // surprisingly, there is no hasAttr() function in Jquery as of 3.2.1
151
+ // return true if object has attribute; otherwise false
152
+ // selector is a Jquery object
153
+ // attribute is a string
154
+
155
+ var attr = object.attr(attribute);
156
+
157
+ // For some browsers, `attr` is undefined; for others,
158
+ // `attr` is false. Check for both.
159
+ if (typeof attr !== typeof undefined && attr !== false) {
160
+ return true;
161
+ }
162
+ else {
163
+ return false;
164
+ }
165
+ };
166
+
167
+ Number.isInteger = Number.isInteger || function(value) {
168
+
169
+ // polyfill for IE11, which doesn't otherwise support Number.isInteger
170
+ // https://stackoverflow.com/a/31720368/744281
171
+ return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
172
+ };
140
173
 
141
174
  })(jQuery);