PageSourceSearch

https://www.uc.edu/etc.clientlibs/news/components/content/newsList…e.lc-82d36eff97b4dded9c424cb66b2c974d-lc.js

js uc.edu collected 2026-09-24 07:15:24 UTC 21,199 bytes, 509 lines download raw bytes

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.