किसी तत्व के बाहर एक क्लिक का पता लगाने के लिए कैसे?
कारण यह है कि यह प्रश्न इतना लोकप्रिय है और इतने सारे उत्तर हैं कि यह भ्रामक रूप से जटिल है। लगभग आठ वर्षों और दर्जनों जवाबों के बाद, मैं वास्तव में यह देखकर आश्चर्यचकित हूं कि अभिगम्यता का कितना कम ध्यान रखा गया है।
जब उपयोगकर्ता मेनू क्षेत्र के बाहर क्लिक करता है तो मैं इन तत्वों को छिपाना चाहूंगा।
यह एक नेक काम है और वास्तविक मुद्दा है। सवाल का शीर्षक- जो कि ज्यादातर जवाबों को संबोधित करने का प्रयास करता है-उसमें एक दुर्भाग्यपूर्ण लाल हेरिंग शामिल है।
संकेत: यह "क्लिक" शब्द है !
आप वास्तव में क्लिक हैंडलर्स को बांधना नहीं चाहते हैं।
यदि आप संवाद को बंद करने के लिए क्लिक हैंडलर्स को बाइंड कर रहे हैं, तो आप पहले ही विफल हो चुके हैं। आपके द्वारा विफल किए जाने का कारण यह है कि हर कोई click
घटनाओं को ट्रिगर नहीं करता है। माउस का उपयोग नहीं करने वाले उपयोगकर्ता आपके डायलॉग (और आपका पॉप-अप मेनू यकीनन एक प्रकार का डायलॉग है) को दबाकर बच सकते हैं Tab, और फिर वे बाद में बिना ट्रिगर किए डायलॉग के पीछे की सामग्री को नहीं पढ़ पाएंगेclick
घटना ।
तो चलिए सवाल फिर से शुरू करते हैं।
जब कोई उपयोगकर्ता इसके साथ समाप्त होता है तो संवाद कैसे बंद करता है?
यही लक्ष्य है। दुर्भाग्य से, अब हमें इसे बांधने की जरूरत हैuserisfinishedwiththedialog
घटना , और यह बाध्यकारी इतना सीधा नहीं है।
तो हम कैसे पता लगा सकते हैं कि एक उपयोगकर्ता ने एक संवाद का उपयोग करके समाप्त कर दिया है?
focusout
प्रतिस्पर्धा
एक अच्छी शुरुआत यह निर्धारित करने के लिए है कि क्या फोकस ने संवाद छोड़ दिया है।
संकेत: blur
घटना से सावधान रहें ,blur
अगर प्रचार बुदबुदाती हुई अवस्था से बंधा हुआ हो तो प्रचार नहीं करता!
jQuery का focusout
काम ठीक रहेगा। यदि आप jQuery का उपयोग नहीं कर सकते हैं, तो आप blur
कैप्चरिंग चरण के दौरान उपयोग कर सकते हैं :
element.addEventListener('blur', ..., true);
// use capture: ^^^^
इसके अलावा, कई संवादों के लिए आपको कंटेनर को फ़ोकस करने की अनुमति देने की आवश्यकता होगी। tabindex="-1"
टैबिंग प्रवाह को बाधित किए बिना संवाद को गतिशील रूप से प्राप्त करने की अनुमति देने के लिए जोड़ें ।
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on('focusout', function () {
$(this).removeClass('active');
});
div {
display: none;
}
.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
यदि आप एक मिनट से अधिक समय तक उस डेमो के साथ खेलते हैं तो आपको जल्दी से मुद्दों को देखना शुरू कर देना चाहिए।
पहला यह है कि संवाद में लिंक क्लिक करने योग्य नहीं है। उस पर क्लिक करने या उस पर टैब करने का प्रयास करने से बातचीत बंद होने से पहले संवाद बंद हो जाएगा। ऐसा इसलिए है क्योंकि आंतरिक तत्व को केंद्रित करने focusout
से पहले एक घटना को ट्रिगर किया जाता हैfocusin
ईवेंट को फिर ।
इवेंट लूप पर स्थिति परिवर्तन की कतार को ठीक करना है। इसका उपयोग करके setImmediate(...)
, या setTimeout(..., 0)
समर्थन न करने वाले ब्राउज़रों के लिए किया जा सकता है setImmediate
। एक बार कतारबद्ध होने के बाद इसे बाद में रद्द किया जा सकता है focusin
:
$('.submenu').on({
focusout: function (e) {
$(this).data('submenuTimer', setTimeout(function () {
$(this).removeClass('submenu--active');
}.bind(this), 0));
},
focusin: function (e) {
clearTimeout($(this).data('submenuTimer'));
}
});
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
}
});
div {
display: none;
}
.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
दूसरा मुद्दा यह है कि जब लिंक फिर से दबाया जाएगा तो संवाद बंद नहीं होगा। ऐसा इसलिए है क्योंकि संवाद ध्यान केंद्रित खो देता है, घनिष्ठ व्यवहार को ट्रिगर करता है, जिसके बाद लिंक फिर से चालू हो जाता है संवाद को फिर से खोलने के लिए।
पिछले अंक की तरह ही, फोकस अवस्था को प्रबंधित करने की आवश्यकता है। यह देखते हुए कि राज्य परिवर्तन पहले ही कतारबद्ध हो चुका है, संवाद ट्रिगर पर ध्यान देने वाली घटनाओं को संभालने की बात है:
यह परिचित दिखना चाहिए
$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
}
});
$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
div {
display: none;
}
.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
Esc चाभी
यदि आपको लगा कि आप फ़ोकस स्टेट्स को हैंडल करके किए गए हैं, तो उपयोगकर्ता अनुभव को सरल बनाने के लिए और भी बहुत कुछ कर सकते हैं।
यह अक्सर एक "अच्छा है" सुविधा है, लेकिन यह सामान्य है कि जब आपके पास किसी भी प्रकार का एक मोडल या पॉपअप होता है, तो Escकुंजी इसे बंद कर देगी।
keydown: function (e) {
if (e.which === 27) {
$(this).removeClass('active');
e.preventDefault();
}
}
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
},
keydown: function (e) {
if (e.which === 27) {
$(this).removeClass('active');
e.preventDefault();
}
}
});
$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
div {
display: none;
}
.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
यदि आप जानते हैं कि आपके पास संवाद के भीतर ध्यान देने योग्य तत्व हैं, तो आपको सीधे संवाद पर ध्यान केंद्रित करने की आवश्यकता नहीं होगी। यदि आप एक मेनू बना रहे हैं, तो आप इसके बजाय पहले मेनू आइटम पर ध्यान केंद्रित कर सकते हैं।
click: function (e) {
$(this.hash)
.toggleClass('submenu--active')
.find('a:first')
.focus();
e.preventDefault();
}
$('.menu__link').on({
click: function (e) {
$(this.hash)
.toggleClass('submenu--active')
.find('a:first')
.focus();
e.preventDefault();
},
focusout: function () {
$(this.hash).data('submenuTimer', setTimeout(function () {
$(this.hash).removeClass('submenu--active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('submenuTimer'));
}
});
$('.submenu').on({
focusout: function () {
$(this).data('submenuTimer', setTimeout(function () {
$(this).removeClass('submenu--active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('submenuTimer'));
},
keydown: function (e) {
if (e.which === 27) {
$(this).removeClass('submenu--active');
e.preventDefault();
}
}
});
.menu {
list-style: none;
margin: 0;
padding: 0;
}
.menu:after {
clear: both;
content: '';
display: table;
}
.menu__item {
float: left;
position: relative;
}
.menu__link {
background-color: lightblue;
color: black;
display: block;
padding: 0.5em 1em;
text-decoration: none;
}
.menu__link:hover,
.menu__link:focus {
background-color: black;
color: lightblue;
}
.submenu {
border: 1px solid black;
display: none;
left: 0;
list-style: none;
margin: 0;
padding: 0;
position: absolute;
top: 100%;
}
.submenu--active {
display: block;
}
.submenu__item {
width: 150px;
}
.submenu__link {
background-color: lightblue;
color: black;
display: block;
padding: 0.5em 1em;
text-decoration: none;
}
.submenu__link:hover,
.submenu__link:focus {
background-color: black;
color: lightblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu__item">
<a class="menu__link" href="#menu-1">Menu 1</a>
<ul class="submenu" id="menu-1" tabindex="-1">
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#1">Example 1</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#2">Example 2</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#3">Example 3</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#4">Example 4</a></li>
</ul>
</li>
<li class="menu__item">
<a class="menu__link" href="#menu-2">Menu 2</a>
<ul class="submenu" id="menu-2" tabindex="-1">
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#1">Example 1</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#2">Example 2</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#3">Example 3</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#4">Example 4</a></li>
</ul>
</li>
</ul>
lorem ipsum <a href="http://example.com/">dolor</a> sit amet.
WAI-ARIA रोल्स और अन्य एक्सेसिबिलिटी सपोर्ट
यह उत्तर उम्मीद है कि इस सुविधा के लिए सुलभ कीबोर्ड और माउस समर्थन की मूल बातें शामिल है, लेकिन जैसा कि यह पहले से ही काफी व्यवहार्य है मैं WAI-ARIA भूमिकाओं और विशेषताओं की किसी भी चर्चा से बचने के लिए जा रहा हूं , हालांकि मैं अत्यधिक अनुशंसा करता हूं कि कार्यान्वयनकर्ता विवरण के लिए कल्पना का संदर्भ देते हैं। उन्हें किन भूमिकाओं का उपयोग करना चाहिए और अन्य उपयुक्त विशेषताएँ।