datatables.net 3.0.0-beta.1 → 3.0.0-beta.2

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/js/dataTables.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! DataTables 3.0.0-beta.1
1
+ /*! DataTables 3.0.0-beta.2
2
2
  * Copyright (c) SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
@@ -80,9 +80,11 @@ const reRegexCharacters = new RegExp('(\\' +
80
80
  // implementations differ between browsers.
81
81
  const reDate = /^\d{2,4}[./-]\d{1,2}[./-]\d{1,2}([T ]{1}\d{1,2}[:.]\d{2}([.:]\d{2})?)?$/;
82
82
  const reNewLines = /[\r\n\u2028]/g;
83
+ const isoTimezone = /[T\s]\d{2}.*?(Z|[+-]\d{2}(?::?\d{2})?)$/;
83
84
 
84
85
  var regex = /*#__PURE__*/Object.freeze({
85
86
  __proto__: null,
87
+ isoTimezone: isoTimezone,
86
88
  reDate: reDate,
87
89
  reFormattedNumeric: reFormattedNumeric,
88
90
  reHtml: reHtml,
@@ -554,6 +556,13 @@ function ajax(optionsIn) {
554
556
  if (options.contentType && !(options.data instanceof FormData)) {
555
557
  xhr.setRequestHeader('Content-Type', options.contentType);
556
558
  }
559
+ // Add a X-Request-With header, as jQuery does so and some server-side
560
+ // platforms look for it. Only for same domain though.
561
+ if (options.headers &&
562
+ !options.headers['X-Requested-With'] &&
563
+ !isCrossDomain(options.url)) {
564
+ options.headers['X-Requested-With'] = 'XMLHttpRequest';
565
+ }
557
566
  each(options.headers, (key, val) => {
558
567
  xhr.setRequestHeader(key, val);
559
568
  });
@@ -651,6 +660,17 @@ function convertSpaces(sendData, options) {
651
660
  ? sendData.replace(/%20/g, '+')
652
661
  : sendData;
653
662
  }
663
+ /**
664
+ * Determine if a url is a cross domain request or not
665
+ *
666
+ * @param url URL to check
667
+ * @returns True if cross domain, false otherwise
668
+ */
669
+ function isCrossDomain(url) {
670
+ // Use the current page as the base to handle relative URLs correctly
671
+ const target = new URL(url, window.location.origin);
672
+ return target.origin !== window.location.origin;
673
+ }
654
674
  /**
655
675
  * Get the HTTP method from the Ajax request options
656
676
  *
@@ -1906,8 +1926,7 @@ class Dom {
1906
1926
  }
1907
1927
  }
1908
1928
  if (sort) {
1909
- Array.prototype.sort.call(this, documentOrder);
1910
- // this.sort(documentOrder);
1929
+ this.sort();
1911
1930
  }
1912
1931
  return this;
1913
1932
  }
@@ -2698,6 +2717,18 @@ class Dom {
2698
2717
  el.style.display = 'block';
2699
2718
  });
2700
2719
  }
2720
+ /**
2721
+ * Sort the DOM elements into document order.
2722
+ *
2723
+ * This is normally not needed as elements selected with a DOM selector are
2724
+ * automatically sorted in document order. However, in the case of elements
2725
+ * being added as an array, their order will be retained. In such as case
2726
+ * you might wish to sort them in document order.
2727
+ */
2728
+ sort() {
2729
+ Array.prototype.sort.call(this, documentOrder);
2730
+ return this;
2731
+ }
2701
2732
  text(txt) {
2702
2733
  if (txt === undefined) {
2703
2734
  return this.count() ? this[0].textContent : null;
@@ -3858,7 +3889,7 @@ const ext = {
3858
3889
  * Software version
3859
3890
  * @type string
3860
3891
  */
3861
- version: '3.0.0-beta.1'
3892
+ version: '3.0.0-beta.2'
3862
3893
  };
3863
3894
  //
3864
3895
  // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
@@ -4151,7 +4182,7 @@ function __mldObj(d, format, locale) {
4151
4182
  var dt;
4152
4183
  resolveWindowLibs();
4153
4184
  if (__moment) {
4154
- dt = __moment.utc(d, format, locale, true);
4185
+ dt = __moment(d, format, locale, true);
4155
4186
  if (!dt.isValid()) {
4156
4187
  return null;
4157
4188
  }
@@ -4254,6 +4285,15 @@ function __mlHelper(localeString) {
4254
4285
  !(d instanceof Date)) {
4255
4286
  return d;
4256
4287
  }
4288
+ // Determine if there is a timezone. If there is, we want to reuse
4289
+ // it for the output, so the timezone doesn't change between the
4290
+ // input and output.
4291
+ let options = {};
4292
+ let tzMatch = typeof d === 'string' ? d.match(util.regex.isoTimezone) : null;
4293
+ if (tzMatch) {
4294
+ options.timeZone = tzMatch[1] === 'Z' ? 'UTC' : tzMatch[1];
4295
+ }
4296
+ // Get a Date object (Luxon, moment or Date)
4257
4297
  var dt = __mldObj(d, from, locale);
4258
4298
  if (dt === null) {
4259
4299
  return d;
@@ -4262,7 +4302,7 @@ function __mlHelper(localeString) {
4262
4302
  return dt;
4263
4303
  }
4264
4304
  var formatted = to === null
4265
- ? __mld(dt, 'toDate', 'toJSDate', '')[localeString](navigator.language, { timeZone: 'UTC' })
4305
+ ? __mld(dt, 'toDate', 'toJSDate', '')[localeString](navigator.language, options)
4266
4306
  : __mld(dt, 'format', 'toFormat', 'toISOString', to);
4267
4307
  // XSS protection
4268
4308
  return type === 'display' ? util.escapeHtml(formatted) : formatted;
@@ -5418,8 +5458,8 @@ function featureTable(settings) {
5418
5458
  let captionSide = caption
5419
5459
  ? caption._captionSide
5420
5460
  : null;
5421
- let headerClone = table.clone(false);
5422
- let footerClone = table.clone(false);
5461
+ let tableCloneHeader = table.clone(false);
5462
+ let tableCloneFooter = table.clone(false);
5423
5463
  let footer = table.children('tfoot');
5424
5464
  let size = function (s) {
5425
5465
  return !s ? '100%' : stringToCss(s);
@@ -5440,11 +5480,10 @@ function featureTable(settings) {
5440
5480
  * table - scroll foot table
5441
5481
  * tfoot - tfoot
5442
5482
  */
5443
- let scroller = Dom
5444
- .c('div')
5483
+ let scroller = Dom.c('div')
5445
5484
  .classAdd(classes.container)
5446
- .append(Dom
5447
- .c('div')
5485
+ .attr('role', 'table')
5486
+ .append(Dom.c('div')
5448
5487
  .classAdd(classes.header.self)
5449
5488
  .css({
5450
5489
  overflow: 'hidden',
@@ -5452,40 +5491,41 @@ function featureTable(settings) {
5452
5491
  border: '0',
5453
5492
  width: scrollX ? size(scrollX) : '100%'
5454
5493
  })
5455
- .append(Dom
5456
- .c('div')
5494
+ .attr('role', 'none')
5495
+ .append(Dom.c('div')
5457
5496
  .classAdd(classes.header.inner)
5458
5497
  .css({
5459
5498
  'box-sizing': 'content-box',
5460
5499
  width: scroll.xInner || '100%'
5461
5500
  })
5462
- .append(headerClone
5501
+ .attr('role', 'none')
5502
+ .append(tableCloneHeader
5463
5503
  .attrRemove('id')
5464
5504
  .css('margin-left', '0')
5465
5505
  .append(captionSide === 'top' ? caption : null)
5466
5506
  .append(table.children('thead')))))
5467
- .append(Dom
5468
- .c('div')
5507
+ .append(Dom.c('div')
5469
5508
  .classAdd(classes.body)
5470
5509
  .css({
5471
5510
  position: 'relative',
5472
5511
  overflow: 'auto',
5473
5512
  width: size(scrollX)
5474
5513
  })
5514
+ .attr('role', 'none')
5475
5515
  .append(table));
5476
5516
  if (footer.count()) {
5477
- scroller.append(Dom
5478
- .c('div')
5517
+ scroller.append(Dom.c('div')
5479
5518
  .classAdd(classes.footer.self)
5480
5519
  .css({
5481
5520
  overflow: 'hidden',
5482
5521
  border: '0',
5483
5522
  width: scrollX ? size(scrollX) : '100%'
5484
5523
  })
5485
- .append(Dom
5486
- .c('div')
5524
+ .attr('role', 'none')
5525
+ .append(Dom.c('div')
5487
5526
  .classAdd(classes.footer.inner)
5488
- .append(footerClone
5527
+ .attr('role', 'none')
5528
+ .append(tableCloneFooter
5489
5529
  .attrRemove('id')
5490
5530
  .css('margin-left', '0')
5491
5531
  .append(captionSide === 'bottom' ? caption : null)
@@ -5523,6 +5563,22 @@ function featureTable(settings) {
5523
5563
  settings.scrollFoot = scrollFoot;
5524
5564
  // On redraw - align columns
5525
5565
  settings.callbacks.draw.push(scrollDraw);
5566
+ // Aria roles - because we break the table up into parts we need to be very
5567
+ // explicit with the roles to create the accessability tree for the table,
5568
+ // otherwise browser's attempt to "fix" the tree by filling in what it
5569
+ // thinks are gaps. The static elements that we can assign roles to are done
5570
+ // here. Dynamic ones are done in the draw function below.
5571
+ table.attr('role', 'none');
5572
+ table.find('tbody').attr('role', 'rowgroup');
5573
+ tableCloneHeader.attr('role', 'none');
5574
+ tableCloneFooter.attr('role', 'none');
5575
+ settings.colgroup.find('colgroup').attr('role', 'none');
5576
+ // Move the info feature's aria desc by to the new "table"
5577
+ let describedBy = table.attr('aria-describedby');
5578
+ if (describedBy) {
5579
+ scroller.attr('aria-describedby', describedBy);
5580
+ table.attrRemove('aria-describedby');
5581
+ }
5526
5582
  return scroller.get(0);
5527
5583
  }
5528
5584
  /**
@@ -5555,10 +5611,13 @@ function scrollDraw(settings) {
5555
5611
  else {
5556
5612
  settings.scrollBarVis = scrollBarVis;
5557
5613
  }
5614
+ header.find('thead').attr('role', 'rowgroup');
5615
+ footer.find('tfoot').attr('role', 'rowgroup');
5558
5616
  // 1. Re-create the table inside the scrolling div
5559
5617
  // Remove the old minimised thead and tfoot elements in the inner table
5560
5618
  table.children('thead, tfoot').remove();
5561
- // Clone the current header and footer elements and then place it into the inner table
5619
+ // Clone the current header and footer elements and then place it into the
5620
+ // inner table
5562
5621
  headerCopy = header.clone(true).prependTo(table);
5563
5622
  headerCopy.find('th, td').attrRemove('tabindex');
5564
5623
  headerCopy.find('[id]').attrRemove('id');
@@ -5593,8 +5652,7 @@ function scrollDraw(settings) {
5593
5652
  }
5594
5653
  }
5595
5654
  if (firstTr) {
5596
- let colSizes = Dom
5597
- .s(firstTr)
5655
+ let colSizes = Dom.s(firstTr)
5598
5656
  .children('th, td')
5599
5657
  .mapTo(function (cell, idx) {
5600
5658
  return {
@@ -5659,6 +5717,18 @@ function scrollDraw(settings) {
5659
5717
  }
5660
5718
  // Correct DOM ordering for colgroup - comes before the thead
5661
5719
  table.children('colgroup').prependTo(table);
5720
+ // Remove tabindex from the hidden row elements
5721
+ table.find('thead, tfoot').find('[tabindex]').attrRemove('tabindex');
5722
+ // Dynamic ARIA roles - see setup for details on why this is needed
5723
+ table
5724
+ .find('thead, tfoot')
5725
+ .attr('role', 'none')
5726
+ .find('[role]')
5727
+ .attrRemove('role');
5728
+ table.find('tbody tr:not([role])').attr('role', 'row');
5729
+ table.find('tbody td:not([role]), tbody th:not([role])').attr('role', 'cell');
5730
+ scrollAria(headerCopy);
5731
+ scrollAria(footerCopy);
5662
5732
  // Adjust the position of the header in case we loose the y-scrollbar
5663
5733
  divBody.trigger('scroll');
5664
5734
  // If sorting or filtering has occurred, jump the scrolling back to the top
@@ -5667,6 +5737,18 @@ function scrollDraw(settings) {
5667
5737
  divBodyEl.scrollTop(0);
5668
5738
  }
5669
5739
  }
5740
+ /**
5741
+ * Apply ARIA roles for the header / footer of a scrolling table
5742
+ * @param element
5743
+ */
5744
+ function scrollAria(element) {
5745
+ if (element) {
5746
+ element.find('tfoot:not([role])').attr('role', 'rowgroup');
5747
+ element.find('tr:not([role])').attr('role', 'row');
5748
+ element.find('th:not([role])').attr('role', 'columnheader');
5749
+ element.find('td:not([role])').attr('role', 'cell');
5750
+ }
5751
+ }
5670
5752
 
5671
5753
  /**
5672
5754
  * Add a column to the list used for the table with default values
@@ -8331,6 +8413,11 @@ function reDraw(settings, holdPosition, recompute) {
8331
8413
  if (holdPosition !== true) {
8332
8414
  settings.displayStart = 0;
8333
8415
  }
8416
+ else {
8417
+ // Keep position, but make sure that there is actually data to display,
8418
+ // otherwise we need to rewind a bit (e.g. if rows were deleted)
8419
+ lengthOverflow(settings);
8420
+ }
8334
8421
  // Let any modules know about the draw hold position state (used by
8335
8422
  // scrolling internally)
8336
8423
  settings.drawHold = holdPosition;