소스 검색

mocha TypeScript unittests are configured.

Ievgen Naida 5 년 전
부모
커밋
0d0037c9a5

+ 15 - 6
.babelrc

@@ -1,7 +1,16 @@
 {
 {
-  "presets": ["@babel/env", "@babel/typescript"],
-  "plugins": [
-    "@babel/proposal-class-properties",
-    "@babel/proposal-object-rest-spread"
-  ]
-}
+  "presets": [
+    [
+      "@babel/env",
+      {
+        "targets": {
+          "browsers": [">0.25%"]
+        },
+        "useBuiltIns": "entry",
+        "corejs": { "version": 3, "proposals": true }
+      }
+    ],
+    "@babel/typescript"
+  ],
+  "plugins": ["@babel/proposal-class-properties", "@babel/proposal-object-rest-spread"]
+}

+ 9 - 1
.eslintignore

@@ -1 +1,9 @@
-*.js
+lib/*.js
+tests/js/*.js
+tests/js/src
+tests/src
+./tests/js/*.js
+./tests/js/src
+./tests/src
+./tests/tests/
+tests/tests/

+ 3 - 1
.gitignore

@@ -1,2 +1,4 @@
 /node_modules/*
 /node_modules/*
-.bak
+.bak
+tests/js/src
+tests/src

+ 24 - 13
README.md

@@ -58,19 +58,6 @@ import {
 timeline.initialize({ id: 'timeline' });
 timeline.initialize({ id: 'timeline' });
 ```
 ```
 
 
-### Build 
-
-run once to install development references:
-```bash
-  npm install
-```
-
-to pack JavaScript as a bundle:
-
-```bash
-  npm run build
-```
-
 ### Draw the outline tree
 ### Draw the outline tree
 
 
 Scroll events can be synchronized with the outline at the left side of the control.
 Scroll events can be synchronized with the outline at the left side of the control.
@@ -110,6 +97,30 @@ Default options:
 
 
 Vanilla js implementation. 
 Vanilla js implementation. 
 
 
+## Development 
+### Build 
+
+run once to install development references:
+```bash
+  npm install
+```
+
+to pack JavaScript as a bundle:
+
+```bash
+  npm run build
+```
+
+### Build tests:
+
+To build TypeScript unittests command should be executed: 
+```bash
+  npm run build-tests
+```
+
+Tests execution can be started by opening tests/unittests.html. 
+External mocha libs are used so internet is required.
+
 ## License
 ## License
 
 
 MIT
 MIT

+ 105 - 81
lib/animation-timeline.js

@@ -743,7 +743,7 @@ var TimelineClickEvent = /*#__PURE__*/function () {
 
 
     timelineClickEvent_defineProperty(this, "args", void 0);
     timelineClickEvent_defineProperty(this, "args", void 0);
 
 
-    timelineClickEvent_defineProperty(this, "pos", new DOMPoint());
+    timelineClickEvent_defineProperty(this, "pos", void 0);
 
 
     timelineClickEvent_defineProperty(this, "val", void 0);
     timelineClickEvent_defineProperty(this, "val", void 0);
 
 
@@ -893,18 +893,19 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
    */
    */
 
 
   /**
   /**
-   * Initialize Timeline
+   * Create Timeline instance
    * @param options Timeline settings.
    * @param options Timeline settings.
    * @param model Timeline model.
    * @param model Timeline model.
    */
    */
-  function Timeline(options) {
+  function Timeline() {
     var _thisSuper, _thisSuper2, _thisSuper3, _this;
     var _thisSuper, _thisSuper2, _thisSuper3, _this;
 
 
+    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
     var model = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
     var model = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
 
 
     timeline_classCallCheck(this, Timeline);
     timeline_classCallCheck(this, Timeline);
 
 
-    _this = _super.call(this);
+    _this = _super.call(this); // Allow to create instance without an error to perform tests.
 
 
     timeline_defineProperty(timeline_assertThisInitialized(_this), "_container", null);
     timeline_defineProperty(timeline_assertThisInitialized(_this), "_container", null);
 
 
@@ -1164,7 +1165,7 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
         return;
         return;
       }
       }
 
 
-      var isTouch = args instanceof TouchEvent && args.changedTouches && args.changedTouches.length > 0;
+      var isTouch = args.changedTouches && args.changedTouches.length > 0;
       _this._currentPos = _this._trackMousePos(_this._canvas, args);
       _this._currentPos = _this._trackMousePos(_this._canvas, args);
 
 
       if (!_this._isPanStarted && _this._selectionRect && _this._clickTimeoutIsOver()) {
       if (!_this._isPanStarted && _this._selectionRect && _this._clickTimeoutIsOver()) {
@@ -1318,76 +1319,88 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
       _this._renderTimeline();
       _this._renderTimeline();
     });
     });
 
 
-    _this._model = model;
-
-    if (!options || !options.id) {
-      throw new Error("Element cannot be empty. Should be string or DOM element.");
+    if (options || model) {
+      _this.initialize(options, model);
     }
     }
 
 
-    var id = options.id;
-    _this._options = _this._mergeOptions(options);
-    _this._currentZoom = _this._options.zoom;
+    return _this;
+  }
+  /**
+   * Initialize Timeline
+   * @param options Timeline settings.
+   * @param model Timeline model.
+   */
 
 
-    if (id instanceof HTMLElement) {
-      _this._container = id;
-    } else {
-      _this._container = document.getElementById(id);
-    }
 
 
-    if (!_this._container) {
-      throw new Error("Element cannot be empty. Should be string or DOM element.");
-    }
+  timeline_createClass(Timeline, [{
+    key: "initialize",
+    value: function initialize(options, model) {
+      this._model = model;
 
 
-    _this._scrollContainer = document.createElement('div');
-    _this._scrollContent = document.createElement('div');
-    _this._canvas = document.createElement('canvas');
+      if (!options || !options.id) {
+        throw new Error("Element cannot be empty. Should be string or DOM element.");
+      }
 
 
-    if (!_this._canvas || !_this._canvas.getContext) {
-      console.log('Cannot initialize canvas context.');
-      return timeline_possibleConstructorReturn(_this, null);
-    }
+      var id = options.id;
+      this._options = this._mergeOptions(options);
+      this._currentZoom = this._options.zoom;
 
 
-    _this._container.style.position = 'relative'; // Generate size container:
+      if (id instanceof HTMLElement) {
+        this._container = id;
+      } else {
+        this._container = document.getElementById(id);
+      }
 
 
-    _this._canvas.style.cssText = 'image-rendering: -moz-crisp-edges;' + 'image-rendering: -webkit-crisp-edges;' + 'image-rendering: pixelated;' + 'image-rendering: crisp-edges;' + 'user-select: none;' + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' + '-o-user-select: none;' + 'user-select: none;' + 'touch-action: none;' + 'position: relative;' + '-webkit-user-drag: none;' + '-khtml-user-drag: none;' + '-moz-user-drag: none;' + '-o-user-drag: none;' + 'user-drag: none;' + 'padding: inherit';
+      if (!this._container) {
+        throw new Error("Element cannot be empty. Should be string or DOM element.");
+      }
 
 
-    _this._scrollContainer.classList.add(_this._options.scrollContainerClass);
+      this._scrollContainer = document.createElement('div');
+      this._scrollContent = document.createElement('div');
+      this._canvas = document.createElement('canvas');
 
 
-    _this._scrollContainer.style.cssText = 'overflow: scroll;' + 'position: absolute;' + 'width:  100%;' + 'height:  100%;';
-    _this._scrollContent.style.width = _this._scrollContent.style.height = '100%'; // add the text node to the created div
+      if (!this._canvas || !this._canvas.getContext) {
+        console.log('Cannot initialize canvas context.');
+        return null;
+      }
 
 
-    _this._scrollContainer.appendChild(_this._scrollContent);
+      this._container.style.position = 'relative'; // Generate size container:
 
 
-    _this._container.appendChild(_this._scrollContainer);
+      this._canvas.style.cssText = 'image-rendering: -moz-crisp-edges;' + 'image-rendering: -webkit-crisp-edges;' + 'image-rendering: pixelated;' + 'image-rendering: crisp-edges;' + 'user-select: none;' + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' + '-o-user-select: none;' + 'user-select: none;' + 'touch-action: none;' + 'position: relative;' + '-webkit-user-drag: none;' + '-khtml-user-drag: none;' + '-moz-user-drag: none;' + '-o-user-drag: none;' + 'user-drag: none;' + 'padding: inherit';
 
 
-    var scrollBarWidth = _this._scrollContainer.offsetWidth - _this._scrollContent.clientWidth; // Calculate current browser scroll bar size and add offset for the canvas
+      this._scrollContainer.classList.add(this._options.scrollContainerClass);
 
 
-    _this._canvas.style.width = _this._canvas.style.height = 'calc(100% -' + (scrollBarWidth || 17) + 'px)';
+      this._scrollContainer.style.cssText = 'overflow: scroll;' + 'position: absolute;' + 'width:  100%;' + 'height:  100%;';
+      this._scrollContent.style.width = this._scrollContent.style.height = '100%'; // add the text node to the created div
 
 
-    _this._container.appendChild(_this._canvas);
+      this._scrollContainer.appendChild(this._scrollContent);
 
 
-    if (_this._options.fillColor) {
-      _this._scrollContainer.style.background = _this._options.fillColor;
-    } // Normalize and validate span per seconds
+      this._container.appendChild(this._scrollContainer);
 
 
+      var scrollBarWidth = this._scrollContainer.offsetWidth - this._scrollContent.clientWidth; // Calculate current browser scroll bar size and add offset for the canvas
 
 
-    _this._options.snapsPerSeconds = Math.max(0, Math.min(60, _this._options.snapsPerSeconds || 0));
-    _this._ctx = _this._canvas.getContext('2d');
+      this._canvas.style.width = this._canvas.style.height = 'calc(100% -' + (scrollBarWidth || 17) + 'px)';
 
 
-    _this._subscribeOnEvents();
+      this._container.appendChild(this._canvas);
 
 
-    _this.rescale();
+      if (this._options.fillColor) {
+        this._scrollContainer.style.background = this._options.fillColor;
+      } // Normalize and validate span per seconds
 
 
-    _this.redraw();
 
 
-    return _this;
-  }
-  /**
-   * Subscribe current component on the related events.
-   */
+      this._options.snapsPerSeconds = Math.max(0, Math.min(60, this._options.snapsPerSeconds || 0));
+      this._ctx = this._canvas.getContext('2d');
 
 
+      this._subscribeOnEvents();
 
 
-  timeline_createClass(Timeline, [{
+      this.rescale();
+      this.redraw();
+    }
+    /**
+     * Subscribe current component on the related events.
+     */
+
+  }, {
     key: "_subscribeOnEvents",
     key: "_subscribeOnEvents",
     value: function _subscribeOnEvents() {
     value: function _subscribeOnEvents() {
       this._container.addEventListener('wheel', this._handleWheelEvent);
       this._container.addEventListener('wheel', this._handleWheelEvent);
@@ -1558,7 +1571,7 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
           selected.push(_this2._convertToElement(rowModel.row, keyframe));
           selected.push(_this2._convertToElement(rowModel.row, keyframe));
         }
         }
 
 
-        return false;
+        return;
       });
       });
 
 
       return selected;
       return selected;
@@ -1614,7 +1627,7 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
           }
           }
         }
         }
 
 
-        return false;
+        return;
       });
       });
 
 
       if (isChanged) {
       if (isChanged) {
@@ -1656,13 +1669,9 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
         var nextRow = true;
         var nextRow = true;
         row.keyframes.filter(function (p) {
         row.keyframes.filter(function (p) {
           return p && !p.hidden;
           return p && !p.hidden;
-        }).find(function (keyframe, keyframeIndex) {
+        }).forEach(function (keyframe, keyframeIndex) {
           if (callback && keyframe) {
           if (callback && keyframe) {
-            var isBreak = callback(keyframe, keyframeIndex, rowSize, index, nextRow);
-
-            if (isBreak) {
-              return true;
-            }
+            callback(keyframe, keyframeIndex, rowSize, index, nextRow);
           }
           }
 
 
           nextRow = false;
           nextRow = false;
@@ -2320,7 +2329,7 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
       } // get center of the lane:
       } // get center of the lane:
 
 
 
 
-      var y = rowSize.y + rowSize.height / 2 - this._scrollContainer.scrollTop; // TODO: keyframe size:
+      var y = rowSize.y + rowSize.height / 2; // TODO: keyframe size:
 
 
       var size = 1; //this._options.keyframeSizePx || keyframe.size;
       var size = 1; //this._options.keyframeSizePx || keyframe.size;
       //if (size == "auto") {
       //if (size == "auto") {
@@ -2450,7 +2459,7 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
           _this7._ctx.restore();
           _this7._ctx.restore();
         }
         }
 
 
-        return false;
+        return;
       });
       });
     }
     }
   }, {
   }, {
@@ -2598,9 +2607,13 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
       var model = this._calculateRowsBounds();
       var model = this._calculateRowsBounds();
 
 
       if (model && model.rows) {
       if (model && model.rows) {
-        return model.rows.find(function (rowData) {
-          return rowData.y >= posY && posY <= rowData.y + rowData.height;
-        });
+        for (var i = 0; i < model.rows.length; i++) {
+          var _row = model.rows[i];
+
+          if (_row && _row.y >= posY && posY <= _row.y + _row.height) {
+            return _row;
+          }
+        }
       }
       }
 
 
       return null;
       return null;
@@ -2727,7 +2740,8 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
       this._model = data;
       this._model = data;
       this.rescale();
       this.rescale();
       this.redraw();
       this.redraw();
-    }
+    } // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
   }, {
   }, {
     key: "_getMousePos",
     key: "_getMousePos",
     value: function _getMousePos(canvas, e) {
     value: function _getMousePos(canvas, e) {
@@ -2735,16 +2749,12 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
       var clientX = 0;
       var clientX = 0;
       var clientY = 0;
       var clientY = 0;
 
 
-      if (e instanceof TouchEvent) {
-        var wheelEvent = e;
-
-        if (wheelEvent.changedTouches && wheelEvent.changedTouches.length > 0) {
-          // TODO: implement better touch support
-          var touch = e.changedTouches[0];
-          clientX = touch.clientX;
-          clientY = touch.clientY;
-          radius = Math.max(radius, touch.radiusX, touch.radiusY);
-        }
+      if (e.changedTouches && e.changedTouches.length > 0) {
+        // TODO: implement better touch support
+        var touch = e.changedTouches[0];
+        clientX = touch.clientX;
+        clientY = touch.clientY;
+        radius = Math.max(radius, touch.radiusX, touch.radiusY);
       } else {
       } else {
         clientX = e.clientX;
         clientX = e.clientX;
         clientY = e.clientY;
         clientY = e.clientY;
@@ -2854,9 +2864,11 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
 
 
   }, {
   }, {
     key: "_findDraggable",
     key: "_findDraggable",
-    value: function _findDraggable(elements, val) {
+    value: function _findDraggable(elements) {
       var _this8 = this;
       var _this8 = this;
 
 
+      var val = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+
       // filter and sort: Timeline, individual keyframes, stripes (distance).
       // filter and sort: Timeline, individual keyframes, stripes (distance).
       var getPriority = function getPriority(type) {
       var getPriority = function getPriority(type) {
         if (type === TimelineElementType.Timeline) {
         if (type === TimelineElementType.Timeline) {
@@ -2872,13 +2884,21 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
 
 
       var filteredElements = elements.filter(function (element) {
       var filteredElements = elements.filter(function (element) {
         if (element.type === TimelineElementType.Keyframe) {
         if (element.type === TimelineElementType.Keyframe) {
-          var draggable = (_this8._options.keyframesDraggable === undefined ? true : !!_this8._options.keyframesDraggable) && (element.keyframe.draggable === undefined ? true : !!element.keyframe.draggable);
+          var draggable = true;
+
+          if (_this8._options) {
+            draggable = (_this8._options.keyframesDraggable === undefined ? true : !!_this8._options.keyframesDraggable) && (element.keyframe.draggable === undefined ? true : !!element.keyframe.draggable);
+          }
 
 
           if (!draggable) {
           if (!draggable) {
             return false;
             return false;
           }
           }
         } else if (element.type === TimelineElementType.Stripe) {
         } else if (element.type === TimelineElementType.Stripe) {
-          var _draggable = (_this8._options.stripesDraggable === undefined ? true : !!_this8._options.stripesDraggable) && (element.row.stripeDraggable === undefined ? true : !!element.row.stripeDraggable);
+          var _draggable = true;
+
+          if (_this8._options) {
+            _draggable = (_this8._options.stripesDraggable === undefined ? true : !!_this8._options.stripesDraggable) && (element.row.stripeDraggable === undefined ? true : !!element.row.stripeDraggable);
+          }
 
 
           if (!_draggable) {
           if (!_draggable) {
             return false;
             return false;
@@ -2894,6 +2914,10 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
         var prioB = getPriority(b.type);
         var prioB = getPriority(b.type);
 
 
         if (prioA == prioB) {
         if (prioA == prioB) {
+          if (val === null) {
+            return 0;
+          }
+
           return TimelineUtils.getDistance(a.val, val) > TimelineUtils.getDistance(b.val, val) ? 1 : 0;
           return TimelineUtils.getDistance(a.val, val) > TimelineUtils.getDistance(b.val, val) ? 1 : 0;
         }
         }
 
 
@@ -2941,12 +2965,12 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
             var rowOverlapped = TimelineUtils.isOverlap(pos.x, pos.y, rowModel);
             var rowOverlapped = TimelineUtils.isOverlap(pos.x, pos.y, rowModel);
 
 
             if (rowOverlapped) {
             if (rowOverlapped) {
-              var _row = {
+              var _row2 = {
                 val: _this9._mousePosToVal(pos.x, true),
                 val: _this9._mousePosToVal(pos.x, true),
                 type: TimelineElementType.Row,
                 type: TimelineElementType.Row,
                 row: rowModel.row
                 row: rowModel.row
               };
               };
-              toReturn.push(_row);
+              toReturn.push(_row2);
             }
             }
 
 
             var keyframesStripeOverlapped = TimelineUtils.isOverlap(pos.x, pos.y, rowModel.stripeRect);
             var keyframesStripeOverlapped = TimelineUtils.isOverlap(pos.x, pos.y, rowModel.stripeRect);
@@ -2981,7 +3005,7 @@ var timeline_Timeline = /*#__PURE__*/function (_TimelineEventsEmitte) {
             }
             }
           }
           }
 
 
-          return false;
+          return;
         }, true);
         }, true);
       }
       }
 
 

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
lib/animation-timeline.min.js


+ 7 - 1
package-lock.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "animation-timeline-js",
   "name": "animation-timeline-js",
-  "version": "1.2.4",
+  "version": "2.0.5",
   "lockfileVersion": 1,
   "lockfileVersion": 1,
   "requires": true,
   "requires": true,
   "dependencies": {
   "dependencies": {
@@ -1038,6 +1038,12 @@
       "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==",
       "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==",
       "dev": true
       "dev": true
     },
     },
+    "@types/mocha": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
+      "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==",
+      "dev": true
+    },
     "@typescript-eslint/eslint-plugin": {
     "@typescript-eslint/eslint-plugin": {
       "version": "2.31.0",
       "version": "2.31.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.31.0.tgz",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.31.0.tgz",

+ 5 - 3
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "animation-timeline-js",
   "name": "animation-timeline-js",
-  "version": "2.0.4",
+  "version": "2.0.5",
   "description": "animation timeline control based on the canvas.",
   "description": "animation timeline control based on the canvas.",
   "main": "lib/animation-timeline.min.js",
   "main": "lib/animation-timeline.min.js",
   "types": "src/index.ts",
   "types": "src/index.ts",
@@ -11,6 +11,7 @@
     "@babel/plugin-proposal-class-properties": "^7.8.3",
     "@babel/plugin-proposal-class-properties": "^7.8.3",
     "@babel/preset-env": "^7.8.3",
     "@babel/preset-env": "^7.8.3",
     "@babel/preset-typescript": "^7.8.3",
     "@babel/preset-typescript": "^7.8.3",
+    "@types/mocha": "^7.0.2",
     "@typescript-eslint/eslint-plugin": "^2.31.0",
     "@typescript-eslint/eslint-plugin": "^2.31.0",
     "@typescript-eslint/parser": "^2.31.0",
     "@typescript-eslint/parser": "^2.31.0",
     "babel-loader": "^8.1.0",
     "babel-loader": "^8.1.0",
@@ -25,9 +26,10 @@
     "webpack-cli": "^3.3.11"
     "webpack-cli": "^3.3.11"
   },
   },
   "scripts": {
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
+    "test": "echo \"Run tests/unittest.html explicitly to execute tests\" && exit 1",
     "build": "webpack",
     "build": "webpack",
-    "webpack": "webpack"
+    "webpack": "webpack",
+    "build-tests": "tsc -p tsconfig.tests.json"
   },
   },
   "repository": {
   "repository": {
     "type": "git",
     "type": "git",

+ 1 - 1
src/utils/rowsCalculationsResults.ts

@@ -1,4 +1,4 @@
-import { TimelineRow } from '..';
+import { TimelineRow } from '../timelineRow';
 
 
 export interface RowsCalculationsResults {
 export interface RowsCalculationsResults {
   /**
   /**

+ 1 - 1
src/utils/timelineDraggableData.ts

@@ -1,5 +1,5 @@
 import { TimelineClickableElement } from './timelineClickableElement';
 import { TimelineClickableElement } from './timelineClickableElement';
-import { TimelineElementType } from '..';
+import { TimelineElementType } from '../enums/timelineElementType';
 
 
 export interface TimelineDraggableData {
 export interface TimelineDraggableData {
   changed: boolean;
   changed: boolean;

+ 27 - 0
tests/tests/timelineTests.js

@@ -0,0 +1,27 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var animation_timeline_js_1 = require("../lib/animation-timeline.js");
+describe('Timeline ', function () {
+    it('closest keyframe should be returned', function () {
+        var timeline = new animation_timeline_js_1.Timeline();
+        var elements = [
+            {
+                type: animation_timeline_js_1.TimelineElementType.Keyframe,
+                val: 0,
+            },
+            {
+                type: animation_timeline_js_1.TimelineElementType.Keyframe,
+                val: 4,
+            },
+            {
+                type: animation_timeline_js_1.TimelineElementType.Keyframe,
+                val: 9,
+            },
+        ];
+        var element = timeline._findDraggable(elements, 5);
+        if (element.val !== elements[2].val) {
+            throw new Error('Wrong keyframe selected');
+        }
+    });
+});
+//# sourceMappingURL=timelineTests.js.map

+ 1 - 0
tests/tests/timelineTests.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"timelineTests.js","sourceRoot":"","sources":["../timelineTests.ts"],"names":[],"mappings":";;AAAA,sEAAuG;AAEvG,QAAQ,CAAC,WAAW,EAAE;IACpB,EAAE,CAAC,qCAAqC,EAAE;QACxC,IAAM,QAAQ,GAAG,IAAI,gCAAQ,EAAE,CAAC;QAChC,IAAM,QAAQ,GAAG;YACf;gBACE,IAAI,EAAE,2CAAmB,CAAC,QAAQ;gBAClC,GAAG,EAAE,CAAC;aACqB;YAC7B;gBACE,IAAI,EAAE,2CAAmB,CAAC,QAAQ;gBAClC,GAAG,EAAE,CAAC;aACqB;YAC7B;gBACE,IAAI,EAAE,2CAAmB,CAAC,QAAQ;gBAClC,GAAG,EAAE,CAAC;aACqB;SAC9B,CAAC;QACF,IAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACrD,IAAI,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

+ 27 - 0
tests/timelineTests.js

@@ -0,0 +1,27 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var animation_timeline_js_1 = require("../lib/animation-timeline.js");
+describe('Timeline ', function () {
+    it('closest keyframe should be returned', function () {
+        var timeline = new animation_timeline_js_1.Timeline();
+        var elements = [
+            {
+                type: animation_timeline_js_1.TimelineElementType.Keyframe,
+                val: 0,
+            },
+            {
+                type: animation_timeline_js_1.TimelineElementType.Keyframe,
+                val: 4,
+            },
+            {
+                type: animation_timeline_js_1.TimelineElementType.Keyframe,
+                val: 9,
+            },
+        ];
+        var element = timeline._findDraggable(elements, 5);
+        if (element.val !== elements[2].val) {
+            throw new Error('Wrong keyframe selected');
+        }
+    });
+});
+//# sourceMappingURL=timelineTests.js.map

+ 1 - 0
tests/timelineTests.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"timelineTests.js","sourceRoot":"","sources":["timelineTests.ts"],"names":[],"mappings":";;AAAA,sEAAuG;AAEvG,QAAQ,CAAC,WAAW,EAAE;IACpB,EAAE,CAAC,qCAAqC,EAAE;QACxC,IAAM,QAAQ,GAAG,IAAI,gCAAQ,EAAE,CAAC;QAChC,IAAM,QAAQ,GAAG;YACf;gBACE,IAAI,EAAE,2CAAmB,CAAC,QAAQ;gBAClC,GAAG,EAAE,CAAC;aACqB;YAC7B;gBACE,IAAI,EAAE,2CAAmB,CAAC,QAAQ;gBAClC,GAAG,EAAE,CAAC;aACqB;YAC7B;gBACE,IAAI,EAAE,2CAAmB,CAAC,QAAQ;gBAClC,GAAG,EAAE,CAAC;aACqB;SAC9B,CAAC;QACF,IAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACrD,IAAI,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC5C;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

+ 25 - 0
tests/timelineTests.ts

@@ -0,0 +1,25 @@
+import { Timeline, TimelineElementType, TimelineClickableElement } from '../lib/animation-timeline.js';
+
+describe('Timeline ', function () {
+  it('closest keyframe should be returned', function () {
+    const timeline = new Timeline();
+    const elements = [
+      {
+        type: TimelineElementType.Keyframe,
+        val: 0,
+      } as TimelineClickableElement,
+      {
+        type: TimelineElementType.Keyframe,
+        val: 4,
+      } as TimelineClickableElement,
+      {
+        type: TimelineElementType.Keyframe,
+        val: 9,
+      } as TimelineClickableElement,
+    ];
+    const element = timeline._findDraggable(elements, 5);
+    if (element.val !== elements[2].val) {
+      throw new Error('Wrong keyframe selected');
+    }
+  });
+});

+ 31 - 0
tests/unittests.html

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8" />
+    <title>Mocha Tests</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <link rel="stylesheet" href="https://unpkg.com/mocha/mocha.css" />
+</head>
+
+<body>
+    <div id="mocha"></div>
+
+    <script src="https://unpkg.com/chai/chai.js"></script>
+    <script src="https://unpkg.com/mocha/mocha.js"></script>
+    <script src="../lib/animation-timeline.js"></script>
+    <script>var exports = {}; var require = function () {
+            return timelineModule;
+        };
+    </script>
+    <script class="mocha-init">
+        mocha.setup('bdd');
+        mocha.checkLeaks();
+    </script>
+    <script src="./tests/timelineTests.js"></script>
+    <script class="mocha-exec">
+        mocha.run();
+    </script>
+</body>
+
+</html>

+ 1 - 1
tsconfig.json

@@ -10,5 +10,5 @@
     "strict": false,
     "strict": false,
     "declaration": true
     "declaration": true
   },
   },
-  "exclude": ["node_modules", "dist"]
+  "exclude": ["node_modules", "lib", "dist", "tests", "*.json"]
 }
 }

+ 16 - 0
tsconfig.tests.json

@@ -0,0 +1,16 @@
+{
+  "compilerOptions": {
+    "module": "CommonJS",
+    "outDir": "./tests",
+    "lib": ["es2015", "dom"],
+    "target": "es5",
+    "allowJs": false,
+    "sourceMap": true,
+    "strict": false,
+    "declaration": false
+  },
+  "include": [
+    "./tests/*"
+],
+  "exclude": ["node_modules", "lib", "tests/js", "src", "src/*", "dist", "*.json", "*.js"]
+}

+ 5 - 3
webpack.config.js

@@ -1,10 +1,12 @@
 /* eslint-disable @typescript-eslint/no-var-requires */
 /* eslint-disable @typescript-eslint/no-var-requires */
 const path = require('path');
 const path = require('path');
-let UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
+const UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
 
 
 //  devtool: 'inline-source-map',
 //  devtool: 'inline-source-map',
 module.exports = {
 module.exports = {
-  entry: './src/index.ts',
+  entry: {
+    'animation-timeline': './lib/animation-timeline.ts',
+  },
   module: {
   module: {
     rules: [
     rules: [
       {
       {
@@ -18,7 +20,7 @@ module.exports = {
     extensions: ['.tsx', '.ts'],
     extensions: ['.tsx', '.ts'],
   },
   },
   output: {
   output: {
-    filename: 'animation-timeline.min.js',
+    filename: '[name].min.js',
     libraryTarget: 'umd',
     libraryTarget: 'umd',
     library: 'timelineModule',
     library: 'timelineModule',
     // eslint-disable-next-line no-undef
     // eslint-disable-next-line no-undef

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.