vanilla-marquee
Advanced tools
Comparing version 1.0.4 to 1.1.0
@@ -33,2 +33,6 @@ declare module "vanilla-marquee" { | ||
/** | ||
* - Recalculate the marquee position on resize (breaks compatibility with jquery.marquee) | ||
*/ | ||
recalcResize?: boolean | undefined; | ||
/** | ||
* - Speed will override duration. Speed allows you to set a relatively constant marquee speed regardless of the width of the containing element. Speed is measured in pixels/second | ||
@@ -54,13 +58,10 @@ */ | ||
constructor(el: Element, opts: defaultOptions); | ||
el: Element; | ||
_loopCount: number; | ||
_marqWrap: any; | ||
_contHeight: number | undefined; | ||
_elHeight: any; | ||
_completeDuration: number | undefined; | ||
_contWidth: number | undefined; | ||
_elWidth: number | undefined; | ||
_marqWrap: Element; | ||
_vertical: boolean; | ||
_duration: number | undefined; | ||
_opts: defaultOptions; | ||
_animName: string; | ||
_animStr: string; | ||
el: Element; | ||
/** | ||
@@ -70,2 +71,3 @@ * Method for animation end event | ||
_animEnd: () => void; | ||
_instance: number; | ||
/** | ||
@@ -90,2 +92,3 @@ * Build the css string for the animation | ||
private _animate; | ||
_status: string | undefined; | ||
/** | ||
@@ -110,6 +113,22 @@ * Event fired on Animation iteration | ||
/** | ||
* Calculates the speed and the dimension of the marquee | ||
* | ||
* @private | ||
*/ | ||
private _calcSizes; | ||
_contHeight: number | undefined; | ||
_elHeight: number | undefined; | ||
_completeDuration: number | undefined; | ||
_contWidth: number | undefined; | ||
_elWidth: number | undefined; | ||
/** | ||
* Recalculates the dimensions and positon of the marquee on page resize | ||
* | ||
* @private | ||
*/ | ||
private _recalcResize; | ||
/** | ||
* Pause the animation | ||
*/ | ||
pause(): void; | ||
_status: string | undefined; | ||
/** | ||
@@ -116,0 +135,0 @@ * Resume the animation |
@@ -0,7 +1,41 @@ | ||
/** | ||
* Shorthand for `document.getElementById` | ||
* | ||
* @param {String} id - The selector's id | ||
* | ||
* @returns {Element|null} - The selected element | ||
*/ | ||
/** | ||
* Shorthand for `document.getElementsByClassName` | ||
* | ||
* @param {String} selClass - The selector's class | ||
* @param {Element} [parent=document] - Parent element | ||
* | ||
* @returns {HTMLCollection} - The selected elements | ||
*/ | ||
function byClass(selClass, parent = document) { | ||
return parent.getElementsByClassName(selClass); | ||
} | ||
/** | ||
* Shorthand for `document.querySelector` | ||
* | ||
* @param {String} selector - Selector | ||
* @param {Element} [parent=document] - Parent element | ||
* | ||
* @returns {Element|null} - The selected element | ||
*/ | ||
function query(selector, parent = document) { | ||
return parent.querySelector(selector); | ||
} | ||
/** | ||
* Shorthand per `document.querySelectorAll` | ||
* | ||
* @param {String} selector - Selector | ||
* @param {Element} [parent=document] - Parent element | ||
* | ||
* @returns {NodeList} - The selected element | ||
*/ | ||
function queryAll(selector, parent = document) { | ||
@@ -11,2 +45,10 @@ return parent.querySelectorAll(selector); | ||
/** | ||
* Foreach polyfill for NodeList and HTMLCollection | ||
* https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/ | ||
* | ||
* @param {Array|NodeList|HTMLCollection} els - A list of elements | ||
* @param {foreachCB} fn - Callback containing ( value, index ) as arguments | ||
* @param {Scope} [scope] - Scope | ||
*/ | ||
function forEachHTML(els, fn, scope) { | ||
@@ -16,2 +58,9 @@ for (let i = 0, numEls = els.length; i < numEls; i++) fn.call(scope, els[i], i); | ||
/** | ||
* Shorthand for `element.classList.add`, works with multiple nodes | ||
* | ||
* @param {Element|HTMLCollection|NodeList} el - A list of elements | ||
* @param {...String} classes - Classes to add | ||
*/ | ||
function addClass(el, ...classes) { | ||
@@ -23,2 +72,8 @@ if (el.length === undefined) addClassEl(el, ...classes);else { | ||
} | ||
/** | ||
* Adds classes to a single element | ||
* | ||
* @param {Element} elem - An HTML element | ||
* @param {...String} remClass - Classes to add | ||
*/ | ||
@@ -32,5 +87,22 @@ function addClassEl(elem, ...remClass) { | ||
/** | ||
* Shorthand for `element.addEventListener` | ||
* | ||
* @param {Element|HTMLCollection|NodeList} el - A list of elements | ||
* @param {String} ev - Event's name | ||
* @param {Function} fn - Event's function | ||
* @param {Object} [opts] - Optional event options | ||
*/ | ||
function addEvent(el, ev, fn, opts) { | ||
el.addEventListener(ev, fn, opts); | ||
} | ||
/** | ||
* Shorthand for `element.removeEventListener` | ||
* | ||
* @param {Element|HTMLCollection|NodeList} el - A list of elements | ||
* @param {String} ev - Event's name | ||
* @param {Function} fn - Event's function | ||
* @param {Object} [opts] - Optional event options | ||
*/ | ||
function removeEvent(el, ev, fn, opts) { | ||
@@ -40,8 +112,31 @@ el.removeEventListener(ev, fn, opts); | ||
/** | ||
* Shorthand for `element.getAttribute` | ||
* | ||
* @param {Element} el - An HTML element | ||
* @param {String} attr - The attribute to retrieve | ||
* | ||
* @returns {String} - The attribute's value | ||
*/ | ||
function getAttr(el, attr) { | ||
return el.getAttribute(attr); | ||
} | ||
/** | ||
* Shorthand for `element.setAttribute` | ||
* | ||
* @param {Element} el - An HTML element | ||
* @param {String} attr - The attribute to retrieve | ||
* @param {String} val - The value to set to the attribute | ||
*/ | ||
function setAttr(el, attr, val) { | ||
el.setAttribute(attr, val); | ||
} | ||
/** | ||
* Shorthand for `element.removeAttribute` | ||
* | ||
* @param {Element} el - An HTML element | ||
* @param {String} attr - The attribute to remove | ||
*/ | ||
function remAttr(el, attr) { | ||
@@ -60,2 +155,3 @@ el.removeAttribute(attr); | ||
* @property {Boolean} [pauseOnHover=false] - Pause the marquee on hover | ||
* @property {Boolean} [recalcResize=false] - Recalculate the marquee position on resize (breaks compatibility with jquery.marquee) | ||
* @property {Number} [speed=0] - Speed will override duration. Speed allows you to set a relatively constant marquee speed regardless of the width of the containing element. Speed is measured in pixels/second | ||
@@ -72,2 +168,3 @@ * @property {Boolean} [startVisible=false] - The marquee will be visible from the start if set to `true` | ||
pauseOnHover: false, | ||
recalcResize: false, | ||
speed: 0, | ||
@@ -77,2 +174,4 @@ startVisible: false, | ||
let instances = 0; | ||
/** | ||
@@ -106,2 +205,3 @@ * Vanilla js marquee based on jQuery.marquee | ||
this.el = el; | ||
this._loopCount = 3; | ||
@@ -154,71 +254,9 @@ | ||
this._marqWrap = marqWrap; | ||
this._vertical = vertical; | ||
this._duration = opts.duration; | ||
this._opts = opts; | ||
// If direction is up or down, get the height of main element | ||
if ( vertical ) { | ||
this._calcSizes(); | ||
const contHeight = el.clientHeight; | ||
this._contHeight = contHeight; | ||
remAttr( marqWrap, 'style' ); | ||
el.style.clientHeight = `${contHeight}px`; | ||
const marqs = byClass( 'js-marquee', el ), | ||
marqNums = marqs.length - 1; | ||
// Change the CSS for js-marquee element | ||
forEachHTML( marqs, ( currEl, ind ) => { | ||
currEl.style.float = 'none'; | ||
currEl.style.marginRight = '0px'; | ||
// Remove bottom margin from 2nd element if duplicated | ||
if ( opts.duplicated && ind === marqNums ) | ||
currEl.style.marginBottom = '0px'; | ||
else | ||
currEl.style.marginBottom = `${opts.gap}px`; | ||
}); | ||
const elHeight = parseInt( marqs[0].clientHeight + opts.gap ); | ||
this._elHeight = el_elHeight; | ||
// adjust the animation duration according to the text length | ||
if ( opts.startVisible && !opts.duplicated ) { | ||
// Compute the complete animation duration and save it for later reference | ||
// formula is to: (Height of the text node + height of the main container / Height of the main container) * duration; | ||
this._completeDuration = ( elHeight + contHeight) / parseInt( contHeight ) * opts.duration; | ||
opts.duration = elHeight / parseInt( contHeight ) * opts.duration; | ||
} else // formula is to: (Height of the text node + height of the main container / Height of the main container) * duration; | ||
opts.duration = elHeight / parseInt( contHeight ) / parseInt( contHeight ) * opts.duration; | ||
} else { | ||
// Save the width of the each element so we can use it in animation | ||
const elWidth = parseInt( byClass( 'js-marquee', el )[0].clientWidth + opts.gap ), | ||
contWidth = el.clientWidth; | ||
this._contWidth = contWidth; | ||
this._elWidth = elWidth; | ||
// adjust the animation duration according to the text length | ||
if ( opts.startVisible && !opts.duplicated ) { | ||
// Compute the complete animation duration and save it for later reference | ||
// formula is to: (Width of the text node + width of the main container / Width of the main container) * duration; | ||
this._completeDuration = ( elWidth + contWidth) / parseInt( contWidth ) * opts.duration; | ||
// (Width of the text node / width of the main container) * duration | ||
opts.duration = elWidth / parseInt( contWidth ) * opts.duration; | ||
} else // formula is to: (Width of the text node + width of the main container / Width of the main container) * duration; | ||
opts.duration = ( elWidth + parseInt( contWidth ) ) / parseInt( contWidth ) * opts.duration; | ||
} | ||
// if duplicated then reduce the duration | ||
if ( opts.duplicated ) | ||
opts.duration = opts.duration / 2; | ||
this._opts = opts; | ||
const animationName = 'marqueeAnimation-' + Math.floor( Math.random() * 10000000 ), | ||
const animationName = `marqueeAnimation-${Math.floor( Math.random() * 10000000 )}`, | ||
animStr = this._animationStr( | ||
@@ -228,3 +266,3 @@ animationName, | ||
opts.delayBeforeStart / 1000, | ||
'infinite' | ||
'infinite', | ||
); | ||
@@ -243,10 +281,10 @@ | ||
else | ||
this._marqWrap.style.transform = `translateY(${opts.direction === 'up' ? this._contHeight : ( -1 * ( ( this._elHeight * 2 ) - opts.gap ) ) }px)`; | ||
this._marqWrap.style.transform = `translateY(${opts.direction === 'up' ? this._contHeight : ( -1 * ( ( this._elHeight * 2 ) - opts.gap ) )}px)`; | ||
} else { | ||
if ( opts.startVisible ) | ||
if ( opts.startVisible ) // eslint-disable-line no-lonely-if | ||
this._marqWrap.style.transform = 'translateX(0px)'; | ||
else | ||
this._marqWrap.style.transform = `translateX(${opts.direction === 'left' ? this._contWidth : ( -1 * ( ( this._elWidth * 2 ) - opts.gap ) ) }px)`; | ||
this._marqWrap.style.transform = `translateX(${opts.direction === 'left' ? this._contWidth : ( -1 * ( ( this._elWidth * 2 ) - opts.gap ) )}px)`; | ||
@@ -265,10 +303,10 @@ } | ||
} else { | ||
if ( vertical ) | ||
if ( vertical ) // eslint-disable-line no-lonely-if | ||
this._repositionVert(); | ||
else | ||
this._repositionHor(); | ||
} | ||
this.el = el; | ||
addEvent( this.el, 'pause', this.pause.bind( this ) ); | ||
@@ -292,4 +330,10 @@ addEvent( this.el, 'resume', this.resume.bind( this ) ); | ||
this._instance = instances; | ||
instances++; | ||
this._animate( vertical ); | ||
if ( opts.recalcResize ) | ||
addEvent( window, 'resize', this._recalcResize.bind( this ) ); | ||
} | ||
@@ -337,3 +381,3 @@ | ||
duration / 1000, | ||
opts.delayBeforeStart / 1000 | ||
opts.delayBeforeStart / 1000, | ||
); | ||
@@ -348,3 +392,3 @@ | ||
0, | ||
'infinite' | ||
'infinite', | ||
); | ||
@@ -366,3 +410,3 @@ } | ||
animationCss = `translateY(${( opts.direction === 'up' ) ? -1 * this._elHeight : 0 }px)`; | ||
animationCss = `translateY(${( opts.direction === 'up' ) ? -1 * this._elHeight : 0}px)`; | ||
@@ -375,8 +419,8 @@ } else if ( opts.startVisible ) { | ||
// Adjust the css3 animation as well | ||
this._animStr = _animationStr( | ||
this._animStr = this._animationStr( | ||
this._animName, | ||
opts.duration / 1000, | ||
opts.delayBeforeStart / 1000 | ||
opts.delayBeforeStart / 1000, | ||
); | ||
animationCss = `translateY(${( opts.direction === 'up' ) ? -1 * this._elHeight : this._contHeight }px)`; | ||
animationCss = `translateY(${( opts.direction === 'up' ) ? -1 * this._elHeight : this._contHeight}px)`; | ||
@@ -388,7 +432,7 @@ this._loopCount++; | ||
this._animName = `${this._animName}0`; | ||
this._animStr = _animationStr( | ||
this._animStr = this._animationStr( | ||
this._animName, | ||
this._completeDuration / 1000, | ||
0, | ||
'infinite' | ||
'infinite', | ||
); | ||
@@ -406,4 +450,5 @@ this._repositionVert(); | ||
} else { | ||
if ( opts.duplicated ) { | ||
if ( opts.duplicated ) { // eslint-disable-line no-lonely-if | ||
// Adjust the starting point of animation only when first loops finishes | ||
@@ -413,3 +458,3 @@ if ( this._loopCount > 2 ) | ||
animationCss = `translateX(${( opts.direction === 'left' ) ? -1 * this._elWidth : 0 }px)`; | ||
animationCss = `translateX(${( opts.direction === 'left' ) ? -1 * this._elWidth : 0}px)`; | ||
@@ -422,8 +467,8 @@ } else if ( opts.startVisible ) { | ||
// Adjust the css3 animation as well | ||
this._animStr = _animationStr( | ||
this._animStr = this._animationStr( | ||
this._animName, | ||
opts.duration / 1000, | ||
opts.delayBeforeStart / 1000 | ||
opts.delayBeforeStart / 1000, | ||
); | ||
animationCss = `translateX(${( opts.direction === 'left' ) ? -1 * this._elWidth : this._contWidth }px)`; | ||
animationCss = `translateX(${( opts.direction === 'left' ) ? -1 * this._elWidth : this._contWidth}px)`; | ||
@@ -436,7 +481,7 @@ this._loopCount++; | ||
this._animName = `${this._animName}0`; | ||
this._animStr = _animationStr( | ||
this._animStr = this._animationStr( | ||
this._animName, | ||
opts.duration / 1000, | ||
0, | ||
'infinite' | ||
'infinite', | ||
); | ||
@@ -460,17 +505,16 @@ this._repositionHor(); | ||
const keyFrameCss = `@keyframes ${this._animName} { | ||
100% { | ||
transform: ${animationCss}; | ||
} | ||
}`; | ||
100% { | ||
transform: ${animationCss}; | ||
} | ||
}`, | ||
styles = queryAll( 'style', this._marqWrap ); | ||
const styles = queryAll( 'style', this._marqWrap ); | ||
if ( styles.length ) | ||
styles[styles.length - 1].innerHTML = keyFrameCss; | ||
else if ( byClass( 'marq-wrap-style' ).length ) | ||
byClass( 'marq-wrap-style' )[0].innerHTML = keyFrameCss; | ||
else if ( byClass( `marq-wrap-style-${this._instance}` ).length ) | ||
byClass( `marq-wrap-style-${this._instance}` )[0].innerHTML = keyFrameCss; | ||
else { | ||
const styleEl = document.createElement( 'style' ); | ||
addClass( styleEl, 'marq-wrap-style' ); | ||
addClass( styleEl, `marq-wrap-style-${this._instance}` ); | ||
styleEl.innerHTML = keyFrameCss; | ||
@@ -492,3 +536,3 @@ | ||
this._status === 'running'; | ||
this._status = 'running'; | ||
setAttr( this.el, 'data-runningStatus', 'resumed' ); | ||
@@ -513,3 +557,3 @@ | ||
_repositionVert() { | ||
this._marqWrap.style.transform = `translateY(${ this._opts.direction === 'up' ? this._contHeight : ( this._elHeight * -1 ) }px)`; | ||
this._marqWrap.style.transform = `translateY(${this._opts.direction === 'up' ? this._contHeight : ( this._elHeight * -1 )}px)`; | ||
} | ||
@@ -523,6 +567,95 @@ | ||
_repositionHor() { | ||
this._marqWrap.style.transform = `translateX(${ this._opts.direction === 'left' ? this._contWidth : ( this._elWidth * -1 ) }px)`; | ||
this._marqWrap.style.transform = `translateX(${this._opts.direction === 'left' ? this._contWidth : ( this._elWidth * -1 )}px)`; | ||
} | ||
/** | ||
* Calculates the speed and the dimension of the marquee | ||
* | ||
* @private | ||
*/ | ||
_calcSizes() { | ||
const el = this.el, | ||
opts = this._opts; | ||
// If direction is up or down, get the height of main element | ||
if ( this._vertical ) { | ||
const contHeight = el.clientHeight; | ||
this._contHeight = contHeight; | ||
remAttr( this._marqWrap, 'style' ); | ||
el.style.clientHeight = `${contHeight}px`; | ||
const marqs = byClass( 'js-marquee', el ), | ||
marqNums = marqs.length - 1; | ||
// Change the CSS for js-marquee element | ||
forEachHTML( marqs, ( currEl, ind ) => { | ||
currEl.style.float = 'none'; | ||
currEl.style.marginRight = '0px'; | ||
// Remove bottom margin from 2nd element if duplicated | ||
if ( opts.duplicated && ind === marqNums ) | ||
currEl.style.marginBottom = '0px'; | ||
else | ||
currEl.style.marginBottom = `${opts.gap}px`; | ||
}); | ||
const elHeight = parseInt( marqs[0].clientHeight + opts.gap ); | ||
this._elHeight = elHeight; | ||
// adjust the animation duration according to the text length | ||
if ( opts.startVisible && !opts.duplicated ) { | ||
// Compute the complete animation duration and save it for later reference | ||
// formula is to: (Height of the text node + height of the main container / Height of the main container) * duration; | ||
this._completeDuration = ( elHeight + contHeight ) / parseInt( contHeight ) * this._duration; // eslint-disable-line max-len | ||
opts.duration = elHeight / parseInt( contHeight ) * this._duration; | ||
} else // formula is to: (Height of the text node + height of the main container / Height of the main container) * duration; | ||
opts.duration = elHeight / parseInt( contHeight ) / parseInt( contHeight ) * this._duration; | ||
} else { | ||
// Save the width of the each element so we can use it in animation | ||
const elWidth = parseInt( byClass( 'js-marquee', el )[0].clientWidth + opts.gap ), | ||
contWidth = el.clientWidth; | ||
this._contWidth = contWidth; | ||
this._elWidth = elWidth; | ||
// adjust the animation duration according to the text length | ||
if ( opts.startVisible && !opts.duplicated ) { | ||
// Compute the complete animation duration and save it for later reference | ||
// formula is to: (Width of the text node + width of the main container / Width of the main container) * duration; | ||
this._completeDuration = ( elWidth + contWidth ) / parseInt( contWidth ) * this._duration; | ||
// (Width of the text node / width of the main container) * duration | ||
opts.duration = elWidth / parseInt( contWidth ) * this._duration; | ||
} else // formula is to: (Width of the text node + width of the main container / Width of the main container) * duration; | ||
opts.duration = ( elWidth + parseInt( contWidth ) ) / parseInt( contWidth ) * this._duration; // eslint-disable-line max-len | ||
} | ||
// if duplicated then reduce the duration | ||
if ( opts.duplicated ) | ||
opts.duration = opts.duration / 2; | ||
} | ||
/** | ||
* Recalculates the dimensions and positon of the marquee on page resize | ||
* | ||
* @private | ||
*/ | ||
_recalcResize() { | ||
this._calcSizes(); | ||
this._loopCount = 2; | ||
this._animEnd(); | ||
} | ||
/** | ||
* Pause the animation | ||
@@ -584,2 +717,5 @@ */ | ||
if ( this._opts.recalcResize ) | ||
removeEvent( window, 'resize', this._recalcResize.bind( this ) ); | ||
} | ||
@@ -586,0 +722,0 @@ |
@@ -1,1 +0,1 @@ | ||
function t(t,s=document){return s.getElementsByClassName(t)}function s(t,s,i){for(let e=0,n=t.length;e<n;e++)s.call(i,t[e],e)}function i(t,s,i,e){t.addEventListener(s,i,e)}function e(t,s,i,e){t.removeEventListener(s,i,e)}function n(t,s){return t.getAttribute(s)}function h(t,s,i){t.setAttribute(s,i)}const a={css3easing:"linear",delayBeforeStart:1e3,direction:"left",duplicated:!1,duration:5e3,gap:20,pauseOnHover:!1,speed:0,startVisible:!1};export default class{constructor(e,h){if(void 0===e)throw new Error("el cannot be undefined");if("string"==typeof e)throw new Error("el cannot be just a selector");if(null===e)throw new Error("el cannot be null");h={...a,...h},this.t=3;for(const t in a){let s=n(e,`data-${a[t]}`);null!==s&&""!==s&&("true"!==s&&"false"!==s||(s=Boolean(s)),h[t]=s)}h.speed&&(h.duration=parseInt(e.clientWidth)/h.speed*1e3),h.gap=h.duplicated?parseInt(h.gap):0,e.innerHTML=`<div class="js-marquee">${e.innerHTML}</div>`;const r=t("js-marquee",e)[0];r.style.marginRight=`${h.gap}px`,r.style.willChange="transform",r.style.float="left",h.duplicated&&e.appendChild(r.cloneNode(!0)),e.innerHTML=`<div style="width:100000px" class="js-marquee-wrapper">${e.innerHTML}</div>`;const o=t("js-marquee-wrapper",e)[0],u="up"===h.direction||"down"===h.direction;if(this.i=o,u){const i=e.clientHeight;this.h=i,function(t,s){t.removeAttribute(s)}(o,"style"),e.style.clientHeight=`${i}px`;const n=t("js-marquee",e),a=n.length-1;s(n,((t,s)=>{t.style.float="none",t.style.marginRight="0px",h.duplicated&&s===a?t.style.marginBottom="0px":t.style.marginBottom=`${h.gap}px`}));const r=parseInt(n[0].clientHeight+h.gap);this.o=el_elHeight,h.startVisible&&!h.duplicated?(this.u=(r+i)/parseInt(i)*h.duration,h.duration=r/parseInt(i)*h.duration):h.duration=r/parseInt(i)/parseInt(i)*h.duration}else{const s=parseInt(t("js-marquee",e)[0].clientWidth+h.gap),i=e.clientWidth;this.p=i,this.l=s,h.startVisible&&!h.duplicated?(this.u=(s+i)/parseInt(i)*h.duration,h.duration=s/parseInt(i)*h.duration):h.duration=(s+parseInt(i))/parseInt(i)*h.duration}h.duplicated&&(h.duration=h.duration/2),this.m=h;const p="marqueeAnimation-"+Math.floor(1e7*Math.random()),l=this.$(p,h.duration/1e3,h.delayBeforeStart/1e3,"infinite");this.v=p,this.g=l,h.duplicated?(u?h.startVisible?this.i.style.transform="translateY(0px)":this.i.style.transform=`translateY(${"up"===h.direction?this.h:-1*(2*this.o-h.gap)}px)`:h.startVisible?this.i.style.transform="translateX(0px)":this.i.style.transform=`translateX(${"left"===h.direction?this.p:-1*(2*this.l-h.gap)}px)`,h.startVisible||(this.t=1)):h.startVisible?this.t=2:u?this.I():this.q(),this.S=e,i(this.S,"pause",this.pause.bind(this)),i(this.S,"resume",this.resume.bind(this)),h.pauseOnHover&&(i(this.S,"mouseover",this.pause.bind(this)),i(this.S,"mouseout",this.resume.bind(this))),this._=()=>{this.j(u),this.S.dispatchEvent(new CustomEvent("finished"))},this.j(u)}$(t="",s=0,i=0,e=""){return`${t} ${s}s ${i}s ${e} ${this.m.css3easing}`}j(e=!1){const n=this.m;if(n.duplicated){if(1===this.t){let t=n.duration;t=e?"up"===n.direction?t+this.h/(this.o/t):2*t:"left"===n.direction?t+this.p/(this.l/t):2*t,this.g=this.$(this.v,t/1e3,n.delayBeforeStart/1e3)}else 2===this.t&&(this.v=`${this.v}0`,this.g=this.$(this.v,n.duration/1e3,0,"infinite"));this.t++}let a="";e?n.duplicated?(this.t>2&&(this.i.style.transform=`translateY(${"up"===n.direction?0:-1*this.o}px)`),a=`translateY(${"up"===n.direction?-1*this.o:0}px)`):n.startVisible?2===this.t?(this.g=_animationStr(this.v,n.duration/1e3,n.delayBeforeStart/1e3),a=`translateY(${"up"===n.direction?-1*this.o:this.h}px)`,this.t++):3===this.t&&(this.v=`${this.v}0`,this.g=_animationStr(this.v,this.u/1e3,0,"infinite"),this.I()):(this.I(),a=`translateY(${"up"===n.direction?-1*this.i.clientHeight:this.h}px)`):n.duplicated?(this.t>2&&(this.i.style.transform=`translateX(${"left"===n.direction?0:-1*this.l}px)`),a=`translateX(${"left"===n.direction?-1*this.l:0}px)`):n.startVisible?2===this.t?(this.g=_animationStr(this.v,n.duration/1e3,n.delayBeforeStart/1e3),a=`translateX(${"left"===n.direction?-1*this.l:this.p}px)`,this.t++):3===this.t&&(this.v=`${this.v}0`,this.g=_animationStr(this.v,n.duration/1e3,0,"infinite"),this.q()):(this.q(),a=`translateX(${"left"===n.direction?-1*this.l:this.h}px)`),this.S.dispatchEvent(new CustomEvent("beforeStarting")),this.i.style.animation=this.g;const r=`@keyframes ${this.v} {\n 100% {\n transform: ${a};\n }\n }`,o=function(t,s=document){return s.querySelectorAll(t)}("style",this.i);if(o.length)o[o.length-1].innerHTML=r;else if(t("marq-wrap-style").length)t("marq-wrap-style")[0].innerHTML=r;else{const t=document.createElement("style");!function(t,...i){function e(t,...s){s.forEach((s=>{t.classList.add(s)}))}void 0===t.length?e(t,...i):s(t,(t=>{e(t,...i)}))}(t,"marq-wrap-style"),t.innerHTML=r,function(t,s=document){return s.querySelector(t)}("head").appendChild(t)}i(this.i,"animationiteration",this.X.bind(this),{once:!0}),i(this.i,"animationend",this._.bind(this),{once:!0}),this.Y,h(this.S,"data-runningStatus","resumed")}X(){this.S.dispatchEvent(new CustomEvent("finished"))}I(){this.i.style.transform=`translateY(${"up"===this.m.direction?this.h:-1*this.o}px)`}q(){this.i.style.transform=`translateX(${"left"===this.m.direction?this.p:-1*this.l}px)`}pause(){this.i.style.animationPlayState="paused",this.Y="paused",h(this.S,"data-runningStatus","paused"),this.S.dispatchEvent(new CustomEvent("paused"))}resume(){this.i.style.animationPlayState="running",this.Y="running",h(this.S,"data-runningStatus","resumed"),this.S.dispatchEvent(new CustomEvent("resumed"))}toggle(){"paused"===this.Y?this.resume():"running"===this.Y&&this.pause()}C(){e(this.S,"pause",this.pause.bind(this)),e(this.S,"resume",this.resume.bind(this)),this.m.pauseOnHover&&(e(this.S,"mouseover",this.pause.bind(this)),e(this.S,"mouseout",this.resume.bind(this))),e(this.i,"animationiteration",this.X.bind(this),{once:!0}),e(this.i,"animationend",this._.bind(this),{once:!0})}} | ||
function t(t,s=document){return s.getElementsByClassName(t)}function s(t,s,i){for(let e=0,h=t.length;e<h;e++)s.call(i,t[e],e)}function i(t,s,i,e){t.addEventListener(s,i,e)}function e(t,s,i,e){t.removeEventListener(s,i,e)}function h(t,s){return t.getAttribute(s)}function n(t,s,i){t.setAttribute(s,i)}const a={css3easing:"linear",delayBeforeStart:1e3,direction:"left",duplicated:!1,duration:5e3,gap:20,pauseOnHover:!1,recalcResize:!1,speed:0,startVisible:!1};let r=0;export default class{constructor(s,e){if(void 0===s)throw new Error("el cannot be undefined");if("string"==typeof s)throw new Error("el cannot be just a selector");if(null===s)throw new Error("el cannot be null");e={...a,...e},this.t=s,this.i=3;for(const t in a){let i=h(s,`data-${a[t]}`);null!==i&&""!==i&&("true"!==i&&"false"!==i||(i=Boolean(i)),e[t]=i)}e.speed&&(e.duration=parseInt(s.clientWidth)/e.speed*1e3),e.gap=e.duplicated?parseInt(e.gap):0,s.innerHTML=`<div class="js-marquee">${s.innerHTML}</div>`;const n=t("js-marquee",s)[0];n.style.marginRight=`${e.gap}px`,n.style.willChange="transform",n.style.float="left",e.duplicated&&s.appendChild(n.cloneNode(!0)),s.innerHTML=`<div style="width:100000px" class="js-marquee-wrapper">${s.innerHTML}</div>`;const o=t("js-marquee-wrapper",s)[0],u="up"===e.direction||"down"===e.direction;this.h=o,this.o=u,this.u=e.duration,this.l=e,this.p();const l=`marqueeAnimation-${Math.floor(1e7*Math.random())}`,p=this.m(l,e.duration/1e3,e.delayBeforeStart/1e3,"infinite");this.$=l,this.v=p,e.duplicated?(u?e.startVisible?this.h.style.transform="translateY(0px)":this.h.style.transform=`translateY(${"up"===e.direction?this.g:-1*(2*this.I-e.gap)}px)`:e.startVisible?this.h.style.transform="translateX(0px)":this.h.style.transform=`translateX(${"left"===e.direction?this.q:-1*(2*this.j-e.gap)}px)`,e.startVisible||(this.i=1)):e.startVisible?this.i=2:u?this.S():this.X(),i(this.t,"pause",this.pause.bind(this)),i(this.t,"resume",this.resume.bind(this)),e.pauseOnHover&&(i(this.t,"mouseover",this.pause.bind(this)),i(this.t,"mouseout",this.resume.bind(this))),this.Y=()=>{this._(u),this.t.dispatchEvent(new CustomEvent("finished"))},this.C=r,r++,this._(u),e.recalcResize&&i(window,"resize",this.B.bind(this))}m(t="",s=0,i=0,e=""){return`${t} ${s}s ${i}s ${e} ${this.l.css3easing}`}_(e=!1){const h=this.l;if(h.duplicated){if(1===this.i){let t=h.duration;t=e?"up"===h.direction?t+this.g/(this.I/t):2*t:"left"===h.direction?t+this.q/(this.j/t):2*t,this.v=this.m(this.$,t/1e3,h.delayBeforeStart/1e3)}else 2===this.i&&(this.$=`${this.$}0`,this.v=this.m(this.$,h.duration/1e3,0,"infinite"));this.i++}let a="";e?h.duplicated?(this.i>2&&(this.h.style.transform=`translateY(${"up"===h.direction?0:-1*this.I}px)`),a=`translateY(${"up"===h.direction?-1*this.I:0}px)`):h.startVisible?2===this.i?(this.v=this.m(this.$,h.duration/1e3,h.delayBeforeStart/1e3),a=`translateY(${"up"===h.direction?-1*this.I:this.g}px)`,this.i++):3===this.i&&(this.$=`${this.$}0`,this.v=this.m(this.$,this.H/1e3,0,"infinite"),this.S()):(this.S(),a=`translateY(${"up"===h.direction?-1*this.h.clientHeight:this.g}px)`):h.duplicated?(this.i>2&&(this.h.style.transform=`translateX(${"left"===h.direction?0:-1*this.j}px)`),a=`translateX(${"left"===h.direction?-1*this.j:0}px)`):h.startVisible?2===this.i?(this.v=this.m(this.$,h.duration/1e3,h.delayBeforeStart/1e3),a=`translateX(${"left"===h.direction?-1*this.j:this.q}px)`,this.i++):3===this.i&&(this.$=`${this.$}0`,this.v=this.m(this.$,h.duration/1e3,0,"infinite"),this.X()):(this.X(),a=`translateX(${"left"===h.direction?-1*this.j:this.g}px)`),this.t.dispatchEvent(new CustomEvent("beforeStarting")),this.h.style.animation=this.v;const r=`@keyframes ${this.$} {\n 100% {\n transform: ${a};\n }\n }`,o=function(t,s=document){return s.querySelectorAll(t)}("style",this.h);if(o.length)o[o.length-1].innerHTML=r;else if(t(`marq-wrap-style-${this.C}`).length)t(`marq-wrap-style-${this.C}`)[0].innerHTML=r;else{const t=document.createElement("style");!function(t,...i){function e(t,...s){s.forEach((s=>{t.classList.add(s)}))}void 0===t.length?e(t,...i):s(t,(t=>{e(t,...i)}))}(t,`marq-wrap-style-${this.C}`),t.innerHTML=r,function(t,s=document){return s.querySelector(t)}("head").appendChild(t)}i(this.h,"animationiteration",this.M.bind(this),{once:!0}),i(this.h,"animationend",this.Y.bind(this),{once:!0}),this.R="running",n(this.t,"data-runningStatus","resumed")}M(){this.t.dispatchEvent(new CustomEvent("finished"))}S(){this.h.style.transform=`translateY(${"up"===this.l.direction?this.g:-1*this.I}px)`}X(){this.h.style.transform=`translateX(${"left"===this.l.direction?this.q:-1*this.j}px)`}p(){const i=this.t,e=this.l;if(this.o){const h=i.clientHeight;this.g=h,function(t,s){t.removeAttribute(s)}(this.h,"style"),i.style.clientHeight=`${h}px`;const n=t("js-marquee",i),a=n.length-1;s(n,((t,s)=>{t.style.float="none",t.style.marginRight="0px",e.duplicated&&s===a?t.style.marginBottom="0px":t.style.marginBottom=`${e.gap}px`}));const r=parseInt(n[0].clientHeight+e.gap);this.I=r,e.startVisible&&!e.duplicated?(this.H=(r+h)/parseInt(h)*this.u,e.duration=r/parseInt(h)*this.u):e.duration=r/parseInt(h)/parseInt(h)*this.u}else{const s=parseInt(t("js-marquee",i)[0].clientWidth+e.gap),h=i.clientWidth;this.q=h,this.j=s,e.startVisible&&!e.duplicated?(this.H=(s+h)/parseInt(h)*this.u,e.duration=s/parseInt(h)*this.u):e.duration=(s+parseInt(h))/parseInt(h)*this.u}e.duplicated&&(e.duration=e.duration/2)}B(){this.p(),this.i=2,this.Y()}pause(){this.h.style.animationPlayState="paused",this.R="paused",n(this.t,"data-runningStatus","paused"),this.t.dispatchEvent(new CustomEvent("paused"))}resume(){this.h.style.animationPlayState="running",this.R="running",n(this.t,"data-runningStatus","resumed"),this.t.dispatchEvent(new CustomEvent("resumed"))}toggle(){"paused"===this.R?this.resume():"running"===this.R&&this.pause()}V(){e(this.t,"pause",this.pause.bind(this)),e(this.t,"resume",this.resume.bind(this)),this.l.pauseOnHover&&(e(this.t,"mouseover",this.pause.bind(this)),e(this.t,"mouseout",this.resume.bind(this))),e(this.h,"animationiteration",this.M.bind(this),{once:!0}),e(this.h,"animationend",this.Y.bind(this),{once:!0}),this.l.recalcResize&&e(window,"resize",this.B.bind(this))}} |
{ | ||
"name": "vanilla-marquee", | ||
"version": "1.0.4", | ||
"version": "1.1.0", | ||
"description": "", | ||
@@ -28,11 +28,13 @@ "main": "./dist/vanilla-marquee.js", | ||
"dependencies": { | ||
"matt-utils": "^1.4.2" | ||
"matt-utils": "^1.4.3" | ||
}, | ||
"devDependencies": { | ||
"@rollup/plugin-commonjs": "^17.1.0", | ||
"@rollup/plugin-eslint": "^8.0.1", | ||
"@rollup/plugin-node-resolve": "^11.2.0", | ||
"rollup": "^2.39.1", | ||
"eslint": "^7.21.0", | ||
"rollup": "^2.40.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"typescript": "^4.2.2" | ||
"typescript": "^4.2.3" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36571
711
7
6
Updatedmatt-utils@^1.4.3