1var airflowSaved = []; 2const airflowDebounce = (callback, wait) => { 3 let timeoutId = null; 4 return (...args) => { 5 window.clearTimeout(timeoutId); 6 timeoutId = window.setTimeout(() => { 7 callback.apply(null, args); 8 }, wait); 9 }; 10} 11 12const handleNewAirflowEntries = airflowDebounce((ev) =>{ 13 var tbody = document.getElementById('search-results'); 14 addBookmarkToggle(tbody); 15}, 100 ) 16 17function addBookmarkToggle(tbody) { 18 var rows = tbody.children; 19 for( var i = 0; i < rows.length; i++ ) { 20 var row = rows[i]; 21 var isSaved = false; 22 var uuid = row.getAttribute('data-uuid'); 23 if( uuid && airflowSaved.indexOf(uuid) > -1 ) { 24 isSaved = true; 25 } 26 var bookmark = row.querySelector('.tac-bookmark'); 27 if( !bookmark ) { 28 var title = row.querySelector('.news-title'); 29 if( title ) { 30 var bookmarkWrap = document.createElement('span'); 31 bookmarkWrap.classList.add('tac-feed-bookmark-wrap'); 32 var bookmarkBox = document.createElement('i'); 33 bookmarkBox.classList.add('tac-bookmark'); 34 if( isSaved ) { 35 bookmarkBox.classList.add('bookmarked'); 36 } 37 bookmarkBox.setAttribute('data-tooltip','Save for later') 38 bookmarkBox.classList.add('fa'); 39 bookmarkBox.classList.add('fa-bookmark'); 40 bookmarkWrap.append(bookmarkBox); 41 var bookmarkMessage = document.createElement('div'); 42 bookmarkMessage.classList.add('tac-feed-bookmark-message'); 43 bookmarkMessage.textContent = 'Saved!'; 44 bookmarkWrap.append(bookmarkMessage); 45 title.prepend(bookmarkWrap); 46 } 47 } 48 } 49} 50 51function airflowBookmarks() { 52 var table = document.querySelector('#airflow-container table'); 53 if( table ) { 54 var tbody = document.getElementById('search-results'); 55 console.log('airflow ready'); 56 const config = { attributes: false, childList: true, subtree: false }; 57 const callback = function (mutationsList, observer) { 58 // Use traditional 'for loops' for IE 11 59 for (const mutation of mutationsList) { 60 if (mutation.type === "childList") { 61 handleNewAirflowEntries(tbody); 62 } 63 } 64 }; 65 66 // Create an observer instance linked to the callback function 67 const observer = new MutationObserver(callback); 68 69 // Start observing the target node for configured mutations 70 observer.observe(tbody, config); 71 addBookmarkToggle(tbody); 72 } else { 73 window.setTimeout( airflowBookmarks, 1000 ); 74 } 75} 76 77function bookmarkAirflowAjax( method = 'GET', url = '/init', payload = {}, fn ) { 78 // Create the XMLHttpRequest object. 79 const xhr = new XMLHttpRequest(); 80 // Initialize the request 81 xhr.open( method, '/wp-json/tac-save-for-later/v1'+ url ); 82 // Send the request 83 if( method != 'GET' ) { 84 var data = JSON.stringify(payload); 85 xhr.send(data); 86 } else { 87 xhr.send(); 88 } 89 // Fired once the request completes successfully 90 xhr.onload = function(e) { 91 // Check if the request was a success 92 if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { 93 // Get and convert the responseText into JSON 94 var response = JSON.parse(xhr.responseText); 95 fn(response); 96 } 97 } 98} 99 100function updateAirflowBookmark( el ) { 101 console.log('updating bookmark - airflow') 102 var url = '/' 103 if( el.classList.contains('bookmarked') ) { 104 url += 'remove_airflow/'; 105 el.classList.remove('bookmarked'); 106 } else { 107 url += 'add_airflow/'; 108 el.nextSibling.classList.add('show'); 109 window.setTimeout(function(){ 110 el.nextSibling.classList.remove('show'); 111 },1300); 112 el.classList.add('bookmarked'); 113 } 114 url += el.closest('tr').getAttribute('data-uuid'); 115 bookmarkAirflowAjax('GET', url, {}, function(response){ 116 console.log('updated') 117 console.log(response) 118 /* In case of failure we revert/update */ 119 if( response.saved ) { 120 el.classList.add('bookmarked'); 121 } else { 122 el.classList.remove('bookmarked'); 123 } 124 }); 125} 126 127function setupAirflowBookmarks() { 128 bookmarkAirflowAjax('GET','/init_airflow', {}, function(response){ 129 console.log(response); 130 if( response.show ) { 131 window.setTimeout( airflowBookmarks, 1000 ); 132 } 133 if( response.saved ) { 134 airflowSaved = response.saved; 135 } 136 document.body.addEventListener("click", function (e) { 137 if (e.target && (e.target.classList.contains("tac-bookmark") 138 ||(e.target.parentElement && e.target.parentElement.classList.contains("tac-bookmark")) ) ) { 139 if( e.target.classList.contains("tac-bookmark") ) {
140 updateAirflowBookmark( e.target ); 141 } else { 142 updateAirflowBookmark( e.target.parentElement ); 143 } 144 e.preventDefault(); 145 e.stopPropagation(); 146 return false; 147 } 148 }); 149 }) 150} 151 152document.addEventListener("DOMContentLoaded", () => { 153 /* Airflow */ 154 if(document.body.classList.contains('page-id-16115')) { 155 setupAirflowBookmarks(); 156 } 157}); 158
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.