Javascript and jQuery to make divs into a tab based content page - javascript

I recently had a 30 min test for a job application using only Javascript with jQuery. Didn't have to be styled well or anything. I created a very basic "30 min" page with Javascript and jQuery which I thought was "ok".. I just wanted to get some feedback if there was a more efficient/better way of doing this? as it turned out, I didn't get the job.. always learning, and also the job was quite a way from where I live.
Anyway, the original HTML page given was as follows, and after that is my humble attempt to turn the basic HTML into a tab based content page - again within 30 mins.
<html>
<head>
<!-- stylesheet, javascript, etc. here -->
</head>
<body>
<h1>My Page</h1>
<h2 class="subheading">The first section</h2>
<div class="content">
<p>Lorem ipsum...</p>
</div>
<h2 class="subheading">The second section</h2>
<div class="content">
<img src="/some_image" alt="Image" title="Image"></img>
<p>Some other text</p>
</div>
<h2 class="subheading">The third section</h2>
<div class="content">
And some more text here
</div>
<div class="footer">
This is at the foot of the page
</div>
</body>
</html>
Ok, so my humble attempt is as follows:
<html>
<head>
<title>Test JS page</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<style type="text/css">
#tabs
{
width:457px;
height:60px;
}
#tab1, #tab2, #tab3
{
width:150px;
border:1px solid #ccc;
}
#tab1
{
float:left;
}
#tab3, #tab2
{
float:right;
}
#tab2_content, #tab3_content
{
display:none;
}
.clear
{
clear:both;
}
#content
{
height:300px;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
$('#tab1_link').click(function (e) {
e.preventDefault();
clearContent();
$('#tab1_content').show();
});
$('#tab2_link').click(function (e) {
e.preventDefault();
clearContent();
$('#tab2_content').show();
});
$('#tab3_link').click(function (e) {
e.preventDefault();
clearContent();
$('#tab3_content').show();
});
});
function clearContent() {
$("div[id*='_content']").each(function() {
$(this).hide();
});
}
</script>
</head>
<body>
<h1>My Page</h1>
<div id="tabs">
<div id="tab1"><a id="tab1_link" class="subheading">The first section</a></div>
<div id="tab2"><a id="tab2_link" class="subheading">The second section</a></div>
<div id="tab3"><a id="tab3_link" class="subheading">The third section</a></div>
</div>
<div class="clear">
</div>
<div id="content">
<div id="tab1_content" class="content">
<p>Lorem ipsum...</p>
</div>
<div id="tab2_content" class="content">
<img src="/some_image" alt="Image" title="Image"></img>
<p>Some other text</p>
</div>
<div id="tab3_content" class="content">
And some more text here
</div>
</div>
<div class="footer">
This is at the foot of the page
</div>
</body>
</html>
So as you can see, not pretty for sure.. the stylesheet was inline as is the script, however this was meant to be a test to show if you knew Javascript/jQuery enough to perform the tasks.. I figured it wasn't great, but not too bad either..
I would be grateful for any feedback on other ways to achieve the desired result.. again it doesn't have to be pretty, just functional.. and of course all within 30 mins..
Thanks!

<div id="tabs">
<ul>
<li>The First Section</li>
<li>The Second Section</li>
<li>The Third Section</li>
</ul>
<div id="tabs-1" class="content">
<p>Lorem ipsum...</p>
</div>
<div id="tabs-2" class="content">
<img src="/some_image" alt="Image" title="Image"></img>
</div>
<div id="tabs-3" class="content">
<p>Some other text</p>
</div>
</div>
<script>
$(function() {
$("#tabs").tabs();
});
</script>
http://jqueryui.com/demos/tabs/

Without knowing something about the company you were taking the test for its hard to say what they were looking for.
In general employers are not looking for perfect code but how you approach the problem. For example you could say that they were looking to see if you would follow their instructions blindly or stick to convention and good practices of adding external style/script references or just clean, standard compliant, concise code.
I am a complete novice so please don't take anything I say too seriously but I would of attempted to create some reusable concise code which would/could be reused and expanded very quickly and easily while being maintenance friendly (Just because its a text doesn't mean that you can forget about these things).
Just doing this very rough and off the top of my head but something like this:
$('#tab-menu').click(function(e) {
e.preventDefault();
clearContent();
$(this).show();
});
If it was for a company that were involved with mobile devices you would probably want to bind the events so you get the same functionality.
Something that I have always done is provided an assumptions document even just if its in notepad. Its always looked upon positively as it shows you are stopping and thinking about what you have to do instead of going gun ho.
Overall I think you did a good job! You have a great attitude and just learn from experiences like these, improve and get better! Today's juniors will be tomorrows experts! if we work hard enough

you don't need jQuery UI for this.
demo http://jsbin.com/atogil/2/edit
HTML
<div class="tabs">
<nav class="tab-btns">
tab btn 1
tab btn 2
tab btn 3
tab btn 4
</nav>
<div class="tab-contents">
<div id="tab1">tab content 1</div>
<div id="tab2">tab content 2</div>
<div id="tab3">tab content 3</div>
<div id="tab4">tab content 4</div>
</div>
</div>
JS
$.fn.myTabs = function(settings){
return this.each(function() {
/*
save cached version of the first elements inside the containers.
by calling the first elements of each container you are not limitng
the plugin user to any specific class or elememt.
*/
var btns = $(settings.nav, this).children(),
tabs = $(settings.tabs, this).children();
/*
we relying on the order of the elements as the conection between
the buttons and the tabs notice that .each() get the index of the btn..
we are useinf it to find the current tab.
*/
btns.each(function(index){
var btn = $(this),
tab = tabs.eq(index);
btn.click(function (e){
/* prevent unnesscry work by checking
if the button clicked is already active */
if(btn.is('.active')) return false;
/* notice that first filter to find the last 'active'
button before we remove the 'active' class otherwise it
remove the class for every button.
unnesscry work prevented again */
btns.filter('.active').removeClass('active');
/* hide previus tab.. */
tabs.filter(':visible').hide();
btn.addClass('active');
tab.show();
return false;
});
});
// emulate click on the first tab button;
btns.first().click();
});
};
and call your script like this;
$(function() {
$('.tabs').myTabs({
// container of navigation inside '.tabs'
nav : '.tab-btns',
// container of contents inside '.tabs'
tabs : '.tab-contents'
});
});

Related

How to expand and collapse multiple divs, without repeating the same code using jQuery

I want to write a code that expands and collapses a div with a paragraph, once you click the header text above it.
<div class="container">
<h3><span class="toggler">Text that toggles</span></h3>
<div class="wrapper">
<p>Random text</p>
</div>
</div>
<div class="container">
<h3><span class="toggler2">Text that toggles</span></h3>
<div class="wrapper2">
<p>Random text</p>
</div>
</div>
I am aware that I could write a function like this which would toggle between display: block and display: none.
I could just repeat the same function for different divs with different classes and it would work, but if I have a lot of them I would end up repeating the same function multiple times and I feel like there has to be a much cleaner way to do this.
$(document).ready(function() {
$(".toggler").on("click", function() {
$(".wrapper").toggleClass("active");
});
});
You don't need write single line of code if you use jquery & bootstrap.
Solution 1:
Add reference bnelow:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
your html:
<div class="container">
<h3><span class="toggler" data-toggle="collapse" data-target="#col1">Text that toggles</span></h3>
<div class="wrapper" id="col1">
<p>Random text</p>
</div>
</div>
<div class="container">
<h3><span class="toggler2" data-toggle="collapse" data-target="#col2">Text that toggles</span></h3>
<div class="wrapper2" id="col2">
<p>Random text</p>
</div>
</div>
Solution 2:
Either you can write simple line code
$(document).ready(function() {
$("h3").on("click", function() {
$(this).next().toggleClass("active");
});
});
we can select header with header Tag. After that, we can add toogleClass to just next element that is "DIV".
so, when click header, toggleClass will be added to next element that is DIV
You dont need to repeat it, give both a single class like "toggle-enabled" then instead of using toggler and toggler2 as two function you can put toggle-enabled as one selector and both will run the same function on click.
If you want to only toggle the one selected then use "this" keyword to get current and hide and show that or slide it whatever you want to do but dont need to repeat the code.
Here is your example code working as expected:
$(document).ready(function() {
$(".toggle-enabled").on("click", function() {
var nextdiv = $(this).parent().siblings("div");
nextdiv.is(":visible")?nextdiv.hide():nextdiv.show();
});
});
.togglethis{color:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h3><span class="toggler toggle-enabled">Text A that toggles</span></h3>
<div class="wrapper togglethis">
<p>Random text</p>
</div>
</div>
<div class="container">
<h3><span class="toggler2 toggle-enabled">Text B that toggles</span></h3>
<div class="wrapper2 togglethis">
<p>I have left your toggler2 class in there and you can add more classes to separate it</p>
</div>
</div>
This code should work for your html:
$(document).ready(function () {
$('[class^="toggler"]').on('click', function () {
$(this).closest('.container').children('[class^="wrapper"]').toggle();
});
});
The code looks for any element on your html whose class name starts with toggle. It then attaches an on-click handler function. That function then looks for the affected element's closest ancestor with class name of container. Then from that ancestor/parent, it selects children with class name starting with wrapper. It then toggles the visibility of those children (or child)
You could give your togglers class names of toggleN (where N is any valid class name character) or simply toggle (same class name for all). Similarity, you could name the classes for your wrappers as wrapperN or simply wrapper.

Toggle div text on click

Here's my jQuery
jQuery(document).ready(function($) {
$("#accordion").find(".accordion-toggle").click(function(){
$(this).next().slideToggle("fast");
$(".accordion-content").not($(this).next()).slideUp("fast");
});
});
Here's my HTML
<div id="accordion">
<header class="accordion-toggle">
<h2>Accordion Title <span id="accordionIcon">▼</span></h2>
</header>
<section class="entry accordion-content">
<p>Accordion Content</p>
</section>
</div>
Whenever a new accordion-toggle is clicked I need the old accordionIcon to change to the opposite arrow, and the new one to change also. I've tried doing it using $(".accordion-content").not($(this).next()).parent().find('#accordionIcon') but it can't find the correct element
Here's a fiddle. Is this what you are looking for?
This is the code I added.
if($(this).find("span#accordionIcon").text()=="▼"){
$(this).find("span#accordionIcon").text("▲");
}
else{
$(this).find("span#accordionIcon").text("▼");
}
Accepted answer will only work with one toggle.
Here is the version (Codepen), that work with multiple:
HTML
<div id="accordion">
<header class="accordion-toggle">
<h2>Accordion Title 1<span>▲</span></h2>
</header>
<section class="entry accordion-content">
<p>Accordion Content</p>
</section>
<header class="accordion-toggle">
<h2>Accordion Title 2<span>▲</span></h2>
</header>
<section class="entry accordion-content">
<p>Accordion Content</p>
</section>
</div>
JS
jQuery(document).ready(function($) {
$("#accordion").find(".accordion-toggle").click(function(){
if ($(this).find('span').text() == '▼') {
$(this).siblings(".accordion-content").slideUp("fast");
$(this).siblings(".accordion-toggle").find('span').text('▼');
$(this).next().slideDown("fast");
$(this).find('span').text('▲');
} else {
$(this).next().slideUp("fast");
$(this).find('span').text('▼');
}
});
});
Or without change your code, you can do like that :
jQuery(document).ready(function($) {
$("#accordion").find(".accordion-toggle").click(function(){
var span = $(this).find('span');
if (span.hasClass('isOpened')) {
span.removeClass('isOpened').html('▲');
} else {
span.addClass('isOpened').html('▼');
}
$(this).next().slideToggle("fast");
$(".accordion-content").not($(this).next()).slideUp("fast");
});
});
JSFIDDLE
If you want to use font-awesome
jQuery(document).ready(function($) {
$("#accordion").find(".accordion-toggle").click(function(){
$(this).next().slideToggle("fast");
if($(".fa").hasClass("fa-arrow-down")){$(".fa").removeClass("fa-arrow-down").addClass("fa-arrow-up");}
else $(".fa").removeClass("fa-arrow-up").addClass("fa-arrow-down");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<div id="accordion">
<header class="accordion-toggle">
<h2>Accordion Title <i class="fa fa-arrow-down"></i></h2>
</header>
<section class="entry accordion-content">
<p>Accordion Content</p>
</section>
</div>
I dropped to use Accordion because a few my customers requested to compare 2 answers, but mostly because of efficiency to use simple HTML5 Details control that I tested for 1000 questions! in a single FAQ page for my new customer's estimate. The issues with the Accordion starts from 140 items, see
https://github.com/twbs/bootstrap/issues/26419
Here is simplest and efficient solution with full control and automatic "Collapse All" button appearance and disappearance. If you would like to see the more advanced implementation on the real website: https://airtempheating.com/faq
<details>
<summary>
Is there any advantage to setting the thermostat fan setting to “On” or “Auto” mode all the time?</summary>
Yes! You will have constant filtering of the air. A second advantage is that the constant airflow will allow an even temperature throughout your home.
However, if your home feels very humid, set the fan to the “Auto” mode.
</details>
<details>
<summary>
How long does a typical furnace or air conditioner last?</summary>
New air conditioning and heating equipment lasts longer than ever! The end of a furnace's or air conditioner’s service life depends on more than just chronological age.
Energy-efficiency issues and the price of any necessary repairs versus the cost of upgrading to a new unit all enter into that determination.
</details> <hr>
<button type="button" id="hdn" class="btn btn-primary" onClick="window.location.reload();">Collapse All</button>
<style>
#hdn{display:none; visibility:visible}
</style>
<script>
$(function() {$('summary').click(function() {if($('#hdn').css("display") == "none"){$('#hdn').show();}});});
</script>

How can I fade a div after the page is loaded using jQuery?

I'm trying to fade the Movies div of this HTML
<div class="row">
<div id=Movies class="col-md-4">
<h2>Movies</h2>
<p>Some text.</p>
</div>
</div>
and I'm using this jquery code
<script>
$(function(){$("#Movies").show("slow");
});
</script>
I've also tried this:
<script>
$(document).ready(function(){$("#Movies").fadeIn(3000);
});
</script>
But it ain't working. The page loads with no fade in. The div just loads like every other element. What's wrong with this?
Add this CSS to make it hidden, then only it will fadeIn slowly when the page loads
#Movies {
display:none;
}
For that to work; #movie has to be hidden, then show when the document is ready as the jQuery function implies.
$(document).ready(function() {
$("#movies").fadeIn(3000);
});
#movies {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div id=movies class="col-md-4">
<h2>Movies</h2>
<p>Some text.</p>
</div>
</div>
First you have to hide the movies div and then fade in. Also i see that your id "Movies" is not withing quotes in the question code snippet. Hope it helps.
Html
<div class="row">
<div id="Movies" class="col-md-4" style="display:none">
<h2>Movies</h2>
<p>Some text.</p>
</div>
</div>
Javascript
$(document).ready(function(){
$("#Movies").fadeIn(3000);
});

Using JQuery hashtags to fade in & fade out content of a certain div

*EDIT: Here's a link to a staging version of the site: http://staging-site.site44.com/ *
I am extremely new to jquery so I apologize if this question is extremely simple. What I'm trying to do on my website is first when the page is loaded have the content in my #topContent div fade in.
But along with this I'd also like my main navigation to use jquery hashtags to switch up the page content displayed in the #topContent div. I've read up a bit on how to do this in jquery and from what I've read I think I need create page sections within my main html doc that are hidden until a certain nav link is selected - then hide the content that is currently showing and show the content associated with the nav link that was just selected, how close am I?
Here's my attempt so far at doing this...
HTML
<nav id="headerNav">
<ul class="navList">
<li class="navItem">Products</li>
<li id="view-about" class="navItem">About</li>
<li class="navItem">Portfolio</li>
<li class="navItem">Contact</li>
</ul>
</nav>
</div>
</div>
<!-- topMain -->
<div id="topContentWrapper">
<div id="topContent">
<div id="#products">
<h2>Test worked! - products </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="#about">
<h2>Test worked! - about </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="#portfolio">
<h2>Test worked! - Portfolio </h2>
<p>this test just worked sooo hard!</p>
</div>
</div>
</div>
JS
// Fade In Effect
$(document).ready(function() {
$("#topContent").css("display", "none");
$("#topContent").fadeIn(2000);
$("a.transition").click(function(event){
event.preventDefault();
linkLocation = this.href;
$("#topContent").fadeOut(1000);
});
function redirectPage() {
window.location = linkLocation;
}
$("#view-about").click(function(event){
$("#products").fadeOut(1000);
$("#portfolio").fadeOut(1000);
$("#about").fadeIn(1000);
});
});
Ok, this code should work:
$(function(){
$last = null;
$(".navList li a").click(function(){
if ($last != null) $last.fadeOut(1000);
$last = $($(this).attr("href"));
$($(this).attr("href")).fadeIn(2000);
});
});
However, you will need to change your topContent to this:
<div id="topContent">
<div id="products" style="display: none;">
<h2>Test worked! - products </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="about" style="display: none;">
<h2>Test worked! - about </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="portfolio" style="display: none;">
<h2>Test worked! - Portfolio </h2>
<p>this test just worked sooo hard!</p>
</div>
</div>
Reasons:
Firstly, you need your ids to be like this: id="about" and not this: id="#about".
The id specified doesn't need a # in front of it. (Same as how class doesn't need a . when setting a tag with it)
The jQuery code I tested locally, so it should work.
Note:
You may want to automatically have some different content automatically displayed, because right now as it loads it is blank until you click one of the links.
Hope this helped!
Edit:
I suggest you change the code to this:
ids = [ "products", "about", "portfolio" ];
links = [ "Products", "About", "Portfolio" ];
$(function(){
$last = null;
$(".navList li a").click(function(){
New = "#" + ids[links.indexOf($(this).text())];
if ($last != null) $last.fadeOut(1000);
$last = $(New);
$(New).fadeIn(2000);
});
});
Because it will keep all the content constantly in the same place. For this to work, you'll need to change two more sections of your code:
<ul class="navList">
<li class="navItem">Products</li>
<li id="view-about" class="navItem">About</li>
<li class="navItem">Portfolio</li>
<li class="navItem">Contact</li>
</ul>
And:
<div id="topContent">
<div id="products" style="display: none; position: absolute">
<h2>Test worked! - products </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="about" style="display: none; position: absolute">
<h2>Test worked! - about </h2>
<p>this test just worked sooo hard!</p>
</div>
<div id="portfolio" style="display: none; position: absolute">
<h2>Test worked! - Portfolio </h2>
<p>this test just worked sooo hard!</p>
</div>
</div>
That last part was just my suggestion, but do whatever you need to.
Instead of doing this in your a.transition handler:
$("#topContent").fadeOut(1000);
do:
$("#topContent").children().fadeOut(1000);
The issue is that you're actually fading out the higher level item thus the children are no longer visible even if you fade them in.

jQuery - how to run one event while delaying another?

I'm a bit of a jQuery newbie, so forgive me if this seems a bit simple! I am setting up a sliding header system, which works very much like an accordion menu, however the links to open and close the elements are in a different part of the HTML, so all the accordion tutorials I found didn't work.
I have got this so far: HTML:
<div class="drawer" id="drawer_about"></div>
<div class="drawer" id="drawer_contact"></div>
<div class="drawer" id="drawer_hire"></div>
<div class="drawer" id="drawer_social"></div>
...
<ul class="navigation">
<li><span>About Me</span></li>
<li><span>Get In Touch</span></li>
<li><span>Hire Me</span></li>
<li><span>Social Networks</span></li>
</ul>
And jQuery:
$(document).ready(function(){
$("#drawer_about").hide();
$("#drawer_contact").hide();
$("#drawer_hire").hide();
$("#drawer_social").hide();
lastBlock = ("#drawer_hire");
$('.show_hide_about').click(function(){
$("#drawer_about").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_about");
});
$('.show_hide_contact').click(function(){
$("#drawer_contact").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_contact");
});
$('.show_hide_hire').click(function(){
$("#drawer_hire").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_hire");
});
$('.show_hide_social').click(function(){
$("#drawer_social").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_social");
});
});
Am I going OTT here? is there a simpler way to do this?
The main problem I'm having is it all works, however if the ABOUT ME panel is open and the user clicks the HIRE ME link, I get a weird effect. What I'd want in this situation is for the ABOUT ME panel to fold up, then the HIRE ME panel to fold down.
Hope that makes sense, thanks folks,
Alex
I'd set up the links like this: asdf
Then you all you need is:
$('.show').click(function(ev) {
var $visibleDrawer = $('.drawer:visible').eq(0); // make sure to get only one (or 0) drawer
// set currentSection to the drawer's id or empty if no drawer was found
var currentSection = $visibleDrawer.length?$visibleDrawer.attr('id').replace('drawer_',''):'';
$('.drawer').slideUp(700);
$('a.show').removeClass('active'); // reset all link classes
(function(clickedSection, $link){ //<-- pass the active link to have access to it inside the closure
if(currentSection != clickedSection){
$link.addClass('active'); // set active class on clicked link
setTimeout(function() {
$('#drawer_'+clickedSection).slideDown(700);
}, ($visibleDrawer.length?700:0)); // set the timeout to 0 if no drawer visible
}
})($(this).data('section'),$(this)); //<--
ev.preventDefault();
});
using .animate() you can parse a callback function which will be executed at the end of the animation, or you can use .queue() to keep track of the point of execution against and element. Some pseudo code of the first way
$('#foo').animate(function() {
// do stuff with foo
}, duration, easing, function() {
$('#bar').animate(function() {
// do stuff with bar
})
});
Here is a link to how it works on jsFiddle (Note that you should choose framework to be jQuery)
I think this would work with you :
$(document).ready(
function(){
$('.header').click(function(){
//To hide all other contents
$('.content').slideUp('slow');
var num=$(this).attr('id').split('_')[1];
//And show this one ..
$('#content_'+num).slideDown('slow');
});
}
);
HTML should look like this :
<div class="header" id="title_111">Category 1</div>
<div class="content" id="content_111">
</div>
<div class="header" id="title_112">Category 2</div>
<div class="content" id="content_112">
</div>
<div class="header" id="title_113">Category 3</div>
<div class="content" id="content_113">
</div>
<div class="header" id="title_114">Category 4</div>
<div class="content" id="content_114">
</div>
<div class="header" id="title_115">Category 5</div>
<div class="content" id="content_115">
</div>
<div class="header" id="title_116">Category 6</div>
<div class="content" id="content_116">
</div>

Categories

Resources