दर्शकों को जोड़े रखने के लिए,

Sérgio Gomes

वेब पर चीज़ों को पॉइंट करना पहले आसान था. आपके पास एक माउस होता था, जिसे इधर-उधर घुमाया जाता था और कभी-कभी बटन दबाए जाते थे. माउस के अलावा, किसी भी डिवाइस को माउस के तौर पर एमुलेट किया जाता था. डेवलपर को यह पता होता था कि किस डिवाइस पर भरोसा किया जा सकता है.

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

इस काम में हमारी मदद करने के लिए, हमारे पास कुछ समय से टच इवेंट हैं. हालांकि, ये खास तौर पर टच के लिए एक अलग एपीआई हैं. इसलिए, अगर आपको माउस और टच, दोनों के साथ काम करना है, तो आपको दो अलग-अलग इवेंट मॉडल कोड करने होंगे. Chrome 55 में एक नया स्टैंडर्ड शामिल है, जो दोनों मॉडल को एक साथ जोड़ता है: पॉइंटर इवेंट.

एक इवेंट मॉडल

पॉइंटर इवेंट, ब्राउज़र के लिए पॉइंटर इनपुट मॉडल को एक साथ जोड़ते हैं. इससे टच, पेन, और माउस को इवेंट के एक ही सेट में शामिल किया जाता है. उदाहरण के लिए:

document.addEventListener('pointermove',
    ev => console.log('The pointer moved.'));
foo.addEventListener('pointerover',
    ev => console.log('The pointer is now over foo.'));

यहां सभी उपलब्ध इवेंट की सूची दी गई है. अगर आपको माउस इवेंट के बारे में पता है, तो ये इवेंट आपको काफ़ी हद तक मिलते-जुलते लगेंगे:

pointerover पॉइंटर, एलिमेंट के बाउंडिंग बॉक्स में चला गया है. यह उन डिवाइसों के लिए तुरंत होता है जिन पर कर्सर घुमाने की सुविधा काम करती है. इसके अलावा, जिन डिवाइसों पर यह सुविधा काम नहीं करती उनके लिए, pointerdown इवेंट से पहले ऐसा होता है.
pointerenter pointerover से मिलता-जुलता है, लेकिन यह बबल नहीं होता और वंशजों को अलग तरीके से मैनेज करता है. स्पेसिफ़िकेशन के बारे में जानकारी.
pointerdown पॉइंटर, ऐक्टिव बटन की स्थिति में है. ऐसा इसलिए होता है, क्योंकि इनपुट डिवाइस के सेमेटिक्स के आधार पर, बटन को दबाया गया है या संपर्क किया गया है.
pointermove पॉइंटर की जगह बदल गई है.
pointerup पॉइंटर, ऐक्टिव बटन की स्थिति से हट गया है.
pointercancel ऐसा कुछ हुआ है जिसकी वजह से, पॉइंटर के किसी और इवेंट को उत्सर्जित करने की संभावना कम है. इसका मतलब है कि आपको अपनी मौजूदा कार्रवाई रद्द करनी चाहिए और फिर से सामान्य इनपुट मोड पर जाना चाहिए.
pointerout पॉइंटर, एलिमेंट या स्क्रीन के बाउंडिंग बॉक्स से बाहर निकल गया है. अगर डिवाइस पर कर्सर घुमाने की सुविधा काम नहीं करती है, तो pointerup के बाद भी ऐसा किया जा सकता है.
pointerleave pointerout से मिलता-जुलता है, लेकिन यह बबल नहीं होता और वंशजों को अलग तरीके से मैनेज करता है. स्पेसिफ़िकेशन के बारे में जानकारी.
gotpointercapture एलिमेंट को पॉइंटर कैप्चर मिला है.
lostpointercapture जिस पॉइंटर को कैप्चर किया जा रहा था उसे रिलीज़ कर दिया गया है.

अलग-अलग तरह के इनपुट

आम तौर पर, पॉइंटर इवेंट की मदद से, अलग-अलग इनपुट डिवाइसों के लिए अलग-अलग इवेंट हैंडलर रजिस्टर किए बिना, इनपुट के हिसाब से कोड लिखा जा सकता है. हालांकि, आपको इनपुट टाइप के बीच के अंतरों का ध्यान रखना होगा. जैसे, क्या कर्सर घुमाने पर, इमेज पर कर्सर का रंग बदलता है. अगर आपको अलग-अलग तरह के इनपुट डिवाइसों को अलग-अलग बताना है, तो ऐसा एक ही इवेंट हैंडलर में किया जा सकता है. इसके लिए, PointerEvent इंटरफ़ेस की pointerType प्रॉपर्टी का इस्तेमाल करें. ऐसा, अलग-अलग इनपुट के लिए अलग कोड/फ़ंक्शन देने के लिए किया जा सकता है. उदाहरण के लिए, अगर साइड नेविगेशन ड्रॉअर को कोड किया जा रहा है, तो आपके pointermove इवेंट में यह लॉजिक हो सकता है:

switch(ev.pointerType) {
    case 'mouse':
    // Do nothing.
    break;
    case 'touch':
    // Allow drag gesture.
    break;
    case 'pen':
    // Also allow drag gesture.
    break;
    default:
    // Getting an empty string means the browser doesn't know
    // what device type it is. Let's assume mouse and do nothing.
    break;
}

डिफ़ॉल्ट कार्रवाइयां

टच-सक्षम ब्राउज़र में, पेज को स्क्रोल करने, ज़ूम करने या रीफ़्रेश करने के लिए, कुछ खास जेस्चर का इस्तेमाल किया जाता है. टच इवेंट के मामले में, आपको डिफ़ॉल्ट कार्रवाइयां होने के दौरान भी इवेंट मिलते रहेंगे. उदाहरण के लिए, उपयोगकर्ता स्क्रोल करते समय भी touchmove ट्रिगर होगा.

जब भी स्क्रोल या ज़ूम जैसी कोई डिफ़ॉल्ट कार्रवाई ट्रिगर होती है, तो आपको pointercancel इवेंट मिलेगा. इससे आपको पता चलेगा कि ब्राउज़र ने पॉइंटर को कंट्रोल कर लिया है. उदाहरण के लिए:

document.addEventListener('pointercancel',
    ev => console.log('Go home, the browser is in charge now.'));

पहले से मौजूद स्पीड: टच इवेंट की तुलना में, यह मॉडल डिफ़ॉल्ट रूप से बेहतर परफ़ॉर्मेंस देता है. टच इवेंट की तरह ही परफ़ॉर्मेंस पाने के लिए, आपको पैसिव इवेंट लिसनर का इस्तेमाल करना होगा.

touch-action सीएसएस प्रॉपर्टी की मदद से, ब्राउज़र को कंट्रोल करने से रोका जा सकता है. किसी एलिमेंट पर इसे none पर सेट करने से, उस एलिमेंट पर शुरू की गई ब्राउज़र की सभी कार्रवाइयां बंद हो जाएंगी. हालांकि, pan-x जैसी कई अन्य वैल्यू का इस्तेमाल करके, ब्राउज़र को बेहतर तरीके से कंट्रोल किया जा सकता है. इससे ब्राउज़र को x-ऐक्सिस पर होने वाली गतिविधि पर प्रतिक्रिया देने की अनुमति मिलती है, लेकिन y-ऐक्सिस पर नहीं. Chrome 55 में ये वैल्यू इस्तेमाल की जा सकती हैं:

auto डिफ़ॉल्ट; ब्राउज़र कोई भी डिफ़ॉल्ट कार्रवाई कर सकता है.
none ब्राउज़र को कोई भी डिफ़ॉल्ट कार्रवाई करने की अनुमति नहीं है.
pan-x ब्राउज़र को सिर्फ़ हॉरिज़ॉन्टल स्क्रोल की डिफ़ॉल्ट कार्रवाई करने की अनुमति है.
pan-y ब्राउज़र को सिर्फ़ वर्टिकल स्क्रोल की डिफ़ॉल्ट कार्रवाई करने की अनुमति है.
pan-left ब्राउज़र को सिर्फ़ हॉरिज़ॉन्टल स्क्रोल की डिफ़ॉल्ट कार्रवाई करने की अनुमति है. साथ ही, वह सिर्फ़ पेज को बाईं ओर पैन कर सकता है.
pan-right ब्राउज़र को सिर्फ़ हॉरिज़ॉन्टल स्क्रोल की डिफ़ॉल्ट कार्रवाई करने की अनुमति है. साथ ही, वह पेज को सिर्फ़ दाईं ओर पैन कर सकता है.
pan-up ब्राउज़र को सिर्फ़ वर्टिकल स्क्रोल की डिफ़ॉल्ट कार्रवाई करने की अनुमति है. साथ ही, वह सिर्फ़ पेज को ऊपर की ओर पैन कर सकता है.
pan-down ब्राउज़र को सिर्फ़ वर्टिकल स्क्रोल की डिफ़ॉल्ट कार्रवाई करने की अनुमति है. साथ ही, वह सिर्फ़ पेज को नीचे की ओर पैन कर सकता है.
manipulation ब्राउज़र को सिर्फ़ स्क्रोल और ज़ूम करने की अनुमति है.

पॉइंटर कैप्‍चर

क्या आपने कभी किसी गड़बड़ी वाले mouseup इवेंट को डीबग करने में एक घंटा बिताया है, ताकि आपको पता चल सके कि उपयोगकर्ता आपके क्लिक टारगेट के बाहर बटन को छोड़ रहा है? नहीं? ठीक है, शायद यह सिर्फ़ मेरे लिए है.

हालांकि, अब तक इस समस्या को हल करने का कोई अच्छा तरीका नहीं था. हां, दस्तावेज़ पर mouseup हैंडलर सेट अप किया जा सकता है. साथ ही, चीज़ों को ट्रैक करने के लिए, अपने ऐप्लिकेशन पर कुछ स्टेटस सेव किया जा सकता है. हालांकि, यह सबसे सही तरीका नहीं है. खास तौर पर, अगर कोई वेब कॉम्पोनेंट बनाया जा रहा है और आपको हर चीज़ को अलग और बेहतर रखना है.

पॉइंटर इवेंट की मदद से, इस समस्या को हल करने का एक बेहतर तरीका है: पॉइंटर को कैप्चर किया जा सकता है, ताकि आपको pointerup इवेंट (या उससे मिलता-जुलता कोई दूसरा इवेंट) मिल सके.

const foo = document.querySelector('#foo');
foo.addEventListener('pointerdown', ev => {
    console.log('Button down, capturing!');
    // Every pointer has an ID, which you can read from the event.
    foo.setPointerCapture(ev.pointerId);
});

foo.addEventListener('pointerup', 
    ev => console.log('Button up. Every time!'));

ब्राउज़र समर्थन

लेख लिखे जाने तक, पॉइंटर इवेंट की सुविधा Internet Explorer 11, Microsoft Edge, Chrome, और Opera पर काम करती है. साथ ही, Firefox पर कुछ हद तक काम करती है. caniuse.com पर जाकर, अप-टू-डेट सूची देखी जा सकती है.

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

if (window.PointerEvent) {
    // Yay, we can use pointer events!
} else {
    // Back to mouse and touch events, I guess.
}

प्रोग्रेसिव बेहतर बनाने के लिए, पॉइंटर इवेंट का इस्तेमाल किया जा सकता है: ऊपर दी गई जांच करने के लिए, अपने शुरू करने के तरीकों में बदलाव करें. इसके बाद, if ब्लॉक में पॉइंटर इवेंट हैंडलर जोड़ें और अपने माउस/टच इवेंट हैंडलर को else ब्लॉक में ले जाएं.

इसलिए, इन्हें आज़माएं और हमें अपने अनुभव के बारे में बताएं!