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);