Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions projects/landing-page/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,25 @@

## Table of Contents

* [Instructions](#instructions)
- [Landing Page Project](#landing-page-project)
- [Table of Contents](#table-of-contents)
- [Instructions](#instructions)
- [Usage](#usage)
- [Description](#description)


## Instructions

The starter project has some HTML and CSS styling to display a static version of the Landing Page project. You'll need to convert this project from a static project to an interactive one. This will require modifying the HTML and CSS files, but primarily the JavaScript file.
Add some sections in the html `index.html` file and assign each of them an `id` and a `data-nav` attribute
then you can start the app by opening `index.html` in your preferable browser.
Hit: browser should support javascript and be relatively modern, examples `chrome` or `Edge`

## Usage

This Project is to be used as a landing page where the user adds sections and the app will calculate
how many are added and build a navbar based on the sections count

To get started, open `js/app.js` and start building out the app's functionality
## Description

For specific, detailed instructions, look at the project instructions in the Udacity Classroom.
A cool landing page with dynamic navbar based on sections count which could be extended by adding more
cool features and maybe new pages and link them to some kind of dropdowns or links
27 changes: 25 additions & 2 deletions projects/landing-page/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,19 @@ section {
.navbar__menu ul {
padding-left: 0;
margin: 0;
text-align: right;
text-align: left;
}

.navbar__menu li {
display: inline-block;
}

.navbar__menu .menu__link {
display: block;
padding: 1em;
font-weight: bold;
text-decoration: none;
color: #000;
cursor: pointer;
}

.navbar__menu .menu__link:hover {
Expand All @@ -88,6 +88,29 @@ section {
transition: ease 0.3s all;
}

.active {
background: #333;
color: #fff;
transition: ease 0.3s all;
}

.active-default {
background: #333;
color: #fff;
transition: ease 0.3s all;
}

.scroll-top {
width: 80px;
height: 40px;
border: none;
cursor: pointer;
display: none;
position: fixed;
right: 50px;
bottom: 50px;
}

/* Header Styles */
.page__header {
background: #fff;
Expand Down
12 changes: 10 additions & 2 deletions projects/landing-page/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<ul id="navbar__list"></ul>
</nav>
</header>
<main>
<main id="main">
<header class="main__hero">
<h1>Landing Page </h1>
</header>
Expand Down Expand Up @@ -47,13 +47,21 @@ <h2>Section 2</h2>
<h2>Section 3</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi fermentum metus faucibus lectus pharetra dapibus. Suspendisse potenti. Aenean aliquam elementum mi, ac euismod augue. Donec eget lacinia ex. Phasellus imperdiet porta orci eget mollis. Sed convallis sollicitudin mauris ac tincidunt. Donec bibendum, nulla eget bibendum consectetur, sem nisi aliquam leo, ut pulvinar quam nunc eu augue. Pellentesque maximus imperdiet elit a pharetra. Duis lectus mi, aliquam in mi quis, aliquam porttitor lacus. Morbi a tincidunt felis. Sed leo nunc, pharetra et elementum non, faucibus vitae elit. Integer nec libero venenatis libero ultricies molestie semper in tellus. Sed congue et odio sed euismod.</p>

<p>Aliquam a convallis justo. Vivamus venenatis, erat eget pulvinar gravida, ipsum lacus aliquet velit, vel luctus diam ipsum a diam. Cras eu tincidunt arcu, vitae rhoncus purus. Vestibulum fermentum consectetur porttitor. Suspendisse imperdiet porttitor tortor, eget elementum tortor mollis non.</p>
</div>
</section>
<section id="section4" data-nav="Section 4">
<div class="landing__container">
<h2>Section 4</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi fermentum metus faucibus lectus pharetra dapibus. Suspendisse potenti. Aenean aliquam elementum mi, ac euismod augue. Donec eget lacinia ex. Phasellus imperdiet porta orci eget mollis. Sed convallis sollicitudin mauris ac tincidunt. Donec bibendum, nulla eget bibendum consectetur, sem nisi aliquam leo, ut pulvinar quam nunc eu augue. Pellentesque maximus imperdiet elit a pharetra. Duis lectus mi, aliquam in mi quis, aliquam porttitor lacus. Morbi a tincidunt felis. Sed leo nunc, pharetra et elementum non, faucibus vitae elit. Integer nec libero venenatis libero ultricies molestie semper in tellus. Sed congue et odio sed euismod.</p>

<p>Aliquam a convallis justo. Vivamus venenatis, erat eget pulvinar gravida, ipsum lacus aliquet velit, vel luctus diam ipsum a diam. Cras eu tincidunt arcu, vitae rhoncus purus. Vestibulum fermentum consectetur porttitor. Suspendisse imperdiet porttitor tortor, eget elementum tortor mollis non.</p>
</div>
</section>
</main>
<footer class="page__footer">
<p>&copy Udacity</p>
</footer>

<script src="./js/app.js"></script>
</body>
</html>
116 changes: 113 additions & 3 deletions projects/landing-page/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,125 @@
* Define Global Variables
*
*/

const sectionsInThePage = [...document.querySelectorAll('[data-nav]')];
const sectionsTitles = sectionsInThePage.map((section) => section.dataset.nav);
const navBarContainer = document.querySelector('#navbar__list');

/**
* End Global Variables
* Start Helper Functions
*
*/


const navBarLinksCreator = (linkTitlesArray=[]) => {
/** map through the existing sections and create li for each section */
const linksToBeAppended = linkTitlesArray.map((link, index) => {
// get the section number to use it as a part of an id
const sectionNumber = link.split(' ')[1];
// create li
const listItem = document.createElement('li');
// set the innerHTML of the li to the relevant section title
listItem.innerHTML = link;
// if first li set an extra class to highlight it by default
index == 0 ?
listItem.setAttribute('class','menu__link active-default') :
listItem.setAttribute('class','menu__link');
listItem.setAttribute('id',`link${sectionNumber}`);
// add event listener to handle the click events
listItem.addEventListener('click', () => scrollToHandler(`section${sectionNumber}`));
// return the new created li element
return listItem;
});

// call `navBarLinksAppendHandler` to append the li elements list
navBarLinksAppendHandler(linksToBeAppended);
}

const scrollTopBtnCreator = () => {
// create a btn and append it to the main
const btn = document.createElement('button');
btn.innerHTML = 'Scroll Top';
btn.setAttribute('id','scroll-top');
btn.setAttribute('class','scroll-top');
btn.addEventListener('click', () => scrollTopHandler());
document.querySelector('#main').appendChild(btn);
}

const showScrollTopBtn = () => {
// if the user scroll more than 500px y axis then show the scroll-top btn
const btn = document.querySelector('#scroll-top');
window.scrollY > 500 ? btn.style.display = 'block' : btn.style.display = 'none';
}

const scrollToHandler = (elementID) => {
// handles the click events of the nav bar li elements and scroll to the correct relevant position
const element = document.querySelector(`#${elementID}`);
const positionToScrollTo = element.getBoundingClientRect().top + window.scrollY;
window.scroll({
top: positionToScrollTo,
// scroll smoothly
behavior: 'smooth'
});
}

const scrollTopHandler = () => {
// scroll to top when scroll-top btn is clicked
window.scroll({
top: 0,
behavior: 'smooth'
});
}

const navBarLinksAppendHandler = (linkElementsArray=[]) => {
// append the li elements list inside `navBarContainer`
navBarContainer.append(...linkElementsArray);
}

const isInViewport = (elements) => {
// loop throw all existing sections to see which is in viewport
const elementsVisibleState = elements.map((el) => {
// convert section height to number
const elementHeight = parseInt(window.getComputedStyle(el).height);
/** calculate the visibility of the section based on its top and bottom position relative to viewport*/
const elementVisibleState = el.getBoundingClientRect().top < 400 &&
el.getBoundingClientRect().top > - (elementHeight - 400) &&
el.getBoundingClientRect().bottom <= elementHeight + 400;

/** get the relevant nav bar link */
const relevantLink = document.querySelector(`#link${el.id.slice(-1)}`);
/** add class when in viewport and remove it when out of it */
elementVisibleState ?
(
// if the section is in viewport set to active
el.classList.add('your-active-class'),
relevantLink.classList.add('active')
) :
(
// if it is not in viewport remove the extra classes
el.classList.remove('your-active-class'),
setTimeout(() => relevantLink.classList.remove('active'),0)
);

return elementVisibleState;
});

// if no section is in viewport set the first to be active by default
!elementsVisibleState.some((state) => state) ?
(elements[0].classList.add('your-active-class'), document.querySelector(`#link${elements[0].id.slice(-1)}`).classList.add('active-default')) :
document.querySelector(`#link${elements[0].id.slice(-1)}`).classList.remove('active-default');
}

document.addEventListener('scroll', () => {
// listen on scroll to see which section is in viewport
isInViewport(sectionsInThePage);
// listen if the user scrolls on y axis to display scroll-top btn
showScrollTopBtn();
}, {passive: true});

document.addEventListener('DOMContentLoaded', () => {
// activate and call the creators functions on document ready
navBarLinksCreator(sectionsTitles);
scrollTopBtnCreator();
});

/**
* End Helper Functions
Expand Down