1 | /**
|
2 | * Most Visible v1.4.0
|
3 | *
|
4 | * @author Andy Palmer <andy@andypalmer.me>
|
5 | * @license MIT
|
6 | */
|
7 |
|
8 | (function (root, factory) {
|
9 | // Universal Module Definition
|
10 | /* jshint strict:false */
|
11 | /* global define: false, module: false */
|
12 | if (typeof define === 'function' && define.amd) {
|
13 | define([], function () {
|
14 | return factory(root);
|
15 | });
|
16 | } else if (typeof module === 'object' && module.exports) {
|
17 | module.exports = factory(root);
|
18 | } else {
|
19 | root.mostVisible = factory(root);
|
20 | }
|
21 | }(typeof self !== 'undefined' ? self : this, function (window) {
|
22 | /* jshint unused: vars */
|
23 |
|
24 | ;
|
25 |
|
26 | /**
|
27 | * MostVisible constructor
|
28 | *
|
29 | * @param {NodeList|string} elements
|
30 | * @param {Object} options
|
31 | * @constructor
|
32 | */
|
33 | function MostVisible(elements, options) {
|
34 | if (!(this instanceof MostVisible)) {
|
35 | return (new MostVisible(elements, options)).getMostVisible();
|
36 | }
|
37 |
|
38 | if (typeof elements === 'string') {
|
39 | elements = document.querySelectorAll(elements);
|
40 | }
|
41 |
|
42 | this.elements = elements;
|
43 | this.options = extend({}, MostVisible.defaults, options);
|
44 | }
|
45 |
|
46 | /**
|
47 | * MostVisible default options
|
48 | *
|
49 | * @namespace
|
50 | * @property {object} defaults Default options hash.
|
51 | * @property {boolean} defaults.percentage Whether to calculate visibility as a percentage of height.
|
52 | * @property {number} defaults.offset An offset to take into account when calculating visibility.
|
53 | */
|
54 | MostVisible.defaults = {
|
55 | percentage: false,
|
56 | offset: 0
|
57 | };
|
58 |
|
59 | MostVisible.prototype = {
|
60 | /**
|
61 | * Returns the most visible element from the instance's NodeList.
|
62 | *
|
63 | * @returns {Element} Most visible element.
|
64 | */
|
65 | getMostVisible: function () {
|
66 | var element = null,
|
67 | viewportHeight = document.documentElement.clientHeight,
|
68 | maxVisible = 0;
|
69 |
|
70 | for (var i = 0; i < this.elements.length; i++) {
|
71 | var currentVisible = this.getVisibleHeight(this.elements[i], viewportHeight);
|
72 |
|
73 | if (currentVisible > maxVisible) {
|
74 | maxVisible = currentVisible;
|
75 | element = this.elements[i];
|
76 | }
|
77 | }
|
78 |
|
79 | return element;
|
80 | },
|
81 |
|
82 | /**
|
83 | * Returns the visible height of an element.
|
84 | *
|
85 | * @param {Element} element Element to check the visibility of.
|
86 | * @param {number} viewportHeight
|
87 | * @returns {number} Visible height of the element in pixels or a percentage of the element's total height.
|
88 | */
|
89 | getVisibleHeight: function (element, viewportHeight) {
|
90 | var rect = element.getBoundingClientRect(),
|
91 | rectTopOffset = rect.top - this.options.offset,
|
92 | rectBottomOffset = rect.bottom - this.options.offset,
|
93 | height = rect.bottom - rect.top,
|
94 | visible = {
|
95 | top: rectTopOffset >= 0 && rectTopOffset < viewportHeight,
|
96 | bottom: rectBottomOffset > 0 && rectBottomOffset < viewportHeight
|
97 | },
|
98 | visiblePx = 0;
|
99 |
|
100 | if (visible.top && visible.bottom) {
|
101 | // Whole element is visible
|
102 | visiblePx = height;
|
103 | } else if (visible.top) {
|
104 | visiblePx = viewportHeight - rect.top;
|
105 | } else if (visible.bottom) {
|
106 | visiblePx = rectBottomOffset;
|
107 | } else if (height > viewportHeight && rectTopOffset < 0) {
|
108 | var absTop = Math.abs(rectTopOffset);
|
109 |
|
110 | if (absTop < height) {
|
111 | // Part of the element is visible
|
112 | visiblePx = height - absTop;
|
113 | }
|
114 | }
|
115 |
|
116 | if (this.options.percentage) {
|
117 | return (visiblePx / height) * 100;
|
118 | }
|
119 |
|
120 | return visiblePx;
|
121 | }
|
122 | };
|
123 |
|
124 | /*
|
125 | MostVisible.makeJQueryPlugin = function ($) {
|
126 | if (!$) {
|
127 | return;
|
128 | }
|
129 |
|
130 | $.fn.mostVisible = function (options) {
|
131 | var instance = new MostVisible(this.get(), options);
|
132 | return this.filter(instance.getMostVisible());
|
133 | };
|
134 | };
|
135 | */
|
136 |
|
137 | // Try adding the jQuery plugin to window.jQuery
|
138 | // MostVisible.makeJQueryPlugin(window.jQuery);
|
139 |
|
140 | /**
|
141 | * Extends obj by adding the properties of all other objects passed to the function.
|
142 | *
|
143 | * @param {...Object} obj
|
144 | * @returns {Object} The extended object.
|
145 | */
|
146 | function extend(obj) {
|
147 | for (var i = 1; i < arguments.length; i++) {
|
148 | for (var key in arguments[i]) {
|
149 | if (arguments[i].hasOwnProperty(key)) {
|
150 | obj[key] = arguments[i][key];
|
151 | }
|
152 | }
|
153 | }
|
154 |
|
155 | return obj;
|
156 | }
|
157 |
|
158 | //noinspection JSAnnotator
|
159 | return MostVisible;
|
160 |
|
161 | }));
|