1// First function run if not run locally, it initializes everything 2// - data: the fetched dataset from the API 3// - cardInfo: person info if in the person context 4function jsFilter_initList(data, cardInfo) { 5 jsFilter_initEventHandlers(); 6 //data = jsFilter_removeDuplicatesObjects(data); 7 jsFilter_putLoadingScreen(); 8 setTimeout(() => { 9 jsFilter_intranetAdaptations(data, cardInfo); 10 11 jsFilter_initNavButtons(cardInfo); 12 13 const listingPanel = document.getElementById("listingPanel"); 14 15 // On a person's page (author profile shown above), leave extra vertical 16 // space between their information and the lists below. 17 if ( 18 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != null && 19 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "" 20 ) { 21 listingPanel.classList.add("member-listingJS"); 22 } 23 24 const infoPanel = iidHTML("div", ""); 25 infoPanel.id = "infoPanel"; 26 27 listingPanel.appendChild(infoPanel); 28 29 if (data.length == 0) { 30 jsFilter_removeLoadingScreen(); 31 const noInfo = iidHTML("h2", ""); 32 switch (jsFilter_currentContext) { 33 case "Publications": 34 noInfo.textContent = "No publications available."; 35 infoPanel.appendChild(noInfo); 36 break; 37 case "Supervision": 38 noInfo.textContent = "No supervisions available."; 39 infoPanel.appendChild(noInfo); 40 break; 41 case "Projects": 42 noInfo.textContent = "No projects available."; 43 infoPanel.appendChild(noInfo); 44 break; 45 case "About": 46 const biographyHeader = iidHTML("h2", "Biography"); 47 if ( 48 cardInfo["biography"] == null || 49 cardInfo["biography"] == "" || 50 cardInfo["biography"] == "<p><span style=" 51 ) { 52 biographyHeader.textContent = "No biography available."; 53 infoPanel.appendChild(biographyHeader); 54 } else { 55 const biography = iidHTML("div", ""); 56 biography.innerHTML = cardInfo["biography"]; 57 infoPanel.appendChild(biographyHeader); 58 infoPanel.appendChild(biography); 59 } 60 if ( 61 !( 62 cardInfo["mainInterests"] == null || 63 cardInfo["mainInterests"] == "" || 64 cardInfo["mainInterests"] == "<p><span style=" 65 ) 66 ) { 67 const mainInterestsHeader = iidHTML( "h2", "Main Interests"); 68 const mainInterests = iidHTML("div", ""); 69 mainInterests.innerHTML = cardInfo["mainInterests"]; 70 infoPanel.appendChild(mainInterestsHeader); 71 infoPanel.appendChild(mainInterests); 72 } 73 break; 74 75 default: 76 break; 77 } 78 } else { 79 const title = iidHTML("h2", ""); 80 title.id = "title"; 81 82 const orderDIV = iidHTML("div", ""); 83 orderDIV.id = "orderDIV"; 84 85 infoPanel.appendChild(title); 86 infoPanel.appendChild(orderDIV); 87 88 // Group the heading, count, and ordering controls into a single top bar. 89 // The page heading (a plain title, not an author card) moves into the 90 // bar; author pages have no heading here and keep their card above. 91 if ( 92 jsFilter_currentContext === "Publications" || 93 jsFilter_currentContext === "People" || 94 jsFilter_currentContext === "Supervision" || 95 jsFilter_currentContext === "Projects" 96 ) { 97 infoPanel.classList.add("listing-topbarJS"); 98 const heading = document.querySelector("#authorNav h1"); 99 if (jsFilter_isGlobalAllListing()) { 100 // The combined #title ("Publications 2013-2016 (386)") becomes the 101 // title here, replacing the "All X" heading. 102 title.classList.add("listing-title-mainJS"); 103 if (heading != null) 104 document.getElementById("authorNav").style.display = "none"; 105 } else if (heading != null) { 106 infoPanel.insertBefore(heading, infoPanel.firstChild); 107 document.getElementById("authorNav").style.display = "none"; 108 } 109 } 110 111 const itemList = iidHTML("div", ""); 112 itemList.id = "itemList"; 113 114 listingPanel.appendChild(itemList); 115 116 const filterPanel = iidHTML("div", ""); 117 filterPanel.id = "filter-panel"; 118 119 const rightSide = document.getElementById("rightSide"); 120 121 rightSide.appendChild(filterPanel); 122 123 jsFilter_originalData = jsFilter_stringDataToInt( 124 data, 125 jsFilter_orderMapping[jsFilter_currentContext]["Year"] 126 ); 127 jsFilter_initOrderBy(); 128 jsFilter_initFilterPanel(jsFilter_contexMapping[jsFilter_currentContext]); 129 jsFilter_createList(jsFilter_originalData); 130 let needsReCalculate = false;
131 Object.keys(jsFilter_currentFilters).forEach((key) => { 132 if (jsFilter_currentFilters[key].length > 0) needsReCalculate = true; 133 }); 134 setTimeout(() => { 135 if (needsReCalculate) { 136 jsFilter_reCalculateFilteredList(); 137 } 138 jsFilter_removeLoadingScreen(); 139 }, 100); 140 } 141 }, 100); 142} 143 144// Function that intializes the top part of the page, including the buttons. 145// - cardInfo: person info if in the person context 146async function jsFilter_initNavButtons(cardInfo) { 147 jsFilter_putLoadingScreen(); 148 const mediaQuery = window.matchMedia("(max-width: 700px)"); 149 if (mediaQuery.matches) 150 d3.select("#page-container").style("margin-top", "25px"); 151 var buttonAbout; 152 var buttonPeople; 153 var buttonPublications; 154 var buttonSupervision; 155 var buttonProjects; 156 157 const body = document.getElementById("mainBody"); 158 159 const leftSide = iidHTML("div", "", {}, {}); 160 leftSide.id = "leftSide"; 161 162 const navPanel = iidHTML("div", ""); 163 navPanel.id = "navPanel"; 164 165 const authorNav = iidHTML("div", ""); 166 authorNav.id = "authorNav"; 167 168 const buttonsNav = iidHTML("div", ""); 169 buttonsNav.id = "buttonsNav"; 170 171 navPanel.appendChild(authorNav); 172 navPanel.appendChild(buttonsNav); 173 174 const listingPanel = iidHTML("div", ""); 175 listingPanel.id = "listingPanel"; 176 177 const mobileButtonDIV = iidHTML("div"); 178 mobileButtonDIV.id = "mobileButtonDIV"; 179 180 const sidebarInfo = iidHTML( "strong", "â Click to filter", {}, 181 { 182 click: function () { 183 if (d3.select("#rightSide").style("left") != "0%") { 184 d3.select("#rightSide") 185 .transition() 186 .duration(500) 187 .style("left", "0%"); 188 document.getElementById("sidebarInfo").textContent = "â¶ Click to filter"; 189 } else { 190 d3.select("#rightSide") 191 .transition() 192 .duration(500) 193 .style("left", "-100%"); 194 document.getElementById("sidebarInfo").textContent = "â Click to filter"; 195 } 196 }, 197 }, 198 ["sideBar"] 199 ); 200 sidebarInfo.id = "sidebarInfo"; 201 202 mobileButtonDIV.appendChild(sidebarInfo); 203 204 if (jsFilter_currentContext != "About") body.appendChild(mobileButtonDIV); 205 206 leftSide.appendChild(navPanel); 207 leftSide.appendChild(listingPanel); 208 209 const rightSide = iidHTML("div", ""); 210 rightSide.id = "rightSide"; 211 212 body.appendChild(leftSide); 213 body.appendChild(rightSide); 214 215 buttonAbout = iidHTML( 216 "button", 217 "About", 218 {}, 219 { 220 click: function () { 221 jsFilter_putLoadingScreen(); 222 setTimeout(() => { 223 window.location.href = jsFilter_urlREF + "member/" + jsFilter_metaFilters["bibtexRankedAuthorsIdName"] + "/"; 224 }, 100); 225 }, 226 }, 227 ["buttonsNav"] 228 ); 229 buttonAbout.id = "buttonAbout"; 230 231 buttonPeople = iidHTML( "button", "People", {}, 232 { 233 click: function () { 234 jsFilter_putLoadingScreen(); 235 setTimeout(() => { 236 window.location.href = jsFilter_urlREF + "ou/" + jsFilter_metaFilters["organizationalUnitIdAcronymName"] + "/members/"; 237 }, 100); 238 }, 239 }, 240 ["buttonsNav"] 241 ); 242 buttonPeople.id = "buttonPeople"; 243 244 buttonPublications = iidHTML( "button", "Publications", {}, 245 { 246 click: function () { 247 jsFilter_putLoadingScreen(); 248 setTimeout(() => { 249 if ( 250 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "" && 251 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != null 252 ) { 253 window.location.href = jsFilter_urlREF + "member/" + jsFilter_metaFilters["bibtexRankedAuthorsIdName"] + "/publications/"; 254 } else { 255 window.location.href = jsFilter_urlREF + "ou/" + jsFilter_metaFilters["organizationalUnitIdAcronymName"] + "/publications/"; 256 } 257 }, 100); 258 }, 259 }, 260 ["buttonsNav"] 261 ); 262 buttonPublications.id = "buttonPublications"; 263 264 buttonSupervision = iidHTML( "button", "Supervisions", {}, 265 { 266 click: function () { 267 jsFilter_putLoadingScreen(); 268 setTimeout(() => { 269 if ( 270 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "" && 271 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != null 272 ) {
273 window.location.href = jsFilter_urlREF + "member/" + jsFilter_metaFilters["bibtexRankedAuthorsIdName"] + "/supervisions/"; 274 } else { 275 window.location.href = jsFilter_urlREF + "ou/" + jsFilter_metaFilters["organizationalUnitIdAcronymName"] + "/supervisions/"; 276 } 277 }, 100); 278 }, 279 }, 280 ["buttonsNav"] 281 ); 282 buttonSupervision.id = "buttonSupervision"; 283 284 buttonProjects = iidHTML( "button", "Projects", {}, 285 { 286 click: function () { 287 jsFilter_putLoadingScreen(); 288 setTimeout(() => { 289 if ( 290 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "" && 291 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != null 292 ) { 293 window.location.href = jsFilter_urlREF + "member/" + jsFilter_metaFilters["bibtexRankedAuthorsIdName"] + "/projects/"; 294 } else { 295 window.location.href = jsFilter_urlREF + "ou/" + jsFilter_metaFilters["organizationalUnitIdAcronymName"] + "/projects/"; 296 } 297 }, 100); 298 }, 299 }, 300 ["buttonsNav"] 301 ); 302 buttonProjects.id = "buttonProjects"; 303 304 if ( 305 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "" && 306 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != null 307 ) { 308 buttonPeople.style.display = "none"; 309 var author = cardInfo; 310 const card = jsFilter_createCard(author); 311 document.getElementById("authorNav").appendChild(card); 312 } else { 313 buttonAbout.style.display = "none"; 314 if (jsFilter_metaFilters["organizationalUnitIdAcronymName"] == "") { 315 buttonPeople.style.display = "none"; 316 buttonPublications.style.display = "none"; 317 buttonSupervision.style.display = "none"; 318 buttonProjects.style.display = "none"; 319 if ( 320 jsFilter_metaFilters["newRoleTypesId"] != "" && 321 jsFilter_metaFilters["newRoleTypesId"] != null 322 ) { 323 const peopleHeader = iidHTML( "h1", jsFilter_people_types_group[jsFilter_metaFilters["newRoleTypesId"]]); 324 authorNav.appendChild(peopleHeader); 325 } else if ( 326 jsFilter_metaFilters["typeId"] != "" && 327 jsFilter_metaFilters["typeId"] != null 328 ) { 329 const peopleHeader = iidHTML( "h1", jsFilter_projectTypes[jsFilter_metaFilters["typeId"]]); 330 authorNav.appendChild(peopleHeader); 331 } else { 332 var headerText; 333 switch (jsFilter_currentContext) { 334 case "Publications": 335 headerText = "All Publications"; 336 break; 337 case "Supervision": 338 headerText = "All Supervisions"; 339 break; 340 case "Projects": 341 headerText = "All Projects"; 342 break; 343 case "People": 344 headerText = "All People"; 345 break; 346 } 347 const globalHeader = iidHTML("h1", headerText); 348 authorNav.appendChild(globalHeader); 349 } 350 } else { 351 const saHeader = iidHTML( "h1", jsFilter_peopleScientificAreasComplete[ jsFilter_metaFilters["organizationalUnitIdAcronymName"] ]); 352 authorNav.appendChild(saHeader); 353 buttonPeople.style.display = "block"; 354 buttonPublications.style.display = "block"; 355 buttonSupervision.style.display = "block"; 356 buttonProjects.style.display = "block"; 357 } 358 } 359 360 var buttonArray = [ 361 buttonAbout, 362 buttonPeople, 363 buttonPublications, 364 buttonSupervision, 365 buttonProjects, 366 ]; 367 368 const changeActive = function () { 369 buttonArray.forEach((element) => { 370 if (element != null) { 371 element.classList.remove("buttonSectionActive"); 372 element.classList.add("buttonSectionInactive"); 373 } 374 }); 375 if (jsFilter_currentContext == "About") { 376 buttonAbout.classList.remove("buttonSectionInactive"); 377 buttonAbout.classList.add("buttonSectionActive"); 378 } else if (jsFilter_currentContext == "People") { 379 buttonPeople.classList.remove("buttonSectionInactive"); 380 buttonPeople.classList.add("buttonSectionActive"); 381 } else if (jsFilter_currentContext == "Publications") { 382 buttonPublications.classList.remove("buttonSectionInactive"); 383 buttonPublications.classList.add("buttonSectionActive"); 384 } else if (jsFilter_currentContext == "Supervision") { 385 buttonSupervision.classList.remove("buttonSectionInactive"); 386 buttonSupervision.classList.add("buttonSectionActive"); 387 } else if (jsFilter_currentContext == "Projects") { 388 buttonProjects.classList.remove("buttonSectionInactive"); 389 buttonProjects.classList.add("buttonSectionActive"); 390 } 391 }; 392 393 changeActive(); 394 395 buttonsNav.appendChild(buttonAbout); 396 buttonsNav.appendChild(buttonPeople); 397 buttonsNav.appendChild(buttonPublications); 398 buttonsNav.appendChild(buttonSupervision); 399 buttonsNav.appendChild(buttonProjects); 400} 401 402// First function run if run locally, it starts to fetch information depending on the meta filters
403async function jsFilter_init() { 404 jsFilter_putLoadingScreen(); 405 setTimeout(async () => { 406 switch (jsFilter_currentContext) { 407 case "Publications": 408 if (jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "") { 409 jsFilter_getPublicationsByAuthor( jsFilter_metaFilters["bibtexRankedAuthorsIdName"]); 410 } else if ( jsFilter_metaFilters["organizationalUnitIdAcronymName"] != "") { 411 jsFilter_getPublicationsByOUID( jsFilter_metaFilters["organizationalUnitIdAcronymName"]); 412 } else { 413 jsFilter_getPublications(); 414 } 415 break; 416 417 case "Supervision": 418 if (jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "") { 419 jsFilter_getSupervisionByAuthor( jsFilter_metaFilters["bibtexRankedAuthorsIdName"]); 420 } else if ( jsFilter_metaFilters["organizationalUnitIdAcronymName"] != "") { 421 jsFilter_getSupervisionByOUID( jsFilter_metaFilters["organizationalUnitIdAcronymName"]); 422 } else { 423 jsFilter_getSupervision(); 424 } 425 break; 426 427 case "Projects": 428 if (jsFilter_metaFilters["bibtexRankedAuthorsIdName"] != "") { 429 jsFilter_getProjectsByAuthor( jsFilter_metaFilters["bibtexRankedAuthorsIdName"]); 430 } else if ( jsFilter_metaFilters["organizationalUnitIdAcronymName"] != "") { 431 jsFilter_getProjectsByOUID( jsFilter_metaFilters["organizationalUnitIdAcronymName"]); 432 } else { 433 jsFilter_getProjects(); 434 } 435 break; 436 437 case "People": 438 if (jsFilter_metaFilters["organizationalUnitIdAcronymName"] != "") { 439 jsFilter_getPeopleByOUID( jsFilter_metaFilters["organizationalUnitIdAcronymName"]); 440 } else { 441 jsFilter_getPeople(); 442 } 443 break; 444 445 case "About": 446 var author = await jsFilter_getSingleAuthor( jsFilter_metaFilters["bibtexRankedAuthorsIdName"]); 447 jsFilter_initList([], author); 448 break; 449 450 default: 451 break; 452 } 453 }, 100); 454} 455 456// Function that inializes the "order by" section 457function jsFilter_initOrderBy() { 458 jsFilter_currentOrder = jsFilter_currentOrderMapping[jsFilter_currentContext]; 459 460 const orderDIV = document.getElementById("orderDIV"); 461 const orderByText = iidHTML( "strong", "Order by:", {}, {}, ["orderByText"]); 462 463 const dropDown = iidHTML( "select", "", {}, 464 { 465 change: function (event) { 466 jsFilter_putLoadingScreen(); 467 setTimeout(() => { 468 jsFilter_currentOrder[0] = event.target.value; 469 jsFilter_updateList(jsFilter_filteredData); 470 jsFilter_removeLoadingScreen(); 471 }, 100); 472 }, 473 }, 474 ["buttonSection"] 475 ); 476 477 Object.keys(jsFilter_orderTextMapping[jsFilter_currentContext]).forEach( 478 (key) => { 479 const titleOption = iidHTML("option", ""); 480 titleOption.value = key; 481 titleOption.textContent = jsFilter_orderTextMapping[jsFilter_currentContext][key]; 482 dropDown.appendChild(titleOption); 483 dropDown.value = jsFilter_currentOrder[0]; 484 } 485 ); 486 487 const arrow = iidHTML( "button", jsFilter_currentOrder[1], {}, 488 { 489 click: function () { 490 jsFilter_putLoadingScreen(); 491 setTimeout(() => { 492 this.textContent = jsFilter_currentOrder[1] === "â" ? "â" : "â"; 493 jsFilter_currentOrder[1] = this.textContent; 494 jsFilter_updateList(jsFilter_filteredData); 495 jsFilter_removeLoadingScreen(); 496 }, 100); 497 }, 498 }, 499 ["orderArrow"] 500 ); 501 502 orderDIV.appendChild(orderByText); 503 orderDIV.appendChild(dropDown); 504 orderDIV.appendChild(arrow); 505} 506 507// Function that inializes the filtering panel 508function jsFilter_initFilterPanel(filters) { 509 jsFilter_checkMetaFilters(filters); 510 Object.keys(filters).forEach((key) => { 511 if ( 512 filters[key][1] != "none" && 513 (jsFilter_metaFilters[filters[key][0]] == "" || 514 jsFilter_metaFilters[filters[key][0]] == null || 515 jsFilter_metaFilters[filters[key][0]].split("|").length > 1) 516 ) { 517 const filterSection = document.createElement("div"); 518 filterSection.classList.add("filter-section"); 519 filterSection.id = key; 520 const heading = document.createElement("h2"); 521 heading.textContent = key.replace("_", " "); 522 filterSection.appendChild(heading); 523 document.getElementById("filter-panel").appendChild(filterSection); 524 525 jsFilter_currentFilters[filters[key][0]] = []; 526 527 switch (filters[key][1]) { 528 case "searchBar": 529 jsFilter_createSearchBar(key, key + "DIV", filters[key][0]); 530 break; 531 case "checkBox": 532 jsFilter_createCheckBoxCategory(key, key + "DIV", filters[key][0]); 533 break; 534 case "slider": 535 // jsFilter_createSlider(key, key + "DIV", filters[key][0]); 536 jsFilter_createSlider2(key, key + "DIV", filters[key][0]); 537 break; 538 case "none": 539 break; 540 default: 541 console.warn(`Unknown filter type for key: ${key}`); 542 break; 543 } 544 } else { 545 jsFilter_currentFilters[filters[key][0]] = []; 546 } 547 }); 548} 549 550// Function that filters the main dataset according to meta filters and drawer category.
551function jsFilter_checkMetaFilters(filters) { 552 const drawers = jsFilter_getList( 553 jsFilter_originalData, 554 jsFilter_drawerMapping[jsFilter_currentContext], 555 jsFilter_contextMappingRecursive[jsFilter_currentContext][ 556 jsFilter_drawerMapping[jsFilter_currentContext] 557 ] 558 ); 559 jsFilter_originalData = jsFilter_originalData.filter(function (obj) { 560 var keep = false; 561 if (Array.isArray(obj[jsFilter_drawerMapping[jsFilter_currentContext]])) { 562 obj[jsFilter_drawerMapping[jsFilter_currentContext]].forEach((elem) => { 563 if ( 564 drawers.includes( 565 elem[ 566 jsFilter_contextMappingRecursive[jsFilter_currentContext][ 567 jsFilter_drawerMapping[jsFilter_currentContext] 568 ] 569 ] 570 ) 571 ) 572 keep = true; 573 }); 574 } else { 575 if ( 576 drawers.includes(obj[jsFilter_drawerMapping[jsFilter_currentContext]]) 577 ) 578 keep = true; 579 } 580 return keep; 581 }); 582 Object.keys(filters).forEach((key) => { 583 if ( 584 jsFilter_metaFilters[filters[key][0]] != null && 585 jsFilter_metaFilters[filters[key][0]] != "" 586 ) { 587 if (jsFilter_metaFilters[filters[key][0]].split("|").length > 0) { 588 jsFilter_originalData = jsFilter_originalData.filter(function (obj) { 589 var keep = false; 590 jsFilter_metaFilters[filters[key][0]] 591 .split("|") 592 .forEach((filterId) => { 593 if (Array.isArray(obj[filters[key][0]])) { 594 obj[filters[key][0]].forEach((elem) => { 595 if ( 596 elem[ 597 jsFilter_contextMappingRecursive[jsFilter_currentContext][ 598 filters[key][0] 599 ] 600 ] == filterId 601 ) 602 keep = true; 603 }); 604 } else { 605 if (obj[filters[key][0]] == filterId) keep = true; 606 } 607 }); 608 return keep; 609 }); 610 } 611 } 612 }); 613 jsFilter_filteredData = jsFilter_originalData; 614 jsFilter_currentData = jsFilter_originalData; 615} 616 617// Function that fetches the data via the API 618async function jsFilter_fetchData(phpFile, apiURL) { 619 const fullApiURL = `${phpFile}?apiURL=${encodeURIComponent(apiURL)}`; 620 try { 621 const response = await fetch(fullApiURL); 622 if (!response.ok) { 623 throw new Error( 624 `Failed to fetch data from ${apiURL}. HTTP error! Status: ${response.status}` 625 ); 626 } 627 return await response.json(); 628 } catch (error) { 629 console.error("Fetch error:", error); 630 throw error; 631 } 632} 633 634// Function that orders the displayed items from the arrayOfObjects 635function jsFilter_orderList(arrayOfObjects) { 636 const bibTag = 637 jsFilter_orderMapping[jsFilter_currentContext][jsFilter_currentOrder[0]]; 638 639 if (typeof arrayOfObjects[0][bibTag] === "number") { 640 arrayOfObjects.sort(function (a, b) { 641 return jsFilter_currentOrder[1] === "â" 642 ? b[bibTag] - a[bibTag] 643 : a[bibTag] - b[bibTag]; 644 }); 645 } else { 646 arrayOfObjects.sort(function (a, b) { 647 return jsFilter_currentOrder[1] === "â" 648 ? a[bibTag].localeCompare(b[bibTag]) 649 : b[bibTag].localeCompare(a[bibTag]); 650 }); 651 } 652} 653 654// True only on the global "All X" listing (no author/OU/role/type filter), 655// where the heading is replaced by the combined "<Type> <period> (<count>)" 656// title. 657function jsFilter_isGlobalAllListing() { 658 return ( 659 (jsFilter_metaFilters["bibtexRankedAuthorsIdName"] == null || 660 jsFilter_metaFilters["bibtexRankedAuthorsIdName"] === "") && 661 (jsFilter_metaFilters["organizationalUnitIdAcronymName"] == null || 662 jsFilter_metaFilters["organizationalUnitIdAcronymName"] === "") && 663 (jsFilter_metaFilters["newRoleTypesId"] == null || 664 jsFilter_metaFilters["newRoleTypesId"] === "") && 665 (jsFilter_metaFilters["typeId"] == null || 666 jsFilter_metaFilters["typeId"] === "") 667 ); 668} 669 670// Builds the listing title, e.g. "Publications 2013-2016 (386)". The period is 671// the year range currently selected on the slider (a-b, forced to a <= b); 672// contexts without a year (People) omit it.
673function jsFilter_buildListingTitle(count) { 674 const typeLabel = jsFilter_listingTypeLabel[jsFilter_currentContext] || ""; 675 const yearMapping = jsFilter_orderMapping[jsFilter_currentContext]; 676 const yearTag = yearMapping ? yearMapping["Year"] : null; 677 let period = ""; 678 if ( 679 yearTag && 680 Array.isArray(jsFilter_currentFilters[yearTag]) && 681 jsFilter_currentFilters[yearTag].length === 2 682 ) { 683 let a = jsFilter_currentFilters[yearTag][1]; 684 let b = jsFilter_currentFilters[yearTag][0]; 685 if (a != null && b != null) { 686 if (a > b) { 687 const tmp = a; 688 a = b; 689 b = tmp; 690 } 691 period = a === b ? " " + a : " " + a + "-" + b; 692 } 693 } 694 return typeLabel + period + " (" + count + ")"; 695} 696 697// Function that updates the displayed items from the arrayOfObjects 698function jsFilter_updateList(arrayOfObjects) { 699 if (arrayOfObjects.length > 0) jsFilter_orderList(arrayOfObjects); 700 701 if (jsFilter_toLog) console.log(arrayOfObjects); 702 703 const drawers = document 704 .getElementById("itemList") 705 .querySelectorAll("button.collapsibleJS"); 706 707 var totalItems = []; 708 709 drawers.forEach((drawer) => { 710 const drawerID = drawer.id.split("Button")[0]; 711 const drawerData = arrayOfObjects.filter((item) => { 712 if ( 713 Array.isArray(item[jsFilter_drawerMapping[jsFilter_currentContext]]) 714 ) { 715 var result = false;
716 item[jsFilter_drawerMapping[jsFilter_currentContext]].forEach( 717 (secondItem) => { 718 if ( 719 secondItem[ 720 jsFilter_contextMappingRecursive[jsFilter_currentContext][ 721 jsFilter_drawerMapping[jsFilter_currentContext] 722 ] 723 ] == drawerID 724 ) 725 result = true; 726 } 727 ); 728 return result; 729 } else 730 return ( 731 item[jsFilter_drawerMapping[jsFilter_currentContext]] === drawerID 732 ); 733 }); 734 735 // The banner/content live inside a delimited section wrapper (publications 736 // and people); hide the wrapper too so filtered-out drawers leave no empty 737 // box behind. 738 const section = drawer.closest(".drawer-sectionJS"); 739 740 if ( 741 drawerData.length > 0 && 742 (jsFilter_currentFilters[ jsFilter_drawerMapping[jsFilter_currentContext] ].includes(drawerID) || 743 jsFilter_currentFilters[jsFilter_drawerMapping[jsFilter_currentContext]] .length == 0) 744 ) { 745 totalItems = totalItems.concat(drawerData); 746 var buttonText; 747 if ( jsFilter_propertyMapping[jsFilter_currentContext][drawerID].substring( 1, 3) == " -") { 748 buttonText = jsFilter_propertyMapping[jsFilter_currentContext][drawerID].substring( 3); 749 } else { 750 buttonText = jsFilter_propertyMapping[jsFilter_currentContext][drawerID]; 751 } 752 753 const drawerContent = drawer.nextElementSibling; 754 drawerContent.style.display = "flex"; 755 if (drawerContent.style.maxHeight == "0px") 756 drawer.textContent = `${buttonText} (${drawerData.length}) â²`; 757 else drawer.textContent = `${buttonText} (${drawerData.length}) â¼`; 758 drawer.style.display = "inline-block"; 759 if (section) section.style.display = ""; 760 } else { 761 drawer.style.display = "none"; 762 const drawerContent = drawer.nextElementSibling; 763 drawerContent.style.display = "none"; 764 if (section) section.style.display = "none"; 765 } 766 767 switch (jsFilter_currentContext) { 768 case "Publications": 769 jsFilter_createListPublications( drawer.nextElementSibling, drawerData, drawerID); 770 break; 771 case "Supervision": 772 jsFilter_createListSupervision(drawer.nextElementSibling, drawerData); 773 break; 774 case "Projects": 775 jsFilter_createListProjects(drawer.nextElementSibling, drawerData); 776 break; 777 case "People": 778 jsFilter_createListPeople(drawer.nextElementSibling, drawerData); 779 break; 780 default: 781 break; 782 } 783 }); 784 785 const titleElement = document.getElementById("title"); 786 const totalCount = jsFilter_removeDuplicatesObjects(totalItems).length; 787 titleElement.textContent = jsFilter_buildListingTitle(totalCount); 788} 789 790// Function that creates the displayed items from the arrayOfObjects 791function jsFilter_createList(arrayOfObjects) { 792 jsFilter_orderList(arrayOfObjects); 793 794 if (jsFilter_toLog) console.log(arrayOfObjects); 795 796 var drawers = jsFilter_getList( 797 arrayOfObjects, 798 jsFilter_drawerMapping[jsFilter_currentContext], 799 jsFilter_contextMappingRecursive[jsFilter_currentContext][ 800 jsFilter_drawerMapping[jsFilter_currentContext] 801 ] 802 ); 803 804 if ( jsFilter_metaFilters[jsFilter_drawerMapping[jsFilter_currentContext]] != null && 805 jsFilter_metaFilters[jsFilter_drawerMapping[jsFilter_currentContext]] != "") 806 drawers = drawers.filter(function (elem) { 807 return jsFilter_metaFilters[ jsFilter_drawerMapping[jsFilter_currentContext] ] .split("|") .includes(elem); 808 }); 809 810 var totalItems = []; 811 812 const itemListContainer = document.getElementById("itemList"); 813 itemListContainer.innerHTML = ""; 814 815 drawers.forEach((drawer, ite) => { 816 const tempArray = arrayOfObjects.filter(function (item) { 817 if ( 818 Array.isArray(item[jsFilter_drawerMapping[jsFilter_currentContext]]) 819 ) { 820 var result = false;
821 item[jsFilter_drawerMapping[jsFilter_currentContext]].forEach( 822 (secondItem) => { 823 if ( 824 secondItem[ 825 jsFilter_contextMappingRecursive[jsFilter_currentContext][ 826 jsFilter_drawerMapping[jsFilter_currentContext] 827 ] 828 ] == drawer 829 ) 830 result = true; 831 } 832 ); 833 return result; 834 } else return item[jsFilter_drawerMapping[jsFilter_currentContext]] === drawer; 835 }); 836 837 totalItems = totalItems.concat(tempArray); 838 839 var buttonText; 840 841 if (jsFilter_propertyMapping[jsFilter_currentContext][drawer] == null) 842 return; 843 if ( 844 jsFilter_propertyMapping[jsFilter_currentContext][drawer].substring( 845 1, 846 3 847 ) == " -" 848 ) { 849 buttonText = 850 jsFilter_propertyMapping[jsFilter_currentContext][drawer].substring(3); 851 } else { 852 buttonText = jsFilter_propertyMapping[jsFilter_currentContext][drawer]; 853 } 854 855 const button = iidHTML( 856 "button", 857 buttonText + " (" + tempArray.length + ") â¼", 858 { marginTop: ite > 0 ? "5px" : "" }, 859 { 860 click: function () { 861 this.classList.toggle("active"); 862 const content = this.nextElementSibling; 863 if (content.style.maxHeight == "none") { 864 this.textContent = this.textContent.slice(0, -1) + "â²"; 865 content.style.maxHeight = 0; 866 } else { 867 this.textContent = this.textContent.slice(0, -1) + "â¼"; 868 content.style.maxHeight = "none"; 869 } 870 }, 871 }, 872 ["collapsibleJS"] 873 ); 874 button.id = drawer + "Button"; 875 876 const div = iidHTML("div", "", {}, {}, ["contentJS"]); 877 878 if ( 879 jsFilter_currentContext === "Publications" || 880 jsFilter_currentContext === "People" || 881 jsFilter_currentContext === "Supervision" || 882 jsFilter_currentContext === "Projects" 883 ) { 884 // Wrap the banner and its cards in a single delimited, collapsible 885 // section. The banner stays the content's previous sibling, so the 886 // collapse/filter logic keeps working unchanged. 887 button.style.marginTop = "0px"; 888 button.classList.add("drawer-bannerJS"); 889 div.classList.add("drawer-section-contentJS"); 890 const section = iidHTML("div", "", {}, {}, ["drawer-sectionJS"]); 891 section.appendChild(button); 892 section.appendChild(div); 893 itemListContainer.appendChild(section); 894 } else { 895 itemListContainer.appendChild(button); 896 itemListContainer.appendChild(div); 897 } 898 899 switch (jsFilter_currentContext) { 900 case "Publications": 901 jsFilter_createListPublications(div, tempArray, drawer); 902 break; 903 case "Supervision": 904 jsFilter_createListSupervision(div, tempArray); 905 break; 906 case "Projects": 907 jsFilter_createListProjects(div, tempArray); 908 break; 909 case "People": 910 div.style.display = "flex"; 911 div.style.flexWrap = "wrap"; 912 jsFilter_createListPeople(div, tempArray); 913 break; 914 915 default: 916 break; 917 } 918 919 button.classList.toggle("active"); 920 const content = button.nextElementSibling; 921 if (content.style.maxHeight == "none") content.style.maxHeight = 0; 922 else content.style.maxHeight = "none"; 923 }); 924 925 const titleElement = document.getElementById("title"); 926 titleElement.style.textAlign = "left"; 927 const totalCount = jsFilter_removeDuplicatesObjects(totalItems).length; 928 titleElement.textContent = jsFilter_buildListingTitle(totalCount); 929} 930 931// Hardcoded adaptations from the intranet that were not be made generic. 932function jsFilter_intranetAdaptations(data, cardInfo) { 933 if (cardInfo != null) { 934 var tempArraySA = []; 935 if (!Array.isArray(cardInfo["activeOUsId"])) { 936 var tempArrayObj = [];
937 Object.keys(cardInfo["activeOUsId"]).forEach((key) => { 938 tempArrayObj.push(cardInfo["activeOUsId"][key]); 939 }); 940 cardInfo["activeOUsId"] = tempArrayObj; 941 } 942 cardInfo["activeOUsId"] = jsFilter_removeDuplicatesArray( 943 cardInfo["activeOUsId"] 944 ); 945 cardInfo["activeOUsId"].forEach((element2) => { 946 if (jsFilter_peopleScientificAreas[element2] != null) 947 tempArraySA.push({ item1: element2 }); 948 }); 949 cardInfo["organizationalUnitIdAcronymName"] = tempArraySA; 950 } 951 952 switch (jsFilter_currentContext) { 953 case "Publications": 954 break; 955 956 case "Supervision": 957 data = jsFilter_stringDataToInt(data, "endTime"); 958 data.forEach((element) => { 959 if (element["endTime"] == null) element["endTime"] = "Ongoing"; 960 else element["endTime"] = "Ended"; 961 }); 962 break; 963 964 case "Projects": 965 data = jsFilter_stringDataToInt(data, "endDate"); 966 data.forEach((element) => { 967 var tempArrayTL = []; 968 element["thematicLinesId"].forEach((element2) => { 969 if (jsFilter_tematicLines[element2] != null) 970 tempArrayTL.push({ item1: element2 }); 971 }); 972 element["thematicLinesId"] = tempArrayTL; 973 }); 974 break; 975 976 case "People": 977 jsFilter_calculateRoles(data); 978 data.forEach((element) => { 979 var tempArraySA = []; 980 element["activeOUsId"] = jsFilter_removeDuplicatesArray( 981 element["activeOUsId"] 982 ); 983 element["activeOUsId"].forEach((element2) => { 984 if (jsFilter_peopleScientificAreas[element2] != null) 985 tempArraySA.push({ item1: element2 }); 986 }); 987 element["organizationalUnitIdAcronymName"] = tempArraySA; 988 989 var tempArrayTL = []; 990 element["rankedOUsId"] = jsFilter_removeDuplicatesArray( 991 element["rankedOUsId"] 992 ); 993 element["rankedOUsId"].forEach((element2) => { 994 if (jsFilter_tematicLines[element2] != null) 995 tempArrayTL.push({ item1: element2 }); 996 }); 997 element["rankedOUsId"] = tempArrayTL; 998 }); 999 break; 1000 1001 default: 1002 break; 1003 } 1004} 1005 1006// Events that are started with the plugin 1007function jsFilter_initEventHandlers() { 1008 document.addEventListener("touchstart", function (event) { 1009 touchStartX = event.touches[0].clientX; 1010 }); 1011 1012 document.addEventListener("touchend", function (event) { 1013 touchEndX = event.changedTouches[0].clientX; 1014 jsFilter_handleSwipe(event); 1015 }); 1016}
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.