dynamic-marquee
Advanced tools
Comparing version 1.2.1 to 1.2.2
@@ -1,796 +0,736 @@ | ||
(function webpackUniversalModuleDefinition(root, factory) { | ||
if(typeof exports === 'object' && typeof module === 'object') | ||
module.exports = factory(); | ||
else if(typeof define === 'function' && define.amd) | ||
define([], factory); | ||
else if(typeof exports === 'object') | ||
exports["dynamicMarquee"] = factory(); | ||
else | ||
root["dynamicMarquee"] = factory(); | ||
})(window, function() { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
/******/ // The module cache | ||
/******/ var installedModules = {}; | ||
/******/ | ||
/******/ // The require function | ||
/******/ function __webpack_require__(moduleId) { | ||
/******/ | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) { | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ } | ||
/******/ // Create a new module (and put it into the cache) | ||
/******/ var module = installedModules[moduleId] = { | ||
/******/ i: moduleId, | ||
/******/ l: false, | ||
/******/ exports: {} | ||
/******/ }; | ||
/******/ | ||
/******/ // Execute the module function | ||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | ||
/******/ | ||
/******/ // Flag the module as loaded | ||
/******/ module.l = true; | ||
/******/ | ||
/******/ // Return the exports of the module | ||
/******/ return module.exports; | ||
/******/ } | ||
/******/ | ||
/******/ | ||
/******/ // expose the modules object (__webpack_modules__) | ||
/******/ __webpack_require__.m = modules; | ||
/******/ | ||
/******/ // expose the module cache | ||
/******/ __webpack_require__.c = installedModules; | ||
/******/ | ||
/******/ // define getter function for harmony exports | ||
/******/ __webpack_require__.d = function(exports, name, getter) { | ||
/******/ if(!__webpack_require__.o(exports, name)) { | ||
/******/ Object.defineProperty(exports, name, { | ||
/******/ configurable: false, | ||
/******/ enumerable: true, | ||
/******/ get: getter | ||
/******/ }); | ||
/******/ } | ||
/******/ }; | ||
/******/ | ||
/******/ // define __esModule on exports | ||
/******/ __webpack_require__.r = function(exports) { | ||
/******/ Object.defineProperty(exports, '__esModule', { value: true }); | ||
/******/ }; | ||
/******/ | ||
/******/ // getDefaultExport function for compatibility with non-harmony modules | ||
/******/ __webpack_require__.n = function(module) { | ||
/******/ var getter = module && module.__esModule ? | ||
/******/ function getDefault() { return module['default']; } : | ||
/******/ function getModuleExports() { return module; }; | ||
/******/ __webpack_require__.d(getter, 'a', getter); | ||
/******/ return getter; | ||
/******/ }; | ||
/******/ | ||
/******/ // Object.prototype.hasOwnProperty.call | ||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | ||
/******/ | ||
/******/ // __webpack_public_path__ | ||
/******/ __webpack_require__.p = ""; | ||
/******/ | ||
/******/ | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 6); | ||
/******/ }) | ||
/************************************************************************/ | ||
/******/ ([ | ||
/* 0 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
(function(global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' | ||
? factory(exports) | ||
: typeof define === 'function' && define.amd | ||
? define(['exports'], factory) | ||
: ((global = global || self), factory((global.dynamicMarquee = {}))); | ||
})(this, function(exports) { | ||
'use strict'; | ||
"use strict"; | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError('Cannot call a class as a function'); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ('value' in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.size = size; | ||
exports.defer = defer; | ||
exports.deferException = deferException; | ||
exports.toDomEl = toDomEl; | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
var _direction = __webpack_require__(1); | ||
var DIRECTION = { | ||
RIGHT: 'right', | ||
DOWN: 'down' | ||
}; | ||
function size($el, direction) { | ||
return $el[direction === _direction.DIRECTION.RIGHT ? 'offsetWidth' : 'offsetHeight']; | ||
} | ||
function defer(fn) { | ||
window.setTimeout(function () { | ||
return fn(); | ||
}, 0); | ||
} | ||
function deferException(cb) { | ||
try { | ||
return cb(); | ||
} catch (e) { | ||
defer(function () { | ||
throw e; | ||
}); | ||
function size($el, direction) { | ||
return $el[direction === DIRECTION.RIGHT ? 'offsetWidth' : 'offsetHeight']; | ||
} | ||
} | ||
function defer(fn) { | ||
window.setTimeout(function() { | ||
return fn(); | ||
}, 0); | ||
} | ||
function deferException(cb) { | ||
try { | ||
return cb(); | ||
} catch (e) { | ||
defer(function() { | ||
throw e; | ||
}); | ||
} | ||
} | ||
function toDomEl($el) { | ||
if (typeof $el === 'string' || typeof $el === 'number') { | ||
// helper. convert string to div | ||
var $div = document.createElement('div'); | ||
$div.textContent = $el + ''; | ||
return $div; | ||
} | ||
function toDomEl($el) { | ||
if (typeof $el === 'string' || typeof $el === 'number') { | ||
// helper. convert string to div | ||
var $div = document.createElement('div'); | ||
$div.textContent = $el + ""; | ||
return $div; | ||
return $el; | ||
} | ||
return $el; | ||
} | ||
/***/ }), | ||
/* 1 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
var Item = /*#__PURE__*/ (function() { | ||
function Item($el, direction, rateWhenAppended) { | ||
_classCallCheck(this, Item); | ||
"use strict"; | ||
var $container = document.createElement('div'); | ||
$container.style.display = 'block'; | ||
$container.style.position = 'absolute'; | ||
$container.style.margin = '0'; | ||
$container.style.padding = '0'; | ||
$container.style[this._direction === DIRECTION.RIGHT ? 'top' : 'left'] = | ||
'0'; | ||
$container.style.whiteSpace = 'nowrap'; | ||
$container.style.willChange = 'auto'; | ||
$container.appendChild($el); | ||
this._$container = $container; | ||
this._$el = $el; | ||
this._direction = direction; | ||
this._rateWhenAppended = rateWhenAppended; | ||
} | ||
_createClass(Item, [ | ||
{ | ||
key: 'getSize', | ||
value: function getSize() { | ||
var _ref = | ||
arguments.length > 0 && arguments[0] !== undefined | ||
? arguments[0] | ||
: {}, | ||
_ref$inverse = _ref.inverse, | ||
inverse = _ref$inverse === void 0 ? false : _ref$inverse; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var DIRECTION = exports.DIRECTION = { | ||
RIGHT: 'right', | ||
DOWN: 'down' | ||
}; | ||
var dir = this._direction; | ||
/***/ }), | ||
/* 2 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
if (inverse) { | ||
dir = dir === DIRECTION.RIGHT ? DIRECTION.DOWN : DIRECTION.RIGHT; | ||
} | ||
"use strict"; | ||
return size(this._$container, dir); | ||
} | ||
}, | ||
{ | ||
key: 'setOffset', | ||
value: function setOffset(offset) { | ||
if (this._direction === DIRECTION.RIGHT) { | ||
this._$container.style.transform = 'translateX('.concat( | ||
offset, | ||
'px)' | ||
); | ||
} else { | ||
this._$container.style.transform = 'translateY('.concat( | ||
offset, | ||
'px)' | ||
); | ||
} | ||
} | ||
}, | ||
{ | ||
key: 'enableAnimationHint', | ||
value: function enableAnimationHint(enable) { | ||
this._$container.style.willChange = enable ? 'transform' : 'auto'; | ||
} | ||
}, | ||
{ | ||
key: 'remove', | ||
value: function remove() { | ||
this._$container.remove(); | ||
} | ||
}, | ||
{ | ||
key: 'getContainer', | ||
value: function getContainer() { | ||
return this._$container; | ||
} | ||
}, | ||
{ | ||
key: 'getOriginalEl', | ||
value: function getOriginalEl() { | ||
return this._$el; | ||
} | ||
}, | ||
{ | ||
key: 'getRateWhenAppended', | ||
value: function getRateWhenAppended() { | ||
return this._rateWhenAppended; | ||
} | ||
} | ||
]); | ||
return Item; | ||
})(); | ||
var VirtualItem = /*#__PURE__*/ (function() { | ||
function VirtualItem(size) { | ||
_classCallCheck(this, VirtualItem); | ||
var indexMap = function indexMap(list) { | ||
var map = {}; | ||
list.forEach(function (each, i) { | ||
map[each] = map[each] || []; | ||
map[each].push(i); | ||
}); | ||
return map; | ||
}; | ||
this._size = size; | ||
} | ||
var longestCommonSubstring = function longestCommonSubstring(seq1, seq2) { | ||
var result = { startString1: 0, startString2: 0, length: 0 }; | ||
var indexMapBefore = indexMap(seq1); | ||
var previousOverlap = []; | ||
seq2.forEach(function (eachAfter, indexAfter) { | ||
var overlapLength; | ||
var overlap = []; | ||
var indexesBefore = indexMapBefore[eachAfter] || []; | ||
indexesBefore.forEach(function (indexBefore) { | ||
overlapLength = (indexBefore && previousOverlap[indexBefore - 1] || 0) + 1; | ||
if (overlapLength > result.length) { | ||
result.length = overlapLength; | ||
result.startString1 = indexBefore - overlapLength + 1; | ||
result.startString2 = indexAfter - overlapLength + 1; | ||
_createClass(VirtualItem, [ | ||
{ | ||
key: 'getSize', | ||
value: function getSize() { | ||
var _ref2 = | ||
arguments.length > 0 && arguments[0] !== undefined | ||
? arguments[0] | ||
: {}, | ||
_ref2$inverse = _ref2.inverse, | ||
inverse = _ref2$inverse === void 0 ? false : _ref2$inverse; | ||
if (inverse) { | ||
throw new Error('Inverse not supported on virtual item.'); | ||
} | ||
return this._size; | ||
} | ||
}, | ||
{ | ||
key: 'setOffset', | ||
value: function setOffset() {} | ||
}, | ||
{ | ||
key: 'enableAnimationHint', | ||
value: function enableAnimationHint() {} | ||
}, | ||
{ | ||
key: 'remove', | ||
value: function remove() {} | ||
} | ||
overlap[indexBefore] = overlapLength; | ||
}); | ||
previousOverlap = overlap; | ||
}); | ||
return result; | ||
}; | ||
]); | ||
module.exports = longestCommonSubstring; | ||
return VirtualItem; | ||
})(); | ||
/***/ }), | ||
/* 3 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
var Marquee = /*#__PURE__*/ (function() { | ||
function Marquee($container) { | ||
var _ref = | ||
arguments.length > 1 && arguments[1] !== undefined | ||
? arguments[1] | ||
: {}, | ||
_ref$rate = _ref.rate, | ||
rate = _ref$rate === void 0 ? -25 : _ref$rate, | ||
_ref$upDown = _ref.upDown, | ||
upDown = _ref$upDown === void 0 ? false : _ref$upDown; | ||
"use strict"; | ||
_classCallCheck(this, Marquee); | ||
this._rendering = false; | ||
this._waitingForItem = true; | ||
this._nextItemImmediatelyFollowsPrevious = false; | ||
this._rate = rate; | ||
this._direction = upDown ? DIRECTION.DOWN : DIRECTION.RIGHT; | ||
this._onItemRequired = []; | ||
this._onItemRemoved = []; | ||
this._onAllItemsRemoved = []; | ||
this._leftItemOffset = 0; | ||
this._containerSize = 0; | ||
this._items = []; | ||
this._pendingItem = null; | ||
var $innerContainer = document.createElement('div'); | ||
$innerContainer.style.position = 'relative'; | ||
$innerContainer.style.display = 'inline-block'; | ||
this._$container = $innerContainer; | ||
this._containerSizeInverse = null; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.loop = loop; | ||
if (this._direction === DIRECTION.RIGHT) { | ||
$innerContainer.style.width = '100%'; | ||
} else { | ||
$innerContainer.style.height = '100%'; | ||
} | ||
var _helpers = __webpack_require__(0); | ||
this._updateContainerSize(); | ||
var _longestCommonSubstring = __webpack_require__(2); | ||
$container.appendChild($innerContainer); | ||
var _longestCommonSubstring2 = _interopRequireDefault(_longestCommonSubstring); | ||
this._scheduleRender(); | ||
} // called when there's room for a new item. | ||
// You can return the item to append next | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
_createClass(Marquee, [ | ||
{ | ||
key: 'onItemRequired', | ||
value: function onItemRequired(cb) { | ||
this._onItemRequired.push(cb); | ||
} // Called when an item is removed | ||
}, | ||
{ | ||
key: 'onItemRemoved', | ||
value: function onItemRemoved(cb) { | ||
this._onItemRemoved.push(cb); | ||
} // Called when the last item is removed | ||
}, | ||
{ | ||
key: 'onAllItemsRemoved', | ||
value: function onAllItemsRemoved(cb) { | ||
this._onAllItemsRemoved.push(cb); | ||
} | ||
}, | ||
{ | ||
key: 'getNumItems', | ||
value: function getNumItems() { | ||
return this._items.filter(function(item) { | ||
return item instanceof Item; | ||
}).length; | ||
} | ||
}, | ||
{ | ||
key: 'setRate', | ||
value: function setRate(rate) { | ||
if (!rate !== !this._rate) { | ||
this._enableAnimationHint(!!rate); | ||
function loop(marquee) { | ||
var buildersIn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var seperatorBuilder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; | ||
if (rate) { | ||
this._scheduleRender(); | ||
} | ||
} | ||
var lastIndex = -1; | ||
var builders = buildersIn.slice(); | ||
this._rate = rate; | ||
} | ||
}, | ||
{ | ||
key: 'getRate', | ||
value: function getRate() { | ||
return this._rate; | ||
} | ||
}, | ||
{ | ||
key: 'clear', | ||
value: function clear() { | ||
var _this = this; | ||
var getNextBuilder = function getNextBuilder() { | ||
var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; | ||
this._items.forEach(function($a) { | ||
return _this._removeItem($a); | ||
}); | ||
var nextIndex = (lastIndex + offset) % builders.length; | ||
return { builder: builders[nextIndex], index: nextIndex }; | ||
}; | ||
this._items = []; | ||
this._waitingForItem = true; | ||
var appendItem = function appendItem(immediatelyFollowsPrevious) { | ||
if (!builders.length || !marquee.isWaitingForItem()) { | ||
return; | ||
} | ||
this._updateContainerSize(); | ||
} | ||
}, | ||
{ | ||
key: 'isWaitingForItem', | ||
value: function isWaitingForItem() { | ||
return this._waitingForItem; | ||
} | ||
}, | ||
{ | ||
key: 'appendItem', | ||
value: function appendItem($el) { | ||
if (!this._waitingForItem) { | ||
throw new Error('No room for item.'); | ||
} // convert to div if $el is a string | ||
var _getNextBuilder = getNextBuilder(), | ||
builder = _getNextBuilder.builder, | ||
index = _getNextBuilder.index; | ||
$el = toDomEl($el); | ||
lastIndex = index; | ||
var $item = (0, _helpers.toDomEl)(builder()); | ||
if (immediatelyFollowsPrevious && seperatorBuilder) { | ||
var $seperator = (0, _helpers.toDomEl)(seperatorBuilder()); | ||
var $container = document.createElement('div'); | ||
$seperator.style.display = 'inline'; | ||
$item.style.display = 'inline'; | ||
if (marquee.getRate() <= 0) { | ||
$container.appendChild($seperator); | ||
$container.appendChild($item); | ||
} else { | ||
$container.appendChild($item); | ||
$container.appendChild($seperator); | ||
} | ||
$item = $container; | ||
} | ||
marquee.appendItem($item); | ||
}; | ||
marquee.onItemRequired(function (_ref) { | ||
var immediatelyFollowsPrevious = _ref.immediatelyFollowsPrevious; | ||
return appendItem(immediatelyFollowsPrevious); | ||
}); | ||
appendItem(); | ||
return { | ||
update: function update(newBuilders) { | ||
// try and start from somewhere that makes sense | ||
var calculateNewIndex = function calculateNewIndex() { | ||
// convert array of function references to array of ids | ||
var buildersStructure = builders.map(function (b, i) { | ||
var prevIndex = builders.indexOf(b); | ||
// if already seen builder, give it the same number | ||
return prevIndex < i ? prevIndex : i; | ||
}); | ||
var newBuildersStructure = newBuilders.map(function (b, i) { | ||
// matching indexes where they exist, and -1 for all unknown | ||
return builders.indexOf(b); | ||
}); | ||
var itemAlreadyExists = this._items.some(function(item) { | ||
return item instanceof Item && item.getOriginalEl() === $el; | ||
}); | ||
var _longestSubstring = (0, _longestCommonSubstring2.default)(buildersStructure, newBuildersStructure), | ||
startString1 = _longestSubstring.startString1, | ||
startString2 = _longestSubstring.startString2, | ||
length = _longestSubstring.length; | ||
if (itemAlreadyExists) { | ||
throw new Error('Item already exists.'); | ||
} | ||
if (lastIndex >= startString1 && lastIndex < startString1 + length) { | ||
// we are in the overlapping region | ||
return lastIndex + (startString2 - startString1); | ||
this._waitingForItem = false; | ||
this._pendingItem = new Item($el, this._direction, this._rate); | ||
this._pendingItem.enableAnimationHint(!!this._rate); | ||
this._scheduleRender(); | ||
} | ||
return -1; | ||
}; | ||
}, | ||
{ | ||
key: '_removeItem', | ||
value: function _removeItem(item) { | ||
var _this2 = this; | ||
lastIndex = calculateNewIndex(); | ||
builders = newBuilders.slice(); | ||
appendItem(false); | ||
} | ||
}; | ||
} | ||
defer(function() { | ||
item.remove(); | ||
/***/ }), | ||
/* 4 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
if (item instanceof Item) { | ||
_this2._onItemRemoved.forEach(function(cb) { | ||
deferException(function() { | ||
return cb(item.getOriginalEl()); | ||
}); | ||
}); | ||
} | ||
}); | ||
} // update size of container so that the marquee items fit inside it. | ||
// This is needed because the items are posisitioned absolutely, so not in normal flow. | ||
// Without this, the height of the container would always be 0px, which is not useful | ||
}, | ||
{ | ||
key: '_updateContainerSize', | ||
value: function _updateContainerSize() { | ||
var maxSize = this._items.reduce(function(size, item) { | ||
if (item instanceof VirtualItem) { | ||
return size; | ||
} | ||
"use strict"; | ||
var a = item.getSize({ | ||
inverse: true | ||
}); | ||
if (a > size) { | ||
return a; | ||
} | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.VirtualItem = exports.Item = undefined; | ||
return size; | ||
}, 0); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
if (this._containerSizeInverse !== maxSize) { | ||
this._containerSizeInverse = maxSize; | ||
var _direction = __webpack_require__(1); | ||
if (this._direction === DIRECTION.RIGHT) { | ||
this._$container.style.height = ''.concat(maxSize, 'px'); | ||
} else { | ||
this._$container.style.width = ''.concat(maxSize, 'px'); | ||
} | ||
} | ||
} | ||
}, | ||
{ | ||
key: '_enableAnimationHint', | ||
value: function _enableAnimationHint(enable) { | ||
this._items.forEach(function(item) { | ||
return item.enableAnimationHint(enable); | ||
}); | ||
} | ||
}, | ||
{ | ||
key: '_scheduleRender', | ||
value: function _scheduleRender() { | ||
var _this3 = this; | ||
var _helpers = __webpack_require__(0); | ||
if (this._rendering) { | ||
// we are already rendering, so call the render method synchronously | ||
this._render(); | ||
} else { | ||
if (!this._requestAnimationID) { | ||
this._lastUpdateTime = performance.now(); | ||
this._requestAnimationID = window.requestAnimationFrame( | ||
function() { | ||
return _this3._onRequestAnimationFrame(); | ||
} | ||
); | ||
} | ||
} | ||
} | ||
}, | ||
{ | ||
key: '_onRequestAnimationFrame', | ||
value: function _onRequestAnimationFrame() { | ||
var _this4 = this; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
this._requestAnimationID = null; | ||
var Item = exports.Item = function () { | ||
function Item($el, direction, rateWhenAppended) { | ||
_classCallCheck(this, Item); | ||
if (!this._rate || (!this._items.length && !this._pendingItem)) { | ||
return; | ||
} | ||
var $container = document.createElement('div'); | ||
$container.style.display = 'block'; | ||
$container.style.position = 'absolute'; | ||
$container.style.margin = '0'; | ||
$container.style.padding = '0'; | ||
$container.style[this._direction === _direction.DIRECTION.RIGHT ? 'top' : 'left'] = '0'; | ||
$container.style.whiteSpace = 'nowrap'; | ||
$container.style.willChange = 'auto'; | ||
$container.appendChild($el); | ||
var now = performance.now(); | ||
var timePassed = now - this._lastUpdateTime; | ||
this._$container = $container; | ||
this._$el = $el; | ||
this._direction = direction; | ||
this._rateWhenAppended = rateWhenAppended; | ||
} | ||
this._scheduleRender(); | ||
_createClass(Item, [{ | ||
key: 'getSize', | ||
value: function getSize() { | ||
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, | ||
_ref$inverse = _ref.inverse, | ||
inverse = _ref$inverse === undefined ? false : _ref$inverse; | ||
this._rendering = true; | ||
var shiftAmount = this._rate * (timePassed / 1000); | ||
this._leftItemOffset += shiftAmount; | ||
this._containerSize = size(this._$container, this._direction); | ||
deferException(function() { | ||
return _this4._render(); | ||
}); | ||
this._rendering = false; | ||
} | ||
}, | ||
{ | ||
key: '_render', | ||
value: function _render() { | ||
var _this5 = this; | ||
var dir = this._direction; | ||
if (inverse) { | ||
dir = dir === _direction.DIRECTION.RIGHT ? _direction.DIRECTION.DOWN : _direction.DIRECTION.RIGHT; | ||
} | ||
return (0, _helpers.size)(this._$container, dir); | ||
} | ||
}, { | ||
key: 'setOffset', | ||
value: function setOffset(offset) { | ||
if (this._direction === _direction.DIRECTION.RIGHT) { | ||
this._$container.style.transform = 'translateX(' + offset + 'px)'; | ||
} else { | ||
this._$container.style.transform = 'translateY(' + offset + 'px)'; | ||
} | ||
} | ||
}, { | ||
key: 'enableAnimationHint', | ||
value: function enableAnimationHint(enable) { | ||
this._$container.style.willChange = enable ? 'transform' : 'auto'; | ||
} | ||
}, { | ||
key: 'remove', | ||
value: function remove() { | ||
this._$container.remove(); | ||
} | ||
}, { | ||
key: 'getContainer', | ||
value: function getContainer() { | ||
return this._$container; | ||
} | ||
}, { | ||
key: 'getOriginalEl', | ||
value: function getOriginalEl() { | ||
return this._$el; | ||
} | ||
}, { | ||
key: 'getRateWhenAppended', | ||
value: function getRateWhenAppended() { | ||
return this._rateWhenAppended; | ||
} | ||
}]); | ||
var containerSize = this._containerSize; | ||
return Item; | ||
}(); | ||
if (this._rate < 0) { | ||
while (this._items.length) { | ||
var item = this._items[0]; | ||
var VirtualItem = exports.VirtualItem = function () { | ||
function VirtualItem(size) { | ||
_classCallCheck(this, VirtualItem); | ||
var _size = item.getSize(); | ||
this._size = size; | ||
} | ||
if (this._leftItemOffset + _size > 0) { | ||
break; | ||
} | ||
_createClass(VirtualItem, [{ | ||
key: 'getSize', | ||
value: function getSize() { | ||
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, | ||
_ref2$inverse = _ref2.inverse, | ||
inverse = _ref2$inverse === undefined ? false : _ref2$inverse; | ||
this._removeItem(this._items[0]); | ||
if (inverse) { | ||
throw new Error('Inverse not supported on virtual item.'); | ||
} | ||
return this._size; | ||
} | ||
}, { | ||
key: 'setOffset', | ||
value: function setOffset() {} | ||
}, { | ||
key: 'enableAnimationHint', | ||
value: function enableAnimationHint() {} | ||
}, { | ||
key: 'remove', | ||
value: function remove() {} | ||
}]); | ||
this._items.shift(); | ||
return VirtualItem; | ||
}(); | ||
this._leftItemOffset += _size; | ||
} | ||
} | ||
/***/ }), | ||
/* 5 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
var offsets = []; | ||
var nextOffset = this._leftItemOffset; | ||
"use strict"; | ||
this._items.some(function(item, i) { | ||
if (nextOffset >= containerSize) { | ||
if (_this5._rate > 0) { | ||
_this5._items.splice(i).forEach(function(a) { | ||
return _this5._removeItem(a); | ||
}); | ||
} | ||
return true; | ||
} | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.Marquee = undefined; | ||
offsets.push(nextOffset); | ||
nextOffset += item.getSize(); | ||
return false; | ||
}); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
if (this._pendingItem) { | ||
this._$container.appendChild(this._pendingItem.getContainer()); | ||
var _item = __webpack_require__(4); | ||
if (this._rate <= 0) { | ||
if (!this._nextItemImmediatelyFollowsPrevious) { | ||
// insert virtual item so that it starts off screen | ||
this._items.push( | ||
new VirtualItem(Math.max(0, containerSize - nextOffset)) | ||
); | ||
var _direction = __webpack_require__(1); | ||
offsets.push(nextOffset); | ||
nextOffset = containerSize; | ||
} | ||
var _helpers = __webpack_require__(0); | ||
offsets.push(nextOffset); | ||
nextOffset += this._pendingItem.getSize(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
this._items.push(this._pendingItem); | ||
} else { | ||
if ( | ||
!this._nextItemImmediatelyFollowsPrevious && | ||
this._items.length && | ||
this._leftItemOffset > 0 | ||
) { | ||
this._items.unshift(new VirtualItem(this._leftItemOffset)); | ||
var Marquee = exports.Marquee = function () { | ||
function Marquee($container) { | ||
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, | ||
_ref$rate = _ref.rate, | ||
rate = _ref$rate === undefined ? -25 : _ref$rate, | ||
_ref$upDown = _ref.upDown, | ||
upDown = _ref$upDown === undefined ? false : _ref$upDown; | ||
offsets.unshift(0); | ||
this._leftItemOffset = 0; | ||
} | ||
_classCallCheck(this, Marquee); | ||
this._leftItemOffset -= this._pendingItem.getSize(); | ||
offsets.unshift(this._leftItemOffset); | ||
this._rendering = false; | ||
this._waitingForItem = true; | ||
this._nextItemImmediatelyFollowsPrevious = false; | ||
this._rate = rate; | ||
this._direction = upDown ? _direction.DIRECTION.DOWN : _direction.DIRECTION.RIGHT; | ||
this._onItemRequired = []; | ||
this._onItemRemoved = []; | ||
this._onAllItemsRemoved = []; | ||
this._leftItemOffset = 0; | ||
this._containerSize = 0; | ||
this._items = []; | ||
this._pendingItem = null; | ||
var $innerContainer = document.createElement('div'); | ||
$innerContainer.style.position = 'relative'; | ||
$innerContainer.style.display = 'inline-block'; | ||
this._$container = $innerContainer; | ||
this._containerSizeInverse = null; | ||
if (this._direction === _direction.DIRECTION.RIGHT) { | ||
$innerContainer.style.width = '100%'; | ||
} else { | ||
$innerContainer.style.height = '100%'; | ||
} | ||
this._updateContainerSize(); | ||
$container.appendChild($innerContainer); | ||
this._scheduleRender(); | ||
} | ||
this._items.unshift(this._pendingItem); | ||
} | ||
// called when there's room for a new item. | ||
// You can return the item to append next | ||
this._pendingItem = null; | ||
} // trim virtual items | ||
while (this._items[0] instanceof VirtualItem) { | ||
offsets.shift(); | ||
_createClass(Marquee, [{ | ||
key: 'onItemRequired', | ||
value: function onItemRequired(cb) { | ||
this._onItemRequired.push(cb); | ||
} | ||
this._items.shift(); | ||
// Called when an item is removed | ||
this._leftItemOffset = offsets[0] || 0; | ||
} | ||
}, { | ||
key: 'onItemRemoved', | ||
value: function onItemRemoved(cb) { | ||
this._onItemRemoved.push(cb); | ||
} | ||
while (this._items[this._items.length - 1] instanceof VirtualItem) { | ||
offsets.pop(); | ||
// Called when the last item is removed | ||
this._items.pop(); | ||
} | ||
}, { | ||
key: 'onAllItemsRemoved', | ||
value: function onAllItemsRemoved(cb) { | ||
this._onAllItemsRemoved.push(cb); | ||
} | ||
}, { | ||
key: 'getNumItems', | ||
value: function getNumItems() { | ||
return this._items.filter(function (item) { | ||
return item instanceof _item.Item; | ||
}).length; | ||
} | ||
}, { | ||
key: 'setRate', | ||
value: function setRate(rate) { | ||
if (!rate !== !this._rate) { | ||
this._enableAnimationHint(!!rate); | ||
if (rate) { | ||
this._scheduleRender(); | ||
} | ||
} | ||
this._rate = rate; | ||
} | ||
}, { | ||
key: 'getRate', | ||
value: function getRate() { | ||
return this._rate; | ||
} | ||
}, { | ||
key: 'clear', | ||
value: function clear() { | ||
var _this = this; | ||
offsets.forEach(function(offset, i) { | ||
return _this5._items[i].setOffset(offset); | ||
}); | ||
this._items.forEach(function ($a) { | ||
return _this._removeItem($a); | ||
}); | ||
this._items = []; | ||
this._waitingForItem = true; | ||
this._updateContainerSize(); | ||
} | ||
}, { | ||
key: 'isWaitingForItem', | ||
value: function isWaitingForItem() { | ||
return this._waitingForItem; | ||
} | ||
}, { | ||
key: 'appendItem', | ||
value: function appendItem($el) { | ||
if (!this._waitingForItem) { | ||
throw new Error('No room for item.'); | ||
} | ||
// convert to div if $el is a string | ||
$el = (0, _helpers.toDomEl)($el); | ||
var itemAlreadyExists = this._items.some(function (item) { | ||
return item instanceof _item.Item && item.getOriginalEl() === $el; | ||
}); | ||
if (itemAlreadyExists) { | ||
throw new Error('Item already exists.'); | ||
} | ||
this._waitingForItem = false; | ||
this._pendingItem = new _item.Item($el, this._direction, this._rate); | ||
this._pendingItem.enableAnimationHint(!!this._rate); | ||
this._scheduleRender(); | ||
} | ||
}, { | ||
key: '_removeItem', | ||
value: function _removeItem(item) { | ||
var _this2 = this; | ||
this._updateContainerSize(); | ||
(0, _helpers.defer)(function () { | ||
item.remove(); | ||
if (item instanceof _item.Item) { | ||
_this2._onItemRemoved.forEach(function (cb) { | ||
(0, _helpers.deferException)(function () { | ||
return cb(item.getOriginalEl()); | ||
if (!this._items.length) { | ||
this._leftItemOffset = 0; | ||
defer(function() { | ||
_this5._onAllItemsRemoved.forEach(function(cb) { | ||
deferException(function() { | ||
return cb(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
// update size of container so that the marquee items fit inside it. | ||
// This is needed because the items are posisitioned absolutely, so not in normal flow. | ||
// Without this, the height of the container would always be 0px, which is not useful | ||
this._nextItemImmediatelyFollowsPrevious = false; | ||
}, { | ||
key: '_updateContainerSize', | ||
value: function _updateContainerSize() { | ||
var maxSize = this._items.reduce(function (size, item) { | ||
if (item instanceof _item.VirtualItem) { | ||
return size; | ||
} | ||
var a = item.getSize({ inverse: true }); | ||
if (a > size) { | ||
return a; | ||
} | ||
return size; | ||
}, 0); | ||
if (this._containerSizeInverse !== maxSize) { | ||
this._containerSizeInverse = maxSize; | ||
if (this._direction === _direction.DIRECTION.RIGHT) { | ||
this._$container.style.height = maxSize + 'px'; | ||
} else { | ||
this._$container.style.width = maxSize + 'px'; | ||
} | ||
} | ||
} | ||
}, { | ||
key: '_enableAnimationHint', | ||
value: function _enableAnimationHint(enable) { | ||
this._items.forEach(function (item) { | ||
return item.enableAnimationHint(enable); | ||
}); | ||
} | ||
}, { | ||
key: '_scheduleRender', | ||
value: function _scheduleRender() { | ||
var _this3 = this; | ||
if ( | ||
!this._waitingForItem && | ||
((this._rate <= 0 && nextOffset <= containerSize) || | ||
(this._rate > 0 && this._leftItemOffset >= 0)) | ||
) { | ||
this._waitingForItem = true; // if an item is appended immediately below, it would be considered immediately following | ||
// the previous if the item it would follow was appended from the same side | ||
// This is useful when deciding whether to add a separator on the side that enters the | ||
// screen first or not | ||
if (this._rendering) { | ||
// we are already rendering, so call the render method synchronously | ||
this._render(); | ||
} else { | ||
if (!this._requestAnimationID) { | ||
this._lastUpdateTime = performance.now(); | ||
this._requestAnimationID = window.requestAnimationFrame(function () { | ||
return _this3._onRequestAnimationFrame(); | ||
}); | ||
} | ||
} | ||
} | ||
}, { | ||
key: '_onRequestAnimationFrame', | ||
value: function _onRequestAnimationFrame() { | ||
var _this4 = this; | ||
var previousItem = null; | ||
this._requestAnimationID = null; | ||
if (!this._rate || !this._items.length && !this._pendingItem) { | ||
return; | ||
} | ||
if (this._items.length) { | ||
if (this._rate <= 0) { | ||
previousItem = this._items[this._items.length - 1]; | ||
} else { | ||
previousItem = this._items[0]; | ||
} | ||
} | ||
var now = performance.now(); | ||
var timePassed = now - this._lastUpdateTime; | ||
this._scheduleRender(); | ||
this._rendering = true; | ||
var shiftAmount = this._rate * (timePassed / 1000); | ||
this._leftItemOffset += shiftAmount; | ||
this._containerSize = (0, _helpers.size)(this._$container, this._direction); | ||
(0, _helpers.deferException)(function () { | ||
return _this4._render(); | ||
}); | ||
this._rendering = false; | ||
} | ||
}, { | ||
key: '_render', | ||
value: function _render() { | ||
var _this5 = this; | ||
this._nextItemImmediatelyFollowsPrevious = | ||
previousItem && | ||
previousItem.getRateWhenAppended() * this._rate >= 0; | ||
var nextItem; | ||
var containerSize = this._containerSize; | ||
if (this._rate < 0) { | ||
while (this._items.length) { | ||
var item = this._items[0]; | ||
var _size = item.getSize(); | ||
if (this._leftItemOffset + _size > 0) { | ||
break; | ||
this._onItemRequired.some(function(cb) { | ||
return deferException(function() { | ||
nextItem = cb({ | ||
immediatelyFollowsPrevious: | ||
_this5._nextItemImmediatelyFollowsPrevious | ||
}); | ||
return !!nextItem; | ||
}); | ||
}); | ||
if (nextItem) { | ||
// Note appendItem() will call _scheduleRender(), which will synchronously call | ||
// _render() again | ||
this.appendItem(nextItem); | ||
} | ||
this._nextItemImmediatelyFollowsPrevious = false; | ||
} | ||
this._removeItem(this._items[0]); | ||
this._items.shift(); | ||
this._leftItemOffset += _size; | ||
} | ||
} | ||
]); | ||
var offsets = []; | ||
var nextOffset = this._leftItemOffset; | ||
this._items.some(function (item, i) { | ||
if (nextOffset >= containerSize) { | ||
if (_this5._rate > 0) { | ||
_this5._items.splice(i).forEach(function (a) { | ||
return _this5._removeItem(a); | ||
}); | ||
} | ||
return true; | ||
return Marquee; | ||
})(); | ||
var indexMap = function(list) { | ||
var map = {}; | ||
list.forEach(function(each, i) { | ||
map[each] = map[each] || []; | ||
map[each].push(i); | ||
}); | ||
return map; | ||
}; | ||
var longestCommonSubstring = function(seq1, seq2) { | ||
var result = { startString1: 0, startString2: 0, length: 0 }; | ||
var indexMapBefore = indexMap(seq1); | ||
var previousOverlap = []; | ||
seq2.forEach(function(eachAfter, indexAfter) { | ||
var overlapLength; | ||
var overlap = []; | ||
var indexesBefore = indexMapBefore[eachAfter] || []; | ||
indexesBefore.forEach(function(indexBefore) { | ||
overlapLength = | ||
((indexBefore && previousOverlap[indexBefore - 1]) || 0) + 1; | ||
if (overlapLength > result.length) { | ||
result.length = overlapLength; | ||
result.startString1 = indexBefore - overlapLength + 1; | ||
result.startString2 = indexAfter - overlapLength + 1; | ||
} | ||
offsets.push(nextOffset); | ||
nextOffset += item.getSize(); | ||
return false; | ||
overlap[indexBefore] = overlapLength; | ||
}); | ||
previousOverlap = overlap; | ||
}); | ||
return result; | ||
}; | ||
if (this._pendingItem) { | ||
this._$container.appendChild(this._pendingItem.getContainer()); | ||
if (this._rate <= 0) { | ||
if (!this._nextItemImmediatelyFollowsPrevious) { | ||
// insert virtual item so that it starts off screen | ||
this._items.push(new _item.VirtualItem(Math.max(0, containerSize - nextOffset))); | ||
offsets.push(nextOffset); | ||
nextOffset = containerSize; | ||
} | ||
offsets.push(nextOffset); | ||
nextOffset += this._pendingItem.getSize(); | ||
this._items.push(this._pendingItem); | ||
} else { | ||
if (!this._nextItemImmediatelyFollowsPrevious && this._items.length && this._leftItemOffset > 0) { | ||
this._items.unshift(new _item.VirtualItem(this._leftItemOffset)); | ||
offsets.unshift(0); | ||
this._leftItemOffset = 0; | ||
} | ||
this._leftItemOffset -= this._pendingItem.getSize(); | ||
offsets.unshift(this._leftItemOffset); | ||
this._items.unshift(this._pendingItem); | ||
} | ||
this._pendingItem = null; | ||
} | ||
var longestCommonSubstring_1 = longestCommonSubstring; | ||
// trim virtual items | ||
while (this._items[0] instanceof _item.VirtualItem) { | ||
offsets.shift(); | ||
this._items.shift(); | ||
this._leftItemOffset = offsets[0] || 0; | ||
} | ||
while (this._items[this._items.length - 1] instanceof _item.VirtualItem) { | ||
offsets.pop(); | ||
this._items.pop(); | ||
} | ||
function loop(marquee) { | ||
var buildersIn = | ||
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var seperatorBuilder = | ||
arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; | ||
var lastIndex = -1; | ||
var builders = buildersIn.slice(); | ||
offsets.forEach(function (offset, i) { | ||
return _this5._items[i].setOffset(offset); | ||
}); | ||
this._updateContainerSize(); | ||
var getNextBuilder = function getNextBuilder() { | ||
var offset = | ||
arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; | ||
var nextIndex = (lastIndex + offset) % builders.length; | ||
return { | ||
builder: builders[nextIndex], | ||
index: nextIndex | ||
}; | ||
}; | ||
if (!this._items.length) { | ||
this._leftItemOffset = 0; | ||
(0, _helpers.defer)(function () { | ||
_this5._onAllItemsRemoved.forEach(function (cb) { | ||
(0, _helpers.deferException)(function () { | ||
return cb(); | ||
}); | ||
}); | ||
}); | ||
var appendItem = function appendItem(immediatelyFollowsPrevious) { | ||
if (!builders.length || !marquee.isWaitingForItem()) { | ||
return; | ||
} | ||
this._nextItemImmediatelyFollowsPrevious = false; | ||
if (!this._waitingForItem && (this._rate <= 0 && nextOffset <= containerSize || this._rate > 0 && this._leftItemOffset >= 0)) { | ||
this._waitingForItem = true; | ||
// if an item is appended immediately below, it would be considered immediately following | ||
// the previous if the item it would follow was appended from the same side | ||
// This is useful when deciding whether to add a separator on the side that enters the | ||
// screen first or not | ||
var previousItem = null; | ||
if (this._items.length) { | ||
if (this._rate <= 0) { | ||
previousItem = this._items[this._items.length - 1]; | ||
} else { | ||
previousItem = this._items[0]; | ||
} | ||
var _getNextBuilder = getNextBuilder(), | ||
builder = _getNextBuilder.builder, | ||
index = _getNextBuilder.index; | ||
lastIndex = index; | ||
var $item = toDomEl(builder()); | ||
if (immediatelyFollowsPrevious && seperatorBuilder) { | ||
var $seperator = toDomEl(seperatorBuilder()); | ||
var $container = document.createElement('div'); | ||
$seperator.style.display = 'inline'; | ||
$item.style.display = 'inline'; | ||
if (marquee.getRate() <= 0) { | ||
$container.appendChild($seperator); | ||
$container.appendChild($item); | ||
} else { | ||
$container.appendChild($item); | ||
$container.appendChild($seperator); | ||
} | ||
this._nextItemImmediatelyFollowsPrevious = previousItem && previousItem.getRateWhenAppended() * this._rate >= 0; | ||
var nextItem = void 0; | ||
this._onItemRequired.some(function (cb) { | ||
return (0, _helpers.deferException)(function () { | ||
nextItem = cb({ immediatelyFollowsPrevious: _this5._nextItemImmediatelyFollowsPrevious }); | ||
return !!nextItem; | ||
}); | ||
}); | ||
if (nextItem) { | ||
// Note appendItem() will call _scheduleRender(), which will synchronously call | ||
// _render() again | ||
this.appendItem(nextItem); | ||
} | ||
this._nextItemImmediatelyFollowsPrevious = false; | ||
$item = $container; | ||
} | ||
} | ||
}]); | ||
return Marquee; | ||
}(); | ||
marquee.appendItem($item); | ||
}; | ||
/***/ }), | ||
/* 6 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
marquee.onItemRequired(function(_ref) { | ||
var immediatelyFollowsPrevious = _ref.immediatelyFollowsPrevious; | ||
return appendItem(immediatelyFollowsPrevious); | ||
}); | ||
appendItem(); | ||
return { | ||
update: function update(newBuilders) { | ||
// try and start from somewhere that makes sense | ||
var calculateNewIndex = function calculateNewIndex() { | ||
// convert array of function references to array of ids | ||
var buildersStructure = builders.map(function(b, i) { | ||
var prevIndex = builders.indexOf(b); // if already seen builder, give it the same number | ||
"use strict"; | ||
return prevIndex < i ? prevIndex : i; | ||
}); | ||
var newBuildersStructure = newBuilders.map(function(b, i) { | ||
// matching indexes where they exist, and -1 for all unknown | ||
return builders.indexOf(b); | ||
}); | ||
var _longestSubstring = longestCommonSubstring_1( | ||
buildersStructure, | ||
newBuildersStructure | ||
), | ||
startString1 = _longestSubstring.startString1, | ||
startString2 = _longestSubstring.startString2, | ||
length = _longestSubstring.length; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
if (lastIndex >= startString1 && lastIndex < startString1 + length) { | ||
// we are in the overlapping region | ||
return lastIndex + (startString2 - startString1); | ||
} | ||
var _marquee = __webpack_require__(5); | ||
return -1; | ||
}; | ||
Object.defineProperty(exports, 'Marquee', { | ||
enumerable: true, | ||
get: function get() { | ||
return _marquee.Marquee; | ||
lastIndex = calculateNewIndex(); | ||
builders = newBuilders.slice(); | ||
appendItem(false); | ||
} | ||
}; | ||
} | ||
}); | ||
var _loop = __webpack_require__(3); | ||
exports.Marquee = Marquee; | ||
exports.loop = loop; | ||
Object.defineProperty(exports, 'loop', { | ||
enumerable: true, | ||
get: function get() { | ||
return _loop.loop; | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}); | ||
/***/ }) | ||
/******/ ]); | ||
}); |
{ | ||
"name": "dynamic-marquee", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"description": "A small library for creating marquees.", | ||
"main": "./dist/dynamic-marquee.js", | ||
"scripts": { | ||
"build": "webpack", | ||
"lint": "eslint ./src/**/*.js", | ||
"lintFix": "eslint --fix ./src/**/*.js" | ||
"build": "rollup --config rollup.config.js", | ||
"watch": "rollup --config rollup.config.js --watch", | ||
"prettier": "prettier --write **/*.{js,md}", | ||
"preversion": "npm run build" | ||
}, | ||
"files": [ | ||
"dist/**/*" | ||
], | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "npm run lint" | ||
"pre-commit": "npm run prettier" | ||
} | ||
@@ -34,11 +38,12 @@ }, | ||
"devDependencies": { | ||
"babel-core": "^6.26.0", | ||
"babel-loader": "^7.1.4", | ||
"babel-preset-env": "^1.6.1", | ||
"eslint": "^4.19.1", | ||
"husky": "^0.14.3", | ||
"@babel/core": "^7.8.7", | ||
"@babel/preset-env": "^7.8.7", | ||
"@rollup/plugin-commonjs": "^11.0.2", | ||
"@rollup/plugin-node-resolve": "^7.1.1", | ||
"husky": "^4.2.3", | ||
"longest-common-substring": "0.0.1", | ||
"webpack": "^4.6.0", | ||
"webpack-cli": "^2.0.15" | ||
"prettier": "^1.19.1", | ||
"rollup": "^2.0.6", | ||
"rollup-plugin-babel": "^4.4.0" | ||
} | ||
} |
[![npm version](https://badge.fury.io/js/dynamic-marquee.svg)](https://badge.fury.io/js/dynamic-marquee) | ||
# Dynamic Marquee | ||
A small library for creating marquees. | ||
Features: | ||
- You can change the rate on the fly. | ||
@@ -15,2 +18,3 @@ - Direction can either be up/down or right/left. | ||
# Demo | ||
View the demo [here](https://tjenkinson.github.io/dynamic-marquee/demo.html). | ||
@@ -21,11 +25,18 @@ | ||
# Installation | ||
``` | ||
npm install --save dynamic-marquee | ||
``` | ||
```js | ||
import { Marquee } from 'dynamic-marquee'; | ||
``` | ||
or | ||
```html | ||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/dynamic-marquee@1"></script> | ||
<script | ||
type="text/javascript" | ||
src="https://cdn.jsdelivr.net/npm/dynamic-marquee@1" | ||
></script> | ||
<script type="text/javascript"> | ||
@@ -35,7 +46,11 @@ const Marquee = dynamicMarquee.Marquee; | ||
``` | ||
thanks to [jsDelivr](https://github.com/jsdelivr/jsdelivr). | ||
# Usage | ||
## Construct Marquee Instance | ||
### With Default Options | ||
```js | ||
@@ -46,2 +61,3 @@ const marquee = new Marquee(document.getElementById('marquee')); | ||
### With Custom Options | ||
```js | ||
@@ -55,5 +71,7 @@ const marquee = new Marquee(document.getElementById('marquee'), { | ||
## Append Item | ||
You can add DOM elements, or just a string (which will automatically be wrapped in a div). | ||
**Each DOM element is only allowed on the marquee at one time.** | ||
```js | ||
@@ -66,2 +84,3 @@ const $item = document.createElement('div'); | ||
You are only allowed to append an item when there is room. You can check this like so: | ||
```js | ||
@@ -74,2 +93,3 @@ if (marquee.isWaitingForItem()) { | ||
You can be notified when an item is required with | ||
```js | ||
@@ -86,2 +106,3 @@ marquee.onItemRequired(({ immediatelyFollowsPrevious }) => { | ||
``` | ||
**Do not perform any long running tasks in this method as it will block rendering.** | ||
@@ -92,3 +113,5 @@ | ||
## Change the scroll rate? (px/s) | ||
You can change the rate at any time, and set to 0 to pause. | ||
```js | ||
@@ -99,3 +122,5 @@ marquee.setRate(-20); | ||
## Reset | ||
To remove all items call | ||
```js | ||
@@ -106,5 +131,7 @@ marquee.clear(); | ||
## When has an item been removed? | ||
You can be notified when an item has been removed with: | ||
```js | ||
marquee.onItemRemove(($el) => { | ||
marquee.onItemRemove($el => { | ||
// $el has just been removed | ||
@@ -115,3 +142,5 @@ }); | ||
## When have all items finished scrolling? | ||
You can be notified when the scroller is empty with: | ||
```js | ||
@@ -122,3 +151,5 @@ marquee.onAllItemsRemoved(() => { | ||
``` | ||
You can check at any time with: | ||
```js | ||
@@ -129,2 +160,3 @@ marquee.getNumItems(); | ||
# Loop | ||
A `loop()` function is provided for making looping content simple. | ||
@@ -139,12 +171,6 @@ | ||
const marquee = new Marquee($marquee); | ||
const control = loop(marquee, [ | ||
() => 'item 1', | ||
() => 'item 2' | ||
]); | ||
const control = loop(marquee, [() => 'item 1', () => 'item 2']); | ||
// later | ||
control.update([ | ||
() => 'new item 1', | ||
() => 'new item 2' | ||
]) | ||
control.update([() => 'new item 1', () => 'new item 2']); | ||
``` |
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
162
37724
9
4
629
1