stat2025 commited on
Commit
7fd37cd
·
verified ·
1 Parent(s): 7662fa0

Upload 2 files

Browse files
Files changed (2) hide show
  1. index.html +223 -0
  2. script.js +147 -0
index.html ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>صفحة البحث عن خريطة باحث</title>
7
+ <style>
8
+ :root{
9
+ --bg:#f7f8fc;
10
+ --card:#ffffff;
11
+ --text:#0f172a;
12
+ --muted:#64748b;
13
+ --border:#e2e8f0;
14
+ --shadow:0 10px 30px rgba(2,8,23,.08);
15
+ --radius:18px;
16
+ }
17
+ *{box-sizing:border-box}
18
+ body{
19
+ margin:0;
20
+ font-family: system-ui, -apple-system, "Segoe UI", Tahoma, Arial, sans-serif;
21
+ background: radial-gradient(1200px 700px at 50% -10%, #e8f0ff 0%, rgba(232,240,255,0) 55%),
22
+ radial-gradient(900px 600px at 90% 20%, #eafbf3 0%, rgba(234,251,243,0) 55%),
23
+ var(--bg);
24
+ color:var(--text);
25
+ min-height:100vh;
26
+ display:flex;
27
+ flex-direction:column;
28
+ }
29
+ header{
30
+ padding:48px 16px 18px;
31
+ text-align:center;
32
+ }
33
+ h1{
34
+ margin:0 0 10px;
35
+ font-size: clamp(22px, 2.2vw, 34px);
36
+ letter-spacing:.2px;
37
+ }
38
+ p.sub{
39
+ margin:0;
40
+ color:var(--muted);
41
+ font-size: 15px;
42
+ line-height: 1.8;
43
+ }
44
+ main{
45
+ width:min(920px, 92vw);
46
+ margin: 0 auto;
47
+ flex:1;
48
+ padding: 16px 0 90px;
49
+ }
50
+ .card{
51
+ background:var(--card);
52
+ border:1px solid var(--border);
53
+ border-radius:var(--radius);
54
+ box-shadow:var(--shadow);
55
+ padding:18px;
56
+ }
57
+ .searchRow{
58
+ display:flex;
59
+ gap:10px;
60
+ align-items:stretch;
61
+ flex-wrap:wrap;
62
+ }
63
+ .inputWrap{
64
+ position:relative;
65
+ flex:1 1 420px;
66
+ min-width:260px;
67
+ }
68
+ input[type="text"]{
69
+ width:100%;
70
+ padding:14px 14px 14px 44px;
71
+ border:1px solid var(--border);
72
+ border-radius:14px;
73
+ outline:none;
74
+ font-size:16px;
75
+ background:#fff;
76
+ }
77
+ input[type="text"]:focus{
78
+ border-color:#93c5fd;
79
+ box-shadow:0 0 0 4px rgba(59,130,246,.12);
80
+ }
81
+ .icon{
82
+ position:absolute;
83
+ left:12px;
84
+ top:50%;
85
+ transform:translateY(-50%);
86
+ color:#94a3b8;
87
+ pointer-events:none;
88
+ font-size:18px;
89
+ }
90
+ button{
91
+ border:1px solid #1d4ed8;
92
+ background:#1d4ed8;
93
+ color:#fff;
94
+ padding: 12px 18px;
95
+ border-radius:14px;
96
+ font-size:16px;
97
+ cursor:pointer;
98
+ transition: transform .06s ease, opacity .2s ease;
99
+ flex: 0 0 auto;
100
+ min-width:120px;
101
+ }
102
+ button:active{ transform: translateY(1px); }
103
+ button.secondary{
104
+ border:1px solid var(--border);
105
+ background:#fff;
106
+ color:var(--text);
107
+ min-width:110px;
108
+ }
109
+ .meta{
110
+ display:flex;
111
+ justify-content:space-between;
112
+ align-items:center;
113
+ gap:12px;
114
+ flex-wrap:wrap;
115
+ margin-top:12px;
116
+ color:var(--muted);
117
+ font-size:13px;
118
+ }
119
+ .badge{
120
+ background:#f1f5f9;
121
+ border:1px solid var(--border);
122
+ color:#0f172a;
123
+ padding:6px 10px;
124
+ border-radius:999px;
125
+ font-size:12px;
126
+ }
127
+ .results{
128
+ margin-top:14px;
129
+ border-top:1px dashed var(--border);
130
+ padding-top:14px;
131
+ display:grid;
132
+ gap:10px;
133
+ }
134
+ .item{
135
+ display:flex;
136
+ align-items:center;
137
+ justify-content:space-between;
138
+ gap:10px;
139
+ padding:12px 12px;
140
+ border:1px solid var(--border);
141
+ border-radius:14px;
142
+ background:#fff;
143
+ }
144
+ .name{
145
+ font-weight:650;
146
+ font-size:15px;
147
+ line-height:1.6;
148
+ }
149
+ .hint{
150
+ color:var(--muted);
151
+ font-size:13px;
152
+ margin-top:2px;
153
+ }
154
+ a.open{
155
+ text-decoration:none;
156
+ border:1px solid #0ea5e9;
157
+ color:#0369a1;
158
+ padding:10px 12px;
159
+ border-radius:12px;
160
+ background: #f0f9ff;
161
+ white-space:nowrap;
162
+ }
163
+ a.open:hover{ opacity:.9; }
164
+ .empty{
165
+ text-align:center;
166
+ color:var(--muted);
167
+ padding:22px 10px;
168
+ border:1px dashed var(--border);
169
+ border-radius:14px;
170
+ background:#fff;
171
+ }
172
+ footer{
173
+ position:fixed;
174
+ bottom:0;
175
+ left:0;
176
+ right:0;
177
+ padding: 10px 14px;
178
+ text-align:center;
179
+ color:#475569;
180
+ font-size:13px;
181
+ background: rgba(255,255,255,.85);
182
+ border-top:1px solid var(--border);
183
+ backdrop-filter: blur(8px);
184
+ }
185
+ mark{
186
+ background: #fff7ed;
187
+ padding: 0 4px;
188
+ border-radius: 6px;
189
+ }
190
+ </style>
191
+ </head>
192
+ <body>
193
+ <header>
194
+ <h1>صفحة البحث عن خريطة باحث</h1>
195
+ <p class="sub">اكتب اسم الباحث أو جزءًا منه، ثم اختر النتيجة لفتح رابط الخريطة.</p>
196
+ </header>
197
+
198
+ <main>
199
+ <section class="card" aria-label="search">
200
+ <div class="searchRow">
201
+ <div class="inputWrap">
202
+ <span class="icon">🔎</span>
203
+ <input id="q" type="text" inputmode="search" autocomplete="off"
204
+ placeholder="مثال: تركي / ��وره / المحيفيظ ..." />
205
+ </div>
206
+ <button id="btnSearch" type="button">بحث</button>
207
+ <button id="btnClear" class="secondary" type="button">مسح</button>
208
+ </div>
209
+
210
+ <div class="meta">
211
+ <div class="badge" id="countBadge">النتائج: 0</div>
212
+ <div>يدعم البحث بجزء من الاسم (حتى كلمة واحدة).</div>
213
+ </div>
214
+
215
+ <div class="results" id="results" aria-live="polite"></div>
216
+ </section>
217
+ </main>
218
+
219
+ <footer>تصميم وإعداد الدعم الفني نوف الناصر</footer>
220
+
221
+ <script src="./script.js"></script>
222
+ </body>
223
+ </html>
script.js ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // بيانات الروابط (تم توليدها من ملف Excel)
2
+ const DATA = [{"name": "أروى سعيد بن عبدالله القحطاني", "url": "https://stat2025-map.static.hf.space/BCS/37.html"}, {"name": "أسماء درويش سالم الدوسري", "url": "https://stat2025-map.static.hf.space/BCS/15.html"}, {"name": "أمل احمد محمد مجرشي", "url": "https://stat2025-map.static.hf.space/BCS/28.html"}, {"name": "أمل بنت علي بن علي السماعيل", "url": "https://stat2025-map.static.hf.space/BCS/07.html"}, {"name": "أمل جعفر بن علي آل حماد", "url": "https://stat2025-map.static.hf.space/BCS/30.html"}, {"name": "أمل صالح بن احمد آل مزعل", "url": "https://stat2025-map.static.hf.space/BCS/47.html"}, {"name": "ابرار بنت يوسف بن علي آل حماد", "url": "https://stat2025-map.static.hf.space/BCS/44.html"}, {"name": "احلام صالح معيوض العصيمي", "url": "https://stat2025-map.static.hf.space/BCS/16.html"}, {"name": "اسعد بن ماجد بن احمد الهاشم", "url": "https://stat2025-map.static.hf.space/BCS/46.html"}, {"name": "اسماء بنت محمد بن حسين العدساني", "url": "https://stat2025-map.static.hf.space/BCS/09.html"}, {"name": "ايمان عبدالعزيز بن صالح الصالح", "url": "https://stat2025-map.static.hf.space/BCS/40.html"}, {"name": "باسمه احمد بن محمد القرني", "url": "https://stat2025-map.static.hf.space/BCS/21.html"}, {"name": "باقر عبدالله بن هاشم الهاشم", "url": "https://stat2025-map.static.hf.space/BCS/11.html"}, {"name": "تركي وحيد بن عيسى المحيفيظ", "url": "https://stat2025-map.static.hf.space/BCS/01.html"}, {"name": "حسن عادل بن حسين الوصيبعي", "url": "https://stat2025-map.static.hf.space/BCS/03.html"}, {"name": "زكي بن عيسى بن عبدالله القفاص", "url": "https://stat2025-map.static.hf.space/BCS/51.html"}, {"name": "زهراء بنت عايش بن علي الصاهود", "url": "https://stat2025-map.static.hf.space/BCS/33.html"}, {"name": "ساره خالد سليمان المحيسن", "url": "https://stat2025-map.static.hf.space/BCS/35.html"}, {"name": "ساره راشد عبدالله المديني", "url": "https://stat2025-map.static.hf.space/BCS/34.html"}, {"name": "ساره عبدالحميد بن حسين البوحمد", "url": "https://stat2025-map.static.hf.space/BCS/12.html"}, {"name": "سميه رياض بن عبدالله البراك", "url": "https://stat2025-map.static.hf.space/BCS/39.html"}, {"name": "سميه سامى بن احمد النعيم", "url": "https://stat2025-map.static.hf.space/BCS/05.html"}, {"name": "شريفه ابراهيم بن عبدالله العقيل", "url": "https://stat2025-map.static.hf.space/BCS/41.html"}, {"name": "شيماء عبدالرحمن بن دحباش سودي", "url": "https://stat2025-map.static.hf.space/BCS/19.html"}, {"name": "صالح دلي الشمري", "url": "https://stat2025-map.static.hf.space/BCS/48.html"}, {"name": "طيبه فالح بن عبدالله الرويشد", "url": "https://stat2025-map.static.hf.space/BCS/31.html"}, {"name": "عائشه سليمان بن نايف الحربي", "url": "https://stat2025-map.static.hf.space/BCS/13.html"}, {"name": "عبدالله خلف الجدعان", "url": "https://stat2025-map.static.hf.space/BCS/49.html"}, {"name": "عقيله محمدحسين بن علي الجباره", "url": "https://stat2025-map.static.hf.space/BCS/06.html"}, {"name": "علياء فيصل بن محمد الكثيري", "url": "https://stat2025-map.static.hf.space/BCS/36.html"}, {"name": "غدير عبدالعزيز بن سعد القاسم", "url": "https://stat2025-map.static.hf.space/BCS/38.html"}, {"name": "فارس ثاني الشمري", "url": "https://stat2025-map.static.hf.space/BCS/50.html"}, {"name": "فاطمه حسين بن ابراهيم القرقوش", "url": "https://stat2025-map.static.hf.space/BCS/45.html"}, {"name": "فايزه محمد مسعود الحازمي", "url": "https://stat2025-map.static.hf.space/BCS/32.html"}, {"name": "فيصل تركي فيصل القحطاني", "url": "https://stat2025-map.static.hf.space/BCS/18.html"}, {"name": "لطيفه صالح بن عبدالرحمن العبد القادر", "url": "https://stat2025-map.static.hf.space/BCS/25.html"}, {"name": "لطيفه علي بن حسين النعيم", "url": "https://stat2025-map.static.hf.space/BCS/29.html"}, {"name": "لين أحمد بن عبدالعزيز القصير", "url": "https://stat2025-map.static.hf.space/BCS/22.html"}, {"name": "محمد دبيان بن مفرج الشمري", "url": "https://stat2025-map.static.hf.space/BCS/27.html"}, {"name": "مرتضى عبدالجليل بن عيسى الحكيم", "url": "https://stat2025-map.static.hf.space/BCS/43.html"}, {"name": "مصطفى احمد بن جمعه الرمضان", "url": "https://stat2025-map.static.hf.space/BCS/10.html"}, {"name": "ممدوح مشعل ضيف الله الصخري", "url": "https://stat2025-map.static.hf.space/BCS/26.html"}, {"name": "منيره سعد بن احمد الجديدي", "url": "https://stat2025-map.static.hf.space/BCS/04.html"}, {"name": "منيره سعود بن عبدالعزيز القوز", "url": "https://stat2025-map.static.hf.space/BCS/42.html"}, {"name": "نبأ عادل بن عبدالكريم آل رضوان", "url": "https://stat2025-map.static.hf.space/BCS/23.html"}, {"name": "نجود عبدالعزيز بن عقيل العمري", "url": "https://stat2025-map.static.hf.space/BCS/20.html"}, {"name": "نوره عبدالله بن زهير الرزقي", "url": "https://stat2025-map.static.hf.space/BCS/24.html"}, {"name": "نوره عبدالله بن مانع الخالدي", "url": "https://stat2025-map.static.hf.space/BCS/02.html"}, {"name": "نوف صالح بن محمد السميح", "url": "https://stat2025-map.static.hf.space/BCS/08.html"}, {"name": "نيللي حسين عبدالله الجعص", "url": "https://stat2025-map.static.hf.space/BCS/17.html"}, {"name": "وضحه خالد بن مشرف الخالدي", "url": "https://stat2025-map.static.hf.space/BCS/14.html"}];
3
+
4
+ // --------- أدوات مساعدة للتطبيع (لتحسين البحث بالعربية) ----------
5
+ function normalizeArabic(s) {
6
+ if (!s) return "";
7
+ return String(s)
8
+ .trim()
9
+ .toLowerCase()
10
+ // إزالة التشكيل
11
+ .replace(/[\u064B-\u065F\u0670\u06D6-\u06ED]/g, "")
12
+ // إزالة التطويل
13
+ .replace(/\u0640/g, "")
14
+ // توحيد الهمزات
15
+ .replace(/[إأآٱ]/g, "ا")
16
+ // توحيد الياء والألف المقصورة
17
+ .replace(/ى/g, "ي")
18
+ // توحيد الهاء/التاء المربوطة (اختياري - يساعد في نتائج أكثر)
19
+ .replace(/ة/g, "ه")
20
+ // توحيد المسافات
21
+ .replace(/\s+/g, " ");
22
+ }
23
+
24
+ function highlightMatch(name, query) {
25
+ // تظليل بسيط بناءً على النص الأصلي (بدون تطبيع كامل لتفادي تعقيد الفهارس)
26
+ if (!query) return escapeHtml(name);
27
+ const q = query.trim();
28
+ if (!q) return escapeHtml(name);
29
+
30
+ // نبحث عن أول ظهور لنفس سلسلة المستخدم في الاسم الأصلي (حرفيًا)
31
+ const idx = name.indexOf(q);
32
+ if (idx === -1) return escapeHtml(name);
33
+ const before = escapeHtml(name.slice(0, idx));
34
+ const mid = escapeHtml(name.slice(idx, idx + q.length));
35
+ const after = escapeHtml(name.slice(idx + q.length));
36
+ return `${before}<mark>${mid}</mark>${after}`;
37
+ }
38
+
39
+ function escapeHtml(str) {
40
+ return String(str)
41
+ .replaceAll("&", "&amp;")
42
+ .replaceAll("<", "&lt;")
43
+ .replaceAll(">", "&gt;")
44
+ .replaceAll('"', "&quot;")
45
+ .replaceAll("'", "&#039;");
46
+ }
47
+
48
+ // --------- منطق البحث ----------
49
+ const elQ = document.getElementById("q");
50
+ const elResults = document.getElementById("results");
51
+ const elBadge = document.getElementById("countBadge");
52
+ const btnSearch = document.getElementById("btnSearch");
53
+ const btnClear = document.getElementById("btnClear");
54
+
55
+ function renderResults(list, rawQuery) {
56
+ elResults.innerHTML = "";
57
+
58
+ if (!list.length) {
59
+ elBadge.textContent = "النتائج: 0";
60
+ elResults.innerHTML = `<div class="empty">لا توجد نتائج مطابقة. جرّب كتابة جزء آخر من الاسم.</div>`;
61
+ return;
62
+ }
63
+
64
+ elBadge.textContent = `النتائج: ${list.length}`;
65
+
66
+ const frag = document.createDocumentFragment();
67
+
68
+ list.forEach(item => {
69
+ const div = document.createElement("div");
70
+ div.className = "item";
71
+
72
+ const left = document.createElement("div");
73
+ const nm = document.createElement("div");
74
+ nm.className = "name";
75
+ nm.innerHTML = highlightMatch(item.name, rawQuery);
76
+ const hint = document.createElement("div");
77
+ hint.className = "hint";
78
+ hint.textContent = "اضغط فتح الخريطة لزيارة الصفحة";
79
+ left.appendChild(nm);
80
+ left.appendChild(hint);
81
+
82
+ const a = document.createElement("a");
83
+ a.className = "open";
84
+ a.href = item.url;
85
+ a.target = "_blank";
86
+ a.rel = "noopener";
87
+ a.textContent = "فتح الخريطة";
88
+
89
+ div.appendChild(left);
90
+ div.appendChild(a);
91
+ frag.appendChild(div);
92
+ });
93
+
94
+ elResults.appendChild(frag);
95
+ }
96
+
97
+ function doSearch() {
98
+ const raw = elQ.value || "";
99
+ const q = normalizeArabic(raw);
100
+
101
+ if (!q) {
102
+ renderResults([], raw);
103
+ return;
104
+ }
105
+
106
+ // يدعم البحث بكلمة أو أكثر (كل الكلمات يجب أن تظهر)
107
+ const tokens = q.split(" ").filter(Boolean);
108
+
109
+ const matched = DATA.filter(d => {
110
+ const nameNorm = normalizeArabic(d.name);
111
+ return tokens.every(t => nameNorm.includes(t));
112
+ });
113
+
114
+ // ترتيب بسيط: الأقرب (أقصر اسم) ثم أبجدي
115
+ matched.sort((a, b) => {
116
+ const al = (a.name || "").length;
117
+ const bl = (b.name || "").length;
118
+ if (al !== bl) return al - bl;
119
+ return (a.name || "").localeCompare(b.name || "","ar");
120
+ });
121
+
122
+ renderResults(matched, raw.trim());
123
+ }
124
+
125
+ btnSearch.addEventListener("click", doSearch);
126
+
127
+ btnClear.addEventListener("click", () => {
128
+ elQ.value = "";
129
+ elQ.focus();
130
+ elResults.innerHTML = "";
131
+ elBadge.textContent = "النتائج: 0";
132
+ });
133
+
134
+ // بحث تلقائي أثناء الكتابة (مع تأخير بسيط)
135
+ let t = null;
136
+ elQ.addEventListener("input", () => {
137
+ clearTimeout(t);
138
+ t = setTimeout(doSearch, 150);
139
+ });
140
+
141
+ // Enter للبحث
142
+ elQ.addEventListener("keydown", (e) => {
143
+ if (e.key === "Enter") doSearch();
144
+ });
145
+
146
+ // تحميل أولي: إظهار حالة فارغة
147
+ elBadge.textContent = "النتائج: 0";