उदाहरण प्रोजेक्ट में मिनी ऐप्लिकेशन की प्रोग्रामिंग के सिद्धांतों को लागू करना

ऐप्लिकेशन का डोमेन

वेब ऐप्लिकेशन पर लागू होने वाली मिनी ऐप्लिकेशन प्रोग्रामिंग दिखाने के लिए, मुझे एक छोटे लेकिन पूरी तरह से काम करने वाले ऐप्लिकेशन के आइडिया की ज़रूरत थी. हाई-इंटेंसिटी इंटरवल ट्रेनिंग (एचआईआईटी) एक तरह की कार्डियोवैस्कुलर कसरत है. इसमें कम समय के लिए, एनारोबिक कसरत (ऐसी कसरत जिसमें ऑक्सीजन की ज़रूरत नहीं होती) की जाती है. इसके बाद, कम इंटेंसिटी वाली कसरत की जाती है, ताकि शरीर को आराम मिल सके. कई एचआईआईटी ट्रेनिंग में एचआईआईटी टाइमर का इस्तेमाल किया जाता है. उदाहरण के लिए, The Body Coach TV YouTube चैनल का यह 30 मिनट का ऑनलाइन सेशन.

ज़्यादा इंटेंसिटी वाले हरे रंग के टाइमर के साथ, एचआईआईटी ट्रेनिंग का ऑनलाइन सेशन.
चालू रहने की अवधि.
कम इंटेंसिटी वाले टाइमर के साथ एचआईआईटी ट्रेनिंग का ऑनलाइन सेशन.
आराम करने की अवधि.

HIIT Time का उदाहरण देने वाला ऐप्लिकेशन

इस चैप्टर के लिए, मैंने इस तरह के एचआईआईटी टाइमर ऐप्लिकेशन का एक बुनियादी उदाहरण बनाया है. इसका नाम "एचआईआईटी टाइम" है. इससे उपयोगकर्ता अलग-अलग टाइमर सेट और मैनेज कर सकता है. इनमें हमेशा हाई और लो इंटेंसिटी इंटरवल शामिल होता है. इसके बाद, वह ट्रेनिंग सेशन के लिए इनमें से किसी एक को चुन सकता है. यह एक रिस्पॉन्सिव ऐप्लिकेशन है. इसमें एक नेवबार, एक टैबबार, और तीन पेज हैं:

  • कसरत: कसरत के दौरान सक्रिय पेज. इससे उपयोगकर्ता को कोई एक टाइमर चुनने का विकल्प मिलता है. इसमें तीन प्रोग्रेस रिंग होती हैं: सेट की संख्या, कसरत की अवधि, और ब्रेक की अवधि.
  • टाइमर: इससे मौजूदा टाइमर मैनेज किए जा सकते हैं. साथ ही, उपयोगकर्ता नए टाइमर बना सकता है.
  • प्राथमिकताएं: इसकी मदद से, साउंड इफ़ेक्ट और स्पीच आउटपुट को टॉगल किया जा सकता है. साथ ही, भाषा और थीम चुनी जा सकती है.

यहां दिए गए स्क्रीनशॉट से, ऐप्लिकेशन के बारे में जानकारी मिलती है.

पोर्ट्रेट मोड में HIIT Time ऐप्लिकेशन का उदाहरण.
पोर्ट्रेट मोड में HIIT Time "Workout" टैब.
लैंडस्केप मोड में HIIT Time ऐप्लिकेशन का उदाहरण.
लैंडस्केप मोड में HIIT Time "Workout" टैब.
टाइमर मैनेज करने की सुविधा दिखाने वाला HIIT Time ऐप्लिकेशन का उदाहरण.
HIIT Time में टाइमर मैनेज करने की सुविधा.

ऐप्लिकेशन का स्ट्रक्चर

ऊपर बताए गए तरीके के मुताबिक, ऐप्लिकेशन में एक नेवबार, एक टैबबार, और तीन पेज होते हैं. इन्हें ग्रिड में व्यवस्थित किया जाता है. नैवबार और टैबबार को iframe के तौर पर दिखाया गया है. इनके बीच में <div> कंटेनर है. इसमें पेजों के लिए तीन और iframe हैं. इनमें से एक हमेशा दिखता है और यह टैबबार में चुने गए विकल्प पर निर्भर करता है. about:blank पर ले जाने वाला फ़ाइनल iframe, ऐप्लिकेशन में डाइनैमिक तौर पर बनाए गए पेजों के लिए काम करता है. इनकी ज़रूरत मौजूदा टाइमर में बदलाव करने या नए टाइमर बनाने के लिए होती है. मैं इस पैटर्न को मल्टी-पेज सिंगल-पेज ऐप्लिकेशन (एमपीएसपीए) कहता हूं.

ऐप्लिकेशन के एचटीएमएल स्ट्रक्चर का Chrome DevTools व्यू. इसमें दिखाया गया है कि इसमें छह iframe शामिल हैं: एक नेवबार के लिए, एक टैबबार के लिए, और तीन ऐप्लिकेशन के हर पेज के लिए ग्रुप किए गए हैं. साथ ही, डाइनैमिक पेजों के लिए फ़ाइनल प्लेसहोल्डर iframe है.
ऐप्लिकेशन में छह iframe शामिल हैं.

कॉम्पोनेंट पर आधारित lit-html मार्कअप

हर पेज का स्ट्रक्चर, lit-html के तौर पर बनाया जाता है. इसे रनटाइम के दौरान डाइनैमिक तौर पर कैलकुलेट किया जाता है. lit-html के बारे में जानकारी: यह JavaScript के लिए एक असरदार, एक्सप्रेशन वाली, और एक्सटेंसिबल एचटीएमएल टेंप्लेटिंग लाइब्रेरी है. इसे सीधे एचटीएमएल फ़ाइलों में इस्तेमाल करने से, मेंटल प्रोग्रामिंग मॉडल सीधे तौर पर आउटपुट पर फ़ोकस करता है. प्रोग्रामर के तौर पर, आपको यह तय करना होता है कि फ़ाइनल आउटपुट कैसा दिखेगा. इसके लिए, आपको एक टेंप्लेट लिखना होता है. इसके बाद, lit-html आपके डेटा के आधार पर, टेंप्लेट में मौजूद खाली जगहों को डाइनैमिक तरीके से भरता है. साथ ही, इवेंट लिसनर को हुक अप करता है. ऐप्लिकेशन, तीसरे पक्ष के कस्टम एलिमेंट का इस्तेमाल करता है. जैसे, Shoelace का <sl-progress-ring> या खुद से लागू किया गया कस्टम एलिमेंट, जिसे <human-duration> कहा जाता है. कस्टम एलिमेंट में डिक्लेरेटिव एपीआई होता है. उदाहरण के लिए, प्रोग्रेस रिंग का percentage एट्रिब्यूट. इसलिए, ये lit-html के साथ मिलकर अच्छी तरह से काम करते हैं. यहां दी गई सूची में इसे देखा जा सकता है.

<div>
  <button class="start" @click="${eventHandlers.start}" type="button">
    ${strings.START}
  </button>
  <button class="pause" @click="${eventHandlers.pause}" type="button">
    ${strings.PAUSE}
  </button>
  <button class="reset" @click="${eventHandlers.reset}" type="button">
    ${strings.RESET}
  </button>
</div>

<div class="progress-rings">
  <sl-progress-ring
    class="sets"
    percentage="${Math.floor(data.sets/data.activeTimer.sets*100)}"
  >
    <div class="progress-ring-caption">
      <span>${strings.SETS}</span>
      <span>${data.sets}</span>
    </div>
  </sl-progress-ring>
</div>
तीन बटन और प्रोग्रेस दिखाने वाली रिंग.
ऊपर दिए गए मार्कअप से जुड़ा पेज का रेंडर किया गया सेक्शन.

प्रोग्रामिंग मॉडल

हर पेज में एक Page क्लास होती है. यह lit-html मार्कअप को इवेंट हैंडलर के साथ-साथ हर पेज के लिए डेटा उपलब्ध कराती है. यह क्लास, लाइफ़साइकल के तरीकों के साथ भी काम करती है. जैसे, onShow(), onHide(), onLoad(), और onUnload(). पेजों के पास एक डेटा स्टोर का ऐक्सेस होता है. इसका इस्तेमाल, हर पेज की स्थिति और ग्लोबल स्थिति को शेयर करने के लिए किया जाता है. सभी स्ट्रिंग को एक ही जगह से मैनेज किया जाता है. इसलिए, अंतरराष्ट्रीय स्तर पर इस्तेमाल करने की सुविधा पहले से मौजूद होती है. ब्राउज़र, राउटिंग को बिना किसी शुल्क के मैनेज करता है. ऐसा इसलिए, क्योंकि ऐप्लिकेशन सिर्फ़ iframe की दृश्यता को टॉगल करता है. साथ ही, डाइनैमिक तरीके से बनाए गए पेजों के लिए, प्लेसहोल्डर iframe के src एट्रिब्यूट में बदलाव करता है. यहां दिए गए उदाहरण में, डाइनैमिक तौर पर बनाए गए पेज को बंद करने का कोड दिखाया गया है.

import Page from '../page.js';

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
ऐप्लिकेशन में मौजूद पेज को iframe के तौर पर दिखाया गया है.
नेविगेशन, iframe से iframe पर होता है.

शैलीकृत करना

पेजों की स्टाइलिंग, हर पेज के हिसाब से उसकी स्कोप की गई सीएसएस फ़ाइल में होती है. इसका मतलब है कि एलिमेंट को आम तौर पर सीधे तौर पर उनके एलिमेंट के नाम से ऐक्सेस किया जा सकता है, क्योंकि अन्य पेजों के साथ कोई टकराव नहीं हो सकता. ग्लोबल स्टाइल को हर पेज में जोड़ा जाता है. इसलिए, font-family या box-sizing जैसी सेंट्रल सेटिंग को बार-बार तय करने की ज़रूरत नहीं होती. थीम और गहरे रंग वाले मोड के विकल्प भी यहीं तय किए जाते हैं. यहां दी गई सूची में, प्राथमिकताओं वाले पेज के लिए नियम दिए गए हैं. इस पेज पर, अलग-अलग फ़ॉर्म एलिमेंट को ग्रिड पर दिखाया जाता है.

main {
  max-width: 600px;
}

form {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-gap: 0.5rem;
  margin-block-end: 1rem;
}

label {
  text-align: end;
  grid-column: 1 / 2;
}

input,
select {
  grid-column: 2 / 3;
}
HIIT Time ऐप्लिकेशन के सेटिंग पेज पर, ग्रिड लेआउट में फ़ॉर्म दिखाया गया है.
हर पेज अपने-आप में एक दुनिया है. स्टाइलिंग, सीधे तौर पर एलिमेंट के नामों से होती है.

स्क्रीन वेक लॉक

कसरत के दौरान, स्क्रीन बंद नहीं होनी चाहिए. जिन ब्राउज़र पर यह सुविधा काम करती है उनमें HIIT Time, स्क्रीन वेक लॉक की मदद से यह पता लगाता है कि स्क्रीन बंद तो नहीं हो गई है. नीचे दिए गए स्निपेट में, इसे करने का तरीका बताया गया है.

if ('wakeLock' in navigator) {
  const requestWakeLock = async () => {
    try {
      page.shared.wakeLock = await navigator.wakeLock.request('screen');
      page.shared.wakeLock.addEventListener('release', () => {
        // Nothing.
      });
    } catch (err) {
      console.error(`${err.name}, ${err.message}`);
    }
  };
  // Request a screen wake lock…
  await requestWakeLock();
  // …and re-request it when the page becomes visible.
  document.addEventListener('visibilitychange', async () => {
    if (
      page.shared.wakeLock !== null &&
      document.visibilityState === 'visible'
    ) {
      await requestWakeLock();
    }
  });
}

ऐप्लिकेशन की टेस्टिंग

HIIT Time ऐप्लिकेशन, GitHub पर उपलब्ध है. नई विंडो में डेमो आज़माया जा सकता है. इसके अलावा, यहां नीचे दिए गए iframe में भी डेमो आज़माया जा सकता है. यह मोबाइल डिवाइस जैसा दिखता है.

Acknowledgements

इस लेख की समीक्षा जो मेडली, केसी बास्क, मिलिका मिहाज्लिया, ऐलन केंट, और कीथ गु ने की है.