1/* 2 * View pages within this site are controled by the 3 * Content Views Pro plugin, this file adjusts submit 4 * buttons text for different view pages based on class. 5 */ 6(function ($) { 7 // We are listening for the view wrapper 8 const targetView = document.querySelector(".pt-cv-wrapper"); 9 10 if (targetView) { 11 // Attach styles for view content, this loads first 12 document.addEventListener( 13 "DOMContentLoaded", 14 function () { 15 document.querySelector(".pt-cv-view").classList.add("view-content"); 16 }, 17 false 18 ); 19 20 // Options for the observer (which mutations to observe) 21 const config = { childList: true, subtree: true }; 22 23 // Create an observer instance linked to the callback function 24 const observer = new MutationObserver(updateView); 25 26 // Start observing the page for changes within the views 27 observer.observe(targetView, config); 28 29 // Handle updating filter buttons within views 30 function updateView() { 31 // Disconnect to make changes 32 observer.disconnect(); 33 34 // Attach styles to view content if content changed/was updated 35 $(".pt-cv-view").addClass("view-content"); 36 37 let visiblePosts = $(".pt-cv-page:not(.no-posts) .pt-cv-content-item"); 38 let searchInput = $(".cvp-live-filter input"); 39 let searchSelect = $(".cvp-live-filter select option[selected]"); 40 let searchString = ""; 41 let searchText = ""; 42 let optionFilters = ""; 43 let options = []; 44 let count = visiblePosts.length ? visiblePosts.length : 0; 45 let resetBtn = $(".cvp-live-reset"); 46 47 if (count == 1) { 48 count = count + " result"; 49 } else { 50 count = count + " results"; 51 } 52 53 // If user selected options 54 if (searchSelect.length > 0) { 55 $.each(searchSelect, (index, value) => { 56 options.push($(value).text()); 57 }); 58 59 optionFilters = options.join(" , "); 60 } 61 // If user searched text 62 if (searchInput.val().length > 0) { 63 searchString = searchInput.val(); 64 } 65 66 // If filters are used, build string 67 if (searchString.length > 0 && optionFilters.length > 0) { 68 searchText = ' for "' + searchString + " , " + optionFilters + '"'; 69 70 // Add text to search results 71 count = count + searchText; 72 73 $(resetBtn).addClass("PC-filter-view-active"); 74 } else if (searchString.length > 0 || optionFilters.length > 0) { 75 searchText = ' for "' + searchString + optionFilters + '"'; 76 77 // Add text to search results 78 count = count + searchText; 79 80 $(resetBtn).addClass("PC-filter-view-active"); 81 } 82 83 // If it already exists, update content 84 if ($("#announcements").length > 0) { 85 $("#announcements").text("Showing " + count); 86 wp.a11y.speak( "Showing " + count, 'polite' ); 87 } else { 88 // Build inital 89 let $announcement = $( 90 "<h2>", 91 { 92 "aria-live": "polite", 93 class: "visually-hidden", 94 id: "announcements", 95 text: "Showing " + count, 96 }, 97 "</h2>" 98 ); 99 $($announcement).insertBefore(".pt-cv-view"); 100 wp.a11y.speak( "Showing " + count, 'polite' ); 101 } 102 103 // Attach aria-labels for filters 104 $('select[name="tx_country"]').attr("aria-label", "Select country"); 105 $('select[name="tx_country"]').attr("id", "tx_country"); 106 $('select[name="tx_country"]').prev().attr("for", "tx_country"); 107 108 $('select[name="tx_post_tag"]').attr("aria-label", "Select media type"); 109 $('select[name="tx_post_tag"]').attr("id", "tx_post_tag"); 110 $('select[name="tx_post_tag"]').prev().attr("for", "tx_post_tag"); 111 112 $('select[name="tx_topic"]').attr("aria-label", "Select topic"); 113 $('select[name="tx_topic"]').attr("id", "tx_topic"); 114 $('select[name="tx_topic"]').prev().attr("for", "tx_topic"); 115 116 // Adjust text for filter buttons 117 var $view = $(".cvp-live-submit"); 118 var pageClasses = ($("#content").attr("class") || "").split(" "); 119 120 for ( 121 var index = 0, length = pageClasses.length; 122 index < length; 123 index++ 124 ) { 125 switch (pageClasses[index]) { 126 case "insights-page": 127 $view.text("Filter Insights"); 128 break;
129 case "media-page": 130 $view.text("Filter Media"); 131 break; 132 case "people-page": 133 $view.text("Search Staff"); 134 break; 135 case "projects-page": 136 $view.text("Filter Projects"); 137 // Replace default images 138 defaultImages(); 139 break; 140 default: 141 break; 142 } 143 } 144 145 // Wrap .pt-cv-ctf-value content inside <p> for semantics 146 $(".pt-cv-ctf-value").each(function () { 147 const $el = $(this); 148 if ($el.children("p").length === 0) { 149 $el.html("<p>" + $el.html().trim() + "</p>"); 150 } 151 }); 152 153 // Transform cards into <article> for Projects page 154 enhanceProjectsGrid(); 155 156 // Listen for when new changes happen 157 observer.observe(targetView, config); 158 } 159 160 // Content Views Pro pulls from inline content when no featured image 161 // override the pulled content with the correct default 162 // NOTE: This only applied to the projects view 163 function defaultImages() { 164 const needReplacement = $(".pt-cv-content-item .img-none.cvp-substitute"); 165 const base_url = window.location.origin; 166 const default_image = document.createElement("img"); 167 168 // Build default image 169 default_image.setAttribute( 170 "src", 171 base_url + 172 "/wp-content/themes/Avada-Child-Theme/assets/images/placeholder.svg" 173 ); 174 default_image.setAttribute("height", "1024"); 175 default_image.setAttribute("width", "1024"); 176 default_image.setAttribute("alt", ""); 177 178 // Replace inline content with default 179 needReplacement.each((element) => { 180 needReplacement[element].replaceWith(default_image); 181 }); 182 } 183 } 184 185 function enhanceProjectsGrid() { 186 // Only run if the #content wrapper has .projects-page 187 if (!document.querySelector("#content.projects-page")) return; 188 189 $(".pt-cv-content-item").each(function (index) { 190 const $item = $(this); 191 192 // Skip if already an <article> 193 if ($item.is("article")) return; 194 195 const $article = $("<article>", { role: "article" }); 196 197 const $heading = $item.find("h3").first(); 198 if ($heading.length) { 199 const headingId = $heading.attr("id") || `project-card-title-${index}`; 200 $heading.attr("id", headingId); 201 $article.attr("aria-labelledby", headingId); 202 } 203 204 $article.append($item.contents()); 205 $item.replaceWith($article); 206 }); 207 } 208})(jQuery); 209 210// Adjust text on search button for search landing page 211(function ($) { 212 const searchButton = $( 213 ".fusion-search-element-3 .fusion-search-form-content .search-button input" 214 ); 215 if (searchButton) { 216 // Adjust input text 217 searchButton.attr("value", "Search"); 218 } 219})(jQuery); 220 221// Remove wrapper around images within views/archives 222// Also remove incorrect aria 223(function ($) { 224 $(".fusion-image-wrapper").removeAttr("aria-haspopup"); 225 $(".fusion-image-wrapper a > img").unwrap(); 226})(jQuery); 227 228// Remove odd title field being set on views 229(function ($) { 230 $(".pt-cv-meta-fields a").each(function () { 231 if ($(this).attr("title")) { 232 $(this).removeAttr("title"); 233 } 234 }); 235})(jQuery); 236 237// Fix search results headings for accessibility 238(function ($) { 239 $(document).ready(function () { 240 // Only run if the body wrapper has .search-results 241 if (!document.querySelector("body.search-results")) return; 242 243 const $resultsHeading = $(".fusion-text-2 p"); 244 const $resultsQuery = $(".fusion-text-3 p"); 245 246 if ($resultsQuery.length) { 247 248 $resultsQuery.prepend(" ").detach().appendTo($resultsHeading); 249 } 250 251 if ($resultsHeading.length && $resultsHeading.prop("tagName") !== "H2") { 252 $resultsHeading.replaceWith(function () { 253 return $("<h2>", { text: $(this).text(), class: "results-count" }); 254 }); 255 } 256 257 $("h2.blog-shortcode-post-title").each(function () { 258 $(this).convertElement('h3'); 259 }); 260 }); 261})(jQuery); 262 263// Converting a DOM element into a specified new type of element 264jQuery.fn.convertElement = function (newType) { 265 if (!jQuery(this[0]) || jQuery(this[0]) == undefined || !jQuery(this[0]).length) { 266 return; 267 } else { 268 var atts = {}; 269 270 jQuery.each(this[0].attributes, function (idx, attr) { 271 atts[attr.nodeName] = attr.nodeValue; 272 }); 273 274 this.replaceWith(function () { 275 return jQuery("<" + newType + "/>", atts).append(jQuery(this).contents()); 276 }); 277 } 278}
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.