javascript - मैं तत्व के बाहर एक क्लिक का पता कैसे लगा सकता हूं?
jquery (20)
तत्व के बाहर एक क्लिक का पता लगाने के लिए कैसे?
कारण यह सवाल इतना लोकप्रिय है और इतने सारे जवाब हैं कि यह भ्रामक रूप से जटिल है। लगभग आठ वर्षों और दर्जनों उत्तरों के बाद, मैं वास्तव में आश्चर्यचकित हूं कि अभिगम्यता को कितनी कम देखभाल दी गई है।
जब उपयोगकर्ता मेनू के क्षेत्र के बाहर क्लिक करता है तो मैं इन तत्वों को छिपाना चाहता हूं।
यह एक महान कारण है और वास्तविक मुद्दा है। प्रश्न का शीर्षक- जो सबसे अधिक जवाब देने के प्रयास में दिखाई देता है-इसमें एक दुर्भाग्यपूर्ण लाल हेरिंग शामिल है।
संकेत: यह शब्द "क्लिक" है !
आप वास्तव में क्लिक हैंडलर बाध्य नहीं करना चाहते हैं।
यदि आप संवाद बंद करने के लिए बाध्यकारी क्लिक हैंडलर हैं, तो आप पहले से ही असफल हो चुके हैं। आपके द्वारा विफल होने का कारण यह है कि हर कोई घटनाओं पर click
नहीं करता है। माउस का उपयोग नहीं करने वाले उपयोगकर्ता टैब को दबाकर आपके संवाद से बचने में सक्षम होंगे (और आपका पॉप-अप मेनू तर्कसंगत रूप से एक प्रकार का संवाद है), और फिर वे एक 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
से पहले focusout
ईवेंट को ट्रिगर करने से पहले focusout
ईवेंट ट्रिगर होता है।
फिक्स इवेंट लूप पर राज्य परिवर्तन को कतार करना है। यह setImmediate(...)
, या setTimeout(..., 0)
का उपयोग करके किया जा सकता है जो ब्राउज़र के लिए सेट नहीं करते हैं। एक बार कतारबद्ध करने के बाद इसे बाद में 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 कुंजी इसे बंद कर देगी।
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.
वाई-एरिया भूमिकाएं और अन्य अभिगम्यता समर्थन
यह उत्तर उम्मीद है कि इस सुविधा के लिए सुलभ कीबोर्ड और माउस समर्थन की मूलभूत बातें शामिल हैं, लेकिन जैसा कि यह पहले से ही काफी बड़ा है, मैं वाई-एआरआईए भूमिकाओं और विशेषताओं की किसी भी चर्चा से बचने जा रहा हूं, हालांकि मैं अत्यधिक अनुशंसा करता हूं कि कार्यान्वयनकर्ता विवरण के लिए spec देखें किस भूमिका पर उन्हें उपयोग करना चाहिए और किसी भी अन्य उपयुक्त विशेषताओं पर।
मेरे पास कुछ HTML मेनू हैं, जो कि जब मैं उपयोगकर्ता इन मेनू के सिर पर क्लिक करता हूं तो मैं पूरी तरह से दिखाता हूं। जब उपयोगकर्ता मेनू के क्षेत्र के बाहर क्लिक करता है तो मैं इन तत्वों को छिपाना चाहता हूं।
JQuery के साथ ऐसा कुछ संभव है?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
नोट:
stopEventPropagation()
का उपयोग करना कुछ ऐसा है जिसे टालना चाहिए क्योंकि यह डोम में सामान्य ईवेंट प्रवाह को तोड़ देता है। अधिक जानकारी के लिए इस आलेख को देखें। इसके बजाय इस विधि का उपयोग करने पर विचार करें।
खिड़की को बंद करने वाले दस्तावेज़ निकाय को एक क्लिक इवेंट संलग्न करें। कंटेनर पर एक अलग क्लिक ईवेंट संलग्न करें जो दस्तावेज़ निकाय के प्रचार को रोकता है।
$(window).click(function() {
//Hide the menus if visible
});
$('#menucontainer').click(function(event){
event.stopPropagation();
});
अब इसके लिए एक प्लगइन है: बाहरी घटनाओं ( ब्लॉग पोस्ट )
निम्न तब होता है जब एक क्लिकआउटसाइड हैंडलर (डब्लूएलजीजी) एक तत्व से बंधे होते हैं:
- तत्व को एक सरणी में जोड़ा जाता है जिसमें क्लिकआउटसाइड हैंडलर वाले सभी तत्व होते हैं
- एक ( namespaced ) क्लिक हैंडलर दस्तावेज़ से जुड़ा हुआ है (यदि पहले से नहीं है)
- दस्तावेज़ में किसी भी क्लिक पर, क्लिकआउटसाइड ईवेंट उस सरणी के उन तत्वों के लिए ट्रिगर किया जाता है जो क्लिक- अवेन्ट्स लक्ष्य के बराबर या माता-पिता के बराबर नहीं हैं
- इसके अतिरिक्त, clickoutside ईवेंट के लिए event.target उस तत्व पर सेट किया गया है जिस पर उपयोगकर्ता ने क्लिक किया था (ताकि आप यह भी जान सकें कि उपयोगकर्ता ने क्या क्लिक किया था, न कि वह बाहर क्लिक किया था)
तो प्रचार से कोई भी घटना बंद नहीं होती है और अतिरिक्त क्लिक हैंडलर को बाहरी-हैंडलर के साथ तत्व "उपरोक्त" का उपयोग किया जा सकता है।
आप document
पर एक क्लिक इवेंट के लिए सुन सकते हैं और फिर सुनिश्चित कर सकते हैं कि #menucontainer
या क्लिक किए गए तत्व का लक्ष्य .closest()
का उपयोग कर नहीं है।
यदि ऐसा नहीं है, तो क्लिक किया गया तत्व #menucontainer
बाहर है और आप इसे सुरक्षित रूप से छुपा सकते हैं।
$(document).click(function(event) {
if(!$(event.target).closest('#menucontainer').length) {
if($('#menucontainer').is(":visible")) {
$('#menucontainer').hide();
}
}
});
संपादित करें - 2017-06-23
यदि आप मेनू को खारिज करने की योजना बना रहे हैं और ईवेंट सुनना बंद करना चाहते हैं तो आप ईवेंट श्रोता के बाद भी साफ कर सकते हैं। यह फ़ंक्शन केवल नए बनाए गए श्रोता को साफ करेगा, document
पर किसी अन्य क्लिक श्रोताओं को संरक्षित करेगा। ES2015 वाक्यविन्यास के साथ:
export function hideOnClickOutside(selector) {
const outsideClickListener = (event) => {
if (!$(event.target).closest(selector).length) {
if ($(selector).is(':visible')) {
$(selector).hide()
removeClickListener()
}
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
संपादित करें - 2018-03-11
उन लोगों के लिए जो jQuery का उपयोग नहीं करना चाहते हैं। सादे वेनिलाजेएस (ईसीएमएस्क्रिप्ट 6) में उपर्युक्त कोड यहां दिया गया है।
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (!element.contains(event.target)) { // or use: event.target.closest(selector) === null
if (isVisible(element)) {
element.style.display = 'none'
removeClickListener()
}
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ) // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
नोट: यह jQuery भाग के बजाय केवल !element.contains(event.target)
उपयोग करने के लिए एलेक्स टिप्पणी पर आधारित है।
लेकिन element.closest()
अब सभी प्रमुख ब्राउज़रों में भी उपलब्ध है (डब्ल्यू 3 सी संस्करण jQuery से थोड़ा अलग है)। पॉलीफिल यहां पाए जा सकते हैं: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
एक संस्करण के रूप में:
var $menu = $('#menucontainer');
$(document).on('click', function (e) {
// If element is opened and click target is outside it, hide it
if ($menu.is(':visible') && !$menu.is(e.target) && !$menu.has(e.target).length) {
$menu.hide();
}
});
css-tricks.com/dangers-stopping-event-propagation को css-tricks.com/dangers-stopping-event-propagation में कोई समस्या नहीं है और उसी पृष्ठ पर एकाधिक मेनू का बेहतर समर्थन करता है, जहां पहले मेनू के दौरान दूसरे मेनू पर क्लिक करना स्टॉपप्रॉपैगेशन समाधान में पहला खुल जाएगा।
जैसा कि एक अन्य पोस्टर ने कहा कि वहां बहुत सारे मिलचास हैं, खासकर यदि आप जिस तत्व को प्रदर्शित कर रहे हैं (इस मामले में एक मेनू में) परस्पर क्रियात्मक तत्व हैं। मुझे निम्नलिखित विधि को काफी मजबूत पाया गया है:
$('#menuscontainer').click(function(event) {
//your code that shows the menus fully
//now set up an event listener so that clicking anywhere outside will close the menu
$('html').click(function(event) {
//check up the tree of the click target to check whether user has clicked outside of menu
if ($(event.target).parents('#menuscontainer').length==0) {
// your code to hide menu
//this event listener has done its job so we can unbind it.
$(this).unbind(event);
}
})
});
मुझे कुछ jQuery कैलेंडर प्लगइन में यह विधि मिली।
function ClickOutsideCheck(e)
{
var el = e.target;
var popup = $('.popup:visible')[0];
if (popup==undefined)
return true;
while (true){
if (el == popup ) {
return true;
} else if (el == document) {
$(".popup").hide();
return false;
} else {
el = $(el).parent()[0];
}
}
};
$(document).bind('mousedown.popup', ClickOutsideCheck);
मुझे नहीं लगता कि आपको वास्तव में क्या चाहिए, जब उपयोगकर्ता बाहर क्लिक करता है तो मेनू बंद करना है; जब उपयोगकर्ता पृष्ठ पर कहीं भी क्लिक करता है तो मेनू को बंद करने के लिए आपको क्या चाहिए। यदि आप मेनू पर क्लिक करते हैं, या मेनू से बाहर है तो इसे सही बंद करना चाहिए?
उपरोक्त कोई संतोषजनक उत्तर नहीं ढूंढने से मुझे दूसरे दिन इस ब्लॉग पोस्ट को लिखने के लिए प्रेरित किया गया। अधिक pedantic के लिए, ध्यान देने के लिए कई मिलचास हैं:
- यदि आप क्लिक समय पर बॉडी एलिमेंट पर एक क्लिक इवेंट हैंडलर संलग्न करते हैं तो मेनू बंद करने से पहले दूसरे क्लिक के लिए प्रतीक्षा करें और ईवेंट को अनबाइंड करना सुनिश्चित करें। अन्यथा मेनू खोलने वाले क्लिक ईवेंट में श्रोता को बबल होगा जो मेनू को बंद करना होगा।
- यदि आप किसी ईवेंट ईवेंट पर event.stopPropogation () का उपयोग करते हैं, तो आपके पृष्ठ के किसी अन्य तत्व में क्लिक-कहीं-टू-क्लोज़ सुविधा नहीं हो सकती है।
- शरीर तत्व को अनिश्चित काल तक एक क्लिक इवेंट हैंडलर संलग्न करना एक सहायक समाधान नहीं है
- घटना के लक्ष्य की तुलना में, और इसके माता-पिता हैंडलर के निर्माता को लगता है कि जब आप इसे बंद करते हैं तो मेनू को बंद करना है, जब आप वास्तव में चाहते हैं तो इसे बंद करना है जब आप पृष्ठ पर कहीं भी क्लिक करते हैं।
- शरीर तत्व पर घटनाओं के लिए सुनना आपके कोड को और अधिक भंगुर बना देगा। निर्दोष के रूप में स्टाइलिंग इसे तोड़ देगा:
body { margin-left:auto; margin-right: auto; width:960px;}
body { margin-left:auto; margin-right: auto; width:960px;}
यह मेरे लिए पूरी तरह से काम किया !!
$('html').click(function (e) {
if (e.target.id == 'YOUR-DIV-ID') {
//do something
} else {
//do something
}
});
यहां अन्य समाधान मेरे लिए काम नहीं करते थे इसलिए मुझे इसका उपयोग करना पड़ा:
if(!$(event.target).is('#foo'))
{
// hide menu
}
शोध के बाद मुझे तीन कामकाजी समाधान मिल गए हैं (मैं संदर्भ के लिए पेज लिंक भूल गया)
पहला समाधान
<script>
//The good thing about this solution is it doesn't stop event propagation.
var clickFlag = 0;
$('body').on('click', function () {
if(clickFlag == 0) {
console.log('hide element here');
/* Hide element here */
}
else {
clickFlag=0;
}
});
$('body').on('click','#testDiv', function (event) {
clickFlag = 1;
console.log('showed the element');
/* Show the element */
});
</script>
दूसरा समाधान
<script>
$('body').on('click', function(e) {
if($(e.target).closest('#testDiv').length == 0) {
/* Hide dropdown here */
}
});
</script>
तीसरा समाधान
<script>
var specifiedElement = document.getElementById('testDiv');
document.addEventListener('click', function(event) {
var isClickInside = specifiedElement.contains(event.target);
if (isClickInside) {
console.log('You clicked inside')
}
else {
console.log('You clicked outside')
}
});
</script>
स्थिति के लिए एक सरल समाधान है:
$(document).mouseup(function (e)
{
var container = $("YOUR SELECTOR"); // Give you class or ID
if (!container.is(e.target) && // If the target of the click is not the desired div or section
container.has(e.target).length === 0) // ... nor a descendant-child of the container
{
container.hide();
}
});
div
क्लिक ईवेंट के बाहर अगर ट्रिगर किया गया है तो उपरोक्त स्क्रिप्ट div
को छुपाएगी।
आप अधिक जानकारी के लिए निम्न ब्लॉग देख सकते हैं: http://www.codecanal.com/detect-click-outside-div-using-javascript/
फ्लो बाधा, धुंध / फोकस इवेंट या किसी भी अन्य मुश्किल तकनीकों का उपयोग करने के बजाय, तत्व के संबंध में ईवेंट प्रवाह से मेल खाते हैं:
$(document).on("click.menu-outside", function(event){
// Test if target and it's parent aren't #menuscontainer
// That means the click event occur on other branch of document tree
if(!$(event.target).parents().andSelf().is("#menuscontainer")){
// Click outisde #menuscontainer
// Hide the menus (but test if menus aren't already hidden)
}
});
ईवेंट श्रोता के बाहर क्लिक को हटाने के लिए, बस:
$(document).off("click.menu-outside");
भविष्य के दर्शकों के लिए वेनिला जावास्क्रिप्ट समाधान यहां दिया गया है।
दस्तावेज़ के भीतर किसी भी तत्व पर क्लिक करने पर, यदि क्लिक किए गए तत्व की आईडी को टॉगल किया गया है, या छुपा तत्व छिपा हुआ नहीं है और छुपे तत्व में क्लिक तत्व नहीं है, तो तत्व को टॉगल करें।
(function () {
"use strict";
var hidden = document.getElementById('hidden');
document.addEventListener('click', function (e) {
if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
}, false);
})();
(function () {
"use strict";
var hidden = document.getElementById('hidden');
document.addEventListener('click', function (e) {
if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
}, false);
})();
<a href="javascript:void(0)" id="toggle">Toggle Hidden Div</a>
<div id="hidden" style="display: none;">This content is normally hidden. click anywhere other than this content to make me disappear</div>
यदि आपके पास एक ही पृष्ठ पर एकाधिक टॉगल होने जा रहे हैं तो आप इस तरह कुछ उपयोग कर सकते हैं:
- कक्षा का नाम
hidden
ढहने योग्य आइटम में जोड़ें। - दस्तावेज़ पर क्लिक करें, उन सभी छिपे हुए तत्वों को बंद करें जिनमें क्लिक किए गए तत्व नहीं हैं और वे छिपे नहीं हैं
- यदि क्लिक किया गया तत्व टॉगल है, तो निर्दिष्ट तत्व को टॉगल करें।
(function () {
"use strict";
var hiddenItems = document.getElementsByClassName('hidden'), hidden;
document.addEventListener('click', function (e) {
for (var i = 0; hidden = hiddenItems[i]; i++) {
if (!hidden.contains(e.target) && hidden.style.display != 'none')
hidden.style.display = 'none';
}
if (e.target.getAttribute('data-toggle')) {
var toggle = document.querySelector(e.target.getAttribute('data-toggle'));
toggle.style.display = toggle.style.display == 'none' ? 'block' : 'none';
}
}, false);
})();
<a href="javascript:void(0)" data-toggle="#hidden1">Toggle Hidden Div</a>
<div class="hidden" id="hidden1" style="display: none;" data-hidden="true">This content is normally hidden</div>
<a href="javascript:void(0)" data-toggle="#hidden2">Toggle Hidden Div</a>
<div class="hidden" id="hidden2" style="display: none;" data-hidden="true">This content is normally hidden</div>
<a href="javascript:void(0)" data-toggle="#hidden3">Toggle Hidden Div</a>
<div class="hidden" id="hidden3" style="display: none;" data-hidden="true">This content is normally hidden</div>
यदि आप आईई और एफएफ 3 के लिए स्क्रिप्टिंग कर रहे हैं। * और आप सिर्फ यह जानना चाहते हैं कि किसी निश्चित बॉक्स क्षेत्र में क्लिक किया गया था, तो आप कुछ भी उपयोग कर सकते हैं:
this.outsideElementClick = function(objEvent, objElement){
var objCurrentElement = objEvent.target || objEvent.srcElement;
var blnInsideX = false;
var blnInsideY = false;
if (objCurrentElement.getBoundingClientRect().left >= objElement.getBoundingClientRect().left && objCurrentElement.getBoundingClientRect().right <= objElement.getBoundingClientRect().right)
blnInsideX = true;
if (objCurrentElement.getBoundingClientRect().top >= objElement.getBoundingClientRect().top && objCurrentElement.getBoundingClientRect().bottom <= objElement.getBoundingClientRect().bottom)
blnInsideY = true;
if (blnInsideX && blnInsideY)
return false;
else
return true;}
यह इस समस्या का मेरा समाधान है:
$(document).ready(function() {
$('#user-toggle').click(function(e) {
$('#user-nav').toggle();
e.stopPropagation();
});
$('body').click(function() {
$('#user-nav').hide();
});
$('#user-nav').click(function(e){
e.stopPropagation();
});
});
समारोह:
$(function() {
$.fn.click_inout = function(clickin_handler, clickout_handler) {
var item = this;
var is_me = false;
item.click(function(event) {
clickin_handler(event);
is_me = true;
});
$(document).click(function(event) {
if (is_me) {
is_me = false;
} else {
clickout_handler(event);
}
});
return this;
}
});
उपयोग:
this.input = $('<input>')
.click_inout(
function(event) { me.ShowTree(event); },
function() { me.Hide(); }
)
.appendTo(this.node);
और कार्य बहुत सरल हैं:
ShowTree: function(event) {
this.data_span.show();
}
Hide: function() {
this.data_span.hide();
}
इस कार्यक्रम में तत्व की Event.path नामक एक संपत्ति है जो "पेड़ के क्रम में अपने सभी पूर्वजों की एक स्थिर आदेश सूची" है । यह जांचने के लिए कि कोई ईवेंट किसी विशिष्ट DOM तत्व या उसके बच्चों में से एक है, बस उस विशिष्ट DOM तत्व के लिए पथ की जांच करें। यह फ़ंक्शन OR
में तत्व जांच में तर्कसंगत रूप से कई तत्वों की जांच के लिए भी उपयोग किया जा सकता है some
।
$("body").click(function() {
target = document.getElementById("main");
flag = event.path.some(function(el, i, arr) {
return (el == target)
})
if (flag) {
console.log("Inside")
} else {
console.log("Outside")
}
});
#main {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<ul>
<li>Test-Main</li>
<li>Test-Main</li>
<li>Test-Main</li>
<li>Test-Main</li>
<li>Test-Main</li>
</ul>
</div>
<div id="main2">
Outside Main
</div>
तो आपके मामले के लिए यह होना चाहिए
$("body").click(function() {
target = $("#menuscontainer")[0];
flag = event.path.some(function(el, i, arr) {
return (el == target)
});
if (!flag) {
// Hide the menus
}
});
हमने एक समाधान लागू किया, आंशिक रूप से ऊपर दिए गए उपयोगकर्ता से एक टिप्पणी के आधार पर, जो हमारे लिए पूरी तरह से काम करता है। मूल रूप से तत्व को छोड़कर, हम उन तत्वों के बाहर क्लिक करते समय खोज बॉक्स / परिणामों को छिपाने के लिए इसका उपयोग करते हैं।
// HIDE SEARCH BOX IF CLICKING OUTSIDE
$(document).click(function(event){
// IF NOT CLICKING THE SEARCH BOX OR ITS CONTENTS OR SEARCH ICON
if ($("#search-holder").is(":visible") && !$(event.target).is("#search-holder *, #search")) {
$("#search-holder").fadeOut('fast');
$("#search").removeClass('active');
}
});
यह जांचता है कि खोज बॉक्स पहले से ही पहले ही दिखाई दे रहा है, और हमारे मामले में, यह छुपा / शो खोज बटन पर एक सक्रिय कक्षा को भी हटा रहा है।
$("#menuscontainer").click(function() {
$(this).focus();
});
$("#menuscontainer").blur(function(){
$(this).hide();
});
मेरे लिए काम करता है बस ठीक है।