I asked my first question last night. Can't believe how helpful this site and its members are. Thank you!
Here's my problem:
I have tabbed navigation to move within a page. There are 4 tabs and the HTML is (I had to remove the links to post bc of the spam filter):
<ol id="toc">
<li><span>Top 3</span></a></li>
<li><span>Reviews</span></a></li>
<li><span>Places to Buy</span></a></li>
<li><span>History</span></a></li>
</ol>
When you click one of those nav links (say, Top 3), you're taken to this:
<div class="tabcontent" id="Top3>
Here's content
</div>
Thanks to helpful answers on this site, I've been able to append all content in #Getit to the bottom of all the other 'tabcontent' nav areas. But when I use this code:
$('.tabcontent#Getit').clone().appendTo('.tabcontent')
It duplicates the Getit tab within the Getit tab, too. Is there anyway to make it so that if someone is viewing the Getit tab that the content won't be appended there and will only be appended to the other tabcontent classes?
Does toggle work that way?
jQuery's .toggle() merely sets an element's display to none if the element is currently visible, or sets it to the appropriate value to display the element if the it is currently hidden. It can also be passed a boolean param which says to force display (true) or hide (false) on the element.
I don't see how it's related to this at all.
If I understand the problem you're having, however, (and it's likely I don't...) you should look into the .not() filtration method:
http://jsfiddle.net/vJc6r/1/
var getit = $( '#Getit' );
getit.clone().appendTo( $( '.tabcontent' ).not( getit ) );
Related
The code below works fine with ONE Reveal/Hide Text process
<div class="reveal">Click Here to READ MORE...</div>
<div style="display:none;">
<div class="collapse" style="display:none;">Collapse Text</div>
However if this code is duplicated multiple times, the Collapse Text shows up and doesn't disappear and in fact conflicts with the Expand to reveal even more text instead of collapsing as it should.
In this http://jsfiddle.net/syEM3/4/ click on any of the Click Here to READ MORE...
Notice how the Collapse Text shows up at the bottom of the paragraphs and doesn't disappear. Click on the Collapse and it reveal more text.
How do I prevent this and getting to work as it should?
The two slideDown function calls are not specific to the .reveal and/or .collapse that you are currently doing. i.e.
$(".collapse").slideDown(100);
will find all the elements with the class .collapse on the page, and slide them down. irrespective of what element you just clicked.
I would change the slideDown call to be relavant to the element you just clicked i.e. something like this
$('.reveal').click(function() {
$(this).slideUp(100);
$(this).next().slideToggle();
$(this).next().next(".collapse").slideToggle(100);
});
in your code
$('.reveal').click(function() {
$(this).slideUp(100);
$(this).next().slideToggle();
$(".collapse").slideDown(100);
});
$('.collapse').click(function() {
$(this).slideUp(100);
$(this).prev().slideToggle();
$(".reveal").slideDown(100);
});
this two rows doesn’t do what you want as they act on all elements of the specified class
$(".reveal").slideDown(100);
$(".collapse").slideDown(100);
When you do $(".collapse").slideDown(100);, jQuery runs slideDown on everything with the .collapse class, not just the one that's related to your current this. To fix this, refer to the collapse based on its location to $(this).
Do do this, use something like $(this).siblings(".collapse").slideDown(100);
Note that this particular selector will only work if you enclose each text block in its own div. With each text element in its own div, like you have it now, .siblings(".collapse"), which selects all the siblings of $(this) with the collapse class, will still select both of the collapse elements.
Okay, I think you should take a different approach to your problem.
See, jQuery basically has two purposes:
Selecting one or more DOM elements from your HTML page
manipulate the selected elements in some way
This can be repeated multiple times, since jQuery functions are chainable (this means you can call function after function after function...).
If I understood your problem correctly, you are trying to build a list of blog posts and only display teasers of them.
After the user clicks the "read more" button, the complete article gets expanded.
Keep in mind: jQuery selects your elements very much like CSS would do. This makes it extremely easy to
come up with a query for certain elements, but you need to structure your HTML in a good way, like
you would do for formatting reasons.
So I suggest you should use this basic markup for each of your articles (heads up, HTML5 at work!):
<article class="article">
<section class="teaser">
Hey, I am a incredible teaser text! I just introduce you to the article.
</section>
<section class="full">
I am the articles body text. You should not see me initially.
</section>
</article>
You can replace the article and section elements with div elements if you like to.
And here is the CSS for this markup:
/* In case you want to display multiple articles underneath, separate them a bit */
.article{
margin-bottom: 50px;
}
/* we want the teaser to stand out a bit, so we format it bold */
.teaser{
font-weight: bold;
}
/* The article body should be a bit separated from the teaser */
.full{
padding-top: 10px;
}
/* This class is used to hide elements */
.hidden{
display: none;
}
The way we created the markup and CSS allows us to put multiple articles underneath.
Okay, you may have noticed: I completely omitted any "read more" or "collapse" buttons. This is done by intention.
If somebody visits the blog site with javascript disabled (maybe a search engine, or a old mobile which doesn't support JS or whatever),
the logic would be broken. Also, many text-snippets like "read more" and "collapse" are not relevant if they don't actually do anything and are not part of the article.
Initially, no article body is hidden, since we didn't apply the hidden css class anywhere. If we would
have embedded it in the HTML and someone really has no JavaScript, he would be unable to read anything.
Adding some jQuery magic
At the bottom of the page, we are embedding the jQuery library from the google CDN.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
This is a best practice and will normally speed up your page loading time. Since MANY websites are embedding
jQuery through this URL, chances are high that its already in the visitors browser cache and doesn't have
to be downloaded another time.
Notice that the http: at the beginning of the URL is omitted. This causes browsers to use the pages current protocol,
may it be http or https. If you would try and embed the jQuery lib via http protocol on a https website, some browsers will refuse to download the file from a unsecure connection.
After you included jQuery into the page, we are going to add our logic into a script tag. Normally we would
save the logic into a separate file (again caching and what not all), but this time a script block will do fine.
Finally some JavaScript
At first, we want to hide all elements with the css-class full, since only teasers should remain displayed. This is very easy with jQuery:
$('.full').hide();
The beginning of the script $('.full') tells jQuery: I need all elements with the CSS-class full. Then we call a function on that result, namingly hide() which purpose should be clear.
Okay, in the next step, we want to add some "read more" buttons, next to every teaser. Thats an easy task, too:
$('.teaser').after('<button class="more">Read more</button>');
We now select every element with the css-class teaser and append some HTML code after() each element - a button with the css-class more.
In the next step, we tell jQuery to observe clicks on every one of this freshly created buttons. When a user has clicked, we want to expand the next element with the css-class full after the clicked button.
$('.more').on('click', function(){
//"this" is a reference to the button element!
$(this).slideUp().next('.full').slideDown();
});
Phew, what did we do here?
First, we told jQuery that we wanted to manipulate this, which is a reference to the clicked button. Then we told
jQuery to hide that button (since its not needed anymore) slowly with slideUp().
We immediately continued telling jQuery what to do: Now take the next() element (with the css-class full) and make it visible by sliding it down with slideDown().
Thats the power of jQuerys chaining!
Hiding again
But wait, you wanted to be able to collapse the articles again! So we need a "collapse" button, too and
some more JavaScript:
$('.full').append('<button class="collapse">Collapse text</button>');
Note: we didn't use the after() function to add this button, but the append() function to place the button
INSIDE every element with the css-class full, rather than next to it. This is because we want the
collapse buttons to be hidden with the full texts, too.
Now we need to have some action when the user clicks one of those buttons, too:
$('.collapse').on('click', function(){
$(this).parent().slideUp().prev('.more').slideDown();
});
Now, this was easy: We start with the button element, move the focus to its parent() (which is the element that contains the full text) and tell jQuery to hide that element by sliding it up with slideUp().
Then we move the focus from the full-text container to its previous element with the css-class more, which is its expanding button that has been hidden when expanding the text. We slowly show that button again by calling slideDown().
Thats it :)
I've uploaded my example on jsBin.
I have made some menu with a slide down submenu. It should work fine but for some reason it doesn't work. I mean if you look at this fiddle: http://jsfiddle.net/yJdFu/2/ , you'll see that the big menus don't slide down when the submenu toogles.
Can you tell me why isn't it working ?
It is actually working. The problem is you have a specified height to the list items. So the submenu is appearing below the existing items.
Remove the height from the list items.
Updated Fiddle
You weren't missing any closing tags. The html is correct. Error was in CSS. Also, I altered the jquery a bit. not sure why you were using .find() when the item can be called by it's class, and I specified which toggle to use.
This fiddle uses jquery which specifies the toggle only occurs on the "dashboard" link. Otherwise the sub navigation closes when one of its links is clicked.
You are missing a closing </li> tag.
<li class="dashboard"><a href="#">
<img src="assets/gfx/dashboard.png" alt="Dashboard">
<span>Dashboard</span></a>
</li>
see here http://jsfiddle.net/yJdFu/4/
As Roland said above, you may also want to look at the built-in JQuery UI Accordion before rolling your own solution.
I'm trying to make a jQuery toggle menu for a mobile website for one of my clients. I'll have to tell you i'm not experienced in javascript and i justed started looking at it.
The current website is a Wordpress website so the menu structure is generated by WP.
Because this is generated by WP i need to use javascript to manipulate the data for adding the + - and > signs for toggleing and if no childeren to go directly to the page.
I use this javascript for adding the spans with the desired icon. I've managed so far.
http://jsfiddle.net/9Dvrr/9/
But there are still 2 problems i can't seem to figure out.
Remove the href from the "a" when the "li" has a "ul" child.
This should remove the links of the items so they will only toggle (not link) to navigate straight throug to the deepest level.
Currently the javascript is adding mutiple spans with the icons. I can't seem to figure out why
I'm stuggeling with this for a while now and was wondering if someone could help me with this.
In the jsfiddle you provided, you loop on the elements to add spans with a "+" or "-" sign inside, depending on the case. The thing is, the HTML you're starting with already has those spans in it, wich is why you're seeing some duplicates.
As you said you can't add those spans in the HTML because of your WP strucutre, I guess they come from a bad copy/paste you did while creating the jsfiddle. I removed them in the HTML and added a return false to prevent linking to another page when there is a ul inside the a tag.
http://jsfiddle.net/wzzGG/
Your first problem can be solved with the following:
$.each($('#menu-mobiel li'), function(i, value) {
var $this = $(this);
if ($this.has('ul').length > 0) {
$this.children('a').attr('href','javascript:');
}
Your second problem is a bit harder for me to understand. Do you only want one + for items with submenus, and one > for items with a link?
So I'm very much a jQuery noob and I don't know whether the following is possible - at least as I'm thinking of it - or how to do it.
The current setup
http://joelglovier.com
So I have a one page mini-site with a fixed navigation at the top of the screen. All (but one) of the navigation elements simply scroll the user down to the corresponding div down the page. I have that all set up just fine.
What I want to do...
I want to use jQuery to add a class of "active" to the list item anchors when they are positioned over their respective div on the page. Preferably it would not use the click function, so that even users who simply scroll down the page without clicking on the nav elements to get their would experience the same thing. Similar to the phpfog home page.
I peeked at the way phpfog.com has it setup and from what I could see it's using some type of calculation with the window selector to apply the class, but A) I don't completely understand what it's doing or how to build something similar, and B) I don't know if they are doing it in the most straightforward manner.
I wrote out what I want to accomplish in a plain english statement, since I don't have a mastery on jQuery enough yet to write it out in a syntax:
If .section-link is in the window on the
href value of same id, add class of
"active"
So here's the code I have (HTML only, the CSS is irrelevant bc I already know how I want to style it, just want to add the active class at the appropriate place):
<div id="site-nav">
<div class="wrap">
<ul id="nav-links">
<li class="section-title-nav top">
<h4>Home</h4>
</li>
<li class="section-title-nav skills">
<h4>Background</h4>
</li>
<li class="section-title-nav projects">
<h4>Projects</h4>
</li>
<li class="section-title-nav blog">
<h4>Blog</h4>
</li>
<li class="section-title-nav random">
<h4>Random</h4>
</li>
<li class="section-title-nav credits">
<h4>Credits</h4>
</li>
</ul>
</div>
</div>
And further down the page, sections that are linked to in the nav are marked up about like this:
<div id="random-section" class="main-section wrap clearfix">
<h2 class="section-title"><span class="bg">Random</span></h2>
<span class="section-title-border"></span>
<h2 class="coming-soon">COMING SOON</h2>
</div><!--/#random-section-->
So, and tips on how to accomplish this, or whether I'm thinking about it the wrong way is what I'm looking for. Thanks!
Here's a working example I put together; I will be the first to admit it can be improved but it might give you a decent starting point to work from.
http://jsfiddle.net/nogoodatcoding/KMwhZ/1/
The basic idea is to listen for scroll events on the window and then, for each navigation link, extract the href value and check if the corresponding element is visible or not. If it is, then it's link is selected and the previously highlighted element is deselected. I'm breaking early when the first visible section is found, you can get slightly different behaviour by going all the way through the list.
My example breaks when the divs are small enough in height that multiple divs are visible when the page is scrolled all the way to the bottom - in the case, the links for the lowest few divs will never get hightlighted. But that appears to be the case even with the phpfog page you linked to - the links for Testimonials and Free Tools never get activated because my display is tall enough to show the last 3 sections when scrolled all the way down. Note that this won't be the case if don't break early - there, the last visible section will be highlighted. But you can then see the opposite problem - the top section's link is never activated since something else is always visible.
<script type="text/javascript">
jQuery(document).ready(function($) {
var url = window.location.pathname,
urlRegExp = new RegExp(url.replace(/\/$/,'') + "$");
$("#navbar li a").each(function() {//alert('dsfgsdgfd');
if(urlRegExp.test(this.href.replace(/\/$/,''))){
$(this).addClass("active");}
});`enter code here`
});
</script>
This question already has an answer here:
How to remember last state with Jquery?
(1 answer)
Closed 7 years ago.
I have a nested ul/li list
<ul>
<li>first</li>
<li>second
<ul>
<li>Third</li>
</ul>
</li>
... and so on
I found this JQuery on the interweb to use as inspiration, but how to keep the one item i expanded open after the page has reloaded?
<script type="text/javascript">
$(document).ready(function() {
$('div#sideNav li li > ul').hide(); //hide all nested ul's
$('div#sideNav li > ul li a[class=current]').parents('ul').show().prev('a').addClass('accordionExpanded'); //show the ul if it has a current link in it (current page/section should be shown expanded)
$('div#sideNav li:has(ul)').addClass('accordion'); //so we can style plus/minus icons
$('div#sideNav li:has(ul) > a').click(function() {
$(this).toggleClass('accordionExpanded'); //for CSS bgimage, but only on first a (sub li>a's don't need the class)
$(this).next('ul').slideToggle('fast');
$(this).parent().siblings('li').children('ul:visible').slideUp('fast')
.parent('li').find('a').removeClass('accordionExpanded');
return true;
});
});
</script>
you can save the current open menu item in a cookie $.cookie('menustate')
similar: How to remember last state with Jquery?
The same way you manage state when passing data from page to page:
Querystring
Cookies
Form post / hidden field
Ajax to and from the server
I'll assume you dont like any of the previous answers since none of them have been accepted and present you with a less "correct" way of doing it. Before I get flamed to death, this is just my attempt at doing it with pure js/jq. You could parse out the URL (http://example/subsite) and select whichever piece is relevant (for the sake of ease, lets assume /subsite is what you want).
$(document).ready(function(){
var pathname = window.location.pathname;
var splitpath = pathname.split("/");
$("#nav-" + splitpath[1] + "").children().class('current')
});
Build your ID's into something like <li id=nav-subsite> and use the parsed out URL to build a selector for the correct tab/li/whatever. Is it weird? Sure, but I figured I'd throw in my $.02
This is not easily doable in JavaScript alone.
Either the server sets the accordionExpanded CSS class correctly when the page is reloaded (directly into the source HTML). This would require the server knows what <li>s the user had clicked on, naturally.
Or you avoid reloading the page at all and do partial page updates through AJAX calls. This is what most "modern" websites do.
Or you do what Glennular suggests and save state info to a cookie.
Your choice.
I'm not sure what your menu is supposed to be doing exactly, but if it's a nav menu, you could add a brief bit of markup to your body element for each base page:
<body class="home"> <!-- for homepage -->
<body class="about"> <!-- for about page -->
<body class="etc"> <!-- for etc. -->
And have jQuery look for this marker and make a decision on how to handle the list tree once the page loads based on which page it is. It wouldn't require setting any cookies, and so long as they have JS enabled (which every user should at this point), everything's kosh magosh.