-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathscript.js
More file actions
425 lines (377 loc) · 21.6 KB
/
script.js
File metadata and controls
425 lines (377 loc) · 21.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
const content = {
en: {
dir: "ltr",
lang: "en",
pageTitle: "Date Icebreakers — 36 Questions to Deepen Your Connection",
metaDescription:
"Discover authentic connection through 36 carefully crafted questions. A bilingual interactive guide in English and Farsi based on Arthur Aron's research on interpersonal closeness.",
ogLocale: "en_US",
welcomeTitle: "🥶 Date Icebreakers",
welcomeDescription:
"A scientifically designed set of 36 questions that gradually build closeness and intimacy between two people. Answer honestly, listen openly, and enjoy the journey.",
startBtn: "Let's Begin",
questionLabel: "Question",
setLabel: "Set",
of: "of",
sets: ["I", "II", "III"],
prevBtn: "Previous Question",
nextBtn: "Next Question",
lastNextBtn: "Finish",
finishBtn: "Start Over",
finishTitle: "That's all 36 questions!",
finishDescription:
"You answered all the questions. Nice! Hope you had a great time together. And after all these questions and answers, don't forget the only right next step: a seriously delicious meal. Also, share this with your friends too, it might help them out!",
referenceText: "Based on <a href=\"https://en.wikipedia.org/wiki/Arthur_Aron\" target=\"_blank\" rel=\"noopener noreferrer\">Arthur Aron's</a> study on interpersonal closeness. Published in The Experimental Generation of Interpersonal Closeness (1997).",
footerText: "Created on May 11, 2026 by ohmydevops - <a href=\"https://github.com/ohmydevops/date-icebreakers\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub</a>",
setBadges: ["Set I: Q 1-12", "Set II: Q 13-24", "Set III: Q 25-36"],
questions: [
// Set I
"Given the choice of anyone in the world, whom would you want as a dinner guest?",
"Would you like to be famous? In what way?",
"Before making a telephone call, do you ever rehearse what you are going to say? Why?",
'What would constitute a "perfect" day for you?',
"When did you last sing to yourself? To someone else?",
"If you were able to live to the age of 90 and retain either the mind or body of a 30-year-old for the last 60 years of your life, which would you want?",
"Do you have a secret hunch about how you will die?",
"Name three things you and your partner appear to have in common.",
"For what in your life do you feel most grateful?",
"If you could change anything about the way you were raised, what would it be?",
"Take four minutes and tell your partner your life story in as much detail as possible.",
"If you could wake up tomorrow having gained any one quality or ability, what would it be?",
// Set II
"If a crystal ball could tell you the truth about yourself, your life, the future or anything else, what would you want to know?",
"Is there something that you've dreamed of doing for a long time? Why haven't you done it?",
"What is the greatest accomplishment of your life?",
"What do you value most in a friendship?",
"What is your most treasured memory?",
"What is your most terrible memory?",
"If you knew that in one year you would die suddenly, would you change anything about the way you are now living? Why?",
"What does friendship mean to you?",
"What roles do love and affection play in your life?",
"Alternate sharing something you consider a positive characteristic of your partner. Share a total of five items.",
"How close and warm is your family? Do you feel your childhood was happier than most other people's?",
"How do you feel about your relationship with your mother?",
// Set III
'Make three true "we" statements each. For instance, "We are both in this room feeling …"',
'Complete this sentence: "I wish I had someone with whom I could share …"',
"If you were going to become a close friend with your partner, please share what would be important for him or her to know about you.",
"Tell your partner what you like about them; be very honest this time, saying things that you might not say to someone you've just met.",
"Share with your partner an embarrassing moment in your life.",
"When did you last cry in front of another person? By yourself?",
"Tell your partner something that you like about them already.",
"What, if anything, is too serious to be joked about?",
"If you were to die this evening with no opportunity to communicate with anyone, what would you most regret not having told someone? Why haven't you told them yet?",
"Your house, containing everything you own, catches fire. After saving your loved ones and pets, you have time to safely make one final dash. What items would you save? Why?",
"Of all the people in your family, whose death would you find most disturbing? Why?",
"Share a personal problem and ask your partner's advice on how he or she might handle it. Also, ask your partner to reflect back to you how you seem to be feeling about the problem you have chosen.",
],
},
fa: {
dir: "rtl",
lang: "fa",
pageTitle: "یخشکن قرار — ۳۶ سؤالی برای نزدیکتر شدن",
metaDescription:
"سایت دو زبانه ۳۶ سؤال برای آشنایی و نزدیکی بیشتر بین دو نفر. بر اساس مطالعه معروف آرتور آرون درباره رابطههای انسانی عمیق و درونی.",
ogLocale: "fa_IR",
welcomeTitle: "🥶 یخشکن قرار",
welcomeDescription:
"مجموعهای از سوالات که به شما توی آشنایی با هم دیگه کمک میکنه. به خصوص اگر توی دیت هستین :) در لحظه جواب بدین و از زندگی لذت ببرین و خوشحال باشین چون چیزهای خوب هم هنوز توی دنیا وجود داره.",
startBtn: "شروع کنیم",
questionLabel: "سؤال",
setLabel: "بخش",
of: "از",
sets: ["اول", "دوم", "سوم"],
prevBtn: "سؤال قبلی",
nextBtn: "سؤال بعدی",
lastNextBtn: "پایان",
finishBtn: "از ابتدا شروع کنید",
finishTitle: "همه ۳۶ سؤال تمام شد!",
finishDescription:
"تمام سؤالها رو پاسخ دادین! ایول. امیدوارم که خوش گذشته باشه حسابی بهتون و فراموش نکنین بعد این همه پرسش و پاسخ یک غذای مَشتی و خوشمزه فقط جوابه. راستی به دوستای دیگهتونم معرفی کنین اینجا رو شاید به کارشون بیاد!",
referenceText: "بر اساس مطالعه <a href=\"https://en.wikipedia.org/wiki/Arthur_Aron\" target=\"_blank\" rel=\"noopener noreferrer\">آرتور آرون</a> درباره نزدیکی بینفردی. منتشر شده در مقاله ایجاد تجربی نزدیکی بینفردی (۱۹۹۷).",
footerText: "ساخته شده در ۲۱ اردیبهشت ۱۴۰۵ توسط ohmydevops - <a href=\"https://github.com/ohmydevops/date-icebreakers\" target=\"_blank\" rel=\"noopener noreferrer\">گیتهاب</a>",
setBadges: ["بخش اول: سوال ۱ تا ۱۲", "بخش دوم: سوال ۱۳ تا ۲۴", "بخش سوم: سوال ۲۵ تا ۳۶"],
questions: [
// Set I
"اگه میتونستی هر کسی رو توی دنیا انتخاب کنی، دوست داشتی مهمون شامت کی باشه؟",
"دوست داری معروف بشی؟ اگه آره، به چه شکلی؟",
"قبل از تماس تلفنی، شده توی ذهنت تمرین کنی چی بگی؟ چرا؟",
"به نظر تو یه روز «بینقص» چه شکلیه؟",
"آخرین بار کی برای خودت آهنگ خوندی؟ برای یه نفر دیگه چی؟",
"اگه بتونی تا ۹۰ سالگی زندگی کنی و توی ۶۰ سال آخر یا ذهن ۳۰ سالگی رو داشته باشی یا بدن ۳۰ سالگی رو، کدوم رو انتخاب میکنی؟",
"ته دلت یه حدس مخفی درباره نحوه مرگت داری؟",
"سه تا چیزی که فکر میکنی با پارتنرت مشترک دارین رو بگو.",
"برای چی توی زندگیت بیشتر از همه حس قدردانی داری؟",
"اگه میتونستی یه چیزی رو توی نحوه بزرگ شدنت تغییر بدی، چی رو عوض میکردی؟",
"چهار دقیقه وقت بذار و داستان زندگیت رو تا جایی که میتونی با جزئیات تعریف کن.",
"اگه فردا صبح بیدار بشی و یه ویژگی یا توانایی جدید داشته باشی، دوست داری اون چی باشه؟",
// Set II
"اگه یه گوی جادویی میتونست حقیقت رو درباره خودت، زندگیت، آینده یا هر چیز دیگهای بهت بگه، دوست داشتی چی رو بدونی؟",
"یه کاری هست که مدتهاست دلت میخواد انجامش بدی؟ چرا هنوز انجامش ندادی؟",
"بزرگترین موفقیت زندگیت چی بوده؟",
"توی دوستی، چی برات از همه مهمتره؟",
"قشنگترین خاطرهای که داری چیه؟",
"سختترین یا بدترین خاطرهای که داری چیه؟",
"اگه بدونی یه سال دیگه ناگهانی میمیری، چیزی رو توی سبک زندگیت عوض میکنی؟ چرا؟",
"دوستی برای تو چه معنیای داره؟",
"عشق و محبت توی زندگیت چه نقشی دارن؟",
"نوبتی یه ویژگی مثبت از پارتنرت بگو. جمعا پنج تا مورد بگین.",
"فضای خانوادهتون چقدر صمیمی و گرمه؟ حس میکنی بچگیت نسبت به بیشتر آدما شادتر بوده؟",
"در مورد رابطهات با مادرت چه حسی داری؟",
// Set III
"هر کدومتون سه تا جمله واقعی با «ما» بسازین. مثلا: «ما الان توی این اتاقیم و ... حس میکنیم.»",
"این جمله رو کامل کن: «کاش یه نفر بود که میتونستم ... رو باهاش شریک بشم.»",
"اگه قرار باشه با پارتنرت خیلی صمیمی بشی، چه چیزی مهمه که دربارهات بدونه؟",
"به پارتنرت بگو چی توی اون دوست داری؛ این بار خیلی صادقانه و حتی چیزهایی که شاید به یه آشنای جدید نگی.",
"یه لحظه خجالتآور از زندگیت رو تعریف کن.",
"آخرین بار کی جلوی یه نفر گریه کردی؟ وقتی تنها بودی چی؟",
"یه چیزی که همین الان توی پارتنرت دوست داری بهش بگو.",
"به نظرت چه چیزی اونقدر جدیه که جای شوخی نداره؟",
"اگه امشب بدون اینکه فرصت حرف زدن با کسی داشته باشی بمیری، بیشتر از نگفتن چه چیزی پشیمون میشی؟ چرا هنوز نگفتیش؟",
"فرض کن خونهات با همه وسایلت آتیش گرفته. بعد از نجات عزیزات و حیوان خونگی، فقط وقت داری یه چیز دیگه برداری. چی رو برمیداری؟ چرا؟",
"بین آدمهای خانوادهات، از دست دادنِ چه کسی بیشتر از همه ناراحتت میکنه؟ چرا؟",
"یه مشکل شخصی رو مطرح کن و از پارتنرت بخواه بگه اگه جای تو بود چطور باهاش روبهرو میشد. بعد ازش بخواه برداشتش از احساس تو نسبت به این مشکل رو هم بگه.",
],
},
};
const BASE_URL = "https://ohmydevops.github.io/date-icebreakers/";
let currentLang = "fa";
let currentIndex = 0;
// ── Cookie Helpers ──────────────────────────────
function setCookie(name, value, days = 365) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
const expires = "expires=" + date.toUTCString();
document.cookie = `${name}=${value}; ${expires}; path=/`;
}
function getCookie(name) {
const nameEQ = name + "=";
const cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.indexOf(nameEQ) === 0) {
return cookie.substring(nameEQ.length);
}
}
return null;
}
// ── Farsi Number Conversion ────────────────────
function toFarsiNumbers(str) {
if (currentLang !== "fa") return str;
const englishDigits = "0123456789";
const farsiDigits = "۰۱۲۳۴۵۶۷۸۹";
let result = str;
for (let i = 0; i < 10; i++) {
result = result.replace(new RegExp(englishDigits[i], "g"), farsiDigits[i]);
}
return result;
}
const welcomeScreen = document.getElementById("welcome-screen");
const questionScreen = document.getElementById("question-screen");
const finishScreen = document.getElementById("finish-screen");
const langToggleBtn = document.getElementById("lang-toggle");
const welcomeTitle = document.getElementById("welcome-title");
const welcomeDescription = document.getElementById("welcome-description");
const startBtn = document.getElementById("start-btn");
const questionLabel = document.getElementById("question-label");
const questionCounter = document.getElementById("question-counter");
const questionText = document.getElementById("question-text");
const prevBtn = document.getElementById("prev-btn");
const nextBtn = document.getElementById("next-btn");
const progressBar = document.getElementById("progress-bar");
const finishTitle = document.getElementById("finish-title");
const finishDescription = document.getElementById("finish-description");
const finishBtn = document.getElementById("finish-btn");
const referenceText = document.getElementById("reference-text");
const footerText = document.getElementById("footer-text");
const setBadge1 = document.getElementById("set-badge-1");
const setBadge2 = document.getElementById("set-badge-2");
const setBadge3 = document.getElementById("set-badge-3");
const qSet1 = document.getElementById("q-set-1");
const qSet2 = document.getElementById("q-set-2");
const qSet3 = document.getElementById("q-set-3");
function updateSetIndicator(setIndex, t) {
qSet1.textContent = `${t.setLabel} ${t.sets[0]}`;
qSet2.textContent = `${t.setLabel} ${t.sets[1]}`;
qSet3.textContent = `${t.setLabel} ${t.sets[2]}`;
qSet1.classList.toggle("active", setIndex === 0);
qSet2.classList.toggle("active", setIndex === 1);
qSet3.classList.toggle("active", setIndex === 2);
}
function getLanguageFromUrl() {
const params = new URLSearchParams(window.location.search);
const lang = params.get("lang");
return lang === "en" || lang === "fa" ? lang : null;
}
function updateLanguageUrl() {
const url = new URL(window.location.href);
url.searchParams.set("lang", currentLang);
window.history.replaceState({}, "", `${url.pathname}${url.search}${window.location.hash}`);
}
function updateSeoForLanguage(t) {
document.title = t.pageTitle;
const description = document.querySelector('meta[name="description"]');
if (description) description.setAttribute("content", t.metaDescription);
const ogTitle = document.querySelector('meta[property="og:title"]');
if (ogTitle) ogTitle.setAttribute("content", t.pageTitle);
const ogDescription = document.querySelector('meta[property="og:description"]');
if (ogDescription) ogDescription.setAttribute("content", t.metaDescription);
const ogLocale = document.querySelector('meta[property="og:locale"]');
if (ogLocale) ogLocale.setAttribute("content", t.ogLocale);
const twitterTitle = document.querySelector('meta[name="twitter:title"]');
if (twitterTitle) twitterTitle.setAttribute("content", t.pageTitle);
const twitterDescription = document.querySelector('meta[name="twitter:description"]');
if (twitterDescription) twitterDescription.setAttribute("content", t.metaDescription);
const canonical = document.getElementById("canonical-url");
if (canonical) canonical.setAttribute("href", `${BASE_URL}?lang=${currentLang}`);
const hreflangEn = document.getElementById("hreflang-en");
if (hreflangEn) hreflangEn.setAttribute("href", `${BASE_URL}?lang=en`);
const hreflangFa = document.getElementById("hreflang-fa");
if (hreflangFa) hreflangFa.setAttribute("href", `${BASE_URL}?lang=fa`);
}
function applyLang() {
const t = content[currentLang];
document.documentElement.setAttribute("dir", t.dir);
document.documentElement.setAttribute("lang", t.lang);
welcomeTitle.textContent = t.welcomeTitle;
welcomeDescription.textContent = t.welcomeDescription;
startBtn.textContent = t.startBtn;
finishTitle.textContent = t.finishTitle;
finishDescription.textContent = t.finishDescription;
finishBtn.textContent = t.finishBtn;
referenceText.innerHTML = t.referenceText;
footerText.innerHTML = t.footerText;
setBadge1.textContent = t.setBadges[0];
setBadge2.textContent = t.setBadges[1];
setBadge3.textContent = t.setBadges[2];
updateSetIndicator(Math.floor(currentIndex / 12), t);
updateSeoForLanguage(t);
updateLanguageUrl();
// Show the opposite language on the button.
const nextLanguage = currentLang === "en" ? "فارسی" : "English";
langToggleBtn.textContent = nextLanguage;
langToggleBtn.title = nextLanguage;
langToggleBtn.classList.toggle("is-fa-label", nextLanguage === "فارسی");
// Swap manifest for correct install-prompt language
const manifestLink = document.getElementById("manifest-link");
if (manifestLink) {
manifestLink.href = currentLang === "en" ? "manifest.en.json" : "manifest.fa.json";
}
// Save language preference to cookie
setCookie("preferredLang", currentLang);
if (!welcomeScreen.classList.contains("hidden")) return;
renderQuestion();
}
function loadSavedLanguage() {
const langFromUrl = getLanguageFromUrl();
const langFromCookie = getCookie("preferredLang");
const validCookieLang = langFromCookie === "en" || langFromCookie === "fa" ? langFromCookie : null;
// Priority: URL param > saved cookie > default
currentLang = langFromUrl || validCookieLang || "fa";
applyLang();
}
function renderQuestion() {
const t = content[currentLang];
const total = t.questions.length;
const setIndex = Math.floor(currentIndex / 12);
let labelText = `${t.questionLabel} ${currentIndex + 1} ${t.of} ${total}`;
let counterText = `${t.setLabel} ${t.sets[setIndex]}`;
labelText = toFarsiNumbers(labelText);
counterText = toFarsiNumbers(counterText);
questionLabel.textContent = labelText;
questionCounter.textContent = counterText;
questionText.textContent = t.questions[currentIndex];
progressBar.style.width = `${((currentIndex + 1) / total) * 100}%`;
updateSetIndicator(setIndex, t);
prevBtn.textContent = t.prevBtn;
prevBtn.disabled = currentIndex === 0;
if (currentIndex === total - 1) {
nextBtn.textContent = t.lastNextBtn;
} else {
nextBtn.textContent = t.nextBtn;
}
}
function showScreen(screen) {
welcomeScreen.classList.add("hidden");
questionScreen.classList.add("hidden");
finishScreen.classList.add("hidden");
screen.classList.remove("hidden");
}
langToggleBtn.addEventListener("click", () => {
currentLang = currentLang === "en" ? "fa" : "en";
applyLang();
router();
});
// Dark Mode Toggle
const themeToggleBtn = document.getElementById("theme-toggle");
const loadTheme = () => {
const savedTheme = localStorage.getItem("theme") || "light";
if (savedTheme === "dark") {
document.documentElement.classList.add("dark-mode");
}
};
loadTheme();
themeToggleBtn.addEventListener("click", () => {
document.documentElement.classList.toggle("dark-mode");
const isDark = document.documentElement.classList.contains("dark-mode");
localStorage.setItem("theme", isDark ? "dark" : "light");
});
startBtn.addEventListener("click", () => {
navigate("#/question/1");
});
prevBtn.addEventListener("click", () => {
if (currentIndex > 0) {
navigate(`#/question/${currentIndex}`);
}
});
nextBtn.addEventListener("click", () => {
const total = content[currentLang].questions.length;
if (currentIndex === total - 1) {
navigate("#/finish");
return;
}
navigate(`#/question/${currentIndex + 2}`);
});
finishBtn.addEventListener("click", () => {
navigate("#/");
});
// ── Routing ─────────────────────────────────────
function navigate(hash) {
window.location.hash = hash;
router();
}
function router() {
const hash = window.location.hash || "#/";
const questionMatch = hash.match(/#\/question\/(\d+)/);
if (questionMatch) {
const id = parseInt(questionMatch[1]) - 1;
if (id >= 0 && id < content[currentLang].questions.length) {
currentIndex = id;
showScreen(questionScreen);
renderQuestion();
questionText.classList.remove("fade-in");
questionText.offsetWidth;
questionText.classList.add("fade-in");
} else {
navigate("#/");
}
} else if (hash === "#/finish") {
showScreen(finishScreen);
applyLang();
} else {
currentIndex = 0;
showScreen(welcomeScreen);
}
}
window.addEventListener("hashchange", () => {
router();
});
// Init
loadSavedLanguage();
router();
// Service Worker
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("./sw.js");
});
}