1/* 2 * Support to fold/unfold various elements: 3 * - Textblock 4 * - Grid Row 5 * - Sections 6 * 7 * HTML for fold container is placed before section to fold. This section is moved inside with js in init() 8 * 9 * @since 5.6 added 10 * @by Günter 11 */ 12 13"use strict"; 14 15// global namespace 16var avia_js_shortcodes = avia_js_shortcodes || {}; 17var aviaJS = aviaJS || {}; 18 19(function() 20{ 21 if( ! avia_js_shortcodes.aviaFoldUnfoldSection ) 22 { 23 class avFoldUnfoldSection 24 { 25 container = null; // container element 26 id = ''; 27 settings = {}; 28 button = []; 29 foldContainer = []; 30 folded = false; 31 preview = false; 32 innerDimension = {}; 33 34 // element specific data 35 textblock = []; 36 multiColumsTextblock = false; 37 gridRow = []; 38 colorSection = []; 39 column = []; 40 41 constructor( container ) 42 { 43 this.container = container; 44 this.container.avFoldUnfoldSection = this; 45 this.id = container.getAttribute('id'); 46 47 this.init(); 48 } 49 50 init() 51 { 52 this.settings = JSON.parse( this.container.dataset.fold_unfold ); 53 this.preview = document.getElementById( 'av-admin-preview' ) != null; 54 55 this.moveIntoFoldContainer(); 56 57 // fallback due to missing containers 58 if( ! this.button.length || ! this.foldContainer.length || this.checkMissingInnerContainers() ) 59 { 60 return; 61 } 62 63 /** 64 * Currently we do not allow nesting. 65 * Remove this to check if we can allow it on complex pages 66 */ 67 if( this.isNested() ) 68 { 69 this.container.classList.remove( 'avia-fold-init' ); 70 this.foldContainer[0].classList.remove( 'unfolded', 'folded' ); 71 this.foldContainer[0].style['max-height'] = 'unset'; 72 this.button[0].remove(); 73 return; 74 } 75 76 // ensure initially folded (max-height should be set by post css to avoid jumping of content) 77 this.foldContainer[0].style['max-height'] = this.settings.height + 'px'; 78 this.foldContainer[0].classList.add( 'folded' ); 79 this.foldContainer[0].classList.remove( 'unfolded' ); 80 this.folded = true; 81 82 this.container.classList.add( 'avia-fold-init-done' ); 83 84 this.getMaxHeight(); 85 this.foldChanged(); 86 this.bindEvents(); 87 88 this.container.classList.remove( 'avia-fold-init' ); 89 } 90 91 moveIntoFoldContainer() 92 { 93 // query child nodes to allow nested elements (e.g. textblock) 94 if( this.container.hasChildNodes() ) 95 { 96 let children = this.container.childNodes; 97 for( const child of children ) 98 { 99 if( child.classList ) 100 { 101 if( child.classList.contains( 'av-fold-unfold-container' ) ) 102 { 103 this.foldContainer[0] = child; 104 } 105 106 if( child.classList.contains( 'av-fold-button-wrapper' ) ) 107 { 108 const btn = child.getElementsByClassName( 'av-fold-button-container' ); 109 if( btn.length ) 110 { 111 this.button[0] = btn[0]; 112 } 113 } 114 } 115 } 116 } 117 118 let move = null; 119 120 if( this.settings.context == 'avia_sc_text' ) 121 { 122 let el = this.foldContainer[0].nextSibling; 123 124 while( el ) 125 { 126 if( el.classList && el.classList.contains( 'avia_textblock' ) ) 127 { 128 move = el; 129 break; 130 } 131 132 el = el.nextSibling; 133 } 134 } 135 else if( this.settings.context == 'avia_sc_columns' ) 136 { 137 let el = this.foldContainer[0].nextSibling; 138 this.column = this.foldContainer[0].getElementsByClassName( 'av-fold-unfold-inner' ); 139 140 if( this.column.length ) 141 { 142 while( el ) 143 { 144 if( el.classList && el.classList.contains( 'av-fold-button-wrapper' ) ) 145 { 146 el = el.nextSibling; 147 } 148 else 149 { 150 const next = el.nextSibling; 151 this.column[0].append( el ); 152 el = next; 153 } 154 } 155 } 156 } 157 else 158 { 159 const el = this.container.nextSibling; 160 if( el ) 161 { 162 move = el; 163 } 164 } 165 166 if( move ) 167 { 168 this.foldContainer[0].append( move ); 169 } 170 } 171 172 checkMissingInnerContainers() 173 { 174 let retVal = false; 175 176 switch( this.settings.context ) 177 { 178 case 'avia_sc_text': 179 this.textblock = this.container.getElementsByClassName( 'avia_textblock' ); 180 181 if( this.textblock.length == 0 ) 182 { 183 retVal = true; 184 } 185 else 186 { 187 this.multiColumsTextblock = this.textblock[0].classList.contains( 'av_multi_colums' ); 188 } 189 break; 190 case 'avia_sc_grid_row': 191 this.gridRow = this.container.getElementsByClassName( 'av-layout-grid-container' ); 192 193 if( this.gridRow.length == 0 ) 194 { 195 retVal = true; 196 } 197 break; 198 case 'avia_sc_section': 199 this.colorSection = this.container.getElementsByClassName( 'avia-section' ); 200 201 if( this.colorSection.length == 0 ) 202 { 203 retVal = true; 204 } 205 break; 206 case 'avia_sc_columns': 207 if( ! this.column[0].childNodes.length ) 208 { 209 retVal = true; 210 } 211 break; 212 default: 213 // if we encounter a not supported container we ignore it 214 retVal = true; 215 } 216 217 return retVal; 218 } 219 220 isNested() 221 { 222 const parent = this.container.parentElement; 223 224 if( null == parent ) 225 { 226 return false;
227 } 228 229 let closest = parent.closest( '.avia-fold-unfold-section' ); 230 231 if( closest == parent ) 232 { 233 closest = null; 234 } 235 return closest != null; 236 } 237 238 bindEvents() 239 { 240 this.container.addEventListener( 'transitionend', this.onTransitionEnd.bind( this ) ); 241 this.container.addEventListener( 'webkitTransitionEnd', this.onTransitionEnd.bind( this ) ); 242 243 this.button[0].addEventListener( 'click', this.onClickFoldUnfold.bind( this ) ); 244 window.addEventListener( 'avia_fold_unfold_changed', this.onFoldUnfoldChanged.bind( this ) ); 245 window.addEventListener( 'resize', aviaJS.aviaJSHelpers.debounce( this.onResize.bind( this ), 200 ) ); 246 } 247 248 getMaxHeight() 249 { 250 switch( this.settings.context ) 251 { 252 case 'avia_sc_text': 253 this.innerDimension = this.textblock[0].getBoundingClientRect(); 254 break; 255 case 'avia_sc_grid_row': 256 this.innerDimension = this.gridRow[0].getBoundingClientRect(); 257 break; 258 case 'avia_sc_section': 259 this.innerDimension = this.colorSection[0].getBoundingClientRect(); 260 break; 261 case 'avia_sc_columns': 262 this.innerDimension = this.column[0].getBoundingClientRect(); 263 break; 264 } 265 } 266 267 foldChanged() 268 { 269 let btnText = '', 270 btnLink = ''; 271 272 if( this.folded ) 273 { 274 this.foldContainer[0].style['max-height'] = this.settings.height + 'px'; 275 btnText = this.settings.more; 276 btnLink = '#'; 277 } 278 else 279 { 280 this.getMaxHeight(); 281 282 // add some extra space to be on the safe side 283 this.foldContainer[0].style['max-height'] = Math.ceil( this.innerDimension.height ) + 200 + 'px'; 284 btnText = this.settings.less; 285 btnLink += '#' + this.id; 286 } 287 288 this.button[0].setAttribute( 'href', btnLink ); 289 this.button[0].textContent = btnText; 290 291 this.triggerHeightChange(); 292 } 293 294 onClickFoldUnfold( event ) 295 { 296 event.preventDefault(); 297 event.stopPropagation(); 298 299 if( this.foldContainer[0].classList.contains( 'folded' ) ) 300 { 301 this.foldContainer[0].classList.remove( 'folded' ); 302 this.foldContainer[0].classList.add( 'unfolded' ); 303 this.folded = false; 304 } 305 else 306 { 307 this.foldContainer[0].classList.remove( 'unfolded' ); 308 this.foldContainer[0].classList.add( 'folded' ); 309 this.folded = true; 310 } 311 312 this.foldChanged(); 313 314 let obj = this; 315 316 setTimeout( function() 317 { 318 const opt = { 319 'bubbles': true, 320 'cancelable': true, 321 detail: { caller: obj } 322 }; 323 324 const event = new CustomEvent( 'avia_fold_unfold_changed', opt ); 325 obj.container.dispatchEvent( event ); 326 }, 500 ); 327 } 328 329 onTransitionEnd( event ) 330 { 331 // removes max-height to allow smooth expanding on page load 332 this.container.classList.remove( 'avia-fold-init-done' ); 333 334 this.triggerHeightChange(); 335 } 336 337 onResize( event ) 338 { 339 this.foldChanged(); 340 } 341 342 onFoldUnfoldChanged( event ) 343 { 344 this.foldChanged(); 345 } 346 347 triggerHeightChange() 348 { 349 const opt = { 350 'bubbles': true, 351 'cancelable': true 352 }; 353 354 const event = new CustomEvent( 'avia_height_change', opt ); 355 window.dispatchEvent( event ); 356 } 357 } 358 359 // class factory 360 avia_js_shortcodes.aviaFoldUnfoldSection = function( container ) 361 { 362 return new avFoldUnfoldSection( container ); 363 }; 364 365 aviaJS.aviaPlugins.register( avia_js_shortcodes.aviaFoldUnfoldSection, '.avia-fold-unfold-section' ); 366 } 367 368})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.