jQuery Drop Down Menu w/ One Shot Collapse
Button opens a hidden div and attaches
a document-wide event handler.
Clicking anywhere other than inside
#innerContainer will hide the original hidden div
and remove the document-wide event handler
HTML
<script src="https://jquery-json.googlecode.com/files/jquery.json-2.4.min.js"></script>
<div id="outer">#outer
<div id="innerContainer"> <span style="font-size: 10px;">#innerContainer</span>
<div id="inner"> <span style="font-size: 10px;">#inner</span>
<form action="/echo/json/" method="post" ajax="true">
<label>Username:</label>
<input type="text" name="user" />
<label>Password:</label>
<input type="text" name="pass" />
<hr />
<button type="submit">Submit</button>
</form>
</div>
<hr />
<button id="trigger">#trigger</button>
</div>
</div>
<div id="instructions">
<p>Button opens a hidden div and attaches a document-wide event handler.
<br />Clicking anywhere other than inside #innerContainer (#outer or higher up the DOM tree) will hide the original hidden div (#inner) and remove the document-wide event handler</p>
</div>
<div id="eTargetStatus">
<label>Status:</label>
<input type="text" />
<img id="loadImg" width="20" src="http://opengraphicdesign.com/wp-content/uploads/2009/01/loader64.gif" />
</div>
<div class="info success error" id="result"></div>
CSS
body {
font-family: Helvetica, Arial, sans-serif;
}
#instructions {
width: 200px;
height: auto;
position: absolute;
top: 10px;
right: 50px;
border: 2px solid #000;
padding: 0 14px;
background-color: #fff;
}
.error {
background-color:#FFBABA;
color:#D8000C;
background-image:url('data:image/png; base64, iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJPSURBVDjLpZPLS5RhFMYfv9QJlelTQZwRb2OKlKuINuHGLlBEBEOLxAu46oL0F0QQFdWizUCrWnjBaDHgThCMoiKkhUONTqmjmDp2GZ0UnWbmfc/ztrC+GbM2dXbv4ZzfeQ7vefKMMfifyP89IbevNNCYdkN2kawkCZKfSPZTOGTf6Y/m1uflKlC3LvsNTWArr9BT2LAf+W73dn5jHclIBFZyfYWU3or7T4K7AJmbl/yG7EtX1BQXNTVCYgtgbAEAYHlqYHlrsTEVQWr63RZFuqsfDAcdQPrGRR/JF5nKGm9xUxMyr0YBAEXXHgIANq/3ADQobD2J9fAkNiMTMSFb9z8ambMAQER3JC1XttkYGGZXoyZEGyTHRuBuPgBTUu7VSnUAgAUAWutOV2MjZGkehgYUA6O5A0AlkAyRnotiX3MLlFKduYCqAtuGXpyH0XQmOj+TIURt51OzURTYZdBKV2UBSsOIcRp/TVTT4ewK6idECAihtUKOArWcjq/B8tQ6UkUR31+OYXP4sTOdisivrkMyHodWejlXwcC38Fvs8dY5xaIId89VlJy7ACpCNCFCuOp8+BJ6A631gANQSg1mVmOxxGQYRW2nHMha4B5WA3chsv22T5/B13AIicWZmNZ6cMchTXUe81Okzz54pLi0uQWp+TmkZqMwxsBV74Or3od4OISPr0e3SHa3PX0f3HXKofNH/UIG9pZ5PeUth+CyS2EMkEqs4fPEOBJLsyske48/+xD8oxcAYPzs4QaS7RR2kbLTTOTQieczfzfTv8QPldGvTGoF6/8AAAAASUVORK5CYII=');
}
.success {
background-color:#DFF2BF;
color:#4F8A10;
background-image:url('data:image/png; base64,...
JavaScript
// ONE SHOT EVENT HANDLER
function attachOneShotClick() {
$(document).on('click', function (e) {
update('log', 'clicked: ' + ((e.target.id) ? '#' + e.target.id : e.target))
if (!$(e.target).is('#innerContainer, #innerContainer *')) {
update('ui', 'warning')
toggleMenu('up')
} else {
e.stopPropagation();
}
});
}
function toggleMenu(dir) {
if (dir === 'down') {
$('#inner').slideDown(1500);
}
if (dir === 'up') {
$('#inner').slideUp(500, function () {
$(document).off('click');
$('#eTargetStatus label').text('Status :');
update('ui', '');
update('log', 'document event listener removed');
});
}
}
// Some dumb convenience function because it is convenient
function update(type, status, data) {
switch (type) {
case 'ui':
$('body').removeClass('warning error success info').addClass(status);
$('#eTargetStatus label').text('Status:');
break;
case 'log':
$('#eTargetStatus input').val(status);
if (data !== 'undefined') {
$('#eTargetStatus label').text(data);
}
break;
default:
break;
}
}
// OPENS MENU, ATTACHES EVENT HANDLER
$('#trigger').on('click', function () {
update('ui', 'info');
toggleMenu('down');
attachOneShotClick();
});
// FORM SUBMISSION
$('form').submit(function (e) {
e.preventDefault();
var d; // data were are going to send via fake POST request
var input = {
user: $('input[name=user]').val(),
pass: $('input[name=pass]').val(),
}; // form inputs
// check dem form inputs!!!
if (input['user'] == '' || (input['pass']) == '') {
update('log', 'no input!', 'Error!');
update('ui', 'error')
return false;
} else {
// let's get it on!
// form attributes
var...