diff --git a/README.md b/README.md index 00c42c0..0ebb34f 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,17 @@ var os = new OnScreen({ The instance, `os`, has the following options: `options.tolerance` is the number of pixels an element is allowed to enter its container boundaries before calling its callback. Defaults to `0`. +May be configured as a number which will be used for all boundaries or as an object containing tolerance values for each boundary. Missing property values also default to `0`. +```javascript +var os = new OnScreen({ + tolerance: { + top: 10, + right: 20, + bottom: 30, + left: 40 + } +}); +``` `options.debounce` is the number of milliseconds to wait before calling an element's callback after the user has stopped scrolling. Defaults to `100`. diff --git a/lib/helpers/in-container.js b/lib/helpers/in-container.js index b2d89d7..51748a7 100644 --- a/lib/helpers/in-container.js +++ b/lib/helpers/in-container.js @@ -5,7 +5,9 @@ * @param {node} element The DOM node you want to check * @return {boolean} A boolean value that indicates wether is on or off the container. */ -function inContainer(el, options = { tolerance: 0, container: '' }) { +function inContainer(el, + options = { tolerance: { top: 0, right: 0, bottom: 0, left: 0 }, + container: '' }) { if (!el) { throw new Error('You should specify the element you want to test'); } @@ -15,7 +17,7 @@ function inContainer(el, options = { tolerance: 0, container: '' }) { } if (typeof options === 'string') { options = { - tolerance: 0, + tolerance: { top: 0, right: 0, bottom: 0, left: 0 }, container: document.querySelector(options) }; } @@ -24,7 +26,7 @@ function inContainer(el, options = { tolerance: 0, container: '' }) { } if (options instanceof HTMLElement) { options = { - tolerance: 0, + tolerance: { top: 0, right: 0, bottom: 0, left: 0 }, container: options }; } @@ -36,19 +38,19 @@ function inContainer(el, options = { tolerance: 0, container: '' }) { return ( // // Check bottom boundary - (el.offsetTop + el.clientHeight) - options.tolerance > + (el.offsetTop + el.clientHeight) - options.tolerance.bottom > options.container.scrollTop && // Check right boundary - (el.offsetLeft + el.clientWidth) - options.tolerance > + (el.offsetLeft + el.clientWidth) - options.tolerance.right > options.container.scrollLeft && // Check left boundary - el.offsetLeft + options.tolerance < + el.offsetLeft + options.tolerance.left < containerRect.width + options.container.scrollLeft && // // Check top boundary - el.offsetTop + options.tolerance < + el.offsetTop + options.tolerance.top < containerRect.height + options.container.scrollTop ); } diff --git a/lib/helpers/in-viewport.js b/lib/helpers/in-viewport.js index 883a628..2d3fb04 100644 --- a/lib/helpers/in-viewport.js +++ b/lib/helpers/in-viewport.js @@ -5,7 +5,7 @@ * @param {node} element The DOM node you want to check * @return {boolean} A boolean value that indicates wether is on or off the viewport. */ -function inViewport(el, options = { tolerance: 0 }) { +function inViewport(el, options = { tolerance: { top: 0, right: 0, bottom: 0, left: 0 } }) { if (!el) { throw new Error('You should specify the element you want to test'); } @@ -18,17 +18,17 @@ function inViewport(el, options = { tolerance: 0 }) { return ( // Check bottom boundary - elRect.bottom - options.tolerance > 0 && + elRect.bottom - options.tolerance.bottom > 0 && // Check right boundary - elRect.right - options.tolerance > 0 && + elRect.right - options.tolerance.right > 0 && // Check left boundary - elRect.left + options.tolerance < (window.innerWidth || + elRect.left + options.tolerance.left < (window.innerWidth || document.documentElement.clientWidth) && // Check top boundary - elRect.top + options.tolerance < (window.innerHeight || + elRect.top + options.tolerance.top < (window.innerHeight || document.documentElement.clientHeight) ); } diff --git a/lib/index.js b/lib/index.js index 8c0cc7f..9161e4b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -48,10 +48,39 @@ function OnScreen(options = { tolerance: 0, debounce: 100, container: window }) }, tolerance: { get() { - return parseInt(options.tolerance, 10) || 0; + if (typeof options.tolerance === 'number') { + const tolerance = parseInt(options.tolerance, 10) || 0; + return { + top: tolerance, + right: tolerance, + bottom: tolerance, + left: tolerance + }; + } + + return { + top: parseInt(options.tolerance.top, 10) || 0, + right: parseInt(options.tolerance.right, 10) || 0, + bottom: parseInt(options.tolerance.bottom, 10) || 0, + left: parseInt(options.tolerance.left, 10) || 0 + }; }, set(value) { - options.tolerance = value; + if (typeof value === 'number') { + options.tolerance = { + top: value, + right: value, + bottom: value, + left: value + }; + } else { + options.tolerance = { + top: value.top || 0, + right: value.right || 0, + bottom: value.bottom || 0, + left: value.left || 0 + }; + } } } }); diff --git a/test/index_test.js b/test/index_test.js index baba109..4a0c402 100644 --- a/test/index_test.js +++ b/test/index_test.js @@ -6,17 +6,65 @@ describe('Instantiation', () => { it('should create an instance with default settings', () => { const instance = new OnScreen(); - expect(instance.options.tolerance).to.equal(0); + ['top', 'right', 'bottom', 'left'].forEach((prop) => { + expect(instance.options.tolerance[prop]).to.equal(0); + }); expect(instance.options.debounce).to.equal(100); }); - it('should create an instance with custom settings', () => { + it('should create an instance with custom settings and single tolerance value', () => { const instance = new OnScreen({ tolerance: 50, debounce: 50 }); - expect(instance.options.tolerance).to.equal(50); + ['top', 'right', 'bottom', 'left'].forEach((prop) => { + expect(instance.options.tolerance[prop]).to.equal(50); + }); + expect(instance.options.debounce).to.equal(50); + }); + + it('should create an instance with custom settings and multiple tolerance values', () => { + const instance = new OnScreen({ + tolerance: { + top: 150, + right: 250, + bottom: 350, + left: 450 + }, + debounce: 50 + }); + + const expectedTolerances = { + top: 150, + right: 250, + bottom: 350, + left: 450 + }; + ['top', 'right', 'bottom', 'left'].forEach((prop) => { + expect(instance.options.tolerance[prop]).to.equal(expectedTolerances[prop]); + }); + expect(instance.options.debounce).to.equal(50); + }); + + it('should create an instance with custom settings and some tolerances missing', () => { + const instance = new OnScreen({ + tolerance: { + top: 150, + right: 250 + }, + debounce: 50 + }); + + const expectedTolerances = { + top: 150, + right: 250, + bottom: 0, + left: 0 + }; + ['top', 'right', 'bottom', 'left'].forEach((prop) => { + expect(instance.options.tolerance[prop]).to.equal(expectedTolerances[prop]); + }); expect(instance.options.debounce).to.equal(50); }); });