PageSourceSearch

https://ajanswork.com/assets/js/selax-search.js

js ajanswork.com collected 2026-10-01 15:03:21 UTC 5,186 bytes, 204 lines download raw bytes

1window.selaxLangs = {
2	en: {
3		searchPlaceholder: "Search",
4		noResults: "No results",
5	},
6	ar: {
7		searchPlaceholder: "إبحث",
8		noResults: "لا توجد نتائج",
9	},
10	tr: {
11		searchPlaceholder: "Ara",
12		noResults: "Sonuç bulunamadı",
13	},
14};
15
16(function ($) {
17	function normalizeForSearch(str, langCode) {
18		if (str == null) return "";
19
20		let s = String(str);
21
22		// Fix Turkish casing properly when lang is tr
23		if (langCode === "tr") {
24			s = s.toLocaleLowerCase("tr");
25		} else {
26			s = s.toLowerCase();
27		}
28
29		// Make search forgiving: remove accents/diacritics (ş->s, ğ->g, etc.)
30		// Works for TR + many other langs
31		s = s.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
32
33		// Optional: normalize special Turkish letters even after diacritics removal
34		// (normalize doesn't convert dotless ı)
35		s = s.replace(/ı/g, "i");
36
37		return s;
38	}
39	$.fn.selaxSearch = function () {
40		function getLangSettings() {
41			const lang =
42				$("html").attr("lang") || $("body").data("lang") || "en";
43			return window.selaxLangs?.[lang] || window.selaxLangs["en"];
44		}
45
46		function createDropdown($select, uniqid, options, lang) {
47			const container = $(
48				'<div class="dropdown-menu custom-select-container"><div class="options_list"></div></div>',
49			);
50
51			const searchInput = $(
52				`<input type="text" class="form-control form-control-sm border-0 border-bottom rounded-0" id="custom-select-search" placeholder="${lang.searchPlaceholder}" style="padding:10px 15px!important; border-bottom:1px solid #e6e8ea!important;">`,
53			);
54
55			container.prepend(searchInput);
56
57			options.forEach((opt) => {
58				const btn = $(
59					`<button class="dropdown-item fs-h5 modal-select-option ${opt.isActive} ${opt.isEmpty}" data-parent-select="${uniqid}" data-value="${opt.value}">${opt.text}</button>`,
60				);
61				container.find(".options_list").append(btn);
62			});
63
64			return container;
65		}
66
67		function buildOptions($select) {
68			const options = [];
69			$select.find("option").each(function () {
70				const $opt = $(this);
71				if (
72					$opt.prop("disabled") ||
73					$opt.prop("hidden") ||
74					$opt.hasClass("d-none")
75				)
76					return;
77
78				options.push({
79					value: $opt.val(),
80					text: $opt.text(),
81					isActive: $opt.is(":selected") ? "active" : "",
82					isEmpty: !$opt.val() ? "h5 text-muted" : "",
83				});
84			});
85			return options;
86		}
87
88		function closeDropdowns() {
89			$("select.opened")
90				.removeClass("opened")
91				.next(".custom-select-container")
92				.remove();
93		}
94
95		$(document)
96			.off("mousedown.selax")
97			.on("mousedown.selax", "select:not(.normal-select)", function (e) {
98				e.preventDefault();
99			});
100
101		$(document)
102			.off("click.selax")
103			.on("click.selax", "select:not(.normal-select)", function (e) {
104				e.preventDefault();
105
106				const $select = $(this);
107				if ($select.hasClass("opened")) return closeDropdowns();
108
109				closeDropdowns();
110
111				const uniqid = `selax-${Math.random()
112					.toString(36)
113					.substr(2, 9)}`;
114				$select.addClass("opened").addClass(uniqid);
115
116				const lang = getLangSettings();
117				const options = buildOptions($select);
118				const dropdown = createDropdown($select, uniqid, options, lang);
119
120				$select.after(dropdown);
121
122				dropdown.css({
123					width: $select.outerWidth(),
124					minWidth: $select.outerWidth() + 20,
125					// maxWidth: $select.outerWidth(),
126					maxWidth: "100%",
127					position: "absolute",
128					top: $select.position().top,
129					left: $select.position().left,
130				});
131
132				if (options.length > 2) {
133					dropdown.find(".options_list").css({
134						maxHeight: "200px",
135						overflowY: "auto",
136					});
137				}
138
139				dropdown.show();
140				dropdown.find("input").focus();
141			});
142
143		$(document)
144			.off("click.selax-option")
145			.on("click.selax-option", ".modal-select-option", function (e) {
146				e.preventDefault();
147				const $btn = $(this);
148				const selectClass = $btn.data("parent-select");
149				const $select = $("." + selectClass);
150
151				$select.val($btn.data("value")).trigger("change");
152				closeDropdowns();
153			});
154
155		$(document)
156			.off("keyup.selax-search")
157			.on("keyup.selax-search", "#custom-select-search", function () {
158				const langSettings = getLangSettings();
159				const langCode =
160					$("html").attr("lang") || $("body").data("lang") || "en";
161
162				const text = normalizeForSearch($(this).val(), langCode);
163
164				const $options = $(this)
165					.siblings(".options_list")
166					.find(".modal-select-option");
167
168				$options.each(function () {
169					const optText = normalizeForSearch(
170						$(this).text(),
171						langCode,
172					);
173					const match = optText.includes(text);
174					$(this).toggle(match);
175				});
176
177				$(this).siblings(".no-result-option").remove();
178
179				if (!$options.filter(":visible").length) {
180					$(this)
181						.parent()
182						.append(
183							`<div class="h5 my-2 mx-auto no-result-option text-center text-muted w-100">${langSettings.noResults}</div>`,
184						);
185				}
186			});
187
188		$(document).on("click.selax-outside", function (e) {
189			if (
190				!$(e.target).closest("select, .custom-select-container").length
191			) {
192				closeDropdowns();
193			}
194		});
195
196		$(document).on("keyup.selax-esc", function (e) {
197			if (e.key === "Escape") {
198				closeDropdowns();
199			}
200		});
201
202		return this;
203	};
204})(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.