Mercurial > hg > isophonics-drupal-site
comparison core/misc/displace.es6.js @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | 1fec387a4317 |
children |
comparison
equal
deleted
inserted
replaced
16:c2387f117808 | 17:129ea1e6d783 |
---|---|
22 * Toolbar toggling. | 22 * Toolbar toggling. |
23 * | 23 * |
24 * @event drupalViewportOffsetChange | 24 * @event drupalViewportOffsetChange |
25 */ | 25 */ |
26 | 26 |
27 (function ($, Drupal, debounce) { | 27 (function($, Drupal, debounce) { |
28 /** | 28 /** |
29 * @name Drupal.displace.offsets | 29 * @name Drupal.displace.offsets |
30 * | 30 * |
31 * @type {Drupal~displaceOffset} | 31 * @type {Drupal~displaceOffset} |
32 */ | 32 */ |
36 bottom: 0, | 36 bottom: 0, |
37 left: 0, | 37 left: 0, |
38 }; | 38 }; |
39 | 39 |
40 /** | 40 /** |
41 * Registers a resize handler on the window. | 41 * Calculates displacement for element based on its dimensions and placement. |
42 * | 42 * |
43 * @type {Drupal~behavior} | 43 * @param {HTMLElement} el |
44 */ | 44 * The jQuery element whose dimensions and placement will be measured. |
45 Drupal.behaviors.drupalDisplace = { | 45 * |
46 attach() { | 46 * @param {string} edge |
47 // Mark this behavior as processed on the first pass. | 47 * The name of the edge of the viewport that the element is associated |
48 if (this.displaceProcessed) { | 48 * with. |
49 return; | 49 * |
50 } | 50 * @return {number} |
51 this.displaceProcessed = true; | 51 * The viewport displacement distance for the requested edge. |
52 | 52 */ |
53 $(window).on('resize.drupalDisplace', debounce(displace, 200)); | 53 function getRawOffset(el, edge) { |
54 }, | 54 const $el = $(el); |
55 }; | 55 const documentElement = document.documentElement; |
56 | 56 let displacement = 0; |
57 /** | 57 const horizontal = edge === 'left' || edge === 'right'; |
58 * Informs listeners of the current offset dimensions. | 58 // Get the offset of the element itself. |
59 * | 59 let placement = $el.offset()[horizontal ? 'left' : 'top']; |
60 * @function Drupal.displace | 60 // Subtract scroll distance from placement to get the distance |
61 * | 61 // to the edge of the viewport. |
62 * @prop {Drupal~displaceOffset} offsets | 62 placement -= |
63 * | 63 window[`scroll${horizontal ? 'X' : 'Y'}`] || |
64 * @param {bool} [broadcast] | 64 document.documentElement[`scroll${horizontal ? 'Left' : 'Top'}`] || |
65 * When true or undefined, causes the recalculated offsets values to be | 65 0; |
66 * broadcast to listeners. | 66 // Find the displacement value according to the edge. |
67 * | 67 switch (edge) { |
68 * @return {Drupal~displaceOffset} | 68 // Left and top elements displace as a sum of their own offset value |
69 * An object whose keys are the for sides an element -- top, right, bottom | 69 // plus their size. |
70 * and left. The value of each key is the viewport displacement distance for | 70 case 'top': |
71 * that edge. | 71 // Total displacement is the sum of the elements placement and size. |
72 * | 72 displacement = placement + $el.outerHeight(); |
73 * @fires event:drupalViewportOffsetChange | 73 break; |
74 */ | 74 |
75 function displace(broadcast) { | 75 case 'left': |
76 offsets = calculateOffsets(); | 76 // Total displacement is the sum of the elements placement and size. |
77 Drupal.displace.offsets = offsets; | 77 displacement = placement + $el.outerWidth(); |
78 if (typeof broadcast === 'undefined' || broadcast) { | 78 break; |
79 $(document).trigger('drupalViewportOffsetChange', offsets); | 79 |
80 // Right and bottom elements displace according to their left and | |
81 // top offset. Their size isn't important. | |
82 case 'bottom': | |
83 displacement = documentElement.clientHeight - placement; | |
84 break; | |
85 | |
86 case 'right': | |
87 displacement = documentElement.clientWidth - placement; | |
88 break; | |
89 | |
90 default: | |
91 displacement = 0; | |
80 } | 92 } |
81 return offsets; | 93 return displacement; |
82 } | |
83 | |
84 /** | |
85 * Determines the viewport offsets. | |
86 * | |
87 * @return {Drupal~displaceOffset} | |
88 * An object whose keys are the for sides an element -- top, right, bottom | |
89 * and left. The value of each key is the viewport displacement distance for | |
90 * that edge. | |
91 */ | |
92 function calculateOffsets() { | |
93 return { | |
94 top: calculateOffset('top'), | |
95 right: calculateOffset('right'), | |
96 bottom: calculateOffset('bottom'), | |
97 left: calculateOffset('left'), | |
98 }; | |
99 } | 94 } |
100 | 95 |
101 /** | 96 /** |
102 * Gets a specific edge's offset. | 97 * Gets a specific edge's offset. |
103 * | 98 * |
115 * @return {number} | 110 * @return {number} |
116 * The viewport displacement distance for the requested edge. | 111 * The viewport displacement distance for the requested edge. |
117 */ | 112 */ |
118 function calculateOffset(edge) { | 113 function calculateOffset(edge) { |
119 let edgeOffset = 0; | 114 let edgeOffset = 0; |
120 const displacingElements = document.querySelectorAll(`[data-offset-${edge}]`); | 115 const displacingElements = document.querySelectorAll( |
116 `[data-offset-${edge}]`, | |
117 ); | |
121 const n = displacingElements.length; | 118 const n = displacingElements.length; |
122 for (let i = 0; i < n; i++) { | 119 for (let i = 0; i < n; i++) { |
123 const el = displacingElements[i]; | 120 const el = displacingElements[i]; |
124 // If the element is not visible, do consider its dimensions. | 121 // If the element is not visible, do consider its dimensions. |
125 if (el.style.display === 'none') { | 122 if (el.style.display === 'none') { |
128 // If the offset data attribute contains a displacing value, use it. | 125 // If the offset data attribute contains a displacing value, use it. |
129 let displacement = parseInt(el.getAttribute(`data-offset-${edge}`), 10); | 126 let displacement = parseInt(el.getAttribute(`data-offset-${edge}`), 10); |
130 // If the element's offset data attribute exits | 127 // If the element's offset data attribute exits |
131 // but is not a valid number then get the displacement | 128 // but is not a valid number then get the displacement |
132 // dimensions directly from the element. | 129 // dimensions directly from the element. |
130 // eslint-disable-next-line no-restricted-globals | |
133 if (isNaN(displacement)) { | 131 if (isNaN(displacement)) { |
134 displacement = getRawOffset(el, edge); | 132 displacement = getRawOffset(el, edge); |
135 } | 133 } |
136 // If the displacement value is larger than the current value for this | 134 // If the displacement value is larger than the current value for this |
137 // edge, use the displacement value. | 135 // edge, use the displacement value. |
140 | 138 |
141 return edgeOffset; | 139 return edgeOffset; |
142 } | 140 } |
143 | 141 |
144 /** | 142 /** |
145 * Calculates displacement for element based on its dimensions and placement. | 143 * Determines the viewport offsets. |
146 * | 144 * |
147 * @param {HTMLElement} el | 145 * @return {Drupal~displaceOffset} |
148 * The jQuery element whose dimensions and placement will be measured. | 146 * An object whose keys are the for sides an element -- top, right, bottom |
149 * | 147 * and left. The value of each key is the viewport displacement distance for |
150 * @param {string} edge | 148 * that edge. |
151 * The name of the edge of the viewport that the element is associated | 149 */ |
152 * with. | 150 function calculateOffsets() { |
153 * | 151 return { |
154 * @return {number} | 152 top: calculateOffset('top'), |
155 * The viewport displacement distance for the requested edge. | 153 right: calculateOffset('right'), |
156 */ | 154 bottom: calculateOffset('bottom'), |
157 function getRawOffset(el, edge) { | 155 left: calculateOffset('left'), |
158 const $el = $(el); | 156 }; |
159 const documentElement = document.documentElement; | 157 } |
160 let displacement = 0; | 158 |
161 const horizontal = (edge === 'left' || edge === 'right'); | 159 /** |
162 // Get the offset of the element itself. | 160 * Informs listeners of the current offset dimensions. |
163 let placement = $el.offset()[horizontal ? 'left' : 'top']; | 161 * |
164 // Subtract scroll distance from placement to get the distance | 162 * @function Drupal.displace |
165 // to the edge of the viewport. | 163 * |
166 placement -= window[`scroll${horizontal ? 'X' : 'Y'}`] || document.documentElement[`scroll${horizontal ? 'Left' : 'Top'}`] || 0; | 164 * @prop {Drupal~displaceOffset} offsets |
167 // Find the displacement value according to the edge. | 165 * |
168 switch (edge) { | 166 * @param {bool} [broadcast] |
169 // Left and top elements displace as a sum of their own offset value | 167 * When true or undefined, causes the recalculated offsets values to be |
170 // plus their size. | 168 * broadcast to listeners. |
171 case 'top': | 169 * |
172 // Total displacement is the sum of the elements placement and size. | 170 * @return {Drupal~displaceOffset} |
173 displacement = placement + $el.outerHeight(); | 171 * An object whose keys are the for sides an element -- top, right, bottom |
174 break; | 172 * and left. The value of each key is the viewport displacement distance for |
175 | 173 * that edge. |
176 case 'left': | 174 * |
177 // Total displacement is the sum of the elements placement and size. | 175 * @fires event:drupalViewportOffsetChange |
178 displacement = placement + $el.outerWidth(); | 176 */ |
179 break; | 177 function displace(broadcast) { |
180 | 178 offsets = calculateOffsets(); |
181 // Right and bottom elements displace according to their left and | 179 Drupal.displace.offsets = offsets; |
182 // top offset. Their size isn't important. | 180 if (typeof broadcast === 'undefined' || broadcast) { |
183 case 'bottom': | 181 $(document).trigger('drupalViewportOffsetChange', offsets); |
184 displacement = documentElement.clientHeight - placement; | |
185 break; | |
186 | |
187 case 'right': | |
188 displacement = documentElement.clientWidth - placement; | |
189 break; | |
190 | |
191 default: | |
192 displacement = 0; | |
193 } | 182 } |
194 return displacement; | 183 return offsets; |
195 } | 184 } |
185 | |
186 /** | |
187 * Registers a resize handler on the window. | |
188 * | |
189 * @type {Drupal~behavior} | |
190 */ | |
191 Drupal.behaviors.drupalDisplace = { | |
192 attach() { | |
193 // Mark this behavior as processed on the first pass. | |
194 if (this.displaceProcessed) { | |
195 return; | |
196 } | |
197 this.displaceProcessed = true; | |
198 | |
199 $(window).on('resize.drupalDisplace', debounce(displace, 200)); | |
200 }, | |
201 }; | |
196 | 202 |
197 /** | 203 /** |
198 * Assign the displace function to a property of the Drupal global object. | 204 * Assign the displace function to a property of the Drupal global object. |
199 * | 205 * |
200 * @ignore | 206 * @ignore |
201 */ | 207 */ |
202 Drupal.displace = displace; | 208 Drupal.displace = displace; |
203 $.extend(Drupal.displace, { | 209 $.extend(Drupal.displace, { |
204 | |
205 /** | 210 /** |
206 * Expose offsets to other scripts to avoid having to recalculate offsets. | 211 * Expose offsets to other scripts to avoid having to recalculate offsets. |
207 * | 212 * |
208 * @ignore | 213 * @ignore |
209 */ | 214 */ |
214 * | 219 * |
215 * @ignore | 220 * @ignore |
216 */ | 221 */ |
217 calculateOffset, | 222 calculateOffset, |
218 }); | 223 }); |
219 }(jQuery, Drupal, Drupal.debounce)); | 224 })(jQuery, Drupal, Drupal.debounce); |