1 2// Keep alerts that were retrieved from the API 3let modalert_alerts = {}; 4 5/** 6 * Retrieve relevant alerts from the API. 7 * This should typically run once per pageload, but can be repeated if necessary. 8 */ 9function modalert_get_alerts() { 10 11 var request = new XMLHttpRequest(); 12 var context = saas_ajax_get_layout_context( document.querySelector( '.page-wrapper' ), {} ); 13 14 request.open( 'POST', modalert.endpoint, true ); 15 request.setRequestHeader( 'Content-Type', 'application/json' ); 16 if ( User_Token.get_token() ) { 17 request.setRequestHeader( 'Authorization', 'Bearer ' + User_Token.get_token() ); 18 } 19 20 request.onload = function() { 21 22 // Process response 23 if ( this.response ) { 24 modalert_alerts = JSON.parse( this.response ); 25 modalert_process_alerts(); 26 } 27 28 }; 29 request.send( JSON.stringify( context ) ); 30 31} 32 33/** 34 * Populate FE elements with alerts. 35 * This can be fired more than once in case alert areas are loaded in later. 36 */ 37function modalert_process_alerts() { 38 39 const top_alert_bar = document.querySelector( '.alert-bar' ); 40 const contentblocks = document.querySelectorAll( '.owcb-block--modalert-alert-block' ); 41 for ( const location in modalert_alerts ) { 42 43 const alerts = modalert_alerts[ location ]; 44 45 // Top bar 46 if ( location === 'top' && top_alert_bar ) { 47 48 const alert = alerts[0]; 49 50 // Set content and styling 51 top_alert_bar.querySelector( '.-content' ).innerHTML = alert.content; 52 top_alert_bar.classList.add( 'bg-' + alert['style'] ); 53 top_alert_bar.classList.add( 'text-' + alert['text-color'] ); 54 top_alert_bar.classList.add( '-link-' + alert['link-color'] ); 55 56 // Show 57 document.querySelector( 'body' ).classList.add( '-has-alert-bar' ); 58 top_alert_bar.classList.remove( 'd-none' ); 59 60 // Re-init icons in the just-populated alert bar 61 if ( typeof window.FontAwesome !== 'undefined' ) { 62 window.FontAwesome.dom.i2svg( { node: top_alert_bar } ); 63 } 64 65 } 66 67 // Contentblock(s) 68 if ( location === 'contentblock' && contentblocks ) { 69 contentblocks.forEach( ( contentblock ) => { 70 71 // Skip closed alerts 72 if ( typeof localStorage !== 'undefined' ) { 73 74 let localstorage_key, alert; 75 for ( const index in alerts ) { 76 alert = alerts[ index ]; 77 localstorage_key = 'modalert-closed-' + alert.id; 78 if ( localStorage.getItem( localstorage_key ) ) { 79 alerts.splice( index, 1 ); 80 } 81 } 82 83 } 84 85 // Populate and show the contentblock 86 if ( alerts.length ) { 87 88 // Populate contentblock alerts 89 saas_set_node_values( { 'modalert-alert': alerts }, contentblock ); 90 91 // Show contentblock 92 contentblock.classList.remove( 'd-none', 'modalert-d-none' ); 93 contentblock.classList.replace( 'owcb-has-bg-image', 'owcb-has-no-bg-image' ); 94 95 // Re-init icons in the just-populated contentblock 96 if ( typeof window.FontAwesome !== 'undefined' ) { 97 window.FontAwesome.dom.i2svg( { node: contentblock } ); 98 } 99 100 } 101 102 } ); 103 } 104 105 } 106 107} 108 109// Init on pageload 110document.addEventListener( 'DOMContentLoaded', modalert_get_alerts ); 111 112// Re-populate when an alert area is loaded in later via an ajax-template-parts swap 113// (e.g. an alert contentblock inside a conditional-content page rendered over ajax). 114// 115// ajax-template-loaded fires after every swap. In "innerHTML" mode the swapped element 116// stays in the document with the new content inside it, so we can scope the re-process to 117// swaps that actually touch an alert block. In "replace" mode the original placeholder is 118// detached and replaced by the new content â and it may be a comment node (e.g. the 119// conditional-content page render) with no matches()/querySelector() â so it can't be 120// introspected; re-process the whole document in that case. 121document.body.addEventListener( 'ajax-template-loaded', ( e ) => { 122 123 const target = e.detail && e.detail.target; 124 const is_attached_element = target && typeof target.matches === 'function' && document.contains( target ); 125 126 if ( 127 ! is_attached_element || 128 target.matches( '.owcb-block--modalert-alert-block' ) || 129 target.querySelector( '.owcb-block--modalert-alert-block' ) 130 ) { 131 modalert_process_alerts(); 132 } 133 134} ); 135 136// Close-alert click event 137document.addEventListener( 'click', ( e ) => { 138 if ( e.target.classList.contains( 'modalert-close' ) ) { 139 140 const parent = e.target.closest( '.modalert-parent' ); 141 const contentblock = parent.closest( '.owcb-block--modalert-alert-block' ); 142 143 // Save status to localstorage 144 const id = parent.querySelector( '[data-node="id"]' ).textContent; 145 const localstorage_key = 'modalert-closed-' + id; 146 if ( typeof localStorage !== 'undefined' ) { 147 localStorage.setItem( localstorage_key, 1 ); 148 } 149 150 // Delete the element 151 parent.remove(); 152 153 // If this is the last showing alert, also hide the block. 154 if ( ! contentblock.querySelector( '[data-clone-target="modalert-alert"] .modalert-parent' ) ) { 155 contentblock.classList.add( 'd-none', 'modalert-d-none' ); 156 contentblock.classList.replace( 'owcb-has-no-bg-image', 'owcb-has-bg-image' ); 157 } 158 159 } 160} );
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.