Skip to content
This repository was archived by the owner on Sep 19, 2022. It is now read-only.

Commit 31f8216

Browse files
Dominik František Bučíkvyskocilpavel
authored andcommitted
fix: refactor disco (#218)
* fix: 🐛 Fix wayf speed Refactored algorithm for inlinesearch should improve the speed of filtering the IdPs. * refactor: 💡 Upgrade jQuery to latest version (v3.6.0.) * fix: 🐛 Further fixes in WAYF
1 parent ec726c6 commit 31f8216

File tree

6 files changed

+170
-100
lines changed

6 files changed

+170
-100
lines changed

dictionaries/disco.definition.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,9 @@
7878
"js_not_loaded_message": {
7979
"en": "Your browser does not support the required functionality to display this page. Please use a different browser and try again. We apologize for the caused difficulties.",
8080
"cs": "Váš prohlížeč nepodporuje funkcionalitu potřebnou pro správné zobrazení této stránky. Zkuste, prosím, použít jiný prohlížeč. Omlouváme se za vzniklé problémy."
81+
},
82+
"search_start_hint": {
83+
"en": "Type in at least 3 characters to start the search",
84+
"cs": "Zadejte alespoň 3 znaky pro zahájení vyhledávání"
8185
}
8286
}

lib/Disco.php

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -385,12 +385,17 @@ public function removeAuthContextClassRefWithPrefixes(&$state)
385385
}
386386

387387
/**
388-
* @param bool $favourite
388+
* @param bool $favourite
389+
* @param mixed $constructSearchData
389390
*
390391
* @return string html
391392
*/
392-
public static function showEntry(DiscoTemplate $t, array $metadata, $favourite = false): string
393-
{
393+
public static function showEntry(
394+
DiscoTemplate $t,
395+
array $metadata,
396+
$favourite = false,
397+
$constructSearchData = false
398+
): string {
394399
$searchData = htmlspecialchars(self::constructSearchData($metadata));
395400
$extra = ($favourite ? ' favourite' : '');
396401
$href = $t->getContinueUrl($metadata[self::IDP_ENTITY_ID]);
@@ -534,18 +539,22 @@ public static function showInlineSearch(
534539
);
535540

536541
$result .= self::addLoginOptionNote($t, $blockConfig, '{perun:disco:institution_search_hint}');
542+
$result .= '<div id="type-more" class="small text-muted">' . $t->t(
543+
'{perun:disco:search_start_hint}'
544+
) . '</div>' . PHP_EOL;
537545
$result .= '<div class="inlinesearch">' . PHP_EOL;
538546
$result .= ' <form id="idpselectform" action="?" method="get">' . PHP_EOL;
539-
$result .= ' <input class="inlinesearchf form-control input-lg" type="text" value=""
540-
name="query" id="query" autofocus oninput="$(\'#list\').show();" placeholder="'
547+
$result .= ' <input class="inlinesearch form-control input-lg" type="text" value=""
548+
name="query" id="query" autofocus placeholder="'
541549
. $t->t($placeholderTranslateKey) . '"/>' . PHP_EOL;
542550
$result .= ' </form>';
543551
// ENTRIES
544-
$result .= ' <div class="metalist list-group" id="list" style="display: none">' . PHP_EOL;
552+
$result .= ' <div class="metalist list-group" id="list"></div>' . PHP_EOL;
553+
$result .= ' <div class="metalist list-group d-none" id="list-hidden">' . PHP_EOL;
545554
foreach ($allIdps as $idpentry) {
546-
$result .= self::showEntry($t, $idpentry) . PHP_EOL;
555+
$result .= self::showEntry($t, $idpentry, false, true) . PHP_EOL;
547556
}
548-
$result .= ' </div>' . PHP_EOL;
557+
$result .= '</div>' . PHP_EOL;
549558
// TOO MUCH ENTRIES BLOCK
550559
$result .= ' <div id="warning-entries" class="alert alert-info entries-warning-block">' . PHP_EOL;
551560
$result .= ' ' . $t->t(
@@ -585,29 +594,13 @@ public static function showInlineSearch(
585594
return $result;
586595
}
587596

588-
public static function displayAllIdps(DiscoTemplate $t): string
589-
{
590-
$allIdps = $t->getAllIdps();
591-
592-
$result = '<div class="metalist list-group">' . PHP_EOL;
593-
foreach ($allIdps as $idpentry) {
594-
$result .= self::showEntry($t, $idpentry) . PHP_EOL;
595-
}
596-
$result .= '</div>' . PHP_EOL;
597-
598-
return $result;
599-
}
600-
601597
public static function getScripts(bool $boxed): string
602598
{
603599
$html = '<script type="text/javascript" src="' .
604-
Module::getModuleUrl('perun/res/js/old-browsers.js') . '"></script>' . PHP_EOL;
605-
606-
$html .= '<script type="text/javascript" src="' .
607-
Module::getModuleUrl('discopower/assets/js/suggest.js') . '"></script>' . PHP_EOL;
600+
Module::getModuleUrl('perun/res/js/jquery.js') . '"></script>' . PHP_EOL;
608601

609602
$html .= '<script type="text/javascript" src="' .
610-
Module::getModuleUrl('perun/res/js/jquery.livesearch.js') . '"></script>' . PHP_EOL;
603+
Module::getModuleUrl('perun/res/js/old-browsers.js') . '"></script>' . PHP_EOL;
611604

612605
$html .= '<script type="text/javascript" src="' .
613606
Module::getModuleUrl('perun/res/js/disco.js') . '"></script>' . PHP_EOL;
@@ -889,14 +882,14 @@ private static function constructSearchData($idpMetadata): string
889882
$idpMetadata = array_merge($idpMetadata, $idpMetadata['UIInfo']);
890883
}
891884

892-
$keys = ['entityid', 'OrganizationName', 'OrganizationDisplayName',
893-
'name', 'url', 'OrganizationURL', 'scope', 'DisplayName', ];
885+
$keys = ['OrganizationName', 'OrganizationDisplayName', 'name', 'scope', 'DisplayName'];
894886

895887
foreach ($keys as $key) {
896888
if (!empty($idpMetadata[$key])) {
897889
$dataSearchKeys = [...$dataSearchKeys, ...self::arrayFlatten($idpMetadata[$key])];
898890
}
899891
}
892+
$dataSearchKeys = array_unique($dataSearchKeys);
900893
$res .= (' ' . implode(' ', $dataSearchKeys));
901894

902895
return strtolower(str_replace('"', '', iconv('UTF-8', 'US-ASCII//TRANSLIT', $res)));

themes/perun/perun/disco-tpl.php

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
*/
1717

1818
$this->data['jquery'] = [
19-
'core' => true,
20-
'ui' => true,
21-
'css' => true,
19+
'core' => false,
20+
'ui' => false,
21+
'css' => false,
2222
];
2323

2424
$this->data['head'] = '<link rel="stylesheet" media="screen" type="text/css" href="' .
@@ -64,11 +64,6 @@
6464

6565
$this->includeAtTemplateBase('includes/header.php');
6666

67-
echo '<div id="deprecation-notice" class="d-none">';
68-
echo $this->t('{perun:disco:js_not_loaded_message}') . PHP_EOL;
69-
echo Disco::displayAllIdps($this) . PHP_EOL;
70-
echo '</div>';
71-
7267
// IF WE HAVE A WARNING, DISPLAY IT TO THE USER
7368
if (null !== $warningAttributes && $warningAttributes->isEnabled()) {
7469
echo Disco::showWarning($this, $warningAttributes);
@@ -101,7 +96,7 @@
10196
// Last selection is not null => Firstly show last selection
10297
if (!empty($this->getPreferredIdp())) {
10398
// ENTRY FOR PREVIOUS SELECTION
104-
echo '<div id="last-used-idp-wrap">' . PHP_EOL;
99+
echo '<div id="last-used-idp-wrap" class="d-none">' . PHP_EOL;
105100
echo ' <p class="discoDescription-left" id="last-used-idp-desc">'
106101
. $this->t('{perun:disco:previous_selection}') . '</p>' . PHP_EOL;
107102
echo ' <div id="last-used-idp" class="metalist list-group">' . PHP_EOL;
@@ -120,7 +115,7 @@
120115
}
121116

122117
// regular wayf contains all entries
123-
echo '<div id="entries">';
118+
echo '<div id="entries" class="d-none">';
124119
$cnt = 1;
125120
$blocksCount = count($wayfConfig->getArray(Disco::IDP_BLOCKS));
126121
$blocksConfig = $wayfConfig->getConfigItem(Disco::IDP_BLOCKS);

www/res/css/disco.css

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
html {
2-
position:relative;
2+
position: relative;
33
min-height: 100%;
44
}
55

@@ -15,21 +15,22 @@ html, body {
1515
margin-bottom: 110px;
1616
}
1717

18-
#show-entries-wrap {
19-
margin-bottom: 5%;
20-
}
21-
2218
#header img {
2319
max-height: 120px;
2420
height: 30%;
2521
width: auto;
2622
}
2723

28-
#deprecation-notice {
29-
font-weight: bold;
24+
.d-none {
25+
display: none;
3026
}
3127

32-
.d-none {
28+
#last-used-idp-wrap {
29+
display: none;
30+
margin-bottom: 5%;
31+
}
32+
33+
#list-hidden {
3334
display: none;
3435
}
3536

@@ -178,14 +179,6 @@ form#idpselectform input {
178179
padding: 2px 5px;
179180
}
180181

181-
#list {
182-
display: none;
183-
}
184-
185-
#entries {
186-
display: none;
187-
}
188-
189182
.add-institution-entries {
190183
margin-top: 5%;
191184
margin-bottom: 10%;

www/res/js/disco.js

Lines changed: 129 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,150 @@
1-
function hideAll () {
2-
$("#list").hide();
3-
$('#no-entries').hide();
4-
$('#warning-entries').hide();
5-
}
6-
71
$(document).ready(function() {
8-
if ($("#last-used-idp-wrap").length > 0) {
2+
let forceShow = false
3+
const entries = $('#entries');
4+
const noEntries = $('#no-entries');
5+
const tooManyEntries = $('#warning-entries');
6+
const displayed = $('#list');
7+
const hidden = $('#list-hidden');
8+
const resultsCnt = $('#results-cnt');
9+
const input = $('#query');
10+
const lastUsedIdpWrap = $("#last-used-idp-wrap");
11+
const showEntries = $("#showEntries");
12+
13+
if (lastUsedIdpWrap.length > 0) {
14+
showEl(lastUsedIdpWrap);
915
$("#last-used-idp .metaentry").focus();
1016
} else {
11-
$("#entries").show();
17+
showEl(entries);
1218
}
1319

14-
$("#showEntries").click(function() {
15-
$("#last-used-idp-wrap").hide();
16-
$("#entries").show();
17-
$("#showEntries").hide();
20+
showEntries.click(function() {
21+
hideEl($("#last-used-idp-wrap"));
22+
showEl(entries);
23+
hideEl(showEntries);
1824
});
1925

20-
let forceShow = false
21-
$('#query').keyup(function() {
22-
const filter = $(this).val().trim().toLowerCase().normalize("NFD").replace(/\p{Diacritic}/gu, "")
23-
if (!filter) {
24-
hideAll();
26+
let lastFilterSize = Number.MAX_SAFE_INTEGER;
27+
let typingTimer;
28+
const doneTypingInterval = 100;
29+
30+
input.on('input propertychange paste', function () {
31+
clearTimeout(typingTimer);
32+
typingTimer = setTimeout(filter, doneTypingInterval);
33+
});
34+
35+
//on keydown, clear the countdown
36+
input.on('keydown', function () {
37+
clearTimeout(typingTimer);
38+
});
39+
40+
function checkAndHandleEmptyFilter(filter) {
41+
if (!filter || filter.trim().length < 3) {
42+
hideEl(noEntries);
43+
hideEl(tooManyEntries);
2544
forceShow = false;
45+
return true;
46+
}
47+
return false;
48+
}
49+
50+
//on keyup, start the countdown
51+
function filter() {
52+
let filter = input.val();
53+
hideEl(displayed);
54+
55+
if (checkAndHandleEmptyFilter(filter)) {
56+
return;
57+
}
58+
filter = filter.toLowerCase().normalize("NFD").replace(/\p{Diacritic}/gu, "");
59+
60+
if (checkAndHandleEmptyFilter(filter)) {
61+
return;
62+
}
63+
64+
const currentlyDisplayed = $('#list a');
65+
const currentlyHidden = $('#list-hidden a');
66+
67+
const newDisplayed = [];
68+
let newHidden = [];
69+
70+
if (lastFilterSize <= filter.length) {
71+
newHidden = newHidden.concat(currentlyHidden);
2672
} else {
27-
let matches = [];
28-
$('#list a').each(function () {
29-
if ($(this).attr('data-search').indexOf(filter) >= 0) {
30-
matches.push(this);
73+
currentlyHidden.each(function () {
74+
const el = $(this);
75+
if (el.attr('data-search').indexOf(filter) >= 0) {
76+
newDisplayed.push(el);
3177
} else {
32-
$(this).hide();
78+
newHidden.push(el);
3379
}
3480
});
35-
if (matches.length <= 0) {
36-
$('#no-entries').show();
37-
$('#warning-entries').hide();
81+
}
82+
83+
lastFilterSize = filter.length;
84+
85+
currentlyDisplayed.each(function () {
86+
const el = $(this);
87+
if (el.attr('data-search').indexOf(filter) >= 0) {
88+
newDisplayed.push(el);
3889
} else {
39-
$("#list").show();
40-
$('#results-cnt').text(matches.length);
41-
$('#no-entries').hide();
42-
if (matches.length > 10 && !forceShow) {
43-
matches.forEach(m => {
44-
$(m).hide();
45-
});
46-
$('#warning-entries').show();
47-
} else {
48-
$('#warning-entries').hide();
49-
matches.forEach(m => {
50-
$(m).show();
51-
});
52-
}
90+
newHidden.push(el);
5391
}
92+
});
93+
94+
displayed.append(newDisplayed);
95+
hidden.append(newHidden);
96+
97+
if (newDisplayed.length === 0) {
98+
hideEl(tooManyEntries);
99+
showEl(noEntries);
100+
return;
54101
}
55-
});
102+
103+
if (newDisplayed.length > 0 && newDisplayed.length <= 10) {
104+
handleFoundResults();
105+
} else {
106+
if (forceShow) {
107+
handleForcedResults();
108+
} else {
109+
handleOverflowResults(newDisplayed.length);
110+
}
111+
}
112+
}
113+
114+
function handleFoundResults() {
115+
hideEl(noEntries);
116+
hideEl(tooManyEntries);
117+
showEl(displayed);
118+
}
119+
120+
function handleForcedResults() {
121+
hideEl(noEntries);
122+
hideEl(tooManyEntries);
123+
showEl(displayed);
124+
}
125+
126+
function handleOverflowResults(newDisplayedCnt) {
127+
hideEl(noEntries);
128+
resultsCnt.text(newDisplayedCnt);
129+
showEl(tooManyEntries);
130+
}
56131

57132
$('#warning-entries-btn-force-show').click(function(event) {
58133
event.preventDefault();
59134
forceShow = true;
60-
$('#warning-entries').hide();
61-
$('#query').trigger('keyup').focus();
135+
tooManyEntries.hide();
136+
input.trigger('input').focus();
62137
});
63138
});
139+
140+
function hideEl(el) {
141+
if (el.is(':visible')) {
142+
el.hide();
143+
}
144+
}
145+
146+
function showEl(el) {
147+
if (el.is(':hidden')) {
148+
el.show();
149+
}
150+
}

www/res/js/jquery.js

Lines changed: 2 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)