This is my pen: http://codepen.io/anon/pen/IszKj
What I want to do is how it so when I click on either any status or any date I open up a hidden div which gives a list of options.
My question is, how do I approach this in the best way?
Do I have two different divs and then open the one which is relevant to the list item which was clicked:
<div id="status" style="display: hidden">Option 1 Option 2</div>
<div id="date" style="display: hidden">Option 1 Option 2</div>
Do I have one div and only show the content inside it which is relevant to that button?
<div style="hidden">
<span id="status">...</span>
<span id="date">...</span>
</div>
In addition to this, should I be using toggle or the traditional open / close function.
It would be nice for it to be degradable if JS is disabled.
Created a Fiddle for you:
http://jsfiddle.net/e4mQD/1/
HTML:
<div style="display: block;
height: 40px;">
<ul id="filter">
<li>
<span>Any status▾</span>
<ul class="options">
<li>Option1</li>
<li>Option2</li>
</ul>
</li>
<li>
<span>Any date▾</span>
<ul class="options">
<li>OptionA</li>
<li>OptionB</li>
</ul>
</li>
</ul>
CSS:
#filter, .options {
list-style-type: none;
}
.options {
display:none;
}
.options li {
cursor: pointer;
}
JavaScript:
$('#filter li').click(function(){
$(this).find('.options').toggle();
});
display:hidden
is not valid css rule. You need to use display:none
My question is, how do I approach this in the best way?
In your particular use-case, it is better that you use different blocks for each of those options.
In fact, as #mh-itc pointed out, it is better if you use nested list i.e. ul instead of div inside those lis.
Also, you may use a instead of span.
It would be nice for it to be degradable if JS is disabled.
This can be achieved by deferring the display:none; until the JavaScript is loaded and run.
Demo: http://jsfiddle.net/abhitalks/928Dj/
Markup:
<div>
<ul id="filter">
<li>
Any status ▾
<ul class="opt">
<li><label><input type="checkbox" />Status 1</label></li>
<li><label><input type="checkbox" />Status 2</label></li>
</ul>
</li>
<li>
Any date ▾
<ul class="opt">
<li><label><input type="checkbox" />Date 1</label></li>
<li><label><input type="checkbox" />Date 2</label></li>
</ul>
</li>
</ul>
</div>
CSS:
ul {
margin: 0; padding: 0;
list-style: none;
}
#filter {
display: inline-block;
}
#filter > li {
display: inline-block;
margin-bottom: 12px;
padding-right: 12px;
vertical-align: top;
}
ul.opt.hidden {
display: none;
}
jQuery Code:
// comment out to see how it degrades without javascript
$("ul.opt").addClass("hidden");
$('#filter > li > a').on("click", function(e) {
$(this).next('ul').toggle();
});
Note: In the demo, un-comment the JavaScript code to see how it will behave when JavaScript is available. And comment out to see how it degrades when JavaScript isn't available.
If you want to keep accessibility in mind change the hidden status when loading the site with javascript, if you do that user that have add-ons like NoScript active get to see every option without loosing functionality.
People who use NoScript tend to dislike sites that force them to deactivate NS to use it properly.
For your solution I suggest to use two separate divs, with this you have the option to show both boxes at the same time and have a styled version that makes clear, that these are separate.
Add a class like "optionbox" to these and throw your css rules in there instead of making a rule with #date, #status
Related
I want to hide the button ONLY if a specific div (.variable-item-3) has the class "selected".
The class "selected" is added when the li is clicked.
if($('.variable-item-3').hasClass('selected')) {
$('.button').hide();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="variable-item-1">Option 1</li>
<li class="variable-item-2">Option 2</li>
<li class="variable-item-3 selected">Option 3</li>
</ul>
<button type="submit" class="button">Add to cart</button>
You need to perform the test after you change the selected class. You're just running it once when the page is loaded, it won't automatically run again when the class changes.
You can use the .toggle() function with a boolean argument to make the visibility depend on a test.
$("li").click(function() {
$("li").removeClass("selected");
$(this).addClass("selected");
$(".button").toggle(!$('.variable-item-3').hasClass('selected'));
});
li.selected {
background-color: yellow;
}
.button {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="variable-item-1">Option 1</li>
<li class="variable-item-2">Option 2</li>
<li class="variable-item-3 selected">Option 3</li>
</ul>
<button type="submit" class="button">Add to cart</button>
Since you are already using javascript to add the .selected class, it's probably easier to use the javascript solutions suggested in the other answers. However, if you prefer using CSS (I personally prefer using CSS to Javascript whenever possible) and if the div you care about comes before the button you care about then you can actually just use CSS.
.variable-item-3.selected ~ .button {
display: none;
}
This assumes that .button and .selected are siblings. It gets more complicated if the two aren't siblings but it's still possible as long as an ancestor of .button is a sibling of .selected. In that case it would look something like this:
.variable-item-3.selected ~ div .button {
display: none;
}
If the HTML isn't structured so that either of these will work, then you'll need to use one of the other solutions that does it with javascript.
I have a list of questions and answers. I want a Plus/Minus icon to toggle, and when it is clicked, the answer appears below. I have written up the basic code, but when I click the Plus button for one of the questions, it toggles the answer to display on all of the questions rather than just that specific one. Please see the jsfiddle.
JS:
$(".plus").click(function(){
$(this).toggleClass("minus plus");
});
$(".plus").click(function(){
$(".answer").toggle();
});
How do I get it so that if I press the icon for Question 1, it only shows me Answer 1, and doesn't toggle the other icons?
Here's an updated JSfiddle: https://jsfiddle.net/ocm81sv8/7/
I would do your script like this:
JavaScript
$(".plus").click(function(){
var $this = $(this);
$this.toggleClass("minus plus");
$this.parent().next(".answer").toggle();
});
HTML
<div class="faq-block">
<ul>
<li class="question">
<p><span class="plus"></span>Question 1</p>
<p class="answer" style="display: none;">Answer 1</p>
</li>
<li class="question">
<p><span class="plus"></span>Question 2</p>
<p class="answer" style="display: none;">Answer 2</p>
</li>
</ul>
</div>
I removed having 2 click handlers for the same item and placed them into one call.
I also corrected your .plus elements to be span tags, as it's invalid for a block level element like div to be within p tags.
Updated Fiddle
You should replace <p><div class="plus"></div>Question 1</p> by <p><span class="plus"></span>Question 1</p> since <p><div></div></p> is not a valid HTML code, check the following post Putting <div> inside <p> is adding an extra <p>.
You should toggle the related answer with clicked .plus, so you could use closest('li') to get the parent question then .find(".answer") to target the related answer :
$(".plus").click(function(){
$(this).closest('li').find(".answer").toggle();
});
Instead of :
$(".plus").click(function(){
$(".answer").toggle();
});
Hope this helps.
$(".plus").click(function(){
$(this).toggleClass("minus plus").closest('li').find(".answer").toggle();
});
.faq-block ul, .faq-block ul li {
list-style-type: none !important;
}
span.plus {
display: block;
width: 30px;
height: 30px;
background-color: red;
float:left;
margin-right: 20px;
cursor:pointer;
}
span.minus {
display: block;
width: 30px;
height: 30px;
background-color: blue !important;
float:left;
margin-right: 20px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="faq-block">
<ul>
<li class="question">
<p><span class="plus"></span>Question 1</p>
<p class="answer" style="display: none;">Answer 1</p>
</li>
<li class="question">
<p><span class="plus"></span>Question 1</p>
<p class="answer" style="display: none;">Answer 1</p>
</li>
</ul>
</div>
The fact that you're already using $(this) to get the currently clicked-on element, and yet still fail to use that to get the right target, makes me sad...
First things first. It is not valid to have <div> inside a <p> tag, causing JSFiddle to highlight these errors. It can be fixed by using <span> instead of <div>.
Now, as for doing the toggle, just navigate your way through the DOM:
$(this).closest(".question").find(".answer").toggle();
Navigates up the tree to the .question, then back down to the .answer, and toggles it.
https://jsfiddle.net/ocm81sv8/3/
https://jsfiddle.net/ocm81sv8/8/
$(".plus").on('click', function() {
$(this).toggleClass("minus plus")
.closest('li').find(".answer").toggle();
});
This will make sure if you click on a plus element, it will only toggle its own item, and then find the answer to show.
You need to use a more specific selector. Currently, you are using the class selector ".plus", which is going to be something common to all your questions. It is not a unique identifier. Your code will match all elements that fit your selector scope. To see what I mean, just enter $(".plus") in the chrome console on that page. It will return an array consisting of all the elements that match.
My suggestion is add a unique id to each question, so perhaps something like "question-0", "question-1" ... and so on, then use the selector "#question-X" to toggle it.
Hopefully that helps,
Good luck
I have inherited some code which uses horizontal lists in a form:
<ul>
<li>...</li>
<li>...</li>
</ul>
Where <li> is inline-block. I need to populate those lists with ng-repeat:
<ul>
<li ng-repeat="item in items">...</li>
</ul>
To avoid (well-known) gaps between inline-block elements they have to be written either:
<li>...</li><li>
...</li>
Or:
<li>...</li><!--
--><li>...</li>
But I have no idea how to achieve that with ng-repeat!
Anyone? :)
P.S.: I read this. I wonder if there's an elegant "angular specific" solution.
You can manage them by applying css rule:
li{
display: inline-block;
margin-right: -4px;
}
Or, if you don't want to use negative margin, then you can use float: left; instead of inline-block.
However, this would be costlier. Another solution I think is using ng-repeat-start and ng-repeat-end like below:
<ul>
<li ng-repeat="item in items">...</li><!--
<myDir ng-repeat-end>--></myDir>
</ul>
May be you need to use > instead of > and so on.
And with the compile function remove the element so that there would remain just --> using element.unwrap()
I'm not sure the above method would work fine as you're requiring. You could try this once in your project and let me inform.
If we want to muck around with css options...
ul {
font-size:0;
}
li {
display:inline-block;
font-size:12pt;
}
I'm really new at trying to use jQuery, so please forgive me for asking what is likely a simple question. Perhaps it isn't even related to jQuery, but anyway, here's the scenario. I'm trying to put in a hidden div which I only want to show up when the user hovers their mouse over the Learner's anchor tag on the page. I've started with only one anchor tag, to get it working first before implementing the rest of them. I've downloaded a jQuery library and included a reference to it, so here's some of what I've got in my page's head section:
<script src="js/jquery-1.11.1.js" type="text/javascript" ></script>
<style type="text/css">
#navcontainer ul { list-style-type: none; }
#navcontainer ul li { display: inline; }
#navcontainer ul li a
{
text-decoration:none;
padding: .2em 1em;
}
</style>
Next I've defined an unordered list, using the styling above to make it horizontal, and I've got a hidden div after it, which I want to show when the user moves their mouse over the first anchor in the unordered list. Here's the relevant HTML from within the body tag:
<body>
<div id="navcontainer">
<ul>
<li>Home</li>
<li>Learners</li>
<li>Teachers</li>
<li>Businesses</li>
<li>Contact Us</li>
</ul>
<div id="dropdown1" style="visibility:hidden;">
<ul>
<li>Description A</li>
<li>Description B</li>
<li>Description C</li>
</ul>
</div>
<!-- other HTML code -->
</body>
However, when I run this from within the browser (IE11) nothing happens. Using the F12 web developers tools built into IE11 I learn that it giving an error of "showHide is undefined". Why is it doing that? The showHide() function is most certainly in the jquery-1-11.1.js file, which most certainly is in my js folder. What have I done wrong, or failed to take into account?
jQuery works kinda different than that. You have to make it look like this:
$("#dropdown1").toggle()
You better make a javascript file and separate the JS from the HTML:
HTML:
<body>
<div id="navcontainer">
<ul>
<li>Home</li>
<li>Learners</li>
<li>Teachers</li>
<li>Businesses</li>
<li>Contact Us</li>
</ul>
<div id="dropdown1" style="visibility:hidden;">
<ul>
<li>Description A</li>
<li>Description B</li>
<li>Description C</li>
</ul>
</div>
<!-- other HTML code -->
</body>
The JS
$(function(){
$("#navcontainer li a").click(function(){
if( this.href.indexOf("#") != -1 ) {
$( $(this).attr("href") ).toggle(); // $( "#container1" )
}
});
});
What this does is on the navcontainer li click, we make a handler, which does something if it contains a #. Then we select that element #container1 which is in the href, also is the selector for the element which we want to show. And we toggle that element.
There is no such function as showHide you could use toggle() or show() or hide()
in you current scenario uou would couple them with $(this). or your chosen selector.
As an example of targetting a particular element with jQuery we have added the class hover-learners and target it with the selector below.
HTML:
<div id="navcontainer">
<ul>
<li>Home
</li>
<li>Learners
</li>
<li>Teachers
</li>
<li>Businesses
</li>
<li>Contact Us
</li>
</ul>
<div id="dropdown1">
<ul>
<li>Description A
</li>
<li>Description B
</li>
<li>Description C
</li>
</ul>
</div>
Add the below javascript as a file or within <script type="text/javascript"> code here</script> after including your jQuery library file.
Javascript:
// wrap everything in jQuery's ready function to make sure the page has fully loaded before executing the javascript
$(document).ready(function () {
//select learners and apply mouseover event
$('.hover-learners').on('mouseover', function () {
$('#dropdown1').show();
});
//select learners and apply mouseout event
$('.hover-learners').on('mouseout', function () {
$('#dropdown1').hide();
});
});
Also since the show and hide methods manipulate the display CSS property I have added
CSS:
#dropdown1 {
display:none;
}
and remove the inline style="visibility:hidden" from the #dropdown1
Working demo here: http://jsfiddle.net/robschmuecker/J6U7d/
I'm coding a tab system for my website that must be entirely CSS/HTML/JS (without using any images). Problem is, I keep hacking the code until when I'm finished its just a mess. I don't know whether to use positioning, or float the tabs or what. Basically one of the big problems is that after I take away the bottom-border CSS of the selected tab, I need to move it down 1px so it seamlessly blends with the sorting headers - I don't know whether to use margin: -1px or position: relative/absolute etc. I'd love some advice on a good way to code a tab system like this, so that it can be reused across the website!
Here's an example with CSS that makes it work:
HTML:
<body>
<div class="tabs">
<ul>
<li>Item 1</li>
<li class="active">Item 2</li>
<li>Item 3</li>
</ul>
<div class="tabInner">
<div id="item1">
bla1
</div>
<div id="item2">
bla2
</div>
<div id="item3">
bla3
</div>
</div>
</div>
</body>
CSS:
.tabs ul {
list-style: none;
}
.tabs ul li {
float: left;
background: #eee;
border: 1px #aaa solid;
border-bottom: none;
margin-right: 10px;
padding: 5px;
}
.tabs ul li.active {
margin-bottom: -1px;
padding-bottom: 6px;
}
.tabInner {
clear: both;
border: 1px solid #aaa;
height: 200px;
overflow: hidden;
background: #eee;
}
.tabInner div {
height: 200px;
padding: 10px;
}
It even works without JS (to some degree). You'll still need some JS to move the 'active' class arround and also if you want fancy transitions.
See it in action here: http://jsfiddle.net/V8CK4/
I would use divs nested inside a list.
<ul>
<li>Tab1
<div> Content for Tab1</div>
</li>
<li>Tab2
<div> Content for Tab2</div>
</li>
<li>Tab3
<div> Content for Tab3</div>
</li>
</ul>
Then with css style ul li div to not show. I would use jQuery to show the child divs upon click of the parent li.
EDIT: Thanks to the comment... Note the li's would have to be styled inline so they do not break line after every one. Also set the li list-style to none.
In my opinion I would write it like this:
<div class="tabContainer">
<ul class="tabList">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<em class="tabMessage">This is the message on the right.</em>
<div class="tabInnerContainer">
<div id="item1">
bla
</div>
<div id="item2">
bla
</div>
<div id="item3">
bla
</div>
</div>
</div>
This way will allow you to make it function al least to some extent without Javascipt, degrading nicely in browsers with JS turned off. Some of the classes could be removed if using CSS3 sleectors.
I assume the problem is to make the tab and the bar below it seem like one piece without using too much code.
What I have done before is to make the two elements I want to join overlap slightly (or not at all) and then put a third element (in the same color as both other elements) where the overlap is. This acts as a kind of patch.
Like this:
I. without patch
_________________
| |
| tab |
__|_________________|________________________________
| |
| menu bar |
|_____________________________________________________|
II. with patch
_________________
| tab |
|- - - - - - - - -|
___| patch |_______________________________
| - - - - - - - - - |
| menu bar |
|_____________________________________________________|
You will only need to use z-indexes to make this work properly. The patch may extend over the tab div it is contained in by using position: absolute and an adequately high value for top.
Update: demonstration
http://jsfiddle.net/7GJaW/
Like #Otis mentioned, nesting is a pretty good technique. I usually nest ul's
Link 1
Link 1 Item 1
Link 1 Item 2
However, if you are not trying to attempt to do a dropdown...