├── LICENSE ├── README.md ├── btt-button ├── index.html └── style.css ├── content-slider ├── arrow-left-out.svg ├── arrow-left-over.svg ├── arrow-right-out.svg ├── arrow-right-over.svg ├── arrow-right.svg ├── index.html ├── script.js └── style.css ├── image-lightbox ├── images │ ├── image-1.jpeg │ ├── image-2.jpeg │ ├── image-3.jpeg │ ├── image-4.jpeg │ ├── image-5.jpeg │ ├── image-6.jpeg │ ├── image-thumb-1.jpeg │ ├── image-thumb-2.jpeg │ ├── image-thumb-3.jpeg │ ├── image-thumb-4.jpeg │ ├── image-thumb-5.jpeg │ ├── image-thumb-6.jpeg │ └── loading.gif ├── index.html ├── script.js └── style.css ├── tabs ├── index.html ├── script.js └── style.css └── vanilla-autocomplete ├── index.html ├── script.js └── style.css /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2016, Tuts+ 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Envato Tuts+ Course: JavaScript for Web Designers 2 | #### Instructor: [Adi Purdila](https://tutsplus.com/authors/adi-purdila) 3 | 4 | In this course you’re going to learn the basics of JavaScript and see some examples that are more geared towards what a web designer might face on a daily basis. 5 | 6 | #### Source Files Description: 7 | 8 | The source files contain the examples presented in the course videos. Use them to double-check your code or work alongside the instructor. 9 | 10 | **Available on [Envato Tuts+](https://tutsplus.com/courses) from December, 2016** 11 | -------------------------------------------------------------------------------- /btt-button/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaScript for Web Designers - Back to top button demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Moby Dick

13 |

by Herman Melville

14 |
15 | 16 |
17 |

Presently a breeze sprang up; Stubb feigned to cast off from the whale; hoisting his boats, the Frenchman soon increased his distance, while the Pequod slid in between him and Stubb's whale. Whereupon Stubb quickly pulled to the floating body, and hailing the Pequod to give notice of his intentions, at once proceeded to reap the fruit of his unrighteous cunning. Seizing his sharp boat-spade, he commenced an excavation in the body, a little behind the side fin. You would almost have thought he was digging a cellar there in the sea; and when at length his spade struck against the gaunt ribs, it was like turning up old Roman tiles and pottery buried in fat English loam. His boat's crew were all in high excitement, eagerly helping their chief, and looking as anxious as gold-hunters.

18 | 19 |

And all the time numberless fowls were diving, and ducking, and screaming, and yelling, and fighting around them. Stubb was beginning to look disappointed, especially as the horrible nosegay increased, when suddenly from out the very heart of this plague, there stole a faint stream of perfume, which flowed through the tide of bad smells without being absorbed by it, as one river will flow into and then along with another, without at all blending with it for a time.

20 | 21 |

"I have it, I have it," cried Stubb, with delight, striking something in the subterranean regions, "a purse! a purse!"

22 | 23 |

Dropping his spade, he thrust both hands in, and drew out handfuls of something that looked like ripe Windsor soap, or rich mottled old cheese; very unctuous and savory withal. You might easily dent it with your thumb; it is of a hue between yellow and ash colour. And this, good friends, is ambergris, worth a gold guinea an ounce to any druggist. Some six handfuls were obtained; but more was unavoidably lost in the sea, and still more, perhaps, might have been secured were it not for impatient Ahab's loud command to Stubb to desist, and come on board, else the ship would bid them good bye.

24 | 25 |

Now this ambergris is a very curious substance, and so important as an article of commerce, that in 1791 a certain Nantucket-born Captain Coffin was examined at the bar of the English House of Commons on that subject. For at that time, and indeed until a comparatively late day, the precise origin of ambergris remained, like amber itself, a problem to the learned. Though the word ambergris is but the French compound for grey amber, yet the two substances are quite distinct. For amber, though at times found on the sea-coast, is also dug up in some far inland soils, whereas ambergris is never found except upon the sea. Besides, amber is a hard, transparent, brittle, odorless substance, used for mouth-pieces to pipes, for beads and ornaments; but ambergris is soft, waxy, and so highly fragrant and spicy, that it is largely used in perfumery, in pastiles, precious candles, hair-powders, and pomatum. The Turks use it in cooking, and also carry it to Mecca, for the same purpose that frankincense is carried to St. Peter's in Rome. Some wine merchants drop a few grains into claret, to flavor it.

26 | 27 |

Who would think, then, that such fine ladies and gentlemen should regale themselves with an essence found in the inglorious bowels of a sick whale! Yet so it is. By some, ambergris is supposed to be the cause, and by others the effect, of the dyspepsia in the whale. How to cure such a dyspepsia it were hard to say, unless by administering three or four boat loads of Brandreth's pills, and then running out of harm's way, as laborers do in blasting rocks.

28 |
29 | 30 | 34 | 35 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /btt-button/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | -webkit-font-smoothing: antialised; 4 | } 5 | 6 | body { 7 | background-color: #313944; 8 | padding: 5em 20em; 9 | } 10 | 11 | h1 { 12 | color: #fff; 13 | font-family: 'Cormorant Infant'; 14 | font-size: 72px; 15 | font-weight: 700; 16 | line-height: 72px; 17 | letter-spacing: -1px; 18 | margin-bottom: 48px; 19 | text-align: center; 20 | } 21 | 22 | h1:after { 23 | color: #1fcfcb; 24 | display: block; 25 | content: '. . .'; 26 | font-size: 26px; 27 | line-height: 24px; 28 | height: 24px; 29 | margin: 48px auto; 30 | } 31 | 32 | h2 { 33 | color: #fff; 34 | font-family: 'Cormorant Infant'; 35 | font-size: 54px; 36 | font-weight: 700; 37 | line-height: 72px; 38 | letter-spacing: -1px; 39 | margin-bottom: 48px; 40 | text-align: center; 41 | } 42 | 43 | p { 44 | color: #bbc8d8; 45 | font-family: 'Lato'; 46 | font-size: 22px; 47 | font-weight: 500; 48 | line-height: 36px; 49 | margin-bottom: 36px; 50 | text-align: center; 51 | } 52 | 53 | a { 54 | color: #1fcfcb; 55 | font-family: 'Lato'; 56 | } 57 | 58 | a:hover { 59 | color: #fff; 60 | } 61 | 62 | #back-to-top { 63 | position: fixed; 64 | bottom: 3em; 65 | right: 3em; 66 | background-color: rgba(255, 255, 255, .9); 67 | color: #313943; 68 | border: none; 69 | border-radius: 5px; 70 | padding: 1em; 71 | text-transform: uppercase; 72 | cursor: pointer; 73 | font-weight: 700; 74 | box-shadow: 0 0 2em 0 rgba(0, 0, 0, .25); 75 | transition: all .3s ease-in-out; 76 | display: inline-block; 77 | opacity: 0; 78 | text-decoration: none; 79 | font-size: .75em; 80 | } 81 | 82 | #back-to-top:hover { 83 | background-color: #fff; 84 | padding: 1em 3em; 85 | } 86 | 87 | #back-to-top.visible { 88 | opacity: 1; 89 | } 90 | -------------------------------------------------------------------------------- /content-slider/arrow-left-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 2 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /content-slider/arrow-left-over.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 2 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /content-slider/arrow-right-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 2 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /content-slider/arrow-right-over.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 2 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /content-slider/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /content-slider/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaScript for Web Designers - Simple content slider demo 6 | 7 | 8 | 9 | 10 |
11 | 55 | 56 | 57 | 58 |
59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /content-slider/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | * - Declare variables 3 | * - Get the slide width 4 | * - Set the proper left value for each slide 5 | * - Calculate tallest slide 6 | * - Add the animated class to each slide 7 | * - Add an event listener for next button 8 | * - Add an event listener for previous button 9 | * - Add an event listener for window resize 10 | * - Declare a function that calculates the tallest slide 11 | * - Declare a function that will change the slide position 12 | */ 13 | var slides = document.getElementsByClassName('slide'), 14 | slider = document.getElementById('slider'), 15 | cursor = 0, 16 | slideWidth = 0, 17 | topHeight = 0, 18 | slideCount = slides.length; 19 | 20 | if (slideCount > 0) { 21 | // Get the slide width 22 | slideWidth = slides[0].offsetWidth; 23 | 24 | // Set the proper left value for each slide 25 | for (var i = 0; i < slideCount; i++) { 26 | slides[i].style.left = slideWidth * i + "px"; 27 | } 28 | 29 | // Calculate tallest slide 30 | calculateTallestSlide(); 31 | 32 | // Add the animated class to each slide 33 | for (i = 0; i < slideCount; i++) { 34 | slides[i].classList.add('animated'); 35 | } 36 | 37 | // Add an event listener for next button 38 | document.getElementById('next').addEventListener('click', function(event) { 39 | event.preventDefault(); 40 | 41 | if (cursor < slideCount - 1) { 42 | moveSlides('forward'); 43 | cursor++; 44 | } 45 | }); 46 | 47 | // Add an event listener for previous button 48 | document.getElementById('prev').addEventListener('click', function(event) { 49 | event.preventDefault(); 50 | 51 | if (cursor > 0) { 52 | moveSlides('backward'); 53 | cursor--; 54 | } 55 | }); 56 | 57 | // Add event listener for window resize 58 | window.addEventListener('resize', function() { 59 | // Get the new slide width 60 | slideWidth = slides[0].offsetWidth; 61 | 62 | // Recalculate the left position of the slides 63 | for (i = 0; i < slides.length; i++) { 64 | if (i <= cursor) { 65 | slides[i].style.left = "-" + slideWidth * (cursor - i) + "px"; 66 | } else if (i > cursor) { 67 | slides[i].style.left = slideWidth * (i - cursor) + "px"; 68 | } 69 | } 70 | 71 | // Recalculate the height of the tallest slide 72 | calculateTallestSlide(); 73 | }); 74 | } 75 | 76 | // Declare a function that calculates the tallest slide 77 | function calculateTallestSlide() { 78 | for (var i = 0; i < slideCount; i++) { 79 | if (slides[i].offsetHeight > topHeight) { 80 | topHeight = slides[i].offsetHeight; 81 | } 82 | } 83 | 84 | slider.style.height = topHeight + "px"; 85 | } 86 | 87 | // Declare a function that will change the slide position 88 | function moveSlides(direction) { 89 | for (var j = 0; j < slides.length; j++) { 90 | if (direction == "backward") { 91 | slides[j].style.left = +slides[j].style.left.replace(/[^-\d\.]/g, '') + slideWidth + "px"; 92 | } else if (direction == "forward") { 93 | slides[j].style.left = +slides[j].style.left.replace(/[^-\d\.]/g, '') - slideWidth + "px"; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /content-slider/style.css: -------------------------------------------------------------------------------- 1 | /* General styles */ 2 | * { 3 | box-sizing: border-box; 4 | -webkit-font-smoothing: antialised; 5 | } 6 | 7 | body { 8 | margin-top: 5em; 9 | font: 20px/1.5 "Helvetica", Arial, sans-serif; 10 | } 11 | 12 | .container { 13 | position: relative; 14 | } 15 | 16 | .slider-container { 17 | position: relative; 18 | overflow: hidden; 19 | width: 80%; 20 | left: 10%; 21 | } 22 | 23 | .slide { 24 | position: absolute; 25 | width: 100%; 26 | top: 50%; 27 | left: 0; 28 | transform: translateY(-50%); 29 | text-align: center; 30 | } 31 | 32 | .slide.animated { 33 | -webkit-transition: left .3s ease-in; 34 | transition: left .3s ease-in; 35 | } 36 | 37 | blockquote { 38 | color: #636363; 39 | font-weight: 300; 40 | font-style: italic; 41 | margin-bottom: 1.5em; 42 | } 43 | 44 | cite { 45 | font-size: .75em; 46 | font-weight: 700; 47 | font-style: normal; 48 | } 49 | 50 | /* Utility */ 51 | .simple-list { 52 | list-style-type: none; 53 | margin: 0; 54 | padding: 0; 55 | } 56 | 57 | /* Nav */ 58 | #prev, 59 | #next { 60 | position: absolute; 61 | top: 50%; 62 | transform: translateY(-50%); 63 | z-index: 999999; 64 | display: inline-block; 65 | height: 5em; 66 | width: 5em; 67 | border-radius: 50%; 68 | background-position: center center; 69 | background-repeat: no-repeat; 70 | -webkit-transition: all .3s ease-in; 71 | transition: all .3s ease-in; 72 | } 73 | 74 | #prev { background-image: url('arrow-left-out.svg'); } 75 | 76 | #prev:hover { background-image: url('arrow-left-over.svg'); } 77 | 78 | #next { 79 | right: 0; 80 | background-image: url('arrow-right-out.svg'); 81 | } 82 | 83 | #next:hover { background-image: url('arrow-right-over.svg'); } 84 | -------------------------------------------------------------------------------- /image-lightbox/images/image-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-1.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-2.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-3.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-4.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-5.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-6.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-thumb-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-thumb-1.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-thumb-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-thumb-2.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-thumb-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-thumb-3.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-thumb-4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-thumb-4.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-thumb-5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-thumb-5.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/image-thumb-6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/image-thumb-6.jpeg -------------------------------------------------------------------------------- /image-lightbox/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutsplus/javascript-for-web-designers/551de9dc70d050a0f3dbcb4e6e206a8762042bcc/image-lightbox/images/loading.gif -------------------------------------------------------------------------------- /image-lightbox/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaScript for Web Designers - Simple image lightbox demo 6 | 7 | 8 | 9 | 10 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /image-lightbox/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | * - Add an event listener for document click 3 | * - Define a function that filters the unwanted click events on the document 4 | */ 5 | 6 | // Add an event listener for document click 7 | document.addEventListener('click', lightboxClick); 8 | 9 | // Define a function that filters the unwanted click events on the document 10 | function lightboxClick(event) { 11 | var elem = event.target, 12 | elemID = elem.getAttribute('id'), 13 | lightboxImg = document.getElementById('lightbox-image'), 14 | lightbox = document.getElementById("lightbox-overlay"), 15 | newImg = new Image(); 16 | 17 | // If we click an element with the attribute "data-lightbox", show the lightbox 18 | if (elem.hasAttribute('data-lightbox')) { 19 | event.preventDefault(); 20 | 21 | newImg.onload = function() { 22 | lightboxImg.src = this.src; 23 | } 24 | 25 | lightboxImg.src = ''; 26 | newImg.src = elem.getAttribute('data-lightbox'); 27 | lightbox.classList.add('visible'); 28 | } 29 | 30 | // If we click any of these 2 elements, close the lightbox 31 | if (elemID == 'lightbox-image' || elemID == 'lightbox-overlay') { 32 | event.preventDefault(); 33 | 34 | lightbox.classList.remove('visible'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /image-lightbox/style.css: -------------------------------------------------------------------------------- 1 | /* General styles */ 2 | * { 3 | box-sizing: border-box; 4 | -webkit-font-smoothing: antialised; 5 | } 6 | 7 | img { 8 | max-width: 100%; 9 | height: auto; 10 | } 11 | 12 | .gallery { 13 | margin: 0; 14 | padding: 0; 15 | list-style: none; 16 | } 17 | 18 | .gallery li { 19 | float: left; 20 | width: 48%; 21 | margin: 1%; 22 | } 23 | 24 | .gallery li img { 25 | transition: opacity .3s ease-in-out; 26 | } 27 | 28 | .gallery li img:hover { 29 | opacity: .75; 30 | } 31 | 32 | #lightbox-overlay { 33 | opacity: 0; 34 | pointer-events: none; 35 | position: fixed; 36 | width: 100%; 37 | height: 100%; 38 | top: 0; 39 | left: 0; 40 | background-color: rgba(29, 31, 33, .95); 41 | transition: opacity .3s ease-in; 42 | } 43 | 44 | #lightbox-overlay.visible { 45 | opacity: 1; 46 | pointer-events: auto; 47 | } 48 | 49 | #lightbox-image { 50 | max-height: 90%; 51 | position: absolute; 52 | left: 50%; 53 | top: 50%; 54 | transform: translate(-50%, -50%); 55 | max-width: 90%; 56 | background: transparent url("images/loading.gif") 50% 50% no-repeat; 57 | text-indent: -99999px; 58 | } 59 | -------------------------------------------------------------------------------- /tabs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaScript for Web Designers - Simple tabs demo 6 | 7 | 8 | 9 | 10 |
11 | 16 | 33 |
34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tabs/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | * - Add an event listener for document click 3 | * - Define a function that filters the unwanted click events on the document 4 | */ 5 | 6 | // Add an event listener for document click 7 | document.addEventListener('click', tabClick); 8 | 9 | // Define a function that filters the unwanted click events on the document 10 | function tabClick(event) { 11 | var elem = event.target, 12 | elemHREF = elem.getAttribute('href'), 13 | tabs = document.querySelectorAll('.tabs li a'), 14 | tabContents = document.querySelectorAll('.tab-contents li'); 15 | 16 | // If we click an element whos href contains "tab-", proceed 17 | if (elemHREF != null && elemHREF.indexOf('tab-') != -1) { 18 | event.preventDefault(); 19 | 20 | // If we didn't click an active item, switch tabs 21 | if (elem.className.indexOf('active') == -1) { 22 | // Remove the active class from the tabs and the visible class from the tab contents 23 | for (var i = 0; i < tabs.length; i++) { 24 | tabs[i].classList.remove('active'); 25 | tabContents[i].classList.remove('visible'); 26 | } 27 | 28 | // Add the active class to the clicked element and the visible class to the corresponding tab 29 | elem.classList.add('active'); 30 | document.getElementById(elemHREF).classList.add('visible'); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tabs/style.css: -------------------------------------------------------------------------------- 1 | /* General styles */ 2 | * { 3 | box-sizing: border-box; 4 | -webkit-font-smoothing: antialised; 5 | } 6 | 7 | body { 8 | margin-top: 5em; 9 | font: 300 20px/1.5 "Helvetica", Arial, sans-serif; 10 | } 11 | 12 | .container { 13 | width: 75%; 14 | margin: 0 auto; 15 | } 16 | 17 | /* Tab styles */ 18 | .tabs, 19 | .tab-contents { 20 | list-style: none; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | .tabs { 26 | text-align: center; 27 | font-size: 0; 28 | } 29 | 30 | .tabs li { 31 | display: inline; 32 | } 33 | 34 | .tabs li a { 35 | font-weight: 700; 36 | font-size: 16px; 37 | text-decoration: none; 38 | color: #8D8D8D; 39 | border: 1px solid #DCDADA; 40 | background-color: #F5F5F5; 41 | height: 5em; 42 | line-height: 5em; 43 | display: inline-block; 44 | padding: 0 3em; 45 | transition: all .3s ease; 46 | } 47 | 48 | .tabs li a.active { 49 | background-color: #FFFFFF; 50 | color: #424242; 51 | cursor: default; 52 | } 53 | 54 | .tabs li a:hover:not(.active) { 55 | background-color: rgba(245, 245, 245, .25); 56 | color: #424242; 57 | } 58 | 59 | 60 | .tabs li:first-child a { 61 | border-radius: 5px 0 0 5px; 62 | } 63 | 64 | .tabs li:last-child a { 65 | border-radius: 0 5px 5px 0; 66 | } 67 | 68 | .tabs li:not(:first-child) { 69 | margin-left: -1px; 70 | } 71 | 72 | .tab-contents { 73 | width: 100%; 74 | position: relative; 75 | } 76 | 77 | .tab-contents li { 78 | padding: 2em; 79 | position: absolute; 80 | top: 0; 81 | left: 0; 82 | opacity: 0; 83 | transition: opacity .3s ease; 84 | pointer-events: none; 85 | } 86 | 87 | .tab-contents li.visible { 88 | opacity: 1; 89 | pointer-events: auto; 90 | } 91 | -------------------------------------------------------------------------------- /vanilla-autocomplete/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaScript for Web Designers - Textbox autocomplete demo 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /vanilla-autocomplete/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | * - Define variables 3 | * - Focus the input 4 | * - Add event listener for the input keyup and keydown 5 | * - Define a function for checking if the input value matches any of the country names 6 | * - Define a function for displaying autocomplete results 7 | * - Define a function for moving the cursor in the results list 8 | * - Define a function for toggling the results list 9 | */ 10 | 11 | var targetInput = document.getElementById('country'), 12 | results = document.getElementById('autocomplete-results'), 13 | countryList = ['Albania', 'Colombia', 'Cuba', 'El Salvador', 'Jordan', 'Kenya', 'Nepal', 'Romania', 'Sri Lanka', 'Wales'], 14 | matches = [], 15 | resultsCursor = 0; 16 | 17 | // Focus the input 18 | targetInput.focus(); 19 | 20 | // Add event listener for the input keydown 21 | targetInput.addEventListener('keydown', function(event) { 22 | if (event.keyCode == '13') { 23 | event.preventDefault(); 24 | } 25 | }); 26 | 27 | // Add event listener for the input keyup 28 | targetInput.addEventListener('keyup', function(event) { 29 | /* 30 | * Key codes 31 | * 32 | * Enter: 13 33 | * Arrow up: 38 34 | * Arrow down: 40 35 | */ 36 | 37 | results.innerHTML = ''; 38 | toggleResults('hide'); 39 | 40 | if (this.value.length > 0) { 41 | matches = getMatches(this.value); 42 | 43 | if (matches.length > 0) { 44 | displayMatches(matches); 45 | } 46 | } 47 | 48 | if (results.classList.contains('visible')) { 49 | switch(event.keyCode) { 50 | case 13: 51 | targetInput.value = results.children[resultsCursor].innerHTML; 52 | toggleResults('hide'); 53 | resultsCursor = 0; 54 | 55 | break; 56 | case 38: 57 | if (resultsCursor > 0) { 58 | resultsCursor--; 59 | 60 | moveCursor(resultsCursor); 61 | } 62 | 63 | break; 64 | case 40: 65 | if (resultsCursor < (matches.length - 1)) { 66 | resultsCursor++; 67 | 68 | moveCursor(resultsCursor); 69 | } 70 | 71 | break; 72 | } 73 | } 74 | }); 75 | 76 | // Define a function for checking if the input value matches any of the country names 77 | function getMatches(inputText) { 78 | var matchList = []; 79 | 80 | for (var i = 0; i < countryList.length; i++) { 81 | if (countryList[i].toLowerCase().indexOf(inputText.toLowerCase()) != -1) { 82 | matchList.push(countryList[i]); 83 | } 84 | } 85 | 86 | return matchList; 87 | } 88 | 89 | // Define a function for displaying autocomplete results 90 | function displayMatches(matchList) { 91 | var j = 0; 92 | 93 | while (j < matchList.length) { 94 | results.innerHTML += '
  • ' + matchList[j] + '
  • '; 95 | j++; 96 | } 97 | 98 | // The first child gets a class of "highlighted" 99 | moveCursor(resultsCursor); 100 | 101 | // Show the results 102 | toggleResults('show'); 103 | } 104 | 105 | // Define a function for moving the cursor in the results list 106 | function moveCursor(pos) { 107 | for (var x = 0; x < results.children.length; x++) { 108 | results.children[x].classList.remove('highlighted'); 109 | } 110 | 111 | results.children[pos].classList.add('highlighted'); 112 | } 113 | 114 | // Define a function for toggling the results list 115 | function toggleResults(action) { 116 | if (action == 'show') { 117 | results.classList.add('visible'); 118 | } else if (action == 'hide') { 119 | results.classList.remove('visible'); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /vanilla-autocomplete/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | -webkit-font-smoothing: antialised; 4 | } 5 | 6 | body { 7 | background-color: #fbfdff; 8 | font: 16px/1.5 Helvetica, Arial, sans-serif; 9 | color: #5E6063; 10 | } 11 | 12 | .container { 13 | width: 30em; 14 | margin: 10em auto; 15 | } 16 | 17 | label { 18 | display: block; 19 | margin-bottom: 1em; 20 | font-weight: bold; 21 | } 22 | 23 | input[type="text"] { 24 | width: 100%; 25 | background: #FFFFFF; 26 | border: none; 27 | border: 1px solid #E2E8EE; 28 | box-shadow: 0 0 0 10px rgba(146,151,156,0.03); 29 | border-radius: 5px; 30 | height: 60px; 31 | font-size: 20px; 32 | outline: none; 33 | padding-left: 1em; 34 | } 35 | 36 | #autocomplete-results { 37 | opacity: 0; 38 | color: #8B8D90; 39 | background: #FFFFFF; 40 | border: 1px solid #E2E8EE; 41 | font-size: 20px; 42 | margin: 10px 0 0 0; 43 | padding: 0; 44 | } 45 | 46 | #autocomplete-results li { 47 | list-style: none; 48 | padding: 1em; 49 | } 50 | 51 | #autocomplete-results li.highlighted { 52 | background-color: #E2E8EE; 53 | color: #5E6063; 54 | } 55 | 56 | #autocomplete-results.visible { 57 | opacity: 1; 58 | } 59 | --------------------------------------------------------------------------------