diff --git a/badges.js b/badges.js
index 63325c0c..5ccc12c9 100644
--- a/badges.js
+++ b/badges.js
@@ -15,6 +15,7 @@
@property {boolean} [unlocked]
@property {boolean} hidden
@property {boolean} [secret]
+ @property {boolean} [secretCondition]
@property {number} originalOrder
*/
@@ -202,7 +203,7 @@ function initBadgeControls() {
return -1;
return 1;
}
- return a.originalOrder - b.originalOrder;
+ return sortOrderDesc ? b.originalOrder - a.originalOrder : a.originalOrder - b.originalOrder;
};
// If we already have cache and it hasn't been invalidated, only update the modal.
@@ -566,6 +567,14 @@ function initBadgeControls() {
exactMatch = true;
}
+ function isMatch(haystack, needle, exact) {
+ if (!haystack) return false;
+ if (exact) {
+ return haystack.localeCompare(needle, undefined, { sensitivity: 'base', usage: 'search' }) === 0;
+ }
+ return haystack.toLocaleLowerCase().indexOf(needle) > -1;
+ }
+
const gameVisibilities = {};
const gameGroupVisibilities = {};
@@ -579,9 +588,10 @@ function initBadgeControls() {
visible &= item.el.classList.contains('locked') === !parseInt(unlockStatus);
if (searchTerm.trim().length) {
switch (searchMode) {
- case 'name':
+ case 'name': {
visible &= item.title && (exactMatch ? item.title === parsedSearchTerm : item.title.indexOf(parsedSearchTerm) > -1);
break;
+ }
case 'location': {
const localizedLocation = gameLocalizedMapLocations[item.game]?.[item.mapId];
let title = determineTitle(localizedLocation, item.mapX, item.mapY);
@@ -596,13 +606,22 @@ function initBadgeControls() {
title = globalConfig.lang === 'ja' ? desc.titleJP : desc.title;
}
}
- visible &= title && (exactMatch ? title.toLocaleLowerCase() === parsedSearchTerm : title.toLocaleLowerCase().indexOf(parsedSearchTerm) > -1);
+ visible &= isMatch(title, parsedSearchTerm, exactMatch);
break;
}
case 'artist': {
visible &= item.art && (exactMatch ? item.art.split(/ & |, /).includes(parsedSearchTerm) : item.art.indexOf(parsedSearchTerm) > -1);
break;
}
+ case 'contents': {
+ const gameBadgeLocalizations = localizedBadges && localizedBadges[item.game];
+ const badgeLocalization = gameBadgeLocalizations && gameBadgeLocalizations[item.badgeId];
+ visible &= badgeLocalization && (
+ (item.unlocked || !item.secret) && isMatch(badgeLocalization.description, parsedSearchTerm, exactMatch)
+ || (item.unlocked || !item.secretCondition) && isMatch(badgeLocalization.condition, parsedSearchTerm, exactMatch)
+ );
+ break;
+ }
}
}
if (!(item.game in gameVisibilities)) {
@@ -638,29 +657,30 @@ function initBadgeControls() {
return;
}
+ let parsedValue = this.value;
+ let modifier = null;
+ if (parsedValue.startsWith('=')) {
+ parsedValue = parsedValue.slice(1);
+ modifier = 'exactMatch';
+ }
+ let value = parsedValue;
+ if (modifier)
+ value += localizedMessages.badges.search.modifier.template.replace('{MODIFIER}', localizedMessages.badges.search.modifier[modifier]);
+
+ // mappings for user input sanitization
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ "/": '/',
+ };
+ const reg = /[&<>"'/]/ig;
+ value = value.replace(reg, match => map[match]);
+
for (const span of badgeDropdown.querySelectorAll('.dropdownItem span')) {
- let parsedValue = this.value;
- let modifier = null;
- if (parsedValue.startsWith('=')) {
- parsedValue = parsedValue.slice(1);
- modifier = 'exactMatch';
- }
- let value = parsedValue;
- if (modifier)
- value += localizedMessages.badges.search.modifier.template.replace('{MODIFIER}', localizedMessages.badges.search.modifier[modifier]);
-
- // mappings for user input sanitization
- const map = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- "/": '/',
- };
-
- const reg = /[&<>"'/]/ig;
- span.innerHTML = value.replace(reg, (match)=>(map[match]));
+ span.innerHTML = value;
}
};
@@ -703,6 +723,9 @@ function initBadgeControls() {
const searchArtist = document.getElementById('searchArtist').parentElement;
onDropdownActivate(searchArtist, () => searchBadges('artist'));
+ const searchContents = document.getElementById('searchContents').parentElement;
+ onDropdownActivate(searchContents, () => searchBadges('contents'));
+
function searchBadges(mode) {
badgeDropdown.classList.add('hidden');
updateBadgeVisibility(mode);
@@ -1083,6 +1106,10 @@ function getBadgeItem(badge, includeTooltip, emptyIcon, lockedIcon, scaled, filt
percent: badge.percent,
badgeId: badge.badgeId,
art: '',
+ originalOrder: badge.originalOrder,
+ unlocked: badge.unlocked,
+ secret: badge.secret,
+ secretCondition: badge.secretCondition,
};
item.dataset.cacheIndex = badgeFilterCache.push(filterItem) - 1;
}
diff --git a/index.php b/index.php
index fce75fcd..022feb73 100644
--- a/index.php
+++ b/index.php
@@ -1080,6 +1080,7 @@ class="joystickBase" />
@@ -1101,6 +1102,10 @@ class="joystickBase" />
+
@@ -1112,6 +1117,9 @@ class="joystickBase" />
Artist:
+
+ Text:
+
✖
diff --git a/lang/ar.json b/lang/ar.json
index 11d1e8b7..f577b59a 100644
--- a/lang/ar.json
+++ b/lang/ar.json
@@ -403,7 +403,8 @@
"label": "البحث: ",
"name": "Name:",
"location": "Location:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/de.json b/lang/de.json
index 0e8c88a3..b369a831 100644
--- a/lang/de.json
+++ b/lang/de.json
@@ -403,7 +403,8 @@
"label": "Suchen nach: ",
"name": "Name:",
"location": "Ort:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/en.json b/lang/en.json
index 87e28083..1bb740ce 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -403,7 +403,8 @@
"label": "Search: ",
"name": "Name:",
"location": "Location:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/eo.json b/lang/eo.json
index bdd021dd..cef5f2e9 100644
--- a/lang/eo.json
+++ b/lang/eo.json
@@ -403,7 +403,8 @@
"label": "Serĉi: ",
"name": "Nomo:",
"location": "Loko:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/es.json b/lang/es.json
index 0716401d..f3468d27 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -403,7 +403,8 @@
"label": "Buscar: ",
"name": "Nombre:",
"location": "Ubicación:",
- "artist": "Artista:"
+ "artist": "Artista:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/fr.json b/lang/fr.json
index 1398cf79..ccc8c425 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -403,7 +403,8 @@
"label": "Rechercher : ",
"name": "Nom :",
"location": "Lieu :",
- "artist": "Artiste :"
+ "artist": "Artiste :",
+ "contents": "Text:"
}
}
},
diff --git a/lang/id.json b/lang/id.json
index cf4d5de8..6e44e8e7 100644
--- a/lang/id.json
+++ b/lang/id.json
@@ -403,7 +403,8 @@
"label": "Search: ",
"name": "Name:",
"location": "Location:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/it.json b/lang/it.json
index f87bafcb..6352fc9b 100644
--- a/lang/it.json
+++ b/lang/it.json
@@ -403,7 +403,8 @@
"label": "Cerca : ",
"name": "Nome :",
"location": "Luogo :",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/ja.json b/lang/ja.json
index 9c67b9cd..ca6307e3 100644
--- a/lang/ja.json
+++ b/lang/ja.json
@@ -403,7 +403,8 @@
"label": "検索:",
"name": "名:",
"location": "場所:",
- "artist": "作者:"
+ "artist": "作者:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/ko.json b/lang/ko.json
index a38690e1..56717b5f 100644
--- a/lang/ko.json
+++ b/lang/ko.json
@@ -403,7 +403,8 @@
"label": "검색: ",
"name": "이름:",
"location": "장소:",
- "artist": "배지 디자이너:"
+ "artist": "배지 디자이너:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/pl.json b/lang/pl.json
index f40d596a..5c8671e2 100644
--- a/lang/pl.json
+++ b/lang/pl.json
@@ -403,7 +403,8 @@
"label": "Szukaj: ",
"name": "Nazwa:",
"location": "Lokalizacja:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/pt.json b/lang/pt.json
index 28ae509a..1b9eeb7f 100644
--- a/lang/pt.json
+++ b/lang/pt.json
@@ -403,7 +403,8 @@
"label": "Buscar: ",
"name": "Nome:",
"location": "Localização:",
- "artist": "Artista:"
+ "artist": "Artista:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/ro.json b/lang/ro.json
index 5fde7651..ed875da1 100644
--- a/lang/ro.json
+++ b/lang/ro.json
@@ -403,7 +403,8 @@
"label": "Caută: ",
"name": "Nume:",
"location": "Locație:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/ru.json b/lang/ru.json
index 5025dae1..a4fcad22 100644
--- a/lang/ru.json
+++ b/lang/ru.json
@@ -403,7 +403,8 @@
"label": "Поиск: ",
"name": "Название:",
"location": "Локация:",
- "artist": "Художник:"
+ "artist": "Художник:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/tr.json b/lang/tr.json
index 05ffb20c..7bfe9bc1 100644
--- a/lang/tr.json
+++ b/lang/tr.json
@@ -403,7 +403,8 @@
"label": "Ara: ",
"name": "İsim:",
"location": "Konum:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/uk.json b/lang/uk.json
index aa977a96..349dbe7d 100644
--- a/lang/uk.json
+++ b/lang/uk.json
@@ -403,7 +403,8 @@
"label": "Пошук: ",
"name": "Назва:",
"location": "Місце:",
- "artist": "Artist:"
+ "artist": "Artist:",
+ "contents": "Text:"
}
}
},
diff --git a/lang/vi.json b/lang/vi.json
index 1c8984c1..81c5919a 100644
--- a/lang/vi.json
+++ b/lang/vi.json
@@ -403,7 +403,8 @@
"label": "Tìm kiếm: ",
"name": "Tên:",
"location": "Địa điểm:",
- "artist": "Họa sĩ:"
+ "artist": "Họa sĩ:",
+ "contents": "Nội dung:"
}
}
},
diff --git a/lang/zh.json b/lang/zh.json
index cc377d1d..667a0383 100644
--- a/lang/zh.json
+++ b/lang/zh.json
@@ -403,7 +403,8 @@
"label": "搜索: ",
"name": "名称:",
"location": "取得位置:",
- "artist": "作者:"
+ "artist": "作者:",
+ "contents": "Text:"
}
}
},