diff --git a/README.md b/README.md
index edcede0..d1c65da 100644
--- a/README.md
+++ b/README.md
@@ -136,11 +136,13 @@ Some additional attributes are available to allow both of those cases, overridin
```
- `data-cartapus-threshold` : overrides the `threshold` option. *Ie : this element will be visible when 50% of its height is visible.*
+- `data-cartapus-root-margin` : overrides the `rootMargin` option. *Ie : the bottom bounding box of this element will be shrunk of 200px.*
- `data-cartapus-once` : overrides the `once` option. *Ie : this element will switch to `visible`, then never switch back to `hidden` again.*
## Methods
diff --git a/build/cartapus.js b/build/cartapus.js
index b1aa00b..fa37c94 100644
--- a/build/cartapus.js
+++ b/build/cartapus.js
@@ -1,2 +1,2 @@
-function t(e,r){return t=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},t(e,r)}function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[s++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(){}n.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function s(){n.off(t,s),e.apply(r,arguments)}return s._=e,this.on(t,s,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,s=r.length;nt.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(){}n.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function o(){n.off(t,o),e.apply(r,arguments)}return o._=e,this.on(t,o,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,o=r.length;n\r\n */\r\n\r\nimport Emitter from 'tiny-emitter'\r\n\r\n/**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @class\r\n */\r\nexport default class Cartapus extends Emitter {\r\n\r\n /**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @constructor\r\n */\r\n constructor(options = {}) {\r\n super()\r\n\r\n // Bind callback method.\r\n this.intersect = this.intersect.bind(this)\r\n\r\n // Set user options based on default options.\r\n const defaults = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0,\r\n once: false,\r\n events: true\r\n }\r\n\r\n this.options = Object.assign(defaults, options)\r\n\r\n // Creates the default observer then start.\r\n this.createMainObserver()\r\n this.init()\r\n }\r\n\r\n /**\r\n * Creates the main IntersectionObserver used with the default options.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createMainObserver() {\r\n this.observers = [{\r\n observer: new IntersectionObserver(this.intersect, this.options),\r\n threshold: this.options.threshold,\r\n elements: []\r\n }]\r\n }\r\n\r\n /**\r\n * Initialization method, starts the IntersectionObservers.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n init() {\r\n this.getElems()\r\n this.createObservers()\r\n this.observe()\r\n }\r\n\r\n /**\r\n * Gets the [data-cartapus] elements from root element.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n getElems() {\r\n const root = this.options.root === null ? document : this.options.root\r\n\r\n this.elems = root.querySelectorAll('[data-cartapus]')\r\n }\r\n\r\n /**\r\n * For each [data-cartapus] element, check its inner data-cartapus parameters\r\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createObservers() {\r\n for (const el of this.elems) {\r\n // If element has data-cartapus-threshold attribute.\r\n if (el.dataset.cartapusThreshold) {\r\n const threshold = parseFloat(el.dataset.cartapusThreshold)\r\n let found = false\r\n\r\n // If an observer already exists with the same threshold, add element to this observer.\r\n for (const observer of this.observers) {\r\n if (threshold === observer.threshold) {\r\n found = true\r\n\r\n observer.elements.push(el)\r\n }\r\n }\r\n\r\n // If no observer has the same threshold, create a new one with the new threshold.\r\n if (!found) {\r\n const observer = {\r\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold })),\r\n threshold,\r\n elements: [el]\r\n }\r\n\r\n this.observers.push(observer)\r\n }\r\n } else this.observers[0].elements.push(el)\r\n }\r\n }\r\n\r\n /**\r\n * Callback function triggered by the observers.\r\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\r\n * Triggers the custom events if the `events` option is enabled.\r\n *\r\n * @param {array.} entries — An array of entries that intersected with the root.\r\n * @param {IntersectionObserver} observer — The observer that triggered the event.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n intersect(entries, observer) {\r\n entries.forEach((entry) => {\r\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\r\n if (entry.isIntersecting) {\r\n entry.target.dataset.cartapus = 'visible'\r\n\r\n // Stop observing this element if \"once\" options it true.\r\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\r\n } else entry.target.dataset.cartapus = 'hidden'\r\n\r\n if (this.options.events) this.dispatch(entry)\r\n })\r\n }\r\n\r\n /**\r\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\r\n * Also triggers an `intersect` event on the class instance.\r\n *\r\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n dispatch(entry) {\r\n // Create event with details.\r\n const detail = {\r\n element: entry.target,\r\n visible: entry.isIntersecting,\r\n intersection: entry\r\n }\r\n const event = new CustomEvent('cartapusintersect', { detail })\r\n\r\n // Dispatch element and instance events.\r\n entry.target.dispatchEvent(event)\r\n this.emit('intersect', detail)\r\n }\r\n\r\n /**\r\n * Turns on all the observers to watch all of their related targets.\r\n *\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n observe() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.observe(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off all the observers to stop watching all of their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n unobserve() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.unobserve(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off observers and empty their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n destroy() {\r\n this.unobserve()\r\n\r\n this.observers.forEach((observer) => {\r\n observer.elements = []\r\n })\r\n }\r\n\r\n /**\r\n * Resets everything.\r\n * Turns off observers and resets their targets.\r\n * Then calls `this.init()` to restart everything with new elements to observe.\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n reset() {\r\n this.destroy()\r\n this.init()\r\n }\r\n}\r\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","_Emitter","Cartapus","options","_this","intersect","bind","_assertThisInitialized","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","Emitter","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","_step","_iterator","_createForOfIteratorHelperLoose","done","el","dataset","cartapusThreshold","_step2","parseFloat","found","_iterator2","entries","_this2","forEach","entry","isIntersecting","target","cartapus","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"cartapus.js","sources":["../node_modules/tiny-emitter/index.js","../src/cartapus.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n","/**\n * @file Cartapus core file, dispatches events based on [data-cartapus] elements' visibility in the viewport.\n * @author Jordan Thiervoz \n */\n\nimport Emitter from 'tiny-emitter'\n\n/**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @class\n */\nexport default class Cartapus extends Emitter {\n\n /**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @constructor\n */\n constructor(options = {}) {\n super()\n\n // Bind callback method.\n this.intersect = this.intersect.bind(this)\n\n // Set user options based on default options.\n const defaults = {\n root: null,\n rootMargin: '0px',\n threshold: 0,\n once: false,\n events: true\n }\n\n this.options = Object.assign(defaults, options)\n\n // Creates the default observer then start.\n this.createMainObserver()\n this.init()\n }\n\n /**\n * Creates the main IntersectionObserver used with the default options.\n *\n * @private\n * @returns {void}\n */\n createMainObserver() {\n this.observers = [{\n observer: new IntersectionObserver(this.intersect, this.options),\n threshold: this.options.threshold,\n rootMargin: this.options.rootMargin,\n elements: []\n }]\n }\n\n /**\n * Initialization method, starts the IntersectionObservers.\n *\n * @private\n * @returns {void}\n */\n init() {\n this.getElems()\n this.createObservers()\n this.observe()\n }\n\n /**\n * Gets the [data-cartapus] elements from root element.\n *\n * @private\n * @returns {void}\n */\n getElems() {\n const root = this.options.root === null ? document : this.options.root\n\n this.elems = root.querySelectorAll('[data-cartapus]')\n }\n\n /**\n * For each [data-cartapus] element, check its inner data-cartapus parameters\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\n *\n * @private\n * @returns {void}\n */\n createObservers() {\n for (const el of this.elems) {\n // If element has data-cartapus-threshold attribute.\n if (el.dataset.cartapusThreshold || el.dataset.cartapusRootMargin) {\n const threshold = el.dataset.cartapusThreshold ? parseFloat(el.dataset.cartapusThreshold) : this.options.threshold\n const rootMargin = el.dataset.cartapusRootMargin ? el.dataset.cartapusRootMargin : this.options.rootMargin\n let found = false\n\n // If an observer already exists with the same threshold & the same rootMargin, add element to this observer.\n for (const observer of this.observers) {\n if (threshold === observer.threshold && rootMargin === observer.rootMargin) {\n found = true\n\n observer.elements.push(el)\n }\n }\n\n // If no observer has the same threshold & rootMargin, create a new one with the new options.\n if (!found) {\n const observer = {\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold, rootMargin })),\n threshold,\n rootMargin,\n elements: [el]\n }\n\n this.observers.push(observer)\n }\n } else this.observers[0].elements.push(el)\n }\n }\n\n /**\n * Callback function triggered by the observers.\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\n * Triggers the custom events if the `events` option is enabled.\n *\n * @param {array.} entries — An array of entries that intersected with the root.\n * @param {IntersectionObserver} observer — The observer that triggered the event.\n *\n * @private\n * @returns {void}\n */\n intersect(entries, observer) {\n entries.forEach((entry) => {\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\n if (entry.isIntersecting) {\n entry.target.dataset.cartapus = 'visible'\n\n // Stop observing this element if \"once\" options it true.\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\n } else entry.target.dataset.cartapus = 'hidden'\n\n if (this.options.events) this.dispatch(entry)\n })\n }\n\n /**\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\n * Also triggers an `intersect` event on the class instance.\n *\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\n *\n * @private\n * @returns {void}\n */\n dispatch(entry) {\n // Create event with details.\n const detail = {\n element: entry.target,\n visible: entry.isIntersecting,\n intersection: entry\n }\n const event = new CustomEvent('cartapusintersect', { detail })\n\n // Dispatch element and instance events.\n entry.target.dispatchEvent(event)\n this.emit('intersect', detail)\n }\n\n /**\n * Turns on all the observers to watch all of their related targets.\n *\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n observe() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.observe(el)\n })\n })\n }\n\n /**\n * Turns off all the observers to stop watching all of their related targets.\n *\n * @public\n * @returns {void}\n */\n unobserve() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.unobserve(el)\n })\n })\n }\n\n /**\n * Turns off observers and empty their related targets.\n *\n * @public\n * @returns {void}\n */\n destroy() {\n this.unobserve()\n\n this.observers.forEach((observer) => {\n observer.elements = []\n })\n }\n\n /**\n * Resets everything.\n * Turns off observers and resets their targets.\n * Then calls `this.init()` to restart everything with new elements to observe.\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n reset() {\n this.destroy()\n this.init()\n }\n}\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","options","_this","_Emitter","intersect","bind","_assertThisInitialized","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","Emitter","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","_iterator","_createForOfIteratorHelperLoose","el","_step","value","dataset","cartapusThreshold","cartapusRootMargin","parseFloat","found","_iterator2","_step2","entries","forEach","entry","isIntersecting","target","cartapus","_this2","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
diff --git a/build/cartapus.modern.js b/build/cartapus.modern.js
index 198cde3..e6fd905 100644
--- a/build/cartapus.modern.js
+++ b/build/cartapus.modern.js
@@ -1,2 +1,2 @@
-function e(){}e.prototype={on:function(e,t,s){var r=this.e||(this.e={});return(r[e]||(r[e]=[])).push({fn:t,ctx:s}),this},once:function(e,t,s){var r=this;function i(){r.off(e,i),t.apply(s,arguments)}return i._=t,this.on(e,i,s)},emit:function(e){for(var t=[].slice.call(arguments,1),s=((this.e||(this.e={}))[e]||[]).slice(),r=0,i=s.length;r{e.isIntersecting?(e.target.dataset.cartapus="visible",this.options.once&&"false"!==e.target.dataset.cartapusOnce&&t.unobserve(e.target)):e.target.dataset.cartapus="hidden",this.options.events&&this.dispatch(e)})}dispatch(e){const t={element:e.target,visible:e.isIntersecting,intersection:e},s=new CustomEvent("cartapusintersect",{detail:t});e.target.dispatchEvent(s),this.emit("intersect",t)}observe(){this.observers.forEach(e=>{e.elements.forEach(t=>{e.observer.observe(t)})})}unobserve(){this.observers.forEach(e=>{e.elements.forEach(t=>{e.observer.unobserve(t)})})}destroy(){this.unobserve(),this.observers.forEach(e=>{e.elements=[]})}reset(){this.destroy(),this.init()}}export{s as default};
+function t(){}t.prototype={on:function(t,e,s){var r=this.e||(this.e={});return(r[t]||(r[t]=[])).push({fn:e,ctx:s}),this},once:function(t,e,s){var r=this;function o(){r.off(t,o),e.apply(s,arguments)}return o._=e,this.on(t,o,s)},emit:function(t){for(var e=[].slice.call(arguments,1),s=((this.e||(this.e={}))[t]||[]).slice(),r=0,o=s.length;r{t.isIntersecting?(t.target.dataset.cartapus="visible",this.options.once&&"false"!==t.target.dataset.cartapusOnce&&e.unobserve(t.target)):t.target.dataset.cartapus="hidden",this.options.events&&this.dispatch(t)})}dispatch(t){const e={element:t.target,visible:t.isIntersecting,intersection:t},s=new CustomEvent("cartapusintersect",{detail:e});t.target.dispatchEvent(s),this.emit("intersect",e)}observe(){this.observers.forEach(t=>{t.elements.forEach(e=>{t.observer.observe(e)})})}unobserve(){this.observers.forEach(t=>{t.elements.forEach(e=>{t.observer.unobserve(e)})})}destroy(){this.unobserve(),this.observers.forEach(t=>{t.elements=[]})}reset(){this.destroy(),this.init()}}export{s as default};
//# sourceMappingURL=cartapus.modern.js.map
diff --git a/build/cartapus.modern.js.map b/build/cartapus.modern.js.map
index bb2b4df..501d89f 100644
--- a/build/cartapus.modern.js.map
+++ b/build/cartapus.modern.js.map
@@ -1 +1 @@
-{"version":3,"file":"cartapus.modern.js","sources":["../node_modules/tiny-emitter/index.js","../src/cartapus.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n","/**\r\n * @file Cartapus core file, dispatches events based on [data-cartapus] elements' visibility in the viewport.\r\n * @author Jordan Thiervoz \r\n */\r\n\r\nimport Emitter from 'tiny-emitter'\r\n\r\n/**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @class\r\n */\r\nexport default class Cartapus extends Emitter {\r\n\r\n /**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @constructor\r\n */\r\n constructor(options = {}) {\r\n super()\r\n\r\n // Bind callback method.\r\n this.intersect = this.intersect.bind(this)\r\n\r\n // Set user options based on default options.\r\n const defaults = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0,\r\n once: false,\r\n events: true\r\n }\r\n\r\n this.options = Object.assign(defaults, options)\r\n\r\n // Creates the default observer then start.\r\n this.createMainObserver()\r\n this.init()\r\n }\r\n\r\n /**\r\n * Creates the main IntersectionObserver used with the default options.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createMainObserver() {\r\n this.observers = [{\r\n observer: new IntersectionObserver(this.intersect, this.options),\r\n threshold: this.options.threshold,\r\n elements: []\r\n }]\r\n }\r\n\r\n /**\r\n * Initialization method, starts the IntersectionObservers.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n init() {\r\n this.getElems()\r\n this.createObservers()\r\n this.observe()\r\n }\r\n\r\n /**\r\n * Gets the [data-cartapus] elements from root element.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n getElems() {\r\n const root = this.options.root === null ? document : this.options.root\r\n\r\n this.elems = root.querySelectorAll('[data-cartapus]')\r\n }\r\n\r\n /**\r\n * For each [data-cartapus] element, check its inner data-cartapus parameters\r\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createObservers() {\r\n for (const el of this.elems) {\r\n // If element has data-cartapus-threshold attribute.\r\n if (el.dataset.cartapusThreshold) {\r\n const threshold = parseFloat(el.dataset.cartapusThreshold)\r\n let found = false\r\n\r\n // If an observer already exists with the same threshold, add element to this observer.\r\n for (const observer of this.observers) {\r\n if (threshold === observer.threshold) {\r\n found = true\r\n\r\n observer.elements.push(el)\r\n }\r\n }\r\n\r\n // If no observer has the same threshold, create a new one with the new threshold.\r\n if (!found) {\r\n const observer = {\r\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold })),\r\n threshold,\r\n elements: [el]\r\n }\r\n\r\n this.observers.push(observer)\r\n }\r\n } else this.observers[0].elements.push(el)\r\n }\r\n }\r\n\r\n /**\r\n * Callback function triggered by the observers.\r\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\r\n * Triggers the custom events if the `events` option is enabled.\r\n *\r\n * @param {array.} entries — An array of entries that intersected with the root.\r\n * @param {IntersectionObserver} observer — The observer that triggered the event.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n intersect(entries, observer) {\r\n entries.forEach((entry) => {\r\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\r\n if (entry.isIntersecting) {\r\n entry.target.dataset.cartapus = 'visible'\r\n\r\n // Stop observing this element if \"once\" options it true.\r\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\r\n } else entry.target.dataset.cartapus = 'hidden'\r\n\r\n if (this.options.events) this.dispatch(entry)\r\n })\r\n }\r\n\r\n /**\r\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\r\n * Also triggers an `intersect` event on the class instance.\r\n *\r\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n dispatch(entry) {\r\n // Create event with details.\r\n const detail = {\r\n element: entry.target,\r\n visible: entry.isIntersecting,\r\n intersection: entry\r\n }\r\n const event = new CustomEvent('cartapusintersect', { detail })\r\n\r\n // Dispatch element and instance events.\r\n entry.target.dispatchEvent(event)\r\n this.emit('intersect', detail)\r\n }\r\n\r\n /**\r\n * Turns on all the observers to watch all of their related targets.\r\n *\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n observe() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.observe(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off all the observers to stop watching all of their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n unobserve() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.unobserve(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off observers and empty their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n destroy() {\r\n this.unobserve()\r\n\r\n this.observers.forEach((observer) => {\r\n observer.elements = []\r\n })\r\n }\r\n\r\n /**\r\n * Resets everything.\r\n * Turns off observers and resets their targets.\r\n * Then calls `this.init()` to restart everything with new elements to observe.\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n reset() {\r\n this.destroy()\r\n this.init()\r\n }\r\n}\r\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","Cartapus","Emitter","constructor","options","super","intersect","bind","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","el","dataset","cartapusThreshold","parseFloat","found","entries","forEach","entry","isIntersecting","target","cartapus","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"cartapus.modern.js","sources":["../node_modules/tiny-emitter/index.js","../src/cartapus.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n","/**\n * @file Cartapus core file, dispatches events based on [data-cartapus] elements' visibility in the viewport.\n * @author Jordan Thiervoz \n */\n\nimport Emitter from 'tiny-emitter'\n\n/**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @class\n */\nexport default class Cartapus extends Emitter {\n\n /**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @constructor\n */\n constructor(options = {}) {\n super()\n\n // Bind callback method.\n this.intersect = this.intersect.bind(this)\n\n // Set user options based on default options.\n const defaults = {\n root: null,\n rootMargin: '0px',\n threshold: 0,\n once: false,\n events: true\n }\n\n this.options = Object.assign(defaults, options)\n\n // Creates the default observer then start.\n this.createMainObserver()\n this.init()\n }\n\n /**\n * Creates the main IntersectionObserver used with the default options.\n *\n * @private\n * @returns {void}\n */\n createMainObserver() {\n this.observers = [{\n observer: new IntersectionObserver(this.intersect, this.options),\n threshold: this.options.threshold,\n rootMargin: this.options.rootMargin,\n elements: []\n }]\n }\n\n /**\n * Initialization method, starts the IntersectionObservers.\n *\n * @private\n * @returns {void}\n */\n init() {\n this.getElems()\n this.createObservers()\n this.observe()\n }\n\n /**\n * Gets the [data-cartapus] elements from root element.\n *\n * @private\n * @returns {void}\n */\n getElems() {\n const root = this.options.root === null ? document : this.options.root\n\n this.elems = root.querySelectorAll('[data-cartapus]')\n }\n\n /**\n * For each [data-cartapus] element, check its inner data-cartapus parameters\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\n *\n * @private\n * @returns {void}\n */\n createObservers() {\n for (const el of this.elems) {\n // If element has data-cartapus-threshold attribute.\n if (el.dataset.cartapusThreshold || el.dataset.cartapusRootMargin) {\n const threshold = el.dataset.cartapusThreshold ? parseFloat(el.dataset.cartapusThreshold) : this.options.threshold\n const rootMargin = el.dataset.cartapusRootMargin ? el.dataset.cartapusRootMargin : this.options.rootMargin\n let found = false\n\n // If an observer already exists with the same threshold & the same rootMargin, add element to this observer.\n for (const observer of this.observers) {\n if (threshold === observer.threshold && rootMargin === observer.rootMargin) {\n found = true\n\n observer.elements.push(el)\n }\n }\n\n // If no observer has the same threshold & rootMargin, create a new one with the new options.\n if (!found) {\n const observer = {\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold, rootMargin })),\n threshold,\n rootMargin,\n elements: [el]\n }\n\n this.observers.push(observer)\n }\n } else this.observers[0].elements.push(el)\n }\n }\n\n /**\n * Callback function triggered by the observers.\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\n * Triggers the custom events if the `events` option is enabled.\n *\n * @param {array.} entries — An array of entries that intersected with the root.\n * @param {IntersectionObserver} observer — The observer that triggered the event.\n *\n * @private\n * @returns {void}\n */\n intersect(entries, observer) {\n entries.forEach((entry) => {\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\n if (entry.isIntersecting) {\n entry.target.dataset.cartapus = 'visible'\n\n // Stop observing this element if \"once\" options it true.\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\n } else entry.target.dataset.cartapus = 'hidden'\n\n if (this.options.events) this.dispatch(entry)\n })\n }\n\n /**\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\n * Also triggers an `intersect` event on the class instance.\n *\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\n *\n * @private\n * @returns {void}\n */\n dispatch(entry) {\n // Create event with details.\n const detail = {\n element: entry.target,\n visible: entry.isIntersecting,\n intersection: entry\n }\n const event = new CustomEvent('cartapusintersect', { detail })\n\n // Dispatch element and instance events.\n entry.target.dispatchEvent(event)\n this.emit('intersect', detail)\n }\n\n /**\n * Turns on all the observers to watch all of their related targets.\n *\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n observe() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.observe(el)\n })\n })\n }\n\n /**\n * Turns off all the observers to stop watching all of their related targets.\n *\n * @public\n * @returns {void}\n */\n unobserve() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.unobserve(el)\n })\n })\n }\n\n /**\n * Turns off observers and empty their related targets.\n *\n * @public\n * @returns {void}\n */\n destroy() {\n this.unobserve()\n\n this.observers.forEach((observer) => {\n observer.elements = []\n })\n }\n\n /**\n * Resets everything.\n * Turns off observers and resets their targets.\n * Then calls `this.init()` to restart everything with new elements to observe.\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n reset() {\n this.destroy()\n this.init()\n }\n}\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","Cartapus","Emitter","constructor","options","super","intersect","bind","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","el","dataset","cartapusThreshold","cartapusRootMargin","parseFloat","found","entries","forEach","entry","isIntersecting","target","cartapus","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
diff --git a/build/cartapus.module.js b/build/cartapus.module.js
index 232c42e..ef1421b 100644
--- a/build/cartapus.module.js
+++ b/build/cartapus.module.js
@@ -1,2 +1,2 @@
-function t(e,r){return t=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},t(e,r)}function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[s++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(){}n.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function s(){n.off(t,s),e.apply(r,arguments)}return s._=e,this.on(t,s,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,s=r.length;nt.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(){}n.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function o(){n.off(t,o),e.apply(r,arguments)}return o._=e,this.on(t,o,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,o=r.length;n\r\n */\r\n\r\nimport Emitter from 'tiny-emitter'\r\n\r\n/**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @class\r\n */\r\nexport default class Cartapus extends Emitter {\r\n\r\n /**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @constructor\r\n */\r\n constructor(options = {}) {\r\n super()\r\n\r\n // Bind callback method.\r\n this.intersect = this.intersect.bind(this)\r\n\r\n // Set user options based on default options.\r\n const defaults = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0,\r\n once: false,\r\n events: true\r\n }\r\n\r\n this.options = Object.assign(defaults, options)\r\n\r\n // Creates the default observer then start.\r\n this.createMainObserver()\r\n this.init()\r\n }\r\n\r\n /**\r\n * Creates the main IntersectionObserver used with the default options.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createMainObserver() {\r\n this.observers = [{\r\n observer: new IntersectionObserver(this.intersect, this.options),\r\n threshold: this.options.threshold,\r\n elements: []\r\n }]\r\n }\r\n\r\n /**\r\n * Initialization method, starts the IntersectionObservers.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n init() {\r\n this.getElems()\r\n this.createObservers()\r\n this.observe()\r\n }\r\n\r\n /**\r\n * Gets the [data-cartapus] elements from root element.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n getElems() {\r\n const root = this.options.root === null ? document : this.options.root\r\n\r\n this.elems = root.querySelectorAll('[data-cartapus]')\r\n }\r\n\r\n /**\r\n * For each [data-cartapus] element, check its inner data-cartapus parameters\r\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createObservers() {\r\n for (const el of this.elems) {\r\n // If element has data-cartapus-threshold attribute.\r\n if (el.dataset.cartapusThreshold) {\r\n const threshold = parseFloat(el.dataset.cartapusThreshold)\r\n let found = false\r\n\r\n // If an observer already exists with the same threshold, add element to this observer.\r\n for (const observer of this.observers) {\r\n if (threshold === observer.threshold) {\r\n found = true\r\n\r\n observer.elements.push(el)\r\n }\r\n }\r\n\r\n // If no observer has the same threshold, create a new one with the new threshold.\r\n if (!found) {\r\n const observer = {\r\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold })),\r\n threshold,\r\n elements: [el]\r\n }\r\n\r\n this.observers.push(observer)\r\n }\r\n } else this.observers[0].elements.push(el)\r\n }\r\n }\r\n\r\n /**\r\n * Callback function triggered by the observers.\r\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\r\n * Triggers the custom events if the `events` option is enabled.\r\n *\r\n * @param {array.} entries — An array of entries that intersected with the root.\r\n * @param {IntersectionObserver} observer — The observer that triggered the event.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n intersect(entries, observer) {\r\n entries.forEach((entry) => {\r\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\r\n if (entry.isIntersecting) {\r\n entry.target.dataset.cartapus = 'visible'\r\n\r\n // Stop observing this element if \"once\" options it true.\r\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\r\n } else entry.target.dataset.cartapus = 'hidden'\r\n\r\n if (this.options.events) this.dispatch(entry)\r\n })\r\n }\r\n\r\n /**\r\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\r\n * Also triggers an `intersect` event on the class instance.\r\n *\r\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n dispatch(entry) {\r\n // Create event with details.\r\n const detail = {\r\n element: entry.target,\r\n visible: entry.isIntersecting,\r\n intersection: entry\r\n }\r\n const event = new CustomEvent('cartapusintersect', { detail })\r\n\r\n // Dispatch element and instance events.\r\n entry.target.dispatchEvent(event)\r\n this.emit('intersect', detail)\r\n }\r\n\r\n /**\r\n * Turns on all the observers to watch all of their related targets.\r\n *\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n observe() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.observe(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off all the observers to stop watching all of their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n unobserve() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.unobserve(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off observers and empty their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n destroy() {\r\n this.unobserve()\r\n\r\n this.observers.forEach((observer) => {\r\n observer.elements = []\r\n })\r\n }\r\n\r\n /**\r\n * Resets everything.\r\n * Turns off observers and resets their targets.\r\n * Then calls `this.init()` to restart everything with new elements to observe.\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n reset() {\r\n this.destroy()\r\n this.init()\r\n }\r\n}\r\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","Cartapus","_Emitter","options","_this","intersect","bind","_assertThisInitialized","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","Emitter","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","_step","_iterator","_createForOfIteratorHelperLoose","done","el","dataset","cartapusThreshold","_step2","parseFloat","found","_iterator2","entries","_this2","forEach","entry","isIntersecting","target","cartapus","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"cartapus.module.js","sources":["../node_modules/tiny-emitter/index.js","../src/cartapus.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n","/**\n * @file Cartapus core file, dispatches events based on [data-cartapus] elements' visibility in the viewport.\n * @author Jordan Thiervoz \n */\n\nimport Emitter from 'tiny-emitter'\n\n/**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @class\n */\nexport default class Cartapus extends Emitter {\n\n /**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @constructor\n */\n constructor(options = {}) {\n super()\n\n // Bind callback method.\n this.intersect = this.intersect.bind(this)\n\n // Set user options based on default options.\n const defaults = {\n root: null,\n rootMargin: '0px',\n threshold: 0,\n once: false,\n events: true\n }\n\n this.options = Object.assign(defaults, options)\n\n // Creates the default observer then start.\n this.createMainObserver()\n this.init()\n }\n\n /**\n * Creates the main IntersectionObserver used with the default options.\n *\n * @private\n * @returns {void}\n */\n createMainObserver() {\n this.observers = [{\n observer: new IntersectionObserver(this.intersect, this.options),\n threshold: this.options.threshold,\n rootMargin: this.options.rootMargin,\n elements: []\n }]\n }\n\n /**\n * Initialization method, starts the IntersectionObservers.\n *\n * @private\n * @returns {void}\n */\n init() {\n this.getElems()\n this.createObservers()\n this.observe()\n }\n\n /**\n * Gets the [data-cartapus] elements from root element.\n *\n * @private\n * @returns {void}\n */\n getElems() {\n const root = this.options.root === null ? document : this.options.root\n\n this.elems = root.querySelectorAll('[data-cartapus]')\n }\n\n /**\n * For each [data-cartapus] element, check its inner data-cartapus parameters\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\n *\n * @private\n * @returns {void}\n */\n createObservers() {\n for (const el of this.elems) {\n // If element has data-cartapus-threshold attribute.\n if (el.dataset.cartapusThreshold || el.dataset.cartapusRootMargin) {\n const threshold = el.dataset.cartapusThreshold ? parseFloat(el.dataset.cartapusThreshold) : this.options.threshold\n const rootMargin = el.dataset.cartapusRootMargin ? el.dataset.cartapusRootMargin : this.options.rootMargin\n let found = false\n\n // If an observer already exists with the same threshold & the same rootMargin, add element to this observer.\n for (const observer of this.observers) {\n if (threshold === observer.threshold && rootMargin === observer.rootMargin) {\n found = true\n\n observer.elements.push(el)\n }\n }\n\n // If no observer has the same threshold & rootMargin, create a new one with the new options.\n if (!found) {\n const observer = {\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold, rootMargin })),\n threshold,\n rootMargin,\n elements: [el]\n }\n\n this.observers.push(observer)\n }\n } else this.observers[0].elements.push(el)\n }\n }\n\n /**\n * Callback function triggered by the observers.\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\n * Triggers the custom events if the `events` option is enabled.\n *\n * @param {array.} entries — An array of entries that intersected with the root.\n * @param {IntersectionObserver} observer — The observer that triggered the event.\n *\n * @private\n * @returns {void}\n */\n intersect(entries, observer) {\n entries.forEach((entry) => {\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\n if (entry.isIntersecting) {\n entry.target.dataset.cartapus = 'visible'\n\n // Stop observing this element if \"once\" options it true.\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\n } else entry.target.dataset.cartapus = 'hidden'\n\n if (this.options.events) this.dispatch(entry)\n })\n }\n\n /**\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\n * Also triggers an `intersect` event on the class instance.\n *\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\n *\n * @private\n * @returns {void}\n */\n dispatch(entry) {\n // Create event with details.\n const detail = {\n element: entry.target,\n visible: entry.isIntersecting,\n intersection: entry\n }\n const event = new CustomEvent('cartapusintersect', { detail })\n\n // Dispatch element and instance events.\n entry.target.dispatchEvent(event)\n this.emit('intersect', detail)\n }\n\n /**\n * Turns on all the observers to watch all of their related targets.\n *\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n observe() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.observe(el)\n })\n })\n }\n\n /**\n * Turns off all the observers to stop watching all of their related targets.\n *\n * @public\n * @returns {void}\n */\n unobserve() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.unobserve(el)\n })\n })\n }\n\n /**\n * Turns off observers and empty their related targets.\n *\n * @public\n * @returns {void}\n */\n destroy() {\n this.unobserve()\n\n this.observers.forEach((observer) => {\n observer.elements = []\n })\n }\n\n /**\n * Resets everything.\n * Turns off observers and resets their targets.\n * Then calls `this.init()` to restart everything with new elements to observe.\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n reset() {\n this.destroy()\n this.init()\n }\n}\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","Cartapus","options","_this","_Emitter","intersect","bind","_assertThisInitialized","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","Emitter","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","_iterator","_createForOfIteratorHelperLoose","el","_step","value","dataset","cartapusThreshold","cartapusRootMargin","parseFloat","found","_iterator2","_step2","entries","forEach","entry","isIntersecting","target","cartapus","_this2","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
diff --git a/build/cartapus.umd.js b/build/cartapus.umd.js
index b8e5dbe..37b9963 100644
--- a/build/cartapus.umd.js
+++ b/build/cartapus.umd.js
@@ -1,2 +1,2 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e||self).cartapus=t()}(this,function(){function e(t,r){return e=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},e(t,r)}function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r=e.length?{done:!0}:{done:!1,value:e[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(){}n.prototype={on:function(e,t,r){var n=this.e||(this.e={});return(n[e]||(n[e]=[])).push({fn:t,ctx:r}),this},once:function(e,t,r){var n=this;function o(){n.off(e,o),t.apply(r,arguments)}return o._=t,this.on(e,o,r)},emit:function(e){for(var t=[].slice.call(arguments,1),r=((this.e||(this.e={}))[e]||[]).slice(),n=0,o=r.length;nt.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(){}n.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function o(){n.off(t,o),e.apply(r,arguments)}return o._=e,this.on(t,o,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,o=r.length;n\r\n */\r\n\r\nimport Emitter from 'tiny-emitter'\r\n\r\n/**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @class\r\n */\r\nexport default class Cartapus extends Emitter {\r\n\r\n /**\r\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\r\n *\r\n * Usually you will only need to instanciate Cartapus once for your whole App.\r\n *\r\n * @param {Object} [options] — User options.\r\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\r\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\r\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\r\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\r\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\r\n *\r\n * @extends Emitter\r\n * @constructor\r\n */\r\n constructor(options = {}) {\r\n super()\r\n\r\n // Bind callback method.\r\n this.intersect = this.intersect.bind(this)\r\n\r\n // Set user options based on default options.\r\n const defaults = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0,\r\n once: false,\r\n events: true\r\n }\r\n\r\n this.options = Object.assign(defaults, options)\r\n\r\n // Creates the default observer then start.\r\n this.createMainObserver()\r\n this.init()\r\n }\r\n\r\n /**\r\n * Creates the main IntersectionObserver used with the default options.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createMainObserver() {\r\n this.observers = [{\r\n observer: new IntersectionObserver(this.intersect, this.options),\r\n threshold: this.options.threshold,\r\n elements: []\r\n }]\r\n }\r\n\r\n /**\r\n * Initialization method, starts the IntersectionObservers.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n init() {\r\n this.getElems()\r\n this.createObservers()\r\n this.observe()\r\n }\r\n\r\n /**\r\n * Gets the [data-cartapus] elements from root element.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n getElems() {\r\n const root = this.options.root === null ? document : this.options.root\r\n\r\n this.elems = root.querySelectorAll('[data-cartapus]')\r\n }\r\n\r\n /**\r\n * For each [data-cartapus] element, check its inner data-cartapus parameters\r\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n createObservers() {\r\n for (const el of this.elems) {\r\n // If element has data-cartapus-threshold attribute.\r\n if (el.dataset.cartapusThreshold) {\r\n const threshold = parseFloat(el.dataset.cartapusThreshold)\r\n let found = false\r\n\r\n // If an observer already exists with the same threshold, add element to this observer.\r\n for (const observer of this.observers) {\r\n if (threshold === observer.threshold) {\r\n found = true\r\n\r\n observer.elements.push(el)\r\n }\r\n }\r\n\r\n // If no observer has the same threshold, create a new one with the new threshold.\r\n if (!found) {\r\n const observer = {\r\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold })),\r\n threshold,\r\n elements: [el]\r\n }\r\n\r\n this.observers.push(observer)\r\n }\r\n } else this.observers[0].elements.push(el)\r\n }\r\n }\r\n\r\n /**\r\n * Callback function triggered by the observers.\r\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\r\n * Triggers the custom events if the `events` option is enabled.\r\n *\r\n * @param {array.} entries — An array of entries that intersected with the root.\r\n * @param {IntersectionObserver} observer — The observer that triggered the event.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n intersect(entries, observer) {\r\n entries.forEach((entry) => {\r\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\r\n if (entry.isIntersecting) {\r\n entry.target.dataset.cartapus = 'visible'\r\n\r\n // Stop observing this element if \"once\" options it true.\r\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\r\n } else entry.target.dataset.cartapus = 'hidden'\r\n\r\n if (this.options.events) this.dispatch(entry)\r\n })\r\n }\r\n\r\n /**\r\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\r\n * Also triggers an `intersect` event on the class instance.\r\n *\r\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n dispatch(entry) {\r\n // Create event with details.\r\n const detail = {\r\n element: entry.target,\r\n visible: entry.isIntersecting,\r\n intersection: entry\r\n }\r\n const event = new CustomEvent('cartapusintersect', { detail })\r\n\r\n // Dispatch element and instance events.\r\n entry.target.dispatchEvent(event)\r\n this.emit('intersect', detail)\r\n }\r\n\r\n /**\r\n * Turns on all the observers to watch all of their related targets.\r\n *\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n observe() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.observe(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off all the observers to stop watching all of their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n unobserve() {\r\n this.observers.forEach((observer) => {\r\n observer.elements.forEach((el) => {\r\n observer.observer.unobserve(el)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Turns off observers and empty their related targets.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n destroy() {\r\n this.unobserve()\r\n\r\n this.observers.forEach((observer) => {\r\n observer.elements = []\r\n })\r\n }\r\n\r\n /**\r\n * Resets everything.\r\n * Turns off observers and resets their targets.\r\n * Then calls `this.init()` to restart everything with new elements to observe.\r\n * This will trigger Cartapus events if events are turned on.\r\n *\r\n * @public\r\n * @returns {void}\r\n */\r\n reset() {\r\n this.destroy()\r\n this.init()\r\n }\r\n}\r\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","_Emitter","Cartapus","options","_this","intersect","bind","_assertThisInitialized","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","Emitter","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","_step","_iterator","_createForOfIteratorHelperLoose","done","el","dataset","cartapusThreshold","_step2","parseFloat","found","_iterator2","entries","_this2","forEach","entry","isIntersecting","target","cartapus","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"cartapus.umd.js","sources":["../node_modules/tiny-emitter/index.js","../src/cartapus.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n","/**\n * @file Cartapus core file, dispatches events based on [data-cartapus] elements' visibility in the viewport.\n * @author Jordan Thiervoz \n */\n\nimport Emitter from 'tiny-emitter'\n\n/**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @class\n */\nexport default class Cartapus extends Emitter {\n\n /**\n * Creates a new Cartapus instance, starting to watch every `[data-cartapus]` elements' visibility right away.\n *\n * Usually you will only need to instanciate Cartapus once for your whole App.\n *\n * @param {Object} [options] — User options.\n * @param {Element} [options.root=document] — The root DOM element into which [data-cartapus] targets will be watched.\n * @param {String} [options.rootMargin=\"0px\"] — A CSS margin property string defining offsets into the `root` element.\n * @param {Number} [options.threshold=0] — A number between 0 and 1 which defines the percentage of height that must be into the viewport for an element to be considered \"visible\".\n * @param {Boolean} [options.once=false] — If \"true\", elements will only toggle to \"visible\" once and never return to their \"hidden\" state.\n * @param {Boolean} [options.event=true] — If \"true\", events will be triggered when an element changes its state. A CustomEvent is triggered on the related element, and an event is also triggered on the Cartapus instance.\n *\n * @extends Emitter\n * @constructor\n */\n constructor(options = {}) {\n super()\n\n // Bind callback method.\n this.intersect = this.intersect.bind(this)\n\n // Set user options based on default options.\n const defaults = {\n root: null,\n rootMargin: '0px',\n threshold: 0,\n once: false,\n events: true\n }\n\n this.options = Object.assign(defaults, options)\n\n // Creates the default observer then start.\n this.createMainObserver()\n this.init()\n }\n\n /**\n * Creates the main IntersectionObserver used with the default options.\n *\n * @private\n * @returns {void}\n */\n createMainObserver() {\n this.observers = [{\n observer: new IntersectionObserver(this.intersect, this.options),\n threshold: this.options.threshold,\n rootMargin: this.options.rootMargin,\n elements: []\n }]\n }\n\n /**\n * Initialization method, starts the IntersectionObservers.\n *\n * @private\n * @returns {void}\n */\n init() {\n this.getElems()\n this.createObservers()\n this.observe()\n }\n\n /**\n * Gets the [data-cartapus] elements from root element.\n *\n * @private\n * @returns {void}\n */\n getElems() {\n const root = this.options.root === null ? document : this.options.root\n\n this.elems = root.querySelectorAll('[data-cartapus]')\n }\n\n /**\n * For each [data-cartapus] element, check its inner data-cartapus parameters\n * Create new IntersectionObservers accordingly if parameters differs from the main observer.\n *\n * @private\n * @returns {void}\n */\n createObservers() {\n for (const el of this.elems) {\n // If element has data-cartapus-threshold attribute.\n if (el.dataset.cartapusThreshold || el.dataset.cartapusRootMargin) {\n const threshold = el.dataset.cartapusThreshold ? parseFloat(el.dataset.cartapusThreshold) : this.options.threshold\n const rootMargin = el.dataset.cartapusRootMargin ? el.dataset.cartapusRootMargin : this.options.rootMargin\n let found = false\n\n // If an observer already exists with the same threshold & the same rootMargin, add element to this observer.\n for (const observer of this.observers) {\n if (threshold === observer.threshold && rootMargin === observer.rootMargin) {\n found = true\n\n observer.elements.push(el)\n }\n }\n\n // If no observer has the same threshold & rootMargin, create a new one with the new options.\n if (!found) {\n const observer = {\n observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold, rootMargin })),\n threshold,\n rootMargin,\n elements: [el]\n }\n\n this.observers.push(observer)\n }\n } else this.observers[0].elements.push(el)\n }\n }\n\n /**\n * Callback function triggered by the observers.\n * Sets the data-cartapus attribute accordingly to the visibility of the elements.\n * Triggers the custom events if the `events` option is enabled.\n *\n * @param {array.} entries — An array of entries that intersected with the root.\n * @param {IntersectionObserver} observer — The observer that triggered the event.\n *\n * @private\n * @returns {void}\n */\n intersect(entries, observer) {\n entries.forEach((entry) => {\n // Set data-cartapus attribute value either to \"visible\" or \"hidden\".\n if (entry.isIntersecting) {\n entry.target.dataset.cartapus = 'visible'\n\n // Stop observing this element if \"once\" options it true.\n if (this.options.once && entry.target.dataset.cartapusOnce !== 'false') observer.unobserve(entry.target)\n } else entry.target.dataset.cartapus = 'hidden'\n\n if (this.options.events) this.dispatch(entry)\n })\n }\n\n /**\n * Triggers the CustomEvent `cartapusintersect` on the entry's target.\n * Also triggers an `intersect` event on the class instance.\n *\n * @param {IntersectionObserverEntry} entry — The entry that intersected.\n *\n * @private\n * @returns {void}\n */\n dispatch(entry) {\n // Create event with details.\n const detail = {\n element: entry.target,\n visible: entry.isIntersecting,\n intersection: entry\n }\n const event = new CustomEvent('cartapusintersect', { detail })\n\n // Dispatch element and instance events.\n entry.target.dispatchEvent(event)\n this.emit('intersect', detail)\n }\n\n /**\n * Turns on all the observers to watch all of their related targets.\n *\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n observe() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.observe(el)\n })\n })\n }\n\n /**\n * Turns off all the observers to stop watching all of their related targets.\n *\n * @public\n * @returns {void}\n */\n unobserve() {\n this.observers.forEach((observer) => {\n observer.elements.forEach((el) => {\n observer.observer.unobserve(el)\n })\n })\n }\n\n /**\n * Turns off observers and empty their related targets.\n *\n * @public\n * @returns {void}\n */\n destroy() {\n this.unobserve()\n\n this.observers.forEach((observer) => {\n observer.elements = []\n })\n }\n\n /**\n * Resets everything.\n * Turns off observers and resets their targets.\n * Then calls `this.init()` to restart everything with new elements to observe.\n * This will trigger Cartapus events if events are turned on.\n *\n * @public\n * @returns {void}\n */\n reset() {\n this.destroy()\n this.init()\n }\n}\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitter","options","_this","_Emitter","intersect","bind","_assertThisInitialized","Object","assign","root","rootMargin","threshold","events","createMainObserver","init","Emitter","observers","observer","IntersectionObserver","elements","getElems","createObservers","observe","document","elems","querySelectorAll","_iterator","_createForOfIteratorHelperLoose","el","_step","value","dataset","cartapusThreshold","cartapusRootMargin","parseFloat","found","_iterator2","_step2","entries","forEach","entry","isIntersecting","target","cartapus","_this2","cartapusOnce","unobserve","dispatch","detail","element","visible","intersection","event","CustomEvent","dispatchEvent","destroy","reset"],"mappings":"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"}
\ No newline at end of file
diff --git a/src/cartapus.js b/src/cartapus.js
index 599733d..2cddf57 100644
--- a/src/cartapus.js
+++ b/src/cartapus.js
@@ -69,6 +69,7 @@ export default class Cartapus extends Emitter {
this.observers = [{
observer: new IntersectionObserver(this.intersect, this.options),
threshold: this.options.threshold,
+ rootMargin: this.options.rootMargin,
elements: []
}]
}
@@ -107,24 +108,26 @@ export default class Cartapus extends Emitter {
createObservers() {
for (const el of this.elems) {
// If element has data-cartapus-threshold attribute.
- if (el.dataset.cartapusThreshold) {
- const threshold = parseFloat(el.dataset.cartapusThreshold)
+ if (el.dataset.cartapusThreshold || el.dataset.cartapusRootMargin) {
+ const threshold = el.dataset.cartapusThreshold ? parseFloat(el.dataset.cartapusThreshold) : this.options.threshold
+ const rootMargin = el.dataset.cartapusRootMargin ? el.dataset.cartapusRootMargin : this.options.rootMargin
let found = false
- // If an observer already exists with the same threshold, add element to this observer.
+ // If an observer already exists with the same threshold & the same rootMargin, add element to this observer.
for (const observer of this.observers) {
- if (threshold === observer.threshold) {
+ if (threshold === observer.threshold && rootMargin === observer.rootMargin) {
found = true
observer.elements.push(el)
}
}
- // If no observer has the same threshold, create a new one with the new threshold.
+ // If no observer has the same threshold & rootMargin, create a new one with the new options.
if (!found) {
const observer = {
- observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold })),
+ observer: new IntersectionObserver(this.intersect, Object.assign(this.options, { threshold, rootMargin })),
threshold,
+ rootMargin,
elements: [el]
}