import { classMixin, mergeData } from "../core/Util" import Events from "../core/Events" import { DOMMixins } from "../dom/DOMMixins" import { I18NMixins } from "../language/I18NMixins" import { easeInSpline } from "../animation/Ease"; import * as DOM from "../dom/DOM" function isInHorizontalViewport(element) { const rect = element.getBoundingClientRect(); return ( rect.left >= 0 && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } export class TimeAxis { constructor(elem, options, language) { if (language) { this.setLanguage(language) } // DOM Elements this._el = { container: {}, content_container: {}, major: {}, minor: {}, }; // Components this._text = {}; // State this._state = { loaded: false }; // Data this.data = {}; // Options this.options = { duration: 1000, ease: easeInSpline, width: 600, height: 600 }; // Actively Displaying this.active = false; // Animation Object this.animator = {}; // Axis Helper this.axis_helper = {}; // Minor tick dom element array this.minor_ticks = []; // Minor tick dom element array this.major_ticks = []; // Main element if (typeof elem === 'object') { this._el.container = elem; } else { this._el.container = DOM.get(elem); } // Merge Data and Options mergeData(this.options, options); this._initLayout(); this._initEvents(); } /* Adding, Hiding, Showing etc ================================================== */ show() { } hide() { } addTo(container) { container.appendChild(this._el.container); } removeFrom(container) { container.removeChild(this._el.container); } updateDisplay(w, h) { this._updateDisplay(w, h); } getLeft() { return this._el.container.style.left.slice(0, -2); } drawTicks(timescale, optimal_tick_width) { var ticks = timescale.getTicks(); // FADE OUT this._el.major.className = "tl-timeaxis-major"; this._el.minor.className = "tl-timeaxis-minor"; this._el.major.style.opacity = 0; this._el.minor.style.opacity = 0; // CREATE MAJOR TICKS this.major_ticks = this._createTickElements( ticks['major'].ticks, this._el.major, timescale.getAxisTickDateFormat(ticks['major'].name) ); // CREATE MINOR TICKS this.minor_ticks = this._createTickElements( ticks['minor'].ticks, this._el.minor, timescale.getAxisTickDateFormat(ticks['minor'].name), ticks['major'].ticks ); this.positionTicks(timescale, optimal_tick_width, true); // FADE IN this._el.major.className = "tl-timeaxis-major tl-animate-opacity tl-timeaxis-animate-opacity"; this._el.minor.className = "tl-timeaxis-minor tl-animate-opacity tl-timeaxis-animate-opacity"; this._el.major.style.opacity = 1; this._el.minor.style.opacity = 1; } _createTickElements(ts_ticks, tick_element, dateformat, ticks_to_skip) { tick_element.innerHTML = ""; var skip_times = {}; var yearZero = new Date(-1, 13, -30); skip_times[yearZero.getTime()] = true; if (ticks_to_skip) { for (var i = 0; i < ticks_to_skip.length; i++) { skip_times[ticks_to_skip[i].getTime()] = true; } } var tick_elements = [] for (var i = 0; i < ts_ticks.length; i++) { var ts_tick = ts_ticks[i]; if (!(ts_tick.getTime() in skip_times)) { var tick = DOM.create("div", "tl-timeaxis-tick", tick_element), tick_text = DOM.create("span", "tl-timeaxis-tick-text tl-animate-opacity", tick); let tick_display_date = ts_tick.getDisplayDate(this.getLanguage(), dateformat) tick_text.innerHTML = tick_display_date; tick_elements.push({ tick: tick, tick_text: tick_text, display_date: tick_display_date, date: ts_tick }); } } return tick_elements; } positionTicks(timescale, optimal_tick_width, no_animate) { // Handle Animation if (no_animate) { this._el.major.className = "tl-timeaxis-major"; this._el.minor.className = "tl-timeaxis-minor"; } else { this._el.major.className = "tl-timeaxis-major tl-timeaxis-animate"; this._el.minor.className = "tl-timeaxis-minor tl-timeaxis-animate"; } this._positionTickArray(this.major_ticks, timescale, optimal_tick_width); this._positionTickArray(this.minor_ticks, timescale, optimal_tick_width); } _positionTickArray(tick_array, timescale, optimal_tick_width) { // Poition Ticks & Handle density of ticks if (tick_array[1] && tick_array[0]) { var distance = (timescale.getPosition(tick_array[1].date.getMillisecond()) - timescale.getPosition(tick_array[0].date.getMillisecond())), fraction_of_array = 1; if (distance < optimal_tick_width) { fraction_of_array = Math.round(optimal_tick_width / timescale.getPixelsPerTick()); } var show = 1; for (var i = 0; i < tick_array.length; i++) { var tick = tick_array[i]; // Poition Ticks tick.tick.style.left = timescale.getPosition(tick.date.getMillisecond()) + "px"; tick.tick_text.innerHTML = tick.display_date; // Handle density of ticks if (fraction_of_array > 1) { if (show >= fraction_of_array) { show = 1; tick.tick_text.style.opacity = 1; tick.tick.className = "tl-timeaxis-tick"; } else { show++; tick.tick_text.style.opacity = 0; tick.tick.className = "tl-timeaxis-tick tl-timeaxis-tick-hidden"; } } else { tick.tick_text.style.opacity = 1; tick.tick.className = "tl-timeaxis-tick"; } } } } getVisibleTicks() { return { major: this._getVisibleTickArray(this.major_ticks), minor: this._getVisibleTickArray(this.minor_ticks) } } _getVisibleTickArray(tick_array) { return tick_array.filter(({ tick }) => isInHorizontalViewport(tick)) } /* Events ================================================== */ /* Private Methods ================================================== */ _initLayout() { this._el.content_container = DOM.create("div", "tl-timeaxis-content-container", this._el.container); this._el.major = DOM.create("div", "tl-timeaxis-major", this._el.content_container); this._el.minor = DOM.create("div", "tl-timeaxis-minor", this._el.content_container); // Fire event that the slide is loaded this.onLoaded(); } _initEvents() { } // Update Display _updateDisplay(width, height, layout) { if (width) { this.options.width = width; } if (height) { this.options.height = height; } } } classMixin(TimeAxis, Events, DOMMixins, I18NMixins)