The issue here is, the div that has a class of filter_sub (the custom menu dropdown) is sliding up (hide thing when click anywhere other than this element and its descendants) when I interact into the jquery ui date picker.
Any ideas, clues, help, suggestions, recommendations to fix my issue?
I want the custom menu dropdown (the one that has a class of filter_sub) to not slide up when I interact into the jquery ui date picker or to be sharpen other that jquery ui datepicker and the custom dropdown menu, when click anywhere then the jquery ui date picker will be hidden as well as the custom dropdown menu will slide up (hide).
$(document).ready(function(){
$(".thehide").hide();
$( ".datepicker" ).datepicker({
dateFormat: "yy-mm-dd"
});
//when authorized person clicks on the attendance menu
$(".filter_pages").unbind().click(function(e){
$(this).next(".filter_sub").slideToggle();
e.preventDefault();
});
$(document).mouseup(function(e)
{
var container = $(".filter_sub");
var calendar = $(".ui-datepicker");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.slideUp();
}
});
});
.filter .filter_has_sub{
padding: 0px;
margin: 0px;
float: left;
margin-left: 7px;
}
.filter_pages{
display: table;
font: normal 12px 'mpregular', san-serif;
padding: 7px;
color: #7e7e7e;
margin-top: 4px;
}
.filter_pages span, .filter_sub a span{
float: left;
display: block;
}
.filter_pages span:first-child, .filter_sub a span:first-child{
margin-right: 6px;
}
.filter_pages span:last-child{
font-size: 8px;
padding-top: 3px;
}
.filter_has_sub:first-child .filter_sub{
margin-left: -100px;
width: 170px;
}
.filter_has_sub:first-child .filter_sub .filter_datepicker{
border: 1px solid #ccc;
display: table;
margin: 5px auto;
}
.filter_has_sub:first-child .filter_sub .filter_datepicker span{
display: block;
margin: 0px 5px 0px 0px;
float: left;
font-size: 20px;
padding: 5px 0px 0px 5px;
color: #7e7e7e;
}
.filter_has_sub:first-child .filter_sub .datepicker{
padding: 5px;
border: none;
margin: 0px;
display: block;
float: left;
width: 120px;
}
.filter_sub{
background: #fff;
position: absolute;
z-index: 99999999;
width: 100px;
margin-left: -30px;
padding: 10px 5px;
margin-top: 5px;
-webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
}
.filter_sub a{
clear: both;
float: none;
display: block;
padding: 5px 10px;
font: normal 14px 'mplight', sans-serif;
color: #555;
text-transform: uppercase;
}
.filter_sub a:hover{
color: #555;
}
.thehide{dsiplay: none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div class="filter_has_sub extend data_filter" style="display: table; margin: 0px auto;">
<span>Filter Data</span><span class="ion-chevron-down"></span>
<div class="filter_sub thehide" id="pagesfilter">
<div class="extend clear" style="height: 5px;"></div>
<div class="filter_datepicker extend clear">
<span class="ion-calendar"></span><input class="form-control datepicker extend" name="from_what_date" placeholder="From what date" required/>
</div>
<div class="filter_datepicker extend clear">
<span class="ion-calendar"></span><input class="form-control datepicker extend" name="to_what_date" placeholder="To what date" required/>
</div>
<button class="btn btn-default center display_table" id="date_filter_button">Go</button>
</div>
</div>
I think you are almost there. Here is what you can do:
In your if clause inside mouseup function, add another
condition: calendar.has(e.target).length===0. Which does the
same thing as the other similar condition i.e. to make sure that the
current target is not a descendant of the ui-datepicker
element.
Also, I noticed that your slideToggle inside click event and your slideUp inside your mouseup event were executing one after another if you clicked on filter_has_sub element to hide the inner elements. Easy fix is to add a stop(true) right before sliding to both slideToggle and slideUp calls.
JS:
$(document).ready(function () {
$(".thehide").hide();
$(".datepicker").datepicker({dateFormat: "yy-mm-dd"});
$(".filter_pages").unbind().click(function (e) {
$(this).next(".filter_sub").stop(true).slideToggle();
e.preventDefault();
});
$(document).mouseup(function (e) {
var container = $(".filter_sub");
var calendar = $(".ui-datepicker");
if (!container.is(e.target) && calendar.has(e.target).length === 0 && container.has(e.target).length === 0) {
container.stop(true).slideUp();
}
});
});
Hope this helps.
The Menu already has toggle enabled, so no problem. So if All you have to do to is to check is if nodeName is HTML if the user clicks outside the target let it be UI calender or the input box of the slide
So, You dont have to check for container.is(e.target)
This is how you can do it ==> (event.target.nodeName === 'HTML')
check out the UPDATED FIDDLE
For more info Look into the jQuery Docs- event.target
Related
I am trying to make a board where users can move sticky notes here and there which contain data.
I am utilizing the sortable jQuery library at the moment. It is working as it is designed to, but I want to modify the functionality a little. When I remove an item from the list, I want an empty space to be left in its place. For example, if I am removing the first item from the list, the rest of the items shouldn't be moved up and take the empty space.
Similarly, when I have only one item in a list and I remove it, I cannot add anything back to that list since the list goes away. I want to stop that from happening as well.
Here's the snippet (click to open).
$(document).ready(function() {
$('.sort-me-alpha').sortable({
connectWith: '.sort-me-gamma',
receive: function (event, ui) {
if ($(ui.item).hasClass('special')) {
ui.sender.sortable('cancel');
}
}
});
$('.sort-me-beta').sortable({
connectWith: '.sort-me-gamma',
receive: function (event, ui) {
if (!$(ui.item).hasClass('special')) {
ui.sender.sortable('cancel');
}
}
});
$('.sort-me-gamma').sortable({
appendTo: document.body,
items: '.sticky',
placeholder: "testclass",
connectWith: '.sort-me-alpha, .sort-me-beta',
receive: function (event, ui) {
//console.log(event, ui.item);
//ui.item.remove(); // remove original item
}
});
});
.sort-me {
/* background-color: #3498db; */
min-height: 30px;
margin: 10px;
padding: 10px;
width: auto;
vertical-align: top;
display: inline-block;
}
.sort-me-alpha {
/* background-color: #3498db; */
min-height: 30px;
margin: 10px;
padding: 10px;
width: auto;
vertical-align: top;
display: inline-block;
}
.sort-me-gamma {
/* background-color: #3498db; */
min-height: 30px;
margin: 10px;
padding: 10px;
width: auto;
vertical-align: top;
display: inline-block;
}
.sort-me-beta {
/* background-color: #3498db; */
min-height: 30px;
margin: 10px;
padding: 10px;
width: fixed;
vertical-align: top;
display: inline-block;
}
.testclass {
background-color: gray;
border: 2px solid gray;
width: 100%;
height: 100%;
}
.sticky {
/* position: absolute; */
right: 0;
z-index: 150;
/* transform: rotate(5deg); */
width: 200px;
min-height: 150px;
margin: 10px 10px 10px;
padding: 10px;
/* font-family: "Comic Sans MS", "Comic Sans", "Chalkboard SE", "Comic Neue", cursive; */
font-size: 14px;
color: #000;
background: rgba(255, 255, 51, 0.8);
box-shadow: -2px 2px 2px rgba(0, 0, 0, 0.3);
}
.sticky:before,
.sticky:after {
content: "";
display: block;
position: absolute;
width: 16px;
height: 16px;
top: 0;
right: 0;
}
.sticky:before {
border-top: solid 8px #fff;
border-right: solid 8px #fff;
border-left: solid 8px transparent;
border-bottom: solid 8px transparent;
}
.sticky:after {
border-bottom: solid 8px #dddd33;
border-left: solid 8px #dddd33;
border-right: solid 8px transparent;
border-top: solid 8px transparent;
}
.ui-helper {
width: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="container">
<div class="sort-me-alpha">
<div class="sticky">
<b>Card 1</b> Put any text in here.
</div>
<div class="sticky">
<b>Card 2</b> Put any text in here.
</div>
</div>
<div class="sort-me-beta">
<div class="sticky">
<b>Card n</b> Put any text in here.
</div>
</div>
<div class="sort-me-gamma">
<div class="sticky">
<b>Card 3</b> Put any text in here.
</div>
<div class="sticky">
<b>Card 4</b> Put any text in here.
</div>
</div>
</div>
When I move Card N to any other list, I cannot bring it back since the list ceases to exist.
Also if I were to move Card 3 to any other list, Card 4 comes up and takes its place, I know this is the default behavior, but can I override it?
One question per question, please. I'll answer the first one.
You should use:
$("#sticky-id").css('visibility','hidden');
The property visibility:hidden keeps the space as it is.
To remove an element, just use remove() instead of touching visibility.
If you want to add an element inside the list use:
remove: function(event, ui) {
console.log(event);
console.log('removed');
$('.sort-me-gamma').prepend('<div class="sticky">' + '<b> I am a dummy card </b>' + '</div>' );
}
And if you want a generic function to do this, you'll need:
.insertAfter('#list :nth-child(<give childnumber here>)')
And to get childnumber use an on click event and set an attribute which contains the ID in each card when creating HTML code, for example id=card-number-[putherevalue]
I have three divs as below:
Here is a JSFiddle.
$(document).on('click', '.top', function (e) {
console.log("Empty space clicked");
});
.top{
width: 208px;
text-transform: uppercase;
text-align: left;
height: 34px;
background-color: #F44336;
border-bottom: 1px solid #ea1c0d;
color: #ffffff;
box-shadow: 0px 3px 3px 0px rgba(50, 50, 50, 0.1);
padding: 3px 8px;
cursor: auto;
}
.inner_1{
font-size: 12px;
}
.inner_2{
font-size: 11px;
text-transform: none;
line-height: 12px;
margin-top: 5px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
.inner_1:hover, .inner_2:hover {
cursor: pointer;
text-decoration: underline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="top">
<div class="inner_1">Top content: This is full width</div>
<div class="inner_2">Bottom</div>
</div>
As you can see from the jsfiddle, when the .top is clicked, it shows a log.
However, I want to make it so that it shows the log ONLY when the empty space is clicked and not when inner_1 or inner_2 div class is clicked (as it shows the log when these two classes are clicked as of now).
What is the best way to achieve this?
Thanks.
Use stopPropagation from jquery. This will stop all child divs from triggering parent onClick
$(document).on('click', '.top > div', function (e) {
e.stopPropagation();
});
Edit:
Code above was building on what OP knows but this way is more efficient for the browser.
$('.top > div').on('click', function (e) {
e.stopPropagation();
});
I'm trying to format an inline navigation, but the last link which has a class tied to a piece of javascript seems to be causing the entire link to become a block element rather than putting it inline with the rest of the links in the navigation.
I tried removing the class, changing the class to something else (not tied to any script) and it puts the link back in line, which is what leads me to believe it has something to do with the javascript it's tied to. I've also tried calling a.show in css to display it inline and inline-block to no avail. I feel like I'm missing a well know rule of thumb.
The <a href="#" class="show"> is on Line 20 and the <script> tag is on Line 25 of the HTML
CSS
#nameTag {
max-width: 800px;
min-width: 320px;
margin: 0 auto;
background-color: #FFFFFF;
-webkit-box-shadow: 2px 2px 2px 1px hsla(0,0%,0%,0.72);
box-shadow: 2px 2px 2px 1px hsla(0,0%,0%,0.72);
border-radius: 43px;
border: 2px solid #4B4949;
}
#tagTop{
width: 100%;
height: auto;
display:block;
color: #fff;
font-size:30px;
text-align: center;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
background-color: #0033AA;
padding-top: 5px;
padding-bottom: 10px;
}
#tagBottom{
width: 100%;
height: 50px;
display: block;
color: #FFFFFF;
text-align: center;
border-bottom-left-radius: 40px;
border-bottom-right-radius: 40px;
background-color: #0033AA;
padding-top: 5px;
padding-bottom: 10px;
}
#tagBottom > a:link, a:visited{
color:#fff;
}
#container{
padding:20px
}
.miniNav{
text-align:center;
font-size:18px;
font-weight:600;
margin-bottom:10px;
}
.miniNav a:link,a:visited{
color:#0033AA;
text-decoration:none;
}
.miniNav a:hover,a:active{
color:#000;
}
HTML
<div id="nameTag">
<div id="tagTop">
<h3>HELLO</h3>
my name is
</div>
<div id="name">
<div class="show">
<img src="images/name.jpg" width="100%" alt="First slide image" class="center-block">
</div>
</div>
<div id="container">
<div class="miniNav">
Change Font
|
Download Graphic CV
|
Download Typed CV
|
<a class="show" href="#">Close CV</a>
</div>
</div>
<div id="tagBottom">
</div>
<script>
$("#container").hide();
$(".show").click(function() {
$("#container").slideToggle("slow");
});
</script>
</div>
UPDATE2
In order to prevent the jerking behavior when clicking the .hide and .show links, simply add event.preventDefault() to your jQuery function.
<script>
$("#container").hide();
$(".show, .hide").click(function(event) { // Pass the event object here
event.preventDefault(); // Then use the preventDefault() property
$("#container").slideToggle("slow");
});
</script>
UPDATE
I misunderstood what the question was, I believe that you wanted the toggle image inline with the other anchors. That would be more trouble than what it's worth. .show is in another div and nested. So just add an identical img inside .miniNav and make sure the other image disappears. Also, I used a background-image for the one inside .miniNav because it's easier to handle as a link. It's better if you look at the jQuery than for me to explain it. I also changed the "Close CV" link's class to .hide so it doesn't share styles and then added .hide to the jQuery in order to keep functionality.
The last link "Close CV" is ok as long as your #nameTag is # 550px wide, else the link will naturally wrap to the next line if less than 550px. If you make .miniNav and the anchors behave like table components, there will be no wrapping to the next line. Add display:table-row to .miniNav and display:table-cell to each anchor.
Changed padding so that links conform when #nameTag is compact. Removed | and added border-right: 1px solid blue;. To center the links, margin: 0 auto; display: table; was added to #container.
You could use percentages or ems instead of px for margins and padding so that your text will stay on one line consistently. That takes some experimenting so I'll leave you that to decide.
BTW, when designating selectors in CSS, if you have multiple selectors that apply to a ruleset, you need to be specific on each one.
Example
.miniNav a:hover,
a:active {
color: #000;
}
Anchors that are descendants of .mini-nav are black when hovered over / Any anchor that is active is black.
.miniNav a:hover,
.miniNav a:active {
color: #000;
}
Anchors that are descendants of .mini-nav are black when hovered over or is active.
Changes
#container {
padding: 10px 0px 15px 7px;
margin: 0 auto;
display: table;
}
.miniNav {
text-align: center;
font-size: 18px;
font-weight: 600;
margin-bottom: 10px;
display: table-row;
}
.miniNav a,
.miniNav a:link,
.miniNav a:visited {
color: #0033AA;
text-decoration: none;
display: table-cell;
border-right: 1px solid blue;
padding: 0 7px;
}
...
.miniNav a:last-of-type {
border-right: 0px none transparent;
}
SNIPPET
$("#container").hide();
$(".show, .hide").click(function() {
$('.show').toggle();
$("#container").slideToggle("slow");
});
#nameTag {
max-width: 800px;
min-width: 550px;
margin: 0 auto;
background-color: #FFFFFF;
-webkit-box-shadow: 2px 2px 2px 1px hsla(0, 0%, 0%, 0.72);
box-shadow: 2px 2px 2px 1px hsla(0, 0%, 0%, 0.72);
border-radius: 43px;
border: 2px solid #4B4949;
}
#tagTop {
width: 100%;
height: auto;
display: block;
color: #fff;
font-size: 30px;
text-align: center;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
background-color: #0033AA;
padding-top: 5px;
padding-bottom: 10px;
}
#tagBottom {
width: 100%;
height: 50px;
display: block;
color: #FFFFFF;
text-align: center;
border-bottom-left-radius: 40px;
border-bottom-right-radius: 40px;
background-color: #0033AA;
padding-top: 5px;
padding-bottom: 10px;
}
#tagBottom > a:link,
a:visited {
color: #fff;
}
#container {
padding: 10px 0px 15px 7px;
margin: 0 auto;
display: table;
}
.miniNav {
text-align: center;
font-size: 18px;
font-weight: 600;
margin: 0px auto 10px;
display: table-row;
}
.miniNav a,
.miniNav a:link,
.miniNav a:visited {
color: #0033AA;
text-decoration: none;
display: table-cell;
border-right: 1px solid blue;
padding: 0 7px;
}
.miniNav a:hover,
.miniNav a:active {
color: #000;
}
.miniNav a:last-of-type {
border-right: 0px none transparent;
}
a.img {
background: url(http://placehold.it/80x50/eea/e00?text=First=slide+image)no-repeat;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="nameTag">
<div id="tagTop">
<h3>HELLO</h3>
my name is
</div>
<div id="name">
<div class="show">
<a href="#">
<img src="images/name.jpg" width="100%" alt="First slide image" class="center-block">
</a>
</div>
</div>
<div id="container">
<div class="miniNav">
<a href="#" class='img'>First slide image</a>
Change Font
Download Graphic CV
Download Typed CV
<a class="hide" href="#">Close CV</a>
</div>
</div>
<div id="tagBottom">
</div>
</div>
It appears jQuery's slideToggle() function defaults to display:block, so you can use a callback to set it to display: inline-block manually, as explained in this answer from user black.
Your code would then be:
$("#container").hide();
$(".show").click(function() {
$("#container").slideToggle("slow", function() {
if ($("#container").is(':visible'))
$("#container").css('display','inline-block');
});
});
You'll also need to style your container as display: inline-block, unless I'm misunderstanding your question.
I have used JavaScript to create 3 clickable drop-down menu button in a webpage. when I click one button, script is works well. I can see the following menu is displayed. When I another button, the following menu is displayed. however, the previous menu is still there.
Here is my script. Hope someone can help me. Thank you!
<script type="text/javascript" >
$(document).ready(function() {
$(".account").click(function() {
var X = $(this).attr('id');
if (X == 1) {
$(".submenu").hide();
$(this).attr('id', '0');
} else {
$(".submenu").show();
$(this).attr('id', '1');
}
});
//Mouse click on sub menu
$(".submenu").mouseup(function() {
return false
});
//Mouse click on my account link
$(".account").mouseup(function() {
return false
});
//Document Click
$(document).mouseup(function() {
$(".submenu").hide();
$(".account").attr('id', '');
});
});
</script>
// CSS
.dropdown
{
color:#000;
margin: 0px 22px 0 0;
width: 300px;
height: 30px;
text-align:center;
}
.submenu
{
background:#FFF ;
position: absolute;
top: 118px;
left: 515px;
z-index: 100;
width: 250px;
display: none;
border-radius: 6px;
border: outset 2px #0066FF;
box-shadow: 0 0px 0px rgba(0, 0, 0, 0.05);
}
.dropdown li a
{
color:#555555;
display: block;
font-family: arial;
font-weight: bold;
padding: 6px 15px;
cursor: pointer;
text-decoration:none;
margin-top:-5px;
}
.dropdown li a:hover
{
background:#155FB0;
color: #FFFFFF;
text-decoration: none;
}
a.account
{
font-size: 18px;
line-height: 10px;
color: #000;
border: ridge 2px #0066FF;
position: absolute;
z-index: 110;
display: block;
padding: 11px 0 0 0px;
height: 20px;
width: 300px;
margin: 0px 0 0 0px;
text-align:center;
text-decoration: none;
background: url(images-new/arrow.png) 275px 9px no-repeat;
cursor:pointer;
}
.root
{
list-style:none;
margin:0px;
padding:0px;
font-size: 11px;
padding: 11px 0 0 0px;
border-top:1px solid #dedede;
}
// html
<div class="dropdown">
<a class="account" >My Account</a>
<div class="submenu">
<ul class="root">
<li ><a href="#Dashboard" >Dashboard</a></li>
<li ><a href="#Profile" >Profile</a></li>
<li >Settings</li>
<li >Send Feedback</li>
</ul>
</div>
</div>
My personal recommendation is to do this with with a combination of JS & CSS.
You should use an active class to hide and show your elements:
//JS
$('.menu a').on('click', function({
$('.menu a').removeClass('active');
$(this).addClass('active');
});
// CSS
.active .submenu {
display: block;
}
What I am trying to do is when you click on a button that has the class ".option" it will show the div that has the id "#dialog" and then it will add the class .active to the button clicked (there maybe more than one button that shows different dialogues later one) as well as adding the class ".noScroll" to the body. When the dialogue is shown it can be closed by clicking anywhere on the "#dialog" but NOT the ".dialogPage" which is the div that is inside the "#dialog" div. If the dialogue has been closed, the class that has been added to the body and to the button shall be removed.
Here is the button that need to be clicked to show the dialog:
<a class="option" href="edit_account.php">Your Account</a>
The following HTML represents the structure of my Dialog:
<div id="dialog">
<div id="dialogPage" class="dialogPage">
<p>Edit your account here</p>
</div>
</div>
Here is the related CSS:
body {
color: #4A4A4A;
background-color: #F7F7F7;
font-family: 'arial', sans-serif;
font-size: 0.95em;
line-height: 150%;
text-align: center;
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
-webkit-overflow-scrolling: touch;
overflow-y: auto;
overflow-x: hidden;
}
#dialog {
display: none;
background-color: rgba(25,30,37,0.95);
width: 100%;
position: fixed;
bottom:0; top: 0; left: 0; right: 0;
margin-top: 70px;
z-index: 900;
overflow-y: auto;
overflow-x: hidden;
}
.dialogPage {
background-color: #F7F7F7;
border: 2px solid #ffffff;
width: 900px; min-width: 900px;
padding: 20px;
margin: 50px auto;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
-webkit-box-shadow: 0px 0px 30px 0px rgba(0,0,0,0.4);
-moz-box-shadow: 0px 0px 30px 0px rgba(0,0,0,0.4);
box-shadow: 0px 0px 30px 0px rgba(0,0,0,0.4);
}
.noScroll {
overflow-y: hidden;
overflow-x: hidden;
}
Here is the JavaScript I am currently using, but please do not built on it as it is wrong I am sure:
$(".option, #dialog").on('click', function() {
$("#dialog").toggle(29);
$("body").toggleClass("noScroll");
if (e.target.id != 'dialogPage' && !$('#dialogPage').find(e.target).length) {
$("#dialog").hide();
}
});
Try the following:
$('.option').click(function(e) {
e.preventDefault();
$('#dialog').show();
$('body').addClass('noScroll');
$(this).addClass('active');
return false;
});
$('#dialog').click(function(e) {
$(this).hide();
$('body').removeClass('noScroll');
$('.option').removeClass('active');
});
$('#dialogPage').click(function(e) {
e.stopPropagation();
});
I didn't see any use of the .active class in your current code, so that is just a guess.
Demo: http://jsfiddle.net/verashn/2Xh7d/