minsky-kit
Version:
Kit of components for MINSKY web agency
274 lines (223 loc) • 7.16 kB
JavaScript
// imports
import Component from 'minsky-kit/js/components/Component';
import Ticker from 'minsky-kit/js/managers/Ticker';
import MarqueeItem from './MarqueeItem';
// class definition
export default class Marquee extends Component {
// constructor
constructor (args, objectName = 'Marquee') {
args.debug = args.debug || false;
// call super constructor
super(args, objectName);
this._useParent = args.useParent || false;
this._speed = args.speed || 1.25;
this._timing = args.timing || 1000 / 60;
this._drawTiming = args.drawTiming || 1000 / 30;
this._autoStart = (typeof args.autoStart === 'boolean') ? args.autoStart : true;
this._running = true;
this._paused = false;
this._currentPageWidth = window.innerWidth;
this._pauseOnHover = null;
this._items = [];
// prepare
if (!this._useParent) {
this.prepareNormal();
}
else {
this.prepareUsingParent();
}
// generate items
this.generateItems();
// launch ticker
this._ticker = new Ticker({
timeout: 1000 / 60,
isInterval: true,
});
this._drawTicker = new Ticker({
timeout: this._drawTiming,
isInterval: true,
});
this._ticker.on('interval', this.blm.add('onTick', onTick));
this._drawTicker.on('interval', this.blm.add('onDrawTick', onDrawTick));
// add resize listener
window.addEventListener(
'resize',
this.blm.add('marquee.onWindowResize', onWindowResize),
);
window.addEventListener(
'scroll',
this.blm.add('marquee.onWindowScroll', onWindowScroll),
);
// show marquee when ready
this.$el.setAttribute('style', 'opacity: 1;');
// autostart
if (this._autoStart) this.start();
// hover listener
this.pauseOnHover = args.pauseOnHover;
}
tick (factor = 1, force = false) {
if (this._running) {
if (this._resized) {
this._resized = false;
this.regenerate();
}
if (!this._paused || force) {
for (let i = 0; i < this._items.length; i++) {
this._items[i].tick(factor);
}
this.dispatch('tick');
}
}
}
draw () {
this._items.forEach((item) => item.draw());
}
start () {
this.running = true;
}
stop () {
this.running = false;
}
generateItems () {
let contentWidth = 0;
// get width of content by adding it to the page first
this.$el.appendChild(this._$content);
contentWidth = this._$content.offsetWidth || 1;
this._$content.parentNode.removeChild(this._$content);
if (contentWidth > 0) {
// calculated nr of items neded for screen width
const nrItems = Math.ceil(this.$el.clientWidth / contentWidth) + 1;
// generate
this._items.length = 0;
for (let i = 0; i < nrItems; i++) {
this._items.push(new MarqueeItem({
$el: this._$content.cloneNode(true),
parent: this,
width: contentWidth,
speed: this._speed,
offset: this.offset,
}));
}
}
else {
this.log('warn', 'Marquee Item width was 0, generation ignored as number of items would be infinite.');
}
}
prepareNormal () {
// create content base (will be used to clone)
this._$content = document.createElement('span');
this._$content.classList.add('marquee-item');
this._$content.innerHTML = this.$el.innerHTML;
// clear el
this.$el.innerHTML = '';
}
prepareUsingParent () {
// move el to content and set el as parent
this._$content = this.$el;
this.$el = this.$el.parentNode;
// clear el
this.$el.innerHTML = '';
}
regenerate () {
this.destroy(true);
this.generateItems();
}
update () {
}
// destroy
destroy (itemsOnly) {
for (let i = 0; i < this._items.length; i++) {
this._items[i].destroy();
}
if (!itemsOnly) {
// continue destroying
window.removeEventListener('resize', this.blm.remove('marquee.onWindowResize', this.onWindowResize));
window.removeEventListener('scroll', this.blm.remove('marquee.onWindowScroll', this.onWindowScroll));
this._ticker.destroy();
}
}
refresh () {
this._resize = true;
}
// getters & setters
get running () { return this._ticker.running; }
set running (value) {
if (this.running !== value) {
if (value) {
this._ticker.start(true);
this._drawTicker.start(true);
}
else {
this._ticker.stop(true);
this._drawTicker.stop(true);
}
}
}
get pauseOnHover () { return this._pauseOnHover; }
set pauseOnHover (value) {
if (value !== this.pauseOnHover) {
if (value) {
this.$el.addEventListener('mouseenter', this.blm.addOnce('onMouseEnter', onMouseEnter));
this.$el.addEventListener('mouseleave', this.blm.addOnce('onMouseLeave', onMouseLeave));
}
else {
this._paused = false;
this.$el.removeEventListener('mouseenter', this.blm.remove('onMouseEnter', onMouseEnter));
this.$el.removeEventListener('mouseleave', this.blm.remove('onMouseLeave', onMouseLeave));
}
this._pauseOnHover = value;
}
}
get paused () { return this._paused; }
set paused (value) {
if (this.paused !== value) {
if (value) {
if (this.running) {
this._ticker.stop();
}
}
else {
if (!this.running) {
this._ticker.start(true);
}
}
this._paused = value;
}
}
get items () {
return this._items;
}
get speed () {
return this._speed;
}
set speed (value) {
if (this.speed !== value) {
this._speed = value;
}
}
}
function onTick () {
this.tick(1);
}
function onDrawTick () {
this.draw();
}
function onWindowResize () {
if (this._currentPageWidth !== window.innerWidth) {
this._resized = true;
this._currentPageWidth = window.innerWidth;
}
}
function onWindowScroll () {
if (!this._running) this.tick(1);
}
function onMouseEnter () {
if (this._running && !this._paused) {
this._paused = true;
}
}
function onMouseLeave () {
if (this._running && this._paused) {
this._paused = false;
}
}