Browse Source

update plugin files

REJack 4 years ago
parent
commit
966a9b0178

+ 7 - 7
plugins/datatables-fixedheader/js/dataTables.fixedHeader.js

@@ -1,16 +1,16 @@
-/*! FixedHeader 3.1.7
- * ©2009-2020 SpryMedia Ltd - datatables.net/license
+/*! FixedHeader 3.1.8
+ * ©2009-2021 SpryMedia Ltd - datatables.net/license
  */
 
 /**
  * @summary     FixedHeader
  * @description Fix a table's header or footer, so it is always visible while
  *              scrolling
- * @version     3.1.7
+ * @version     3.1.8
  * @file        dataTables.fixedHeader.js
  * @author      SpryMedia Ltd (www.sprymedia.co.uk)
  * @contact     www.sprymedia.co.uk/contact
- * @copyright   Copyright 2009-2020 SpryMedia Ltd.
+ * @copyright   Copyright 2009-2021 SpryMedia Ltd.
  *
  * This source file is free software, available under the following license:
  *   MIT license - http://datatables.net/license/mit
@@ -340,7 +340,7 @@ $.extend( FixedHeader.prototype, {
 		var get = function ( name ) {
 			return $(name, from)
 				.map( function () {
-					return $(this).width();
+					return $(this).css('width').replace(/[^\d\.]/g, '') * 1;
 				} ).toArray();
 		};
 
@@ -622,7 +622,7 @@ $.extend( FixedHeader.prototype, {
  * @type {String}
  * @static
  */
-FixedHeader.version = "3.1.7";
+FixedHeader.version = "3.1.8";
 
 /**
  * Defaults
@@ -691,7 +691,7 @@ DataTable.Api.register( 'fixedHeader.enable()', function ( flag ) {
 
 DataTable.Api.register( 'fixedHeader.enabled()', function () {
 	if ( this.context.length ) {
-		var fh = this.content[0]._fixedHeader;
+		var fh = this.context[0]._fixedHeader;
 
 		if ( fh ) {
 			return fh.enabled();

File diff suppressed because it is too large
+ 11 - 11
plugins/datatables-fixedheader/js/dataTables.fixedHeader.min.js


+ 52 - 13
plugins/datatables-keytable/js/dataTables.keyTable.js

@@ -1,15 +1,15 @@
-/*! KeyTable 2.5.3
- * ©2009-2020 SpryMedia Ltd - datatables.net/license
+/*! KeyTable 2.6.0
+ * ©2009-2021 SpryMedia Ltd - datatables.net/license
  */
 
 /**
  * @summary     KeyTable
  * @description Spreadsheet like keyboard navigation for DataTables
- * @version     2.5.3
+ * @version     2.6.0
  * @file        dataTables.keyTable.js
  * @author      SpryMedia Ltd (www.sprymedia.co.uk)
  * @contact     www.sprymedia.co.uk/contact
- * @copyright   Copyright 2009-2020 SpryMedia Ltd.
+ * @copyright   Copyright 2009-2021 SpryMedia Ltd.
  *
  * This source file is free software, available under the following license:
  *   MIT license - http://datatables.net/license/mit
@@ -132,6 +132,13 @@ $.extend( KeyTable.prototype, {
 	},
 
 	/**
+	 * Get enable status
+	 */
+	enabled: function () {
+		return this.s.enable;
+	},
+
+	/**
 	 * Focus on a cell
 	 * @param  {integer} row    Row index
 	 * @param  {integer} column Column index
@@ -224,7 +231,10 @@ $.extend( KeyTable.prototype, {
 				}
 
 				// Or an Editor date input
-				if ( $(e.target).parents('div.editor-datetime').length ) {
+				if (
+					$(e.target).parents('div.editor-datetime').length ||
+					$(e.target).parents('div.dt-datetime').length 
+				) {
 					return;
 				}
 
@@ -513,6 +523,11 @@ $.extend( KeyTable.prototype, {
 			return;	
 		}
 
+		// DataTables draw event
+		if (orig.type === 'draw') {
+			return;
+		}
+
 		var that = this;
 		var dt = this.s.dt;
 		var editor = this.c.editor;
@@ -587,6 +602,10 @@ $.extend( KeyTable.prototype, {
 						dt.off( 'key-blur.editor' );
 						editor.off( namespace );
 						$( dt.table().container() ).removeClass('dtk-focus-alt');
+
+						if (that.s.returnSubmit) {
+							that._emitEvent( 'key-return-submit', [dt, editCell] );
+						}
 					} );
 				} )
 				.one( 'cancelOpen'+namespace, function () {
@@ -778,6 +797,10 @@ $.extend( KeyTable.prototype, {
 		}
 
 		var enable = this.s.enable;
+		this.s.returnSubmit = (enable === 'navigation-only' || enable === 'tab-only') && e.keyCode === 13
+			? true
+			: false;
+
 		var navEnable = enable === true || enable === 'navigation-only';
 		if ( ! enable ) {
 			return;
@@ -961,13 +984,17 @@ $.extend( KeyTable.prototype, {
 	 */
 	_shift: function ( e, direction, keyBlurable )
 	{
-		var that         = this;
-		var dt           = this.s.dt;
-		var pageInfo     = dt.page.info();
-		var rows         = pageInfo.recordsDisplay;
-		var currentCell  = this.s.lastFocus.cell;
-		var columns      = this._columns();
-
+		var that      = this;
+		var dt        = this.s.dt;
+		var pageInfo  = dt.page.info();
+		var rows      = pageInfo.recordsDisplay;
+		var columns   = this._columns();
+		var last      = this.s.lastFocus;
+		if ( ! last ) {
+			return;
+		}
+	
+		var currentCell  = last.cell;
 		if ( ! currentCell ) {
 			return;
 		}
@@ -1180,7 +1207,7 @@ KeyTable.defaults = {
 
 
 
-KeyTable.version = "2.5.3";
+KeyTable.version = "2.6.0";
 
 
 $.fn.dataTable.KeyTable = KeyTable;
@@ -1219,6 +1246,18 @@ DataTable.Api.register( 'keys.enable()', function ( opts ) {
 	} );
 } );
 
+DataTable.Api.register( 'keys.enabled()', function ( opts ) {
+	let ctx = this.context;
+
+	if (ctx.length) {
+		return ctx[0].keytable
+			? ctx[0].keytable.enabled()
+			: false;
+	}
+
+	return false;
+} );
+
 DataTable.Api.register( 'keys.move()', function ( dir ) {
 	return this.iterator( 'table', function (ctx) {
 		if ( ctx.keytable ) {

File diff suppressed because it is too large
+ 0 - 25
plugins/datatables-keytable/js/dataTables.keyTable.min.js


+ 41 - 36
plugins/dropzone/basic.css

@@ -1,39 +1,44 @@
-/*
- * The MIT License
- * Copyright (c) 2012 Matias Meno <m@tias.me>
- */
 .dropzone, .dropzone * {
-  box-sizing: border-box; }
+  box-sizing: border-box;
+}
 
 .dropzone {
-  position: relative; }
-  .dropzone .dz-preview {
-    position: relative;
-    display: inline-block;
-    width: 120px;
-    margin: 0.5em; }
-    .dropzone .dz-preview .dz-progress {
-      display: block;
-      height: 15px;
-      border: 1px solid #aaa; }
-      .dropzone .dz-preview .dz-progress .dz-upload {
-        display: block;
-        height: 100%;
-        width: 0;
-        background: green; }
-    .dropzone .dz-preview .dz-error-message {
-      color: red;
-      display: none; }
-    .dropzone .dz-preview.dz-error .dz-error-message, .dropzone .dz-preview.dz-error .dz-error-mark {
-      display: block; }
-    .dropzone .dz-preview.dz-success .dz-success-mark {
-      display: block; }
-    .dropzone .dz-preview .dz-error-mark, .dropzone .dz-preview .dz-success-mark {
-      position: absolute;
-      display: none;
-      left: 30px;
-      top: 30px;
-      width: 54px;
-      height: 58px;
-      left: 50%;
-      margin-left: -27px; }
+  position: relative;
+}
+.dropzone .dz-preview {
+  position: relative;
+  display: inline-block;
+  width: 120px;
+  margin: 0.5em;
+}
+.dropzone .dz-preview .dz-progress {
+  display: block;
+  height: 15px;
+  border: 1px solid #aaa;
+}
+.dropzone .dz-preview .dz-progress .dz-upload {
+  display: block;
+  height: 100%;
+  width: 0;
+  background: green;
+}
+.dropzone .dz-preview .dz-error-message {
+  color: red;
+  display: none;
+}
+.dropzone .dz-preview.dz-error .dz-error-message, .dropzone .dz-preview.dz-error .dz-error-mark {
+  display: block;
+}
+.dropzone .dz-preview.dz-success .dz-success-mark {
+  display: block;
+}
+.dropzone .dz-preview .dz-error-mark, .dropzone .dz-preview .dz-success-mark {
+  position: absolute;
+  display: none;
+  left: 30px;
+  top: 30px;
+  width: 54px;
+  height: 58px;
+  left: 50%;
+  margin-left: -27px;
+}

File diff suppressed because it is too large
+ 8142 - 1201
plugins/dropzone/dropzone-amd-module.js


+ 318 - 246
plugins/dropzone/dropzone.css

@@ -1,7 +1,3 @@
-/*
- * The MIT License
- * Copyright (c) 2012 Matias Meno <m@tias.me>
- */
 @-webkit-keyframes passing-through {
   0% {
     opacity: 0;
@@ -9,21 +5,25 @@
     -moz-transform: translateY(40px);
     -ms-transform: translateY(40px);
     -o-transform: translateY(40px);
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30%, 70% {
     opacity: 1;
     -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
     -ms-transform: translateY(0px);
     -o-transform: translateY(0px);
-    transform: translateY(0px); }
+    transform: translateY(0px);
+  }
   100% {
     opacity: 0;
     -webkit-transform: translateY(-40px);
     -moz-transform: translateY(-40px);
     -ms-transform: translateY(-40px);
     -o-transform: translateY(-40px);
-    transform: translateY(-40px); } }
+    transform: translateY(-40px);
+  }
+}
 @-moz-keyframes passing-through {
   0% {
     opacity: 0;
@@ -31,21 +31,25 @@
     -moz-transform: translateY(40px);
     -ms-transform: translateY(40px);
     -o-transform: translateY(40px);
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30%, 70% {
     opacity: 1;
     -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
     -ms-transform: translateY(0px);
     -o-transform: translateY(0px);
-    transform: translateY(0px); }
+    transform: translateY(0px);
+  }
   100% {
     opacity: 0;
     -webkit-transform: translateY(-40px);
     -moz-transform: translateY(-40px);
     -ms-transform: translateY(-40px);
     -o-transform: translateY(-40px);
-    transform: translateY(-40px); } }
+    transform: translateY(-40px);
+  }
+}
 @keyframes passing-through {
   0% {
     opacity: 0;
@@ -53,21 +57,25 @@
     -moz-transform: translateY(40px);
     -ms-transform: translateY(40px);
     -o-transform: translateY(40px);
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30%, 70% {
     opacity: 1;
     -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
     -ms-transform: translateY(0px);
     -o-transform: translateY(0px);
-    transform: translateY(0px); }
+    transform: translateY(0px);
+  }
   100% {
     opacity: 0;
     -webkit-transform: translateY(-40px);
     -moz-transform: translateY(-40px);
     -ms-transform: translateY(-40px);
     -o-transform: translateY(-40px);
-    transform: translateY(-40px); } }
+    transform: translateY(-40px);
+  }
+}
 @-webkit-keyframes slide-in {
   0% {
     opacity: 0;
@@ -75,14 +83,17 @@
     -moz-transform: translateY(40px);
     -ms-transform: translateY(40px);
     -o-transform: translateY(40px);
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30% {
     opacity: 1;
     -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
     -ms-transform: translateY(0px);
     -o-transform: translateY(0px);
-    transform: translateY(0px); } }
+    transform: translateY(0px);
+  }
+}
 @-moz-keyframes slide-in {
   0% {
     opacity: 0;
@@ -90,14 +101,17 @@
     -moz-transform: translateY(40px);
     -ms-transform: translateY(40px);
     -o-transform: translateY(40px);
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30% {
     opacity: 1;
     -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
     -ms-transform: translateY(0px);
     -o-transform: translateY(0px);
-    transform: translateY(0px); } }
+    transform: translateY(0px);
+  }
+}
 @keyframes slide-in {
   0% {
     opacity: 0;
@@ -105,292 +119,350 @@
     -moz-transform: translateY(40px);
     -ms-transform: translateY(40px);
     -o-transform: translateY(40px);
-    transform: translateY(40px); }
+    transform: translateY(40px);
+  }
   30% {
     opacity: 1;
     -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
     -ms-transform: translateY(0px);
     -o-transform: translateY(0px);
-    transform: translateY(0px); } }
+    transform: translateY(0px);
+  }
+}
 @-webkit-keyframes pulse {
   0% {
     -webkit-transform: scale(1);
     -moz-transform: scale(1);
     -ms-transform: scale(1);
     -o-transform: scale(1);
-    transform: scale(1); }
+    transform: scale(1);
+  }
   10% {
     -webkit-transform: scale(1.1);
     -moz-transform: scale(1.1);
     -ms-transform: scale(1.1);
     -o-transform: scale(1.1);
-    transform: scale(1.1); }
+    transform: scale(1.1);
+  }
   20% {
     -webkit-transform: scale(1);
     -moz-transform: scale(1);
     -ms-transform: scale(1);
     -o-transform: scale(1);
-    transform: scale(1); } }
+    transform: scale(1);
+  }
+}
 @-moz-keyframes pulse {
   0% {
     -webkit-transform: scale(1);
     -moz-transform: scale(1);
     -ms-transform: scale(1);
     -o-transform: scale(1);
-    transform: scale(1); }
+    transform: scale(1);
+  }
   10% {
     -webkit-transform: scale(1.1);
     -moz-transform: scale(1.1);
     -ms-transform: scale(1.1);
     -o-transform: scale(1.1);
-    transform: scale(1.1); }
+    transform: scale(1.1);
+  }
   20% {
     -webkit-transform: scale(1);
     -moz-transform: scale(1);
     -ms-transform: scale(1);
     -o-transform: scale(1);
-    transform: scale(1); } }
+    transform: scale(1);
+  }
+}
 @keyframes pulse {
   0% {
     -webkit-transform: scale(1);
     -moz-transform: scale(1);
     -ms-transform: scale(1);
     -o-transform: scale(1);
-    transform: scale(1); }
+    transform: scale(1);
+  }
   10% {
     -webkit-transform: scale(1.1);
     -moz-transform: scale(1.1);
     -ms-transform: scale(1.1);
     -o-transform: scale(1.1);
-    transform: scale(1.1); }
+    transform: scale(1.1);
+  }
   20% {
     -webkit-transform: scale(1);
     -moz-transform: scale(1);
     -ms-transform: scale(1);
     -o-transform: scale(1);
-    transform: scale(1); } }
+    transform: scale(1);
+  }
+}
 .dropzone, .dropzone * {
-  box-sizing: border-box; }
+  box-sizing: border-box;
+}
 
 .dropzone {
   min-height: 150px;
   border: 2px solid rgba(0, 0, 0, 0.3);
   background: white;
-  padding: 20px 20px; }
-  .dropzone.dz-clickable {
-    cursor: pointer; }
-    .dropzone.dz-clickable * {
-      cursor: default; }
-    .dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
-      cursor: pointer; }
-  .dropzone.dz-started .dz-message {
-    display: none; }
-  .dropzone.dz-drag-hover {
-    border-style: solid; }
-    .dropzone.dz-drag-hover .dz-message {
-      opacity: 0.5; }
-  .dropzone .dz-message {
-    text-align: center;
-    margin: 2em 0; }
-    .dropzone .dz-message .dz-button {
-      background: none;
-      color: inherit;
-      border: none;
-      padding: 0;
-      font: inherit;
-      cursor: pointer;
-      outline: inherit; }
-  .dropzone .dz-preview {
-    position: relative;
-    display: inline-block;
-    vertical-align: top;
-    margin: 16px;
-    min-height: 100px; }
-    .dropzone .dz-preview:hover {
-      z-index: 1000; }
-      .dropzone .dz-preview:hover .dz-details {
-        opacity: 1; }
-    .dropzone .dz-preview.dz-file-preview .dz-image {
-      border-radius: 20px;
-      background: #999;
-      background: linear-gradient(to bottom, #eee, #ddd); }
-    .dropzone .dz-preview.dz-file-preview .dz-details {
-      opacity: 1; }
-    .dropzone .dz-preview.dz-image-preview {
-      background: white; }
-      .dropzone .dz-preview.dz-image-preview .dz-details {
-        -webkit-transition: opacity 0.2s linear;
-        -moz-transition: opacity 0.2s linear;
-        -ms-transition: opacity 0.2s linear;
-        -o-transition: opacity 0.2s linear;
-        transition: opacity 0.2s linear; }
-    .dropzone .dz-preview .dz-remove {
-      font-size: 14px;
-      text-align: center;
-      display: block;
-      cursor: pointer;
-      border: none; }
-      .dropzone .dz-preview .dz-remove:hover {
-        text-decoration: underline; }
-    .dropzone .dz-preview:hover .dz-details {
-      opacity: 1; }
-    .dropzone .dz-preview .dz-details {
-      z-index: 20;
-      position: absolute;
-      top: 0;
-      left: 0;
-      opacity: 0;
-      font-size: 13px;
-      min-width: 100%;
-      max-width: 100%;
-      padding: 2em 1em;
-      text-align: center;
-      color: rgba(0, 0, 0, 0.9);
-      line-height: 150%; }
-      .dropzone .dz-preview .dz-details .dz-size {
-        margin-bottom: 1em;
-        font-size: 16px; }
-      .dropzone .dz-preview .dz-details .dz-filename {
-        white-space: nowrap; }
-        .dropzone .dz-preview .dz-details .dz-filename:hover span {
-          border: 1px solid rgba(200, 200, 200, 0.8);
-          background-color: rgba(255, 255, 255, 0.8); }
-        .dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
-          overflow: hidden;
-          text-overflow: ellipsis; }
-          .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
-            border: 1px solid transparent; }
-      .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
-        background-color: rgba(255, 255, 255, 0.4);
-        padding: 0 0.4em;
-        border-radius: 3px; }
-    .dropzone .dz-preview:hover .dz-image img {
-      -webkit-transform: scale(1.05, 1.05);
-      -moz-transform: scale(1.05, 1.05);
-      -ms-transform: scale(1.05, 1.05);
-      -o-transform: scale(1.05, 1.05);
-      transform: scale(1.05, 1.05);
-      -webkit-filter: blur(8px);
-      filter: blur(8px); }
-    .dropzone .dz-preview .dz-image {
-      border-radius: 20px;
-      overflow: hidden;
-      width: 120px;
-      height: 120px;
-      position: relative;
-      display: block;
-      z-index: 10; }
-      .dropzone .dz-preview .dz-image img {
-        display: block; }
-    .dropzone .dz-preview.dz-success .dz-success-mark {
-      -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-      -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-      -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-      -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-      animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
-    .dropzone .dz-preview.dz-error .dz-error-mark {
-      opacity: 1;
-      -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-      -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-      -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-      -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-      animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
-    .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
-      pointer-events: none;
-      opacity: 0;
-      z-index: 500;
-      position: absolute;
-      display: block;
-      top: 50%;
-      left: 50%;
-      margin-left: -27px;
-      margin-top: -27px; }
-      .dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
-        display: block;
-        width: 54px;
-        height: 54px; }
-    .dropzone .dz-preview.dz-processing .dz-progress {
-      opacity: 1;
-      -webkit-transition: all 0.2s linear;
-      -moz-transition: all 0.2s linear;
-      -ms-transition: all 0.2s linear;
-      -o-transition: all 0.2s linear;
-      transition: all 0.2s linear; }
-    .dropzone .dz-preview.dz-complete .dz-progress {
-      opacity: 0;
-      -webkit-transition: opacity 0.4s ease-in;
-      -moz-transition: opacity 0.4s ease-in;
-      -ms-transition: opacity 0.4s ease-in;
-      -o-transition: opacity 0.4s ease-in;
-      transition: opacity 0.4s ease-in; }
-    .dropzone .dz-preview:not(.dz-processing) .dz-progress {
-      -webkit-animation: pulse 6s ease infinite;
-      -moz-animation: pulse 6s ease infinite;
-      -ms-animation: pulse 6s ease infinite;
-      -o-animation: pulse 6s ease infinite;
-      animation: pulse 6s ease infinite; }
-    .dropzone .dz-preview .dz-progress {
-      opacity: 1;
-      z-index: 1000;
-      pointer-events: none;
-      position: absolute;
-      height: 16px;
-      left: 50%;
-      top: 50%;
-      margin-top: -8px;
-      width: 80px;
-      margin-left: -40px;
-      background: rgba(255, 255, 255, 0.9);
-      -webkit-transform: scale(1);
-      border-radius: 8px;
-      overflow: hidden; }
-      .dropzone .dz-preview .dz-progress .dz-upload {
-        background: #333;
-        background: linear-gradient(to bottom, #666, #444);
-        position: absolute;
-        top: 0;
-        left: 0;
-        bottom: 0;
-        width: 0;
-        -webkit-transition: width 300ms ease-in-out;
-        -moz-transition: width 300ms ease-in-out;
-        -ms-transition: width 300ms ease-in-out;
-        -o-transition: width 300ms ease-in-out;
-        transition: width 300ms ease-in-out; }
-    .dropzone .dz-preview.dz-error .dz-error-message {
-      display: block; }
-    .dropzone .dz-preview.dz-error:hover .dz-error-message {
-      opacity: 1;
-      pointer-events: auto; }
-    .dropzone .dz-preview .dz-error-message {
-      pointer-events: none;
-      z-index: 1000;
-      position: absolute;
-      display: block;
-      display: none;
-      opacity: 0;
-      -webkit-transition: opacity 0.3s ease;
-      -moz-transition: opacity 0.3s ease;
-      -ms-transition: opacity 0.3s ease;
-      -o-transition: opacity 0.3s ease;
-      transition: opacity 0.3s ease;
-      border-radius: 8px;
-      font-size: 13px;
-      top: 130px;
-      left: -10px;
-      width: 140px;
-      background: #be2626;
-      background: linear-gradient(to bottom, #be2626, #a92222);
-      padding: 0.5em 1.2em;
-      color: white; }
-      .dropzone .dz-preview .dz-error-message:after {
-        content: '';
-        position: absolute;
-        top: -6px;
-        left: 64px;
-        width: 0;
-        height: 0;
-        border-left: 6px solid transparent;
-        border-right: 6px solid transparent;
-        border-bottom: 6px solid #be2626; }
+  padding: 20px 20px;
+}
+.dropzone.dz-clickable {
+  cursor: pointer;
+}
+.dropzone.dz-clickable * {
+  cursor: default;
+}
+.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
+  cursor: pointer;
+}
+.dropzone.dz-started .dz-message {
+  display: none;
+}
+.dropzone.dz-drag-hover {
+  border-style: solid;
+}
+.dropzone.dz-drag-hover .dz-message {
+  opacity: 0.5;
+}
+.dropzone .dz-message {
+  text-align: center;
+  margin: 2em 0;
+}
+.dropzone .dz-message .dz-button {
+  background: none;
+  color: inherit;
+  border: none;
+  padding: 0;
+  font: inherit;
+  cursor: pointer;
+  outline: inherit;
+}
+.dropzone .dz-preview {
+  position: relative;
+  display: inline-block;
+  vertical-align: top;
+  margin: 16px;
+  min-height: 100px;
+}
+.dropzone .dz-preview:hover {
+  z-index: 1000;
+}
+.dropzone .dz-preview:hover .dz-details {
+  opacity: 1;
+}
+.dropzone .dz-preview.dz-file-preview .dz-image {
+  border-radius: 20px;
+  background: #999;
+  background: linear-gradient(to bottom, #eee, #ddd);
+}
+.dropzone .dz-preview.dz-file-preview .dz-details {
+  opacity: 1;
+}
+.dropzone .dz-preview.dz-image-preview {
+  background: white;
+}
+.dropzone .dz-preview.dz-image-preview .dz-details {
+  -webkit-transition: opacity 0.2s linear;
+  -moz-transition: opacity 0.2s linear;
+  -ms-transition: opacity 0.2s linear;
+  -o-transition: opacity 0.2s linear;
+  transition: opacity 0.2s linear;
+}
+.dropzone .dz-preview .dz-remove {
+  font-size: 14px;
+  text-align: center;
+  display: block;
+  cursor: pointer;
+  border: none;
+}
+.dropzone .dz-preview .dz-remove:hover {
+  text-decoration: underline;
+}
+.dropzone .dz-preview:hover .dz-details {
+  opacity: 1;
+}
+.dropzone .dz-preview .dz-details {
+  z-index: 20;
+  position: absolute;
+  top: 0;
+  left: 0;
+  opacity: 0;
+  font-size: 13px;
+  min-width: 100%;
+  max-width: 100%;
+  padding: 2em 1em;
+  text-align: center;
+  color: rgba(0, 0, 0, 0.9);
+  line-height: 150%;
+}
+.dropzone .dz-preview .dz-details .dz-size {
+  margin-bottom: 1em;
+  font-size: 16px;
+}
+.dropzone .dz-preview .dz-details .dz-filename {
+  white-space: nowrap;
+}
+.dropzone .dz-preview .dz-details .dz-filename:hover span {
+  border: 1px solid rgba(200, 200, 200, 0.8);
+  background-color: rgba(255, 255, 255, 0.8);
+}
+.dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
+  border: 1px solid transparent;
+}
+.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
+  background-color: rgba(255, 255, 255, 0.4);
+  padding: 0 0.4em;
+  border-radius: 3px;
+}
+.dropzone .dz-preview:hover .dz-image img {
+  -webkit-transform: scale(1.05, 1.05);
+  -moz-transform: scale(1.05, 1.05);
+  -ms-transform: scale(1.05, 1.05);
+  -o-transform: scale(1.05, 1.05);
+  transform: scale(1.05, 1.05);
+  -webkit-filter: blur(8px);
+  filter: blur(8px);
+}
+.dropzone .dz-preview .dz-image {
+  border-radius: 20px;
+  overflow: hidden;
+  width: 120px;
+  height: 120px;
+  position: relative;
+  display: block;
+  z-index: 10;
+}
+.dropzone .dz-preview .dz-image img {
+  display: block;
+}
+.dropzone .dz-preview.dz-success .dz-success-mark {
+  -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+  -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+  -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+  -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+  animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+}
+.dropzone .dz-preview.dz-error .dz-error-mark {
+  opacity: 1;
+  -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+  -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+  -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+  -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+  animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+}
+.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
+  pointer-events: none;
+  opacity: 0;
+  z-index: 500;
+  position: absolute;
+  display: block;
+  top: 50%;
+  left: 50%;
+  margin-left: -27px;
+  margin-top: -27px;
+}
+.dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
+  display: block;
+  width: 54px;
+  height: 54px;
+}
+.dropzone .dz-preview.dz-processing .dz-progress {
+  opacity: 1;
+  -webkit-transition: all 0.2s linear;
+  -moz-transition: all 0.2s linear;
+  -ms-transition: all 0.2s linear;
+  -o-transition: all 0.2s linear;
+  transition: all 0.2s linear;
+}
+.dropzone .dz-preview.dz-complete .dz-progress {
+  opacity: 0;
+  -webkit-transition: opacity 0.4s ease-in;
+  -moz-transition: opacity 0.4s ease-in;
+  -ms-transition: opacity 0.4s ease-in;
+  -o-transition: opacity 0.4s ease-in;
+  transition: opacity 0.4s ease-in;
+}
+.dropzone .dz-preview:not(.dz-processing) .dz-progress {
+  -webkit-animation: pulse 6s ease infinite;
+  -moz-animation: pulse 6s ease infinite;
+  -ms-animation: pulse 6s ease infinite;
+  -o-animation: pulse 6s ease infinite;
+  animation: pulse 6s ease infinite;
+}
+.dropzone .dz-preview .dz-progress {
+  opacity: 1;
+  z-index: 1000;
+  pointer-events: none;
+  position: absolute;
+  height: 16px;
+  left: 50%;
+  top: 50%;
+  margin-top: -8px;
+  width: 80px;
+  margin-left: -40px;
+  background: rgba(255, 255, 255, 0.9);
+  -webkit-transform: scale(1);
+  border-radius: 8px;
+  overflow: hidden;
+}
+.dropzone .dz-preview .dz-progress .dz-upload {
+  background: #333;
+  background: linear-gradient(to bottom, #666, #444);
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  width: 0;
+  -webkit-transition: width 300ms ease-in-out;
+  -moz-transition: width 300ms ease-in-out;
+  -ms-transition: width 300ms ease-in-out;
+  -o-transition: width 300ms ease-in-out;
+  transition: width 300ms ease-in-out;
+}
+.dropzone .dz-preview.dz-error .dz-error-message {
+  display: block;
+}
+.dropzone .dz-preview.dz-error:hover .dz-error-message {
+  opacity: 1;
+  pointer-events: auto;
+}
+.dropzone .dz-preview .dz-error-message {
+  pointer-events: none;
+  z-index: 1000;
+  position: absolute;
+  display: block;
+  display: none;
+  opacity: 0;
+  -webkit-transition: opacity 0.3s ease;
+  -moz-transition: opacity 0.3s ease;
+  -ms-transition: opacity 0.3s ease;
+  -o-transition: opacity 0.3s ease;
+  transition: opacity 0.3s ease;
+  border-radius: 8px;
+  font-size: 13px;
+  top: 130px;
+  left: -10px;
+  width: 140px;
+  background: #be2626;
+  background: linear-gradient(to bottom, #be2626, #a92222);
+  padding: 0.5em 1.2em;
+  color: white;
+}
+.dropzone .dz-preview .dz-error-message:after {
+  content: "";
+  position: absolute;
+  top: -6px;
+  left: 64px;
+  width: 0;
+  height: 0;
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid #be2626;
+}

File diff suppressed because it is too large
+ 8146 - 1190
plugins/dropzone/dropzone.js


File diff suppressed because it is too large
+ 1 - 0
plugins/dropzone/min/basic.css


File diff suppressed because it is too large
+ 1 - 1
plugins/dropzone/min/dropzone-amd-module.min.js


File diff suppressed because it is too large
+ 1 - 0
plugins/dropzone/min/dropzone.css


File diff suppressed because it is too large
+ 1 - 1
plugins/dropzone/min/dropzone.min.js


+ 70 - 49
plugins/uplot/uPlot.cjs.js

@@ -4,7 +4,7 @@
 *
 * uPlot.js (μPlot)
 * A small, fast chart for time series, lines, areas, ohlc & bars
-* https://github.com/leeoniya/uPlot (v1.6.3)
+* https://github.com/leeoniya/uPlot (v1.6.4)
 */
 
 'use strict';
@@ -336,13 +336,13 @@ function assign(targ) {
 }
 
 // nullModes
-const NULL_IGNORE = 0;  // all nulls are ignored, converted to undefined (e.g. spanGaps: true)
-const NULL_GAP    = 1;  // nulls are retained, alignment artifacts = undefined values (default)
-const NULL_EXPAND = 2;  // nulls are expanded to include adjacent alignment artifacts (undefined values)
+const NULL_REMOVE = 0;  // nulls are converted to undefined (e.g. for spanGaps: true)
+const NULL_RETAIN = 1;  // nulls are retained, with alignment artifacts set to undefined (default)
+const NULL_EXPAND = 2;  // nulls are expanded to include any adjacent alignment artifacts
 
-// mark all filler nulls as explicit when adjacent to existing explicit nulls (minesweeper)
+// sets undefined values to nulls when adjacent to existing nulls (minesweeper)
 function nullExpand(yVals, nullIdxs, alignedLen) {
-	for (let i = 0, xi, lastNullIdx = -inf; i < nullIdxs.length; i++) {
+	for (let i = 0, xi, lastNullIdx = -1; i < nullIdxs.length; i++) {
 		let nullIdx = nullIdxs[i];
 
 		if (nullIdx > lastNullIdx) {
@@ -358,10 +358,8 @@ function nullExpand(yVals, nullIdxs, alignedLen) {
 }
 
 // nullModes is a tables-matched array indicating how to treat nulls in each series
+// output is sorted ASC on the joined field (table[0]) and duplicate join values are collapsed
 function join(tables, nullModes) {
-	if (tables.length == 1)
-		return tables[0];
-
 	let xVals = new Set();
 
 	for (let ti = 0; ti < tables.length; ti++) {
@@ -391,7 +389,7 @@ function join(tables, nullModes) {
 
 			let yVals = Array(alignedLen).fill(undefined);
 
-			let nullMode = nullModes ? nullModes[ti][si] : NULL_GAP;
+			let nullMode = nullModes ? nullModes[ti][si] : NULL_RETAIN;
 
 			let nullIdxs = [];
 
@@ -400,7 +398,7 @@ function join(tables, nullModes) {
 				let alignedIdx = xIdxs.get(xs[i]);
 
 				if (yVal == null) {
-					if (nullMode != NULL_IGNORE) {
+					if (nullMode != NULL_REMOVE) {
 						yVals[alignedIdx] = yVal;
 
 						if (nullMode == NULL_EXPAND)
@@ -874,7 +872,7 @@ const [ timeIncrsMs, _timeAxisStampsMs, timeAxisSplitsMs ] =  genTimeStuffs(1);
 const [ timeIncrsS,  _timeAxisStampsS,  timeAxisSplitsS  ] =  genTimeStuffs(1e-3);
 
 // base 2
-const binIncrs = genIncrs(2, -53, 53, [1]);
+genIncrs(2, -53, 53, [1]);
 
 /*
 console.log({
@@ -1468,9 +1466,11 @@ function bezierCurveToH(p, bp1x, bp1y, bp2x, bp2y, p2x, p2y) { p.bezierCurveTo(b
 
 function _drawAcc(lineTo) {
 	return (stroke, accX, minY, maxY, outY) => {
-		lineTo(stroke, accX, minY);
-		lineTo(stroke, accX, maxY);
-		lineTo(stroke, accX, outY);
+		if (minY != maxY) {
+			lineTo(stroke, accX, minY);
+			lineTo(stroke, accX, maxY);
+			lineTo(stroke, accX, outY);
+		}
 	};
 }
 
@@ -2089,6 +2089,8 @@ function uPlot(opts, data, then) {
 
 	opts = copy(opts);
 
+	const pxAlign = ifNull(opts.pxAlign, true);
+
 	(opts.plugins || []).forEach(p => {
 		if (p.opts)
 			opts = p.opts(self, opts) || opts;
@@ -2553,10 +2555,11 @@ function uPlot(opts, data, then) {
 			s.width  = s.width == null ? 1 : s.width;
 			s.paths  = s.paths || linearPath || retNull;
 			s.fillTo = fnOrSelf(s.fillTo || seriesFillTo);
+			s.pxAlign = ifNull(s.pxAlign, true);
 
 			s.stroke = fnOrSelf(s.stroke || null);
 			s.fill   = fnOrSelf(s.fill || null);
-			s._stroke = s._fill = s._paths = null;
+			s._stroke = s._fill = s._paths = s._focus = null;
 
 			let _ptDia = ptDia(s.width, 1);
 			let points = s.points = assign({}, {
@@ -2916,7 +2919,9 @@ function uPlot(opts, data, then) {
 		let rad = (p.size - p.width) / 2 * pxRatio;
 		let dia = roundDec(rad * 2, 3);
 
-		ctx.translate(offset, offset);
+		const _pxAlign = pxAlign && s.pxAlign;
+
+		_pxAlign && ctx.translate(offset, offset);
 
 		ctx.save();
 
@@ -2978,7 +2983,7 @@ function uPlot(opts, data, then) {
 
 		ctx.restore();
 
-		ctx.translate(-offset, -offset);
+		_pxAlign && ctx.translate(-offset, -offset);
 	}
 
 	// grabs the nearest indices with y data outside of x-scale limits
@@ -3025,14 +3030,14 @@ function uPlot(opts, data, then) {
 		const width = roundDec(s.width * pxRatio, 3);
 		const offset = (width % 2) / 2;
 
-		const _stroke = s._stroke = s.stroke(self, si);
-		const _fill   = s._fill   = s.fill(self, si);
-
-		setCtxStyle(_stroke, width, s.dash, s.cap, _fill);
+		const strokeStyle = s._stroke = s.stroke(self, si);
+		const fillStyle   = s._fill   = s.fill(self, si);
 
 		ctx.globalAlpha = s.alpha;
 
-		ctx.translate(offset, offset);
+		const _pxAlign = pxAlign && s.pxAlign;
+
+		_pxAlign && ctx.translate(offset, offset);
 
 		ctx.save();
 
@@ -3057,43 +3062,53 @@ function uPlot(opts, data, then) {
 
 		clip && ctx.clip(clip);
 
-		let isUpperEdge = fillBands(si, _fill);
-
-		!isUpperEdge && _fill   && fill   && ctx.fill(fill);
-
-		width        && _stroke && stroke && ctx.stroke(stroke);
+		fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill);
 
 		ctx.restore();
 
-		ctx.translate(-offset, -offset);
+		_pxAlign && ctx.translate(-offset, -offset);
 
 		ctx.globalAlpha = 1;
 	}
 
-	function fillBands(si, seriesFill) {
-		let isUpperEdge = false;
-		let s = series[si];
+	function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath) {
+		let didStrokeFill = false;
 
 		// for all bands where this series is the top edge, create upwards clips using the bottom edges
 		// and apply clips + fill with band fill or dfltFill
 		bands.forEach((b, bi) => {
+			// isUpperEdge?
 			if (b.series[0] == si) {
-				isUpperEdge = true;
 				let lowerEdge = series[b.series[1]];
 
 				let clip = (lowerEdge._paths || EMPTY_OBJ).band;
 
+				ctx.save();
+
+				let _fillStyle = null;
+
+				// hasLowerEdge?
 				if (lowerEdge.show && clip) {
-					ctx.save();
-					setCtxStyle(null, null, null, null, b.fill(self, bi) || seriesFill);
+					_fillStyle = b.fill(self, bi) || fillStyle;
 					ctx.clip(clip);
-					ctx.fill(s._paths.fill);
-					ctx.restore();
 				}
+
+				strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath);
+
+				ctx.restore();
+
+				didStrokeFill = true;
 			}
 		});
 
-		return isUpperEdge;
+		if (!didStrokeFill)
+			strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath);
+	}
+
+	function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath) {
+		setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle);
+		fillStyle   && fillPath                && ctx.fill(fillPath);
+		strokeStyle && strokePath && lineWidth && ctx.stroke(strokePath);
 	}
 
 	function getIncrSpace(axisIdx, min, max, fullDim) {
@@ -3115,7 +3130,7 @@ function uPlot(opts, data, then) {
 	function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) {
 		let offset = (width % 2) / 2;
 
-		ctx.translate(offset, offset);
+		pxAlign && ctx.translate(offset, offset);
 
 		setCtxStyle(stroke, width, dash, cap);
 
@@ -3147,7 +3162,7 @@ function uPlot(opts, data, then) {
 
 		ctx.stroke();
 
-		ctx.translate(-offset, -offset);
+		pxAlign && ctx.translate(-offset, -offset);
 	}
 
 	function axesCalc(cycleNum) {
@@ -3197,7 +3212,7 @@ function uPlot(opts, data, then) {
 			let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits;
 			let incr   = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr;
 
-			let values = axis._values  = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
+			let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
 
 			// rotating of labels only supported on bottom x axis
 			axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0;
@@ -3240,7 +3255,7 @@ function uPlot(opts, data, then) {
 			let plotDim = ori == 0 ? plotWid : plotHgt;
 			let plotOff = ori == 0 ? plotLft : plotTop;
 
-			let axisGap  = round(axis.gap * pxRatio);
+			let axisGap = round(axis.gap * pxRatio);
 
 			let ticks = axis.ticks;
 			let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0;
@@ -3273,7 +3288,7 @@ function uPlot(opts, data, then) {
 			ctx.textBaseline = angle ||
 			                   ori == 1 ? "middle" : side == 2 ? TOP   : BOTTOM;
 
-			let lineHeight   = axis.font[1] * lineMult;
+			let lineHeight = axis.font[1] * lineMult;
 
 			let canOffs = _splits.map(val => round(getPos(val, scale, plotDim, plotOff)));
 
@@ -3464,7 +3479,9 @@ function uPlot(opts, data, then) {
 		queuedCommit = false;
 	}
 
-	self.redraw = rebuildPaths => {
+	self.redraw = (rebuildPaths, recalcAxes) => {
+		shouldConvergeSize = recalcAxes || false;
+
 		if (rebuildPaths !== false)
 			_setScale(xScaleKey, scaleX.min, scaleX.max);
 		else
@@ -3563,10 +3580,10 @@ function uPlot(opts, data, then) {
 	const select = self.select = assign({
 		show:   true,
 		over:   true,
-		left:	0,
-		width:	0,
-		top:	0,
-		height:	0,
+		left:   0,
+		width:  0,
+		top:    0,
+		height: 0,
 	}, opts.select);
 
 	const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null;
@@ -3648,8 +3665,12 @@ function uPlot(opts, data, then) {
 		if (i != focusedSeries) {
 		//	log("setFocus()", arguments);
 
+			let allFocused = i == null;
+
 			series.forEach((s, i2) => {
-				_setAlpha(i2, i == null || i2 == 0 || i2 == i ? 1 : focus.alpha);
+				let isFocused = allFocused || i2 == 0 || i2 == i;
+				s._focus = allFocused ? null : isFocused;
+				_setAlpha(i2, isFocused ? 1 : focus.alpha);
 			});
 
 			focusedSeries = i;

+ 70 - 49
plugins/uplot/uPlot.esm.js

@@ -4,7 +4,7 @@
 *
 * uPlot.js (μPlot)
 * A small, fast chart for time series, lines, areas, ohlc & bars
-* https://github.com/leeoniya/uPlot (v1.6.3)
+* https://github.com/leeoniya/uPlot (v1.6.4)
 */
 
 const FEAT_TIME          = true;
@@ -334,13 +334,13 @@ function assign(targ) {
 }
 
 // nullModes
-const NULL_IGNORE = 0;  // all nulls are ignored, converted to undefined (e.g. spanGaps: true)
-const NULL_GAP    = 1;  // nulls are retained, alignment artifacts = undefined values (default)
-const NULL_EXPAND = 2;  // nulls are expanded to include adjacent alignment artifacts (undefined values)
+const NULL_REMOVE = 0;  // nulls are converted to undefined (e.g. for spanGaps: true)
+const NULL_RETAIN = 1;  // nulls are retained, with alignment artifacts set to undefined (default)
+const NULL_EXPAND = 2;  // nulls are expanded to include any adjacent alignment artifacts
 
-// mark all filler nulls as explicit when adjacent to existing explicit nulls (minesweeper)
+// sets undefined values to nulls when adjacent to existing nulls (minesweeper)
 function nullExpand(yVals, nullIdxs, alignedLen) {
-	for (let i = 0, xi, lastNullIdx = -inf; i < nullIdxs.length; i++) {
+	for (let i = 0, xi, lastNullIdx = -1; i < nullIdxs.length; i++) {
 		let nullIdx = nullIdxs[i];
 
 		if (nullIdx > lastNullIdx) {
@@ -356,10 +356,8 @@ function nullExpand(yVals, nullIdxs, alignedLen) {
 }
 
 // nullModes is a tables-matched array indicating how to treat nulls in each series
+// output is sorted ASC on the joined field (table[0]) and duplicate join values are collapsed
 function join(tables, nullModes) {
-	if (tables.length == 1)
-		return tables[0];
-
 	let xVals = new Set();
 
 	for (let ti = 0; ti < tables.length; ti++) {
@@ -389,7 +387,7 @@ function join(tables, nullModes) {
 
 			let yVals = Array(alignedLen).fill(undefined);
 
-			let nullMode = nullModes ? nullModes[ti][si] : NULL_GAP;
+			let nullMode = nullModes ? nullModes[ti][si] : NULL_RETAIN;
 
 			let nullIdxs = [];
 
@@ -398,7 +396,7 @@ function join(tables, nullModes) {
 				let alignedIdx = xIdxs.get(xs[i]);
 
 				if (yVal == null) {
-					if (nullMode != NULL_IGNORE) {
+					if (nullMode != NULL_REMOVE) {
 						yVals[alignedIdx] = yVal;
 
 						if (nullMode == NULL_EXPAND)
@@ -872,7 +870,7 @@ const [ timeIncrsMs, _timeAxisStampsMs, timeAxisSplitsMs ] =  genTimeStuffs(1);
 const [ timeIncrsS,  _timeAxisStampsS,  timeAxisSplitsS  ] =  genTimeStuffs(1e-3);
 
 // base 2
-const binIncrs = genIncrs(2, -53, 53, [1]);
+genIncrs(2, -53, 53, [1]);
 
 /*
 console.log({
@@ -1466,9 +1464,11 @@ function bezierCurveToH(p, bp1x, bp1y, bp2x, bp2y, p2x, p2y) { p.bezierCurveTo(b
 
 function _drawAcc(lineTo) {
 	return (stroke, accX, minY, maxY, outY) => {
-		lineTo(stroke, accX, minY);
-		lineTo(stroke, accX, maxY);
-		lineTo(stroke, accX, outY);
+		if (minY != maxY) {
+			lineTo(stroke, accX, minY);
+			lineTo(stroke, accX, maxY);
+			lineTo(stroke, accX, outY);
+		}
 	};
 }
 
@@ -2087,6 +2087,8 @@ function uPlot(opts, data, then) {
 
 	opts = copy(opts);
 
+	const pxAlign = ifNull(opts.pxAlign, true);
+
 	(opts.plugins || []).forEach(p => {
 		if (p.opts)
 			opts = p.opts(self, opts) || opts;
@@ -2551,10 +2553,11 @@ function uPlot(opts, data, then) {
 			s.width  = s.width == null ? 1 : s.width;
 			s.paths  = s.paths || linearPath || retNull;
 			s.fillTo = fnOrSelf(s.fillTo || seriesFillTo);
+			s.pxAlign = ifNull(s.pxAlign, true);
 
 			s.stroke = fnOrSelf(s.stroke || null);
 			s.fill   = fnOrSelf(s.fill || null);
-			s._stroke = s._fill = s._paths = null;
+			s._stroke = s._fill = s._paths = s._focus = null;
 
 			let _ptDia = ptDia(s.width, 1);
 			let points = s.points = assign({}, {
@@ -2914,7 +2917,9 @@ function uPlot(opts, data, then) {
 		let rad = (p.size - p.width) / 2 * pxRatio;
 		let dia = roundDec(rad * 2, 3);
 
-		ctx.translate(offset, offset);
+		const _pxAlign = pxAlign && s.pxAlign;
+
+		_pxAlign && ctx.translate(offset, offset);
 
 		ctx.save();
 
@@ -2976,7 +2981,7 @@ function uPlot(opts, data, then) {
 
 		ctx.restore();
 
-		ctx.translate(-offset, -offset);
+		_pxAlign && ctx.translate(-offset, -offset);
 	}
 
 	// grabs the nearest indices with y data outside of x-scale limits
@@ -3023,14 +3028,14 @@ function uPlot(opts, data, then) {
 		const width = roundDec(s.width * pxRatio, 3);
 		const offset = (width % 2) / 2;
 
-		const _stroke = s._stroke = s.stroke(self, si);
-		const _fill   = s._fill   = s.fill(self, si);
-
-		setCtxStyle(_stroke, width, s.dash, s.cap, _fill);
+		const strokeStyle = s._stroke = s.stroke(self, si);
+		const fillStyle   = s._fill   = s.fill(self, si);
 
 		ctx.globalAlpha = s.alpha;
 
-		ctx.translate(offset, offset);
+		const _pxAlign = pxAlign && s.pxAlign;
+
+		_pxAlign && ctx.translate(offset, offset);
 
 		ctx.save();
 
@@ -3055,43 +3060,53 @@ function uPlot(opts, data, then) {
 
 		clip && ctx.clip(clip);
 
-		let isUpperEdge = fillBands(si, _fill);
-
-		!isUpperEdge && _fill   && fill   && ctx.fill(fill);
-
-		width        && _stroke && stroke && ctx.stroke(stroke);
+		fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill);
 
 		ctx.restore();
 
-		ctx.translate(-offset, -offset);
+		_pxAlign && ctx.translate(-offset, -offset);
 
 		ctx.globalAlpha = 1;
 	}
 
-	function fillBands(si, seriesFill) {
-		let isUpperEdge = false;
-		let s = series[si];
+	function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath) {
+		let didStrokeFill = false;
 
 		// for all bands where this series is the top edge, create upwards clips using the bottom edges
 		// and apply clips + fill with band fill or dfltFill
 		bands.forEach((b, bi) => {
+			// isUpperEdge?
 			if (b.series[0] == si) {
-				isUpperEdge = true;
 				let lowerEdge = series[b.series[1]];
 
 				let clip = (lowerEdge._paths || EMPTY_OBJ).band;
 
+				ctx.save();
+
+				let _fillStyle = null;
+
+				// hasLowerEdge?
 				if (lowerEdge.show && clip) {
-					ctx.save();
-					setCtxStyle(null, null, null, null, b.fill(self, bi) || seriesFill);
+					_fillStyle = b.fill(self, bi) || fillStyle;
 					ctx.clip(clip);
-					ctx.fill(s._paths.fill);
-					ctx.restore();
 				}
+
+				strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath);
+
+				ctx.restore();
+
+				didStrokeFill = true;
 			}
 		});
 
-		return isUpperEdge;
+		if (!didStrokeFill)
+			strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath);
+	}
+
+	function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath) {
+		setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle);
+		fillStyle   && fillPath                && ctx.fill(fillPath);
+		strokeStyle && strokePath && lineWidth && ctx.stroke(strokePath);
 	}
 
 	function getIncrSpace(axisIdx, min, max, fullDim) {
@@ -3113,7 +3128,7 @@ function uPlot(opts, data, then) {
 	function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) {
 		let offset = (width % 2) / 2;
 
-		ctx.translate(offset, offset);
+		pxAlign && ctx.translate(offset, offset);
 
 		setCtxStyle(stroke, width, dash, cap);
 
@@ -3145,7 +3160,7 @@ function uPlot(opts, data, then) {
 
 		ctx.stroke();
 
-		ctx.translate(-offset, -offset);
+		pxAlign && ctx.translate(-offset, -offset);
 	}
 
 	function axesCalc(cycleNum) {
@@ -3195,7 +3210,7 @@ function uPlot(opts, data, then) {
 			let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits;
 			let incr   = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr;
 
-			let values = axis._values  = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
+			let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
 
 			// rotating of labels only supported on bottom x axis
 			axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0;
@@ -3238,7 +3253,7 @@ function uPlot(opts, data, then) {
 			let plotDim = ori == 0 ? plotWid : plotHgt;
 			let plotOff = ori == 0 ? plotLft : plotTop;
 
-			let axisGap  = round(axis.gap * pxRatio);
+			let axisGap = round(axis.gap * pxRatio);
 
 			let ticks = axis.ticks;
 			let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0;
@@ -3271,7 +3286,7 @@ function uPlot(opts, data, then) {
 			ctx.textBaseline = angle ||
 			                   ori == 1 ? "middle" : side == 2 ? TOP   : BOTTOM;
 
-			let lineHeight   = axis.font[1] * lineMult;
+			let lineHeight = axis.font[1] * lineMult;
 
 			let canOffs = _splits.map(val => round(getPos(val, scale, plotDim, plotOff)));
 
@@ -3462,7 +3477,9 @@ function uPlot(opts, data, then) {
 		queuedCommit = false;
 	}
 
-	self.redraw = rebuildPaths => {
+	self.redraw = (rebuildPaths, recalcAxes) => {
+		shouldConvergeSize = recalcAxes || false;
+
 		if (rebuildPaths !== false)
 			_setScale(xScaleKey, scaleX.min, scaleX.max);
 		else
@@ -3561,10 +3578,10 @@ function uPlot(opts, data, then) {
 	const select = self.select = assign({
 		show:   true,
 		over:   true,
-		left:	0,
-		width:	0,
-		top:	0,
-		height:	0,
+		left:   0,
+		width:  0,
+		top:    0,
+		height: 0,
 	}, opts.select);
 
 	const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null;
@@ -3646,8 +3663,12 @@ function uPlot(opts, data, then) {
 		if (i != focusedSeries) {
 		//	log("setFocus()", arguments);
 
+			let allFocused = i == null;
+
 			series.forEach((s, i2) => {
-				_setAlpha(i2, i == null || i2 == 0 || i2 == i ? 1 : focus.alpha);
+				let isFocused = allFocused || i2 == 0 || i2 == i;
+				s._focus = allFocused ? null : isFocused;
+				_setAlpha(i2, isFocused ? 1 : focus.alpha);
 			});
 
 			focusedSeries = i;

+ 70 - 49
plugins/uplot/uPlot.iife.js

@@ -4,7 +4,7 @@
 *
 * uPlot.js (μPlot)
 * A small, fast chart for time series, lines, areas, ohlc & bars
-* https://github.com/leeoniya/uPlot (v1.6.3)
+* https://github.com/leeoniya/uPlot (v1.6.4)
 */
 
 var uPlot = (function () {
@@ -336,13 +336,13 @@ var uPlot = (function () {
 	}
 
 	// nullModes
-	var NULL_IGNORE = 0;  // all nulls are ignored, converted to undefined (e.g. spanGaps: true)
-	var NULL_GAP    = 1;  // nulls are retained, alignment artifacts = undefined values (default)
-	var NULL_EXPAND = 2;  // nulls are expanded to include adjacent alignment artifacts (undefined values)
+	var NULL_REMOVE = 0;  // nulls are converted to undefined (e.g. for spanGaps: true)
+	var NULL_RETAIN = 1;  // nulls are retained, with alignment artifacts set to undefined (default)
+	var NULL_EXPAND = 2;  // nulls are expanded to include any adjacent alignment artifacts
 
-	// mark all filler nulls as explicit when adjacent to existing explicit nulls (minesweeper)
+	// sets undefined values to nulls when adjacent to existing nulls (minesweeper)
 	function nullExpand(yVals, nullIdxs, alignedLen) {
-		for (var i = 0, xi = (void 0), lastNullIdx = -inf; i < nullIdxs.length; i++) {
+		for (var i = 0, xi = (void 0), lastNullIdx = -1; i < nullIdxs.length; i++) {
 			var nullIdx = nullIdxs[i];
 
 			if (nullIdx > lastNullIdx) {
@@ -358,10 +358,8 @@ var uPlot = (function () {
 	}
 
 	// nullModes is a tables-matched array indicating how to treat nulls in each series
+	// output is sorted ASC on the joined field (table[0]) and duplicate join values are collapsed
 	function join(tables, nullModes) {
-		if (tables.length == 1)
-			{ return tables[0]; }
-
 		var xVals = new Set();
 
 		for (var ti = 0; ti < tables.length; ti++) {
@@ -391,7 +389,7 @@ var uPlot = (function () {
 
 				var yVals = Array(alignedLen).fill(undefined);
 
-				var nullMode = nullModes ? nullModes[ti$1][si] : NULL_GAP;
+				var nullMode = nullModes ? nullModes[ti$1][si] : NULL_RETAIN;
 
 				var nullIdxs = [];
 
@@ -400,7 +398,7 @@ var uPlot = (function () {
 					var alignedIdx = xIdxs.get(xs$1[i$2]);
 
 					if (yVal == null) {
-						if (nullMode != NULL_IGNORE) {
+						if (nullMode != NULL_REMOVE) {
 							yVals[alignedIdx] = yVal;
 
 							if (nullMode == NULL_EXPAND)
@@ -875,7 +873,7 @@ var uPlot = (function () {
 	var timeAxisSplitsS = ref$1[2];
 
 	// base 2
-	var binIncrs = genIncrs(2, -53, 53, [1]);
+	genIncrs(2, -53, 53, [1]);
 
 	/*
 	console.log({
@@ -1469,9 +1467,11 @@ var uPlot = (function () {
 
 	function _drawAcc(lineTo) {
 		return (stroke, accX, minY, maxY, outY) => {
-			lineTo(stroke, accX, minY);
-			lineTo(stroke, accX, maxY);
-			lineTo(stroke, accX, outY);
+			if (minY != maxY) {
+				lineTo(stroke, accX, minY);
+				lineTo(stroke, accX, maxY);
+				lineTo(stroke, accX, outY);
+			}
 		};
 	}
 
@@ -2083,6 +2083,8 @@ var uPlot = (function () {
 
 		opts = copy(opts);
 
+		var pxAlign = ifNull(opts.pxAlign, true);
+
 		(opts.plugins || []).forEach(p => {
 			if (p.opts)
 				{ opts = p.opts(self, opts) || opts; }
@@ -2551,10 +2553,11 @@ var uPlot = (function () {
 				s.width  = s.width == null ? 1 : s.width;
 				s.paths  = s.paths || linearPath || retNull;
 				s.fillTo = fnOrSelf(s.fillTo || seriesFillTo);
+				s.pxAlign = ifNull(s.pxAlign, true);
 
 				s.stroke = fnOrSelf(s.stroke || null);
 				s.fill   = fnOrSelf(s.fill || null);
-				s._stroke = s._fill = s._paths = null;
+				s._stroke = s._fill = s._paths = s._focus = null;
 
 				var _ptDia = ptDia(s.width, 1);
 				var points = s.points = assign({}, {
@@ -2919,7 +2922,9 @@ var uPlot = (function () {
 			var rad = (p.size - p.width) / 2 * pxRatio;
 			var dia = roundDec(rad * 2, 3);
 
-			ctx.translate(offset, offset);
+			var _pxAlign = pxAlign && s.pxAlign;
+
+			_pxAlign && ctx.translate(offset, offset);
 
 			ctx.save();
 
@@ -2981,7 +2986,7 @@ var uPlot = (function () {
 
 			ctx.restore();
 
-			ctx.translate(-offset, -offset);
+			_pxAlign && ctx.translate(-offset, -offset);
 		}
 
 		// grabs the nearest indices with y data outside of x-scale limits
@@ -3031,14 +3036,14 @@ var uPlot = (function () {
 			var width = roundDec(s.width * pxRatio, 3);
 			var offset = (width % 2) / 2;
 
-			var _stroke = s._stroke = s.stroke(self, si);
-			var _fill   = s._fill   = s.fill(self, si);
-
-			setCtxStyle(_stroke, width, s.dash, s.cap, _fill);
+			var strokeStyle = s._stroke = s.stroke(self, si);
+			var fillStyle   = s._fill   = s.fill(self, si);
 
 			ctx.globalAlpha = s.alpha;
 
-			ctx.translate(offset, offset);
+			var _pxAlign = pxAlign && s.pxAlign;
+
+			_pxAlign && ctx.translate(offset, offset);
 
 			ctx.save();
 
@@ -3063,43 +3068,53 @@ var uPlot = (function () {
 
 			clip && ctx.clip(clip);
 
-			var isUpperEdge = fillBands(si, _fill);
-
-			!isUpperEdge && _fill   && fill   && ctx.fill(fill);
-
-			width        && _stroke && stroke && ctx.stroke(stroke);
+			fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill);
 
 			ctx.restore();
 
-			ctx.translate(-offset, -offset);
+			_pxAlign && ctx.translate(-offset, -offset);
 
 			ctx.globalAlpha = 1;
 		}
 
-		function fillBands(si, seriesFill) {
-			var isUpperEdge = false;
-			var s = series[si];
+		function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath) {
+			var didStrokeFill = false;
 
 			// for all bands where this series is the top edge, create upwards clips using the bottom edges
 			// and apply clips + fill with band fill or dfltFill
 			bands.forEach((b, bi) => {
+				// isUpperEdge?
 				if (b.series[0] == si) {
-					isUpperEdge = true;
 					var lowerEdge = series[b.series[1]];
 
 					var clip = (lowerEdge._paths || EMPTY_OBJ).band;
 
+					ctx.save();
+
+					var _fillStyle = null;
+
+					// hasLowerEdge?
 					if (lowerEdge.show && clip) {
-						ctx.save();
-						setCtxStyle(null, null, null, null, b.fill(self, bi) || seriesFill);
+						_fillStyle = b.fill(self, bi) || fillStyle;
 						ctx.clip(clip);
-						ctx.fill(s._paths.fill);
-						ctx.restore();
 					}
+
+					strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath);
+
+					ctx.restore();
+
+					didStrokeFill = true;
 				}
 			});
 
-			return isUpperEdge;
+			if (!didStrokeFill)
+				{ strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath); }
+		}
+
+		function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath) {
+			setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle);
+			fillStyle   && fillPath                && ctx.fill(fillPath);
+			strokeStyle && strokePath && lineWidth && ctx.stroke(strokePath);
 		}
 
 		function getIncrSpace(axisIdx, min, max, fullDim) {
@@ -3121,7 +3136,7 @@ var uPlot = (function () {
 		function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) {
 			var offset = (width % 2) / 2;
 
-			ctx.translate(offset, offset);
+			pxAlign && ctx.translate(offset, offset);
 
 			setCtxStyle(stroke, width, dash, cap);
 
@@ -3153,7 +3168,7 @@ var uPlot = (function () {
 
 			ctx.stroke();
 
-			ctx.translate(-offset, -offset);
+			pxAlign && ctx.translate(-offset, -offset);
 		}
 
 		function axesCalc(cycleNum) {
@@ -3206,7 +3221,7 @@ var uPlot = (function () {
 				var splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits;
 				var incr   = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr;
 
-				var values = axis._values  = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
+				var values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
 
 				// rotating of labels only supported on bottom x axis
 				axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0;
@@ -3249,7 +3264,7 @@ var uPlot = (function () {
 				var plotDim = ori == 0 ? plotWid : plotHgt;
 				var plotOff = ori == 0 ? plotLft : plotTop;
 
-				var axisGap  = round(axis.gap * pxRatio);
+				var axisGap = round(axis.gap * pxRatio);
 
 				var ticks = axis.ticks;
 				var tickSize = ticks.show ? round(ticks.size * pxRatio) : 0;
@@ -3284,7 +3299,7 @@ var uPlot = (function () {
 				ctx.textBaseline = angle ||
 				                   ori == 1 ? "middle" : side == 2 ? TOP   : BOTTOM;
 
-				var lineHeight   = axis.font[1] * lineMult;
+				var lineHeight = axis.font[1] * lineMult;
 
 				var canOffs = _splits.map(val => round(getPos(val, scale, plotDim, plotOff)));
 
@@ -3475,7 +3490,9 @@ var uPlot = (function () {
 			queuedCommit = false;
 		}
 
-		self.redraw = rebuildPaths => {
+		self.redraw = (rebuildPaths, recalcAxes) => {
+			shouldConvergeSize = recalcAxes || false;
+
 			if (rebuildPaths !== false)
 				{ _setScale(xScaleKey, scaleX.min, scaleX.max); }
 			else
@@ -3574,10 +3591,10 @@ var uPlot = (function () {
 		var select = self.select = assign({
 			show:   true,
 			over:   true,
-			left:	0,
-			width:	0,
-			top:	0,
-			height:	0,
+			left:   0,
+			width:  0,
+			top:    0,
+			height: 0,
 		}, opts.select);
 
 		var selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null;
@@ -3659,8 +3676,12 @@ var uPlot = (function () {
 			if (i != focusedSeries) {
 			//	log("setFocus()", arguments);
 
+				var allFocused = i == null;
+
 				series.forEach((s, i2) => {
-					_setAlpha(i2, i == null || i2 == 0 || i2 == i ? 1 : focus.alpha);
+					var isFocused = allFocused || i2 == 0 || i2 == i;
+					s._focus = allFocused ? null : isFocused;
+					_setAlpha(i2, isFocused ? 1 : focus.alpha);
 				});
 
 				focusedSeries = i;

File diff suppressed because it is too large
+ 2 - 2
plugins/uplot/uPlot.iife.min.js