1(function ( $ ) { 2 let NewsWall = function (el) { 3 let emergencyTemplate = { 4 rows: 1, 5 cols: 4, 6 cssClass: "grid-article-rectangle-emergency", 7 multiply: 1, 8 requiresImage: false 9 }; 10 let templates = [ 11 { 12 rows: 2, 13 cols: 2, 14 cssClass: "grid-article-square-large", 15 multiply: 1, 16 requiresImage: false 17 }, 18 { 19 rows: 1, 20 cols: 1, 21 cssClass: "grid-article-square-small", 22 multiply: 2, 23 requiresImage: false 24 }, 25 { 26 rows: 2, 27 cols: 1, 28 cssClass: "grid-article-rectangle-vertical-small", 29 multiply: 2, 30 requiresImage: true 31 }, 32 { 33 rows: 1, 34 cols: 2, 35 cssClass: "grid-article-rectangle-horizontal-small", 36 multiply: 2, 37 requiresImage: true 38 } 39 ]; 40 return $.extend(el,{ 41 articleList: null, 42 grid: null, 43 cursor: null, 44 getMaxCols: function () { 45 46 let passedCols = this.articleList.closest(".component.newslist").attr("data-wall-columns"); 47 48 if(passedCols !== "" && parseInt(passedCols)) { 49 passedCols = parseInt(passedCols); 50 } else { 51 passedCols = 7; 52 } 53 54 let width = this.articleList.width(); 55 let calcColumns; 56 57 if(width >= 1900) { 58 calcColumns = 7; 59 } else if (width >= 1600) { 60 calcColumns = 6; 61 } else if (width >= 1300) { 62 calcColumns = 5; 63 } else if (width >= 1000) { 64 calcColumns = 4; 65 } else if (width >= 768) { 66 calcColumns = 3 67 } else if (width >= 520) { 68 calcColumns = 2 69 }else { 70 calcColumns = 1; 71 } 72 //return smaller of toRet and wall columns 73 return Math.min(calcColumns,passedCols); 74 }, 75 addRow : function () { 76 let toAdd = []; 77 let maxCols = this.getMaxCols(); 78 for(let i = 0; i < maxCols; i++) { 79 toAdd.push(false); 80 } 81 this.grid.push(toAdd); 82 }, 83 reset: function() { 84 this.articleList = $(this).find(".article-list"); 85 this.cursor = { 86 row: 0, 87 col: 0 88 }; 89 this.grid = []; 90 this.addRow(); 91 }, 92 buildGrid: function() { 93 if(this.articleList == null) { 94 this.reset(); 95 } 96 97 let articles = this.articleList.find("article"); 98 99 let maxCols = this.getMaxCols(); 100 101 //check to see if we need to rebuild: 102 //if the size of untouched articles is 0 AND our resize operation didn't result in achange in the number of columns 103 if(articles.filter(".grid-article-base").size() === 0 && maxCols === this.articleList.attr("data-max-cols")) { 104 return; 105 } 106 107 //if this isn't a resize, filter down to just the new elements 108 if(maxCols === this.articleList.attr("data-max-cols")) { 109 articles = articles.filter(".grid-article-base"); 110 } else { 111 //else reset 112 this.reset() 113 } 114 115 this.articleList.attr("data-max-cols",maxCols); 116 117 //set the style for the number of columns 118 let gtc = ""; 119 for(let col = 0; col < maxCols; col++){ 120 gtc += "1fr "; 121 } 122 this.articleList.css({ 123 "grid-template-columns": gtc.trim() 124 }); 125 126 for(let i = 0; i < articles.length; i++) { 127 let seed = articles.eq(0).attr("data-article-id").substring(1); 128 //holds our search criteria when looking for a correctly sized block 129 let search = { 130 min: { 131 rows: 1, 132 cols: 1 133 }, 134 max: { 135 rows: 2, 136 cols: 1 137 } 138 }; 139 //look for the first blank spot in the grid, starting at the current row, 140 this.cursor.col = this.grid[this.cursor.row].indexOf(false); 141 //if there are no blank spots in the current row, look at the next row and advance the cursor 142 while(this.cursor.col === -1) { 143 this.cursor.row++; 144 if(typeof this.grid[this.cursor.row] == 'undefined') { 145 this.addRow(); 146 } 147 this.cursor.col = this.grid[this.cursor.row].indexOf(false); 148 } 149 let cardStyleForced = this.articleList.attr("data-card-style") === 'forceCard' && this.articleList.attr("data-force-card-style") != null; 150 let cssStyleForced = this.articleList.attr("data-card-style") === 'forceCSS' && this.articleList.attr("data-force-css-style") != null; 151 if(!cssStyleForced) { 152 if(cardStyleForced) { 153 let fcs = this.articleList.attr("data-force-card-style").split(","); 154 search.min.cols = fcs[0]; 155 search.max.cols = fcs[0]; 156 search.min.rows = fcs[1]; 157 search.max.rows = fcs[1]; 158 } else { 159 //allowed tempaltes 160 //get the blank spaces available to the right 161 while(this.cursor.col + search.max.cols < maxCols && 162 this.grid[this.cursor.row][this.cursor.col + search.max.cols] === false) { 163 search.max.cols++; 164 } 165 //DISABLED FOR NOW, since 1,1 isn't an option pre latest changes (aug 2018) 166 // if we have maxCols or fewer, set to the max available rows dont allow the createion of new rows, avoids hanging items 167 // if(i > articles.length - maxCols) { 168 // search.max.rows = 1; 169 // } 170 } 171 172 let $article = $(articles).eq(i); 173 //let articleImageAssigned = ($article.attr("data-image-assigned") === 'true'); 174 let isEmergency = $article.hasClass("emergency") 175 176 let choice = emergencyTemplate; 177 if(isEmergency) { 178 choice.cols = this.getMaxCols(); 179 } else { 180 //we've got our search criteria, now filter the templates array and choose a random one 181 //horizontal image isn't an option for regular newslists 182 let allowedTemplates = templates.filter(function(candidate) { 183 return (cardStyleForced || candidate.cssClass !== "grid-article-rectangle-horizontal-small" && candidate.cssClass !== "grid-article-square-small") 184 }) 185 186 let filtered = allowedTemplates.filter(function(template) { 187 let colsAndRowsLTMax = (template.cols <= search.max.cols && template.rows <= search.max.rows); 188 let colsAndRowsGTMIN = (template.cols >= search.min.cols && template.rows >= search.min.rows); 189 //let imageRequired = (cardStyleForced || !template.requiresImage || template.requiresImage && articleImageAssigned) 190 return colsAndRowsLTMax && colsAndRowsGTMIN; // && imageRequired; 191 }); 192 193 //multiply each filter item by its multiplier 194 let choices = []; 195 filtered.forEach(function(fi){ 196 for(let n = 0; n < fi.multiply; n++) { 197 choices.push(fi); 198 } 199 }) 200 let choiceIndex = Math.floor(Math.random(seed) * choices.length) 201 choice = choices[choiceIndex]; 202 203 } 204 //random choice 205 //set the css and add the class name 206 let gridCss = { 207 "grid-row": (this.cursor.row + 1) + " / " + (this.cursor.row + 1 + choice.rows), 208 "grid-column": (this.cursor.col + 1) + " / " + (this.cursor.col + 1 + choice.cols) 209 }; 210 211 $article.css(gridCss).removeClass(function (index, className) { 212 return (className.match (/(^|\s)grid-article-\S+/g) || []).join(' '); 213 }).addClass(choice.cssClass); 214 215 //potentially adding a new rows, if the number of rows or c
215ols needed exceeds those available 216 if(this.cursor.row + choice.rows > this.grid.length || this.cursor.col + choice.cols === maxCols) { 217 for(let j = 0; j < choice.rows; j++) { 218 this.addRow(); 219 } 220 } 221 //shade in the grid 222 for(let j = this.cursor.row; j < this.cursor.row + choice.rows; j++) { 223 for(let k = this.cursor.col; k < this.cursor.col + choice.cols; k++) { 224 this.grid[j][k] = true; 225 } 226 } 227 } 228 } 229 let btn = this.articleList.find("span[data-replace-with]"); 230 //set the end of the load more button, if applicale 231 $(btn).css({ 232 "grid-column" : "1" + " / " + (maxCols + 1) 233 }); 234 window.initImages(); 235 } 236 }); 237 }; 238 $(document).ready(function() { 239 $(".component.newslist").each(function(index,element) { 240 let articleList = $(element).find(".article-list"); 241 if(!(articleList.is(".wall") || articleList.is(".list") )) { 242 return 243 } 244 if(articleList.is(".list")) { 245 articleList.attr("data-force-card-style","2,1"); 246 } 247 element = NewsWall(element); 248 element.buildGrid(); 249 let resizeTimer; 250 $(window).on('resize', function() { 251 //throttles 252 clearTimeout(resizeTimer); 253 resizeTimer = setTimeout(function() { 254 element.reset(); 255 element.buildGrid(); 256 }, 250); 257 }); 258 return element; 259 }); 260 }) 261}( jQuery )); 262(function ( $ ) { 263 264 var selector = "button,[role='button']" 265 266 //replace with -- next page button 267 function registerReplaceWith() { 268 $("span[data-replace-with]").off("click.replacewith keypress.replacewith"); 269 $("span[data-replace-with]").on("click.replacewith keypress.replacewith",function(event) { 270 event.preventDefault(); 271 $(event.currentTarget).off("click.replacewith keypress.replacewith"); 272 if(event.type=="keypress" && (event.keyCode == 32 || event.keyCode == 13) 273 || event.type == "click") 274 getReplaceContent(event.currentTarget); 275 }); 276 } 277 function getReplaceContent(element) { 278 $(element).addClass("loading").find(selector).text("loading..."); 279 280 var path = $(element).attr("data-path"); 281 var url = path + (path.indexOf('?') > -1 ? '&' : '?') + 'nocache=true'; 282 var req = $.ajax({ 283 url: url, 284 beforeSend: function( xhr ) { 285 xhr.setRequestHeader("unwrap","true"); 286 xhr.setRequestHeader("loadmore","true"); 287 xhr.setRequestHeader("hide-search-header","true"); 288 } 289 }); 290 req.setRequestHeader("unwrap","true") 291 var lma = $(element).attr("data-load-more-attr"); 292 var lmv = $(element).attr("data-load-more-value"); 293 var $list = $(element).closest(".article-list"); 294 $list.parent().find(".rss-link").remove(); 295 296 $("[data-notifier]").html(""); 297 298 req.done(function(data) { 299 //replace the old replace with, with this content 300 $(element).after(data); 301 if($list.is(".wall") || $list.is(".list")) { 302 $(element).closest(".component.newslist")[0].buildGrid(); 303 } 304 305 $(element).remove(); 306 registerReplaceWith(); 307 308 if(lma != null) { 309 var params = window.location.search.split("&"); 310 var foundPage = false; 311 var url = new URL(window.location.href); 312 url.searchParams.set(lma,lmv); 313 window.history.pushState({"html":document.documentElement.innerHTML},"",url.href); 314 $("[data-notifier]").html("Next Page loaded"); 315 } 316 317 }) 318 .fail(function(data) { 319 320 $(element).removeClass("loading").find(selector).text("Load More"); 321 var error = $("<span></span>") 322 .addClass("alert alert-warning") 323 .text("Error loading next page, please try again"); 324 console.log(data) 325 $(element).find(selector).after(error); 326 registerReplaceWith(); 327 //display some error 328 }) 329 330 } 331 window.registerReplaceWith = function() { 332 registerReplaceWith(); 333 } 334 $(document).ready(function() { 335 registerReplaceWith(); 336 }); 337 338}( jQuery )); 339(function ( $ ) { 340 341 var SearchList = function(el) { 342 343 return $.extend(el,{ 344 345 query: {}, 346 query_props: [], 347 currentReq: null, 348 initQuery: function() { 349 350 var passed_hash = {}; 351 var $that = $(this); 352 353 this.query_props = ["term","start","end","showEvents","authors","orderby","orderby.sort"]; 354 var namespaces = $that.attr("data-namespaces").split(","); 355 this.query_props = this.query_props.concat(namespaces); 356 357 this.query_props.forEach(function(prop) { 358 passed_hash[prop] = $that.find(".search_options").find("[data-key='" +prop +"']").attr("data-value"); 359 }) 360 361 this.query = passed_hash; 362 }, 363 reload: function(facets, fromsearch) { 364 365 if(typeof facets != "undefined") { 366 this.query = facets; 367 } 368 369 if(this.query == null) 370 this.query = {}; 371 372 this.query["submitted"] = "submitted"; 373 374 var $that = $(this); 375 //update the search options 376 if(typeof facets != "undefined") { 377 this.query_props.forEach(function(prop) { 378 $that.find(".search_options").find("[data-key='" +prop +"']").attr("data-value",facets[prop]); 379 }) 380 } 381 382 var list = $(this).find(".article-list"); 383 384 //abort any requests currently loading 385 if(list.hasClass("loading")){ 386 if(this.currentReq != null) 387 this.currentReq.abort(); 388 } 389 390 //get the page 391 392 var path = $(this).attr("data-path"); 393 394 this.currentReq = $.ajax({ 395 url: path + ".html?nocache=true", 396 method: "GET", 397 data: this.getQueryString(this.query), 398 beforeSend: function( xhr ) { 399 xhr.setRequestHeader("unwrap","true"); 400 } 401 }); 402 403 list.addClass("loading"); 404 $(this).find(".rss-link").remove(); 405 var that = this; 406 407 $("[data-notifier]").html(""); 408 409 this.currentReq.done(function(data) { 410 411 var list = $(that).find(".article-list"); 412 var runOnce = false;
413 414 list.empty(); 415 list.append(data) 416 .removeClass("loading"); 417 registerReplaceWith(); 418 that.reset(); 419 that.registerReorder(); 420 that.buildGrid({row: 1, col: 0}); 421 window.refreshPopup(list); 422 423 $("[data-notifier]").html("Stories loaded"); 424 425 return true; 426 }) 427 .fail(function(data,status) { 428 if(status != 'abort') { 429 var error = $("<span></span>") 430 .addClass("alert").addClass("alert-warning") 431 .text("Error Updating Search Results. Click here to try again.") 432 .on("click keydown",function(event) { 433 list.closest(".newslist").reload(); 434 }); 435 list.removeClass("loading"); 436 $(list.children()[0]).before(error); 437 //display some error 438 } 439 440 return false; 441 }); 442 }, 443 getQueryString: function(hash) { 444 //builds a new query string 445 var qs = "page=0"; 446 447 qs += "&submitted=submitted"; 448 449 450 if(typeof hash == "undefined") 451 return qs; 452 453 this.query_props.forEach(function(prop){ 454 if(typeof hash[prop] != "undefined" && hash[prop] != null) { 455 if(Object.prototype.toString.call( hash[prop] ) === '[object Array]') { 456 hash[prop].forEach(function(facet) { 457 qs += "&" + prop + "=" + facet; 458 }); 459 } else { 460 qs += "&" + prop + "=" + hash[prop]; 461 } 462 } 463 }) 464 return qs 465 }, 466 registerReorder: function() { 467 468 var that = this; 469 var button = $(this).find("button[aria-controls=sort-dims]"); 470 var dims = $(this).find("#sort-dims"); 471 var dim = dims.find("li a"); 472 473 474 dim.on("click",function(event){ 475 that.reorder(event.currentTarget); 476 button.trigger("click"); 477 dims.find(".active").removeClass("active"); 478 $(event.currentTarget).addClass("active") 479 }); 480 dim.on("keypress",function(event){ 481 if(event.keycode == 13 || event.keycode == 32) { 482 that.reorder(event.currentTarget) 483 button.trigger("click"); 484 dims.find(".active").removeClass("active"); 485 $(event.currentTarget).addClass("active") 486 } 487 }); 488 489 }, 490 reorder: function(element) { 491 this.query.orderby = $(element).attr("data-orderby"); 492 this.query["orderby.sort"] = $(element).attr("data-orderby-sort"); 493 this.reload(); 494 } 495 }); 496 497 } 498 $(document).ready(function() { 499 //reloading for search page 500 $(".component.newslist").each(function(index,element) { 501 if(!$(element).hasClass("newslist-v2")) { 502 element = SearchList(element); 503 element.initQuery(); 504 element.registerReorder(); 505 } 506 }); 507 }) 508 509}( jQuery ));
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.