2014-08-29 4 views
30

मैं कुछ जावास्क्रिप्ट यूआई पर काम कर रहा हूं, और स्पर्श उपकरणों पर बेहतर प्रतिक्रिया के लिए 'टचचेन्ड' जैसी कई स्पर्श घटनाओं का उपयोग कर रहा हूं। हालांकि, कुछ तार्किक मुद्दे हैं जो मुझे परेशान कर रहे हैं ...जावास्क्रिप्ट टचेंडा बनाम क्लिक करें दुविधा

मैंने देखा है कि कई डेवलपर्स एक ही घटना में 'टचचेन्ड' और 'क्लिक' को जोड़ते हैं। कई मामलों में यह चोट नहीं है, लेकिन अनिवार्य रूप से समारोह टच डिवाइस पर दो बार से निकाल देते थे:

button.on('click touchend', function(event) { 
    // this fires twice on touch devices 
}); 

यह सुझाव दिया गया है कि एक स्पर्श क्षमता का पता लगा सकता है, और उदाहरण के लिए उचित रूप से घटना सेट:

var myEvent = ('ontouchstart' in document.documentElement) ? 'touchend' : 'click'; 
button.on(myEvent, function(event) { 
    // this fires only once regardless of device 
}); 

उपरोक्त के साथ समस्या यह है कि यह उन डिवाइसों पर तोड़ देगा जो स्पर्श और माउस दोनों का समर्थन करते हैं। यदि उपयोगकर्ता वर्तमान में दोहरी इनपुट डिवाइस पर माउस का उपयोग कर रहा है, तो 'क्लिक' आग नहीं लगेगी क्योंकि बटन पर केवल 'touchend' असाइन किया गया है।

डिवाइस का पता लगाने का एक और समाधान है (उदा। "आईओएस") और उस पर आधारित एक ईवेंट असाइन करें: Click event called twice on touchend in iPad। बेशक, उपरोक्त लिंक में समाधान केवल आईओएस (एंड्रॉइड या अन्य डिवाइस नहीं) के लिए है, और कुछ काफी प्राथमिक हल करने के लिए "हैक" जैसा लगता है।

एक और समाधान माउस-गति का पता लगाने के लिए होगा, और यह पता लगाने के लिए स्पर्श करें कि उपयोगकर्ता माउस या स्पर्श पर है या नहीं। निश्चित रूप से समस्या यह है कि जब आप इसे पहचानना चाहते हैं तो उपयोगकर्ता माउस को नहीं ले जा रहा है ...

सबसे विश्वसनीय समाधान मैं सोच सकता हूं, सरल debounce फ़ंक्शन का उपयोग केवल यह सुनिश्चित करने के लिए है कि केवल फ़ंक्शन (उदाहरण के लिए 100ms) एक छोटे अंतराल के भीतर एक बार चलाता है:

button.on('click touchend', $.debounce(100, function(event) { 
    // this fires only once on all devices 
})); 

मैं कुछ याद आ रही हूँ, या किसी को भी किसी भी बेहतर सुझाव हैं?

संपादित करें: मैं अपनी पोस्ट है, जो ऊपर के रूप में एक ऐसी ही समाधान का सुझाव के बाद यह लिंक मिल गया: How to bind 'touchstart' and 'click' events but not respond to both?

+2

जो कुछ हल नहीं करता है ... Modernizr बस 'स्पर्श' का पता लगाता है। घटना अभी भी स्पर्श उपकरणों पर दो बार आग लग जाएगी। या यदि आप टच डिवाइस (आधुनिकता के माध्यम से) के लिए 'स्पर्श' ईवेंट असाइन करते हैं, तो यह माउस के उपयोग से उपयोगकर्ताओं को दोहरी-इनपुट डिवाइस जैसे कई विंडोज 8 उपकरणों पर काम करना बंद कर देगा। – suncat100

उत्तर

24

अनुसंधान के एक दिन बाद, मैं लगा सबसे अच्छा समाधान सिर्फ क्लिक से चिपक है और स्पर्श विलंब को हटाने के लिए https://github.com/ftlabs/fastclick का उपयोग करें। मुझे 100% यकीन नहीं है कि यह touchend जितना कुशल है, लेकिन कम से कम नहीं है।

मैं stopPropagation और preventDefault का उपयोग करके छूने पर दो बार ईवेंट ट्रिगर निष्क्रिय करने के लिए एक तरह से यह पता लगाने किया था, लेकिन इस के रूप में यह तत्व के आधार पर अन्य स्पर्श जेस्चर जहां यह लागू किया जाता है साथ हस्तक्षेप कर सकता कुशल है:

button.on('touchend click', function(event) { 
    event.stopPropagation(); 
    event.preventDefault(); 
    // this fires once on all devices 
}); 

मैं वास्तव में कुछ यूआई तत्वों पर टचस्टार्ट को गठबंधन करने के लिए एक समाधान की तलाश में था, लेकिन मैं नहीं देख सकता कि इसे के साथ कैसे जोड़ा जा सकता है, ऊपर दिए गए समाधान के अलावा पर क्लिक करें।

+0

क्या यह पता लगाने का कोई मूल तरीका है कि ब्राउज़र टचस्टार्ट/अंत का समर्थन करता है या नहीं? – BenRacicot

-1

हां डबल-टैप ज़ूम अक्षम करना (और इसलिए क्लिक विलंब) आमतौर पर सबसे अच्छा विकल्प होता है। और आखिर में ऐसा करने के लिए अच्छी सलाह है जो soon work on all browsers होगा।

यदि, किसी कारण से, आप ऐसा नहीं करना चाहते हैं।अनावश्यक click को स्पष्ट रूप से अनदेखा करने के लिए आप UIEvent.sourceCapabilities.firesTouchEvents का भी उपयोग कर सकते हैं। polyfill for this आपके debouncing कोड के समान कुछ करता है।

3

इस प्रश्न का उत्तर दिया गया है, लेकिन शायद इसे अद्यतन करने की आवश्यकता है।

a notice from Google के अनुसार, यदि हम <head> तत्व में नीचे दी गई रेखा शामिल करते हैं तो 300-350ms देरी नहीं होगी।

<meta name="viewport" content="width=device-width"> 

यही है! और अब क्लिक और टच इवेंट के बीच कोई अंतर नहीं होगा!

+0

यह दिलचस्प है। शायद fastclick.js से छुटकारा पाने का समय ... मैं इसे मोबाइल ब्राउज़र में थोड़ा सा परीक्षण करूंगा। – suncat100

+0

मेटा टैग 'हेडर' टैग में रखा जाना चाहिए, न कि 'हेडर' टैग। – James

+1

यह मेरे लिए सच नहीं रहा है। – skybondsor

0

हैलो आप निम्न तरीके से कार्यान्वित कर सकते हैं।

function eventHandler(event, selector) { 
    event.stopPropagation(); // Stop event bubbling. 
    event.preventDefault(); // Prevent default behaviour 
    if (event.type === 'touchend') selector.off('click'); // If event type was touch turn off clicks to prevent phantom clicks. 
} 

// Implement 
$('.class').on('touchend click', function(event) { 
    eventHandler(event, $(this)); // Handle the event. 
    // Do somethings... 
}); 
0

आपका debounce समारोह 100 एमएस के लिए हर क्लिक से निपटने में विलंब होगा: इसके बजाय

button.on('click touchend', $.debounce(100, function(event) { 
    // this is delayed a minimum of 100 ms 
})); 

, मैं एक cancelDuplicates समारोह है कि अभी आग बनाया है, लेकिन 10 एमएस के भीतर किसी भी आगामी कॉल रद्द कर दिया जाएगा:

function cancelDuplicates(fn, threshhold, scope) { 
    if (typeof threshhold !== 'number') threshhold = 10; 
    var last = 0; 

    return function() { 
     var now = +new Date; 

     if (now >= last + threshhold) { 
      last = now; 
      fn.apply(scope || this, arguments); 
     } 
    }; 
} 

उपयोग:

button.on('click touchend', cancelDuplicates(function(event) { 
    // This fires right away, and calls within 10 ms after are cancelled. 
})); 
संबंधित मुद्दे