├── 01 - JavaScript Drum Kit ├── aesthetic-background-music-1.webp ├── index-START.html ├── script.js ├── sounds │ ├── boom.wav │ ├── clap.wav │ ├── hihat.wav │ ├── kick.wav │ ├── openhat.wav │ ├── ride.wav │ ├── snare.wav │ ├── tink.wav │ └── tom.wav └── style.css ├── 02 - JS and CSS Clock ├── index-START.html ├── script.js └── style.css ├── 03 - CSS Variables ├── Script.js ├── florian-olivo-4hbJ-eymZ1o-unsplash.jpg ├── index-START.html └── style.css ├── 04 - Array Cardio Day 1 ├── index-START.html └── script.js ├── 05 - Flex Panel Gallery ├── index-START.html ├── script.js └── style.css ├── 06 - Type Ahead ├── index-START.html ├── script.js └── style.css ├── 07 - Array Cardio Day 2 ├── index-START.html └── script.js ├── 08 - Fun with HTML5 Canvas ├── index-START.html └── script.js ├── 09 - Dev Tools Domination ├── index-START.html └── sript.js ├── 10 - Hold Shift and Check Checkboxes ├── index-START.html └── script.js ├── 11 - Custom Video Player ├── 652333414.mp4 ├── index.html ├── scripts.js └── style.css ├── 12 - Key Sequence Detection ├── cornify.js └── index-START.html ├── 13 - Slide in on Scroll ├── index-START.html └── script.js ├── 14 - JavaScript References VS Copying ├── index-START.html └── script.js ├── 15 - LocalStorage ├── index-START.html ├── oh-la-la.jpeg ├── script.js └── style.css ├── 16 - Mouse Move Shadow ├── index-START.html └── script.js ├── 17 - Follow Along Link Highlighter ├── index-START.html ├── script.js └── style.css ├── 18 - Speech Synthesis ├── index-START.html ├── script.js └── style.css ├── 19 - Stripe Follow Along Nav ├── Untitled design (2).png ├── index-START.html ├── script.js ├── style.css └── wallpaperflare.com_wallpaper_2.jpg ├── 20 - Sticky Nav ├── index-START.html ├── script.js └── style-START.css └── Digital Clock ├── index.html ├── script.js └── style.css /01 - JavaScript Drum Kit/aesthetic-background-music-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/aesthetic-background-music-1.webp -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JS Drum Kit 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | A 15 | clap 16 |
17 |
18 | S 19 | hihat 20 |
21 |
22 | D 23 | kick 24 |
25 |
26 | F 27 | openhat 28 |
29 |
30 | G 31 | boom 32 |
33 |
34 | H 35 | ride 36 |
37 |
38 | J 39 | snare 40 |
41 |
42 | K 43 | tom 44 |
45 |
46 | L 47 | tink 48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/script.js: -------------------------------------------------------------------------------- 1 | 2 | window.addEventListener('keydown', function(e) { 3 | console.log(e.keycode); 4 | const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`); 5 | const key = document.querySelector(`.key[data-key="${e.keyCode}"]`); // select the element with the class of key 6 | 7 | console.log(audio); 8 | console.log(key); 9 | if (!audio) return; // stop the function from running all together 10 | audio.currentTime = 0; // rewind to the start 11 | audio.play(); 12 | 13 | key.classList.add('playing'); 14 | 15 | this.setTimeout(function() { 16 | key.classList.remove('playing'); 17 | },500); 18 | }); -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/boom.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/boom.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/clap.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/clap.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/hihat.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/hihat.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/kick.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/kick.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/openhat.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/openhat.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/ride.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/ride.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/snare.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/snare.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/tink.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/tink.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/sounds/tom.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/01 - JavaScript Drum Kit/sounds/tom.wav -------------------------------------------------------------------------------- /01 - JavaScript Drum Kit/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 10px; 3 | background: url('./aesthetic-background-music-1.webp') bottom center; 4 | background-size: cover; 5 | } 6 | 7 | body,html { 8 | margin: 0; 9 | padding: 0; 10 | font-family: sans-serif; 11 | } 12 | 13 | .keys { 14 | display: flex; 15 | flex: 1; 16 | min-height: 100vh; 17 | align-items: center; 18 | justify-content: center; 19 | } 20 | 21 | .key { 22 | border: .4rem solid black; 23 | border-radius: .5rem; 24 | margin: 1rem; 25 | font-size: 1.5rem; 26 | padding: 1rem .5rem; 27 | transition: all .07s ease; 28 | width: 10rem; 29 | text-align: center; 30 | color: white; 31 | background: rgba(76, 33, 33, 0.4); 32 | text-shadow: 0 0 .5rem black; 33 | } 34 | 35 | .playing { 36 | transform: scale(1.1); 37 | border-color: #b436aa; 38 | box-shadow: 0 0 1rem #ffc600; 39 | } 40 | 41 | kbd { 42 | display: block; 43 | font-size: 4rem; 44 | } 45 | 46 | .sound { 47 | font-size: 1.2rem; 48 | text-transform: uppercase; 49 | letter-spacing: .1rem; 50 | color: #00f2ff; 51 | } 52 | -------------------------------------------------------------------------------- /02 - JS and CSS Clock/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Analog Clock 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /02 - JS and CSS Clock/script.js: -------------------------------------------------------------------------------- 1 | const secondHand = document.querySelector('.second-hand'); 2 | const minHand = document.querySelector('.min-hand'); 3 | const hourHand = document.querySelector('.hour-hand'); 4 | 5 | function setdate(){ 6 | const now = new Date(); 7 | const seconds = now.getSeconds(); 8 | const secondsDegrees = ((seconds / 60) * 360) + 90; // 90 is the offset to make the clock start at 12 9 | secondHand.style.transform = `rotate(${secondsDegrees}deg)`; 10 | console.log(seconds); 11 | 12 | const mins = now.getMinutes(); 13 | const minsDegrees = ((mins / 60) * 360) + 90; // 90 is the offset to make the clock start at 12 14 | minHand.style.transform = `rotate(${minsDegrees}deg)`; 15 | console.log(mins); 16 | 17 | const hours = now.getHours(); 18 | const hoursDegrees = ((hours / 12) * 360) + 90; // 90 is the offset to make the clock start at 12 19 | hourHand.style.transform = `rotate(${hoursDegrees}deg)`; 20 | 21 | } 22 | 23 | 24 | setInterval(setdate, 1000); // 1000 is the interval in milliseconds 25 | 26 | 27 | function digital() { 28 | const now = new Date(); 29 | const seconds = now.getSeconds(); 30 | const mins = now.getMinutes(); 31 | const hours = now.getHours(); 32 | const currentDate = now.getDate(); 33 | const currentMonth = now.getMonth(); 34 | const currentYear = now.getFullYear(); 35 | 36 | console.log(`${hours}:${mins}:${seconds}`); 37 | document.getElementById("display").innerHTML = `Time: ${hours}:${mins}:${seconds}
Date: ${currentDate}:${currentMonth}:${currentYear}`; 38 | } 39 | 40 | setInterval(digital, 1000); 41 | 42 | function displayDateTime() { 43 | var currentDateTime = new Date(); 44 | 45 | var date = currentDateTime.toDateString(); 46 | var time = currentDateTime.toLocaleTimeString(); 47 | 48 | var dateTimeString = 'Current Date: ' + date + '
Current Time: ' + time; 49 | 50 | document.getElementById('datetime').innerHTML = dateTimeString; 51 | } 52 | setInterval(displayDateTime, 1000); -------------------------------------------------------------------------------- /02 - JS and CSS Clock/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | background: #018DED url(https://unsplash.it/1500/1000?image=881&blur=5); 3 | background-size: cover; 4 | font-family: 'helvetica neue'; 5 | text-align: center; 6 | font-size: 10px; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | font-size: 2rem; 12 | display: flex; 13 | flex-direction: column; 14 | flex: 1; 15 | min-height: 100vh; 16 | align-items: center; 17 | } 18 | 19 | .clock { 20 | width: 30rem; 21 | height: 30rem; 22 | border: 20px solid white; 23 | border-radius: 50%; 24 | margin: 50px auto; 25 | position: relative; 26 | padding: 2rem; 27 | box-shadow: 28 | 0 0 0 4px rgba(0,0,0,0.1), 29 | inset 0 0 0 3px #EFEFEF, 30 | inset 0 0 10px black, 31 | 0 0 10px rgba(0,0,0,0.2); 32 | } 33 | 34 | .clock-face { 35 | position: relative; 36 | width: 100%; 37 | height: 100%; 38 | transform: translateY(-3px); 39 | } 40 | 41 | .hand { 42 | width: 50%; 43 | height: 6px; 44 | background: black; 45 | position: absolute; 46 | top: 50%; 47 | border-radius: 0 15px 15px 0; 48 | transform-origin: 100%; 49 | transform: rotate(90deg); 50 | transition: all 0.05s; 51 | transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1); 52 | } 53 | 54 | .display{ 55 | display: flex; 56 | justify-content: center; 57 | background-color: transparent; 58 | font-family: monospace; 59 | font-size: 2rem; 60 | letter-spacing: 2px; 61 | } 62 | 63 | 64 | .container{ 65 | display: flex; 66 | justify-content: space-around; 67 | align-items: center; 68 | background-color: transparent; 69 | font-family: monospace; 70 | width: 100%; 71 | font-size: 2rem; 72 | letter-spacing: 2px; 73 | } -------------------------------------------------------------------------------- /03 - CSS Variables/Script.js: -------------------------------------------------------------------------------- 1 | const input = document.querySelectorAll('.controls input'); 2 | 3 | function handleUpdate() { 4 | console.log(this.value); 5 | const suffix = this.dataset.sizing || ''; 6 | console.log(suffix); 7 | document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix); 8 | } 9 | 10 | input.forEach(input => input.addEventListener('change', handleUpdate)); 11 | input.forEach(input => input.addEventListener('mousemove', handleUpdate)); -------------------------------------------------------------------------------- /03 - CSS Variables/florian-olivo-4hbJ-eymZ1o-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/03 - CSS Variables/florian-olivo-4hbJ-eymZ1o-unsplash.jpg -------------------------------------------------------------------------------- /03 - CSS Variables/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Scoped CSS Variables and JS 8 | 9 | 10 | 11 |

Update CSS Variables with JS

12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /03 - CSS Variables/style.css: -------------------------------------------------------------------------------- 1 | 2 | :root{ 3 | --base: #00eeff; 4 | --spacing: 10px; 5 | --blur: 10px; 6 | } 7 | 8 | img{ 9 | padding: var(--spacing); 10 | background: var(--base); 11 | filter: blur(var(--blur)); 12 | } 13 | .hl{ 14 | color: var(--base); 15 | } 16 | body { 17 | text-align: center; 18 | background: #193549; 19 | color: white; 20 | font-family: 'cursive'; 21 | font-weight: 100; 22 | font-size: 40px; 23 | } 24 | 25 | .controls { 26 | margin-bottom: 50px; 27 | } 28 | 29 | input { 30 | width: 100px; 31 | } -------------------------------------------------------------------------------- /04 - Array Cardio Day 1/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Array Cardio 💪 6 | 7 | 8 | 9 |

Psst: have a look at the JavaScript Console 💁

10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /04 - Array Cardio Day 1/script.js: -------------------------------------------------------------------------------- 1 | // Get your shorts on - this is an array workout! 2 | // ## Array Cardio Day 1 3 | 4 | // Some data we can work with 5 | 6 | const inventors = [ 7 | { first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 }, 8 | { first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 }, 9 | { first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 }, 10 | { first: 'Marie', last: 'Curie', year: 1867, passed: 1934 }, 11 | { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 }, 12 | { first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 }, 13 | { first: 'Max', last: 'Planck', year: 1858, passed: 1947 }, 14 | { first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 }, 15 | { first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 }, 16 | { first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 }, 17 | { first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 }, 18 | { first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 } 19 | ]; 20 | 21 | const people = [ 22 | 'Bernhard, Sandra', 'Bethea, Erin', 'Becker, Carl', 'Bentsen, Lloyd', 'Beckett, Samuel', 'Blake, William', 'Berger, Ric', 'Beddoes, Mick', 'Beethoven, Ludwig', 23 | 'Belloc, Hilaire', 'Begin, Menachem', 'Bellow, Saul', 'Benchley, Robert', 'Blair, Robert', 'Benenson, Peter', 'Benjamin, Walter', 'Berlin, Irving', 24 | 'Benn, Tony', 'Benson, Leana', 'Bent, Silas', 'Berle, Milton', 'Berry, Halle', 'Biko, Steve', 'Beck, Glenn', 'Bergman, Ingmar', 'Black, Elk', 'Berio, Luciano', 25 | 'Berne, Eric', 'Berra, Yogi', 'Berry, Wendell', 'Bevan, Aneurin', 'Ben-Gurion, David', 'Bevel, Ken', 'Biden, Joseph', 'Bennington, Chester', 'Bierce, Ambrose', 26 | 'Billings, Josh', 'Birrell, Augustine', 'Blair, Tony', 'Beecher, Henry', 'Biondo, Frank' 27 | ]; 28 | // Array.prototype.filter() 29 | // 1. Filter the list of inventors for those who were born in the 1500's 30 | 31 | 32 | const fifteen =inventors.filter(function(inventors){ 33 | if (inventors.year >= 1500 && inventors.year < 1600){ 34 | return true; 35 | } 36 | 37 | }); 38 | console.table(fifteen); 39 | // Array.prototype.map() 40 | // 2. Give us an array of the inventors first and last names 41 | const fullNames = inventors.map(inventor => inventor.first + ' ' + inventor.last); 42 | console.table(fullNames); 43 | 44 | // Array.prototype.sort() 45 | // 3. Sort the inventors by birthdate, oldest to youngest 46 | const ordered = inventors.sort(function(a,b){ 47 | if(a.year > b.year){ 48 | return 1; 49 | }else{ 50 | return -1; 51 | } 52 | }); 53 | console.table(ordered); 54 | // Array.prototype.reduce() 55 | // 4. How many years did all the inventors live all together? 56 | 57 | const totalYears = inventors.reduce((total, inventor) => { 58 | return total + (inventor.passed - inventor.year); 59 | }, 0); 60 | console.log(totalYears); 61 | // 5. Sort the inventors by years lived 62 | const oldest = inventors.sort(function(a,b){ 63 | const lastGuy = a.passed - a.year; 64 | const nextGuy = b.passed - b.year; 65 | if(lastGuy > nextGuy){ 66 | return -1; 67 | }else{ 68 | return 1; 69 | } 70 | }); 71 | console.table(oldest); 72 | 73 | // 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name 74 | // https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris 75 | 76 | 77 | // 7. sort Exercise 78 | // Sort the people alphabetically by last name 79 | const alpha = people.sort(function(lastOne, nextOne){ 80 | const [aLast, aFirst] = lastOne.split(', '); 81 | const [bLast, bFirst] = nextOne.split(', '); 82 | return aLast > bLast ? 1 : -1; 83 | }); 84 | console.table(alpha); 85 | // 8. Reduce Exercise 86 | // Sum up the instances of each of these 87 | const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ]; 88 | 89 | const transportation = data.reduce(function(obj, item){ 90 | if(!obj[item]){ 91 | obj[item] = 0; 92 | } 93 | obj[item]++; 94 | return obj; 95 | } 96 | ,{}); 97 | console.log(transportation); 98 | 99 | -------------------------------------------------------------------------------- /05 - Flex Panel Gallery/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flex Panels 💪 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Hey

17 |

Let's

18 |

Dance

19 |
20 |
21 |

Give

22 |

Take

23 |

Receive

24 |
25 |
26 |

Experience

27 |

It

28 |

Today

29 |
30 |
31 |

Give

32 |

All

33 |

You can

34 |
35 |
36 |

Life

37 |

In

38 |

Motion

39 |
40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /05 - Flex Panel Gallery/script.js: -------------------------------------------------------------------------------- 1 | const panels = document.querySelectorAll('.panel'); 2 | 3 | function toggleOpen(){ 4 | this.classList.toggle('open'); 5 | } 6 | function toggleActive(e){ 7 | if(e.propertyName.includes('flex')){ 8 | this.classList.toggle('open-active'); 9 | } 10 | } 11 | 12 | panels.forEach(panel => panel.addEventListener('click', toggleOpen)); 13 | panels.forEach(panel => panel.addEventListener('transitionend', toggleActive)); -------------------------------------------------------------------------------- /05 - Flex Panel Gallery/style.css: -------------------------------------------------------------------------------- 1 | 2 | html { 3 | box-sizing: border-box; 4 | background: #ffc600; 5 | font-family: 'helvetica neue'; 6 | font-size: 20px; 7 | font-weight: 200; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | } 13 | 14 | *, *:before, *:after { 15 | box-sizing: inherit; 16 | } 17 | 18 | .panels { 19 | min-height: 100vh; 20 | overflow: hidden; 21 | display: flex; 22 | } 23 | 24 | .panel { 25 | background: #6B0F9C; 26 | box-shadow: inset 0 0 0 5px rgba(255,255,255,0.1); 27 | color: white; 28 | text-align: center; 29 | align-items: center; 30 | /* Safari transitionend event.propertyName === flex */ 31 | /* Chrome + FF transitionend event.propertyName === flex-grow */ 32 | transition: 33 | font-size 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11), 34 | flex 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11), 35 | background 0.2s; 36 | font-size: 20px; 37 | background-size: cover; 38 | background-position: center; 39 | flex: 1; 40 | justify-content: center; 41 | align-items: center; 42 | display: flex; 43 | flex-direction: column; 44 | } 45 | 46 | .panel1 { background-image:url(https://source.unsplash.com/gYl-UtwNg_I/1500x1500); } 47 | .panel2 { background-image:url(https://source.unsplash.com/rFKUFzjPYiQ/1500x1500); } 48 | .panel3 { background-image:url(https://images.unsplash.com/photo-1465188162913-8fb5709d6d57?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&w=1500&h=1500&fit=crop&s=967e8a713a4e395260793fc8c802901d); } 49 | .panel4 { background-image:url(https://source.unsplash.com/ITjiVXcwVng/1500x1500); } 50 | .panel5 { background-image:url(https://source.unsplash.com/3MNzGlQM7qs/1500x1500); } 51 | 52 | /* Flex Children */ 53 | .panel > * { 54 | margin: 0; 55 | width: 100%; 56 | transition: transform 0.5s; 57 | flex: 1 0 auto; 58 | display: flex; 59 | justify-content: center; 60 | align-items: center; 61 | } 62 | 63 | .panel>*:first-child { transform: translateY(-100%); } 64 | .panel.open-active>*:first-child { transform: translateY(0); } 65 | .panel>*:last-child { transform: translateY(100%); } 66 | .panel.open-active>*:last-child { transform: translateY(0); } 67 | 68 | .panel p { 69 | text-transform: uppercase; 70 | font-family: 'Amatic SC', cursive; 71 | text-shadow: 0 0 4px rgba(0, 0, 0, 0.72), 0 0 14px rgba(0, 0, 0, 0.45); 72 | font-size: 2em; 73 | } 74 | 75 | .panel p:nth-child(2) { 76 | font-size: 4em; 77 | } 78 | 79 | .panel.open { 80 | font-size: 40px; 81 | flex: 5; 82 | } 83 | -------------------------------------------------------------------------------- /06 - Type Ahead/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Type Ahead 👀 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 17 |
18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /06 - Type Ahead/script.js: -------------------------------------------------------------------------------- 1 | const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json'; 2 | 3 | const cities = []; 4 | 5 | fetch(endpoint) 6 | .then(blob => blob.json()) 7 | .then(data => cities.push(...data)); 8 | 9 | function findMatches(wordToMatch, cities) { 10 | return cities.filter(place => { 11 | // here we need to figure out if the city or state matches what was searched 12 | const regex = new RegExp(wordToMatch, 'gi'); 13 | return place.city.match(regex) || place.state.match(regex) 14 | }); 15 | } 16 | 17 | function displayMatches(){ 18 | console.log(this.value); 19 | const matchArray = findMatches(this.value, cities); 20 | console.log(matchArray); 21 | const html = matchArray.map(place => { 22 | const regex = new RegExp(this.value, 'gi'); 23 | const cityName = place.city.replace(regex, `${this.value}`); 24 | const stateName = place.state.replace(regex, `${this.value}`); 25 | 26 | return ` 27 |
  • 28 | ${place.city}, ${place.state} 29 | ${place.population} 30 |
  • 31 | `; 32 | }).join(''); 33 | suggestions.innerHTML = html; 34 | } 35 | 36 | 37 | const searchInput = document.querySelector('.search'); 38 | const suggestions = document.querySelector('.suggestions'); 39 | 40 | 41 | searchInput.addEventListener('change', displayMatches); 42 | searchInput.addEventListener('keyup', displayMatches); 43 | 44 | -------------------------------------------------------------------------------- /06 - Type Ahead/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | background: #ffc600; 4 | font-family: 'helvetica neue'; 5 | font-size: 20px; 6 | font-weight: 200; 7 | } 8 | 9 | *, *:before, *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | input { 14 | width: 100%; 15 | padding: 20px; 16 | } 17 | 18 | .search-form { 19 | max-width: 400px; 20 | margin: 50px auto; 21 | } 22 | 23 | input.search { 24 | margin: 0; 25 | text-align: center; 26 | outline: 0; 27 | border: 10px solid #F7F7F7; 28 | width: 120%; 29 | left: -10%; 30 | position: relative; 31 | top: 10px; 32 | z-index: 2; 33 | border-radius: 5px; 34 | font-size: 40px; 35 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.19); 36 | } 37 | 38 | .suggestions { 39 | margin: 0; 40 | padding: 0; 41 | position: relative; 42 | /*perspective: 20px;*/ 43 | } 44 | 45 | .suggestions li { 46 | background: white; 47 | list-style: none; 48 | border-bottom: 1px solid #D8D8D8; 49 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.14); 50 | margin: 0; 51 | padding: 20px; 52 | transition: background 0.2s; 53 | display: flex; 54 | justify-content: space-between; 55 | text-transform: capitalize; 56 | } 57 | 58 | .suggestions li:nth-child(even) { 59 | transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001); 60 | background: linear-gradient(to bottom, #ffffff 0%,#EFEFEF 100%); 61 | } 62 | 63 | .suggestions li:nth-child(odd) { 64 | transform: perspective(100px) rotateX(-3deg) translateY(3px); 65 | background: linear-gradient(to top, #ffffff 0%,#EFEFEF 100%); 66 | } 67 | 68 | span.population { 69 | font-size: 15px; 70 | } 71 | 72 | .hl { 73 | background: #ffc600; 74 | } 75 | -------------------------------------------------------------------------------- /07 - Array Cardio Day 2/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Array Cardio 6 | 7 | 8 | 9 |

    Psst: have a look at the JavaScript Console 💁

    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /07 - Array Cardio Day 2/script.js: -------------------------------------------------------------------------------- 1 | 2 | // ## Array Cardio Day 2 3 | 4 | const people = [ 5 | { name: 'Wes', year: 1988 }, 6 | { name: 'Kait', year: 1986 }, 7 | { name: 'Irv', year: 1970 }, 8 | { name: 'Lux', year: 2015 } 9 | ]; 10 | 11 | const comments = [ 12 | { text: 'Love this!', id: 523423 }, 13 | { text: 'Super good', id: 823423 }, 14 | { text: 'You are the best', id: 2039842 }, 15 | { text: 'Ramen is my fav food ever', id: 123523 }, 16 | { text: 'Nice Nice Nice!', id: 542328 } 17 | ]; 18 | 19 | // Some and Every Checks 20 | // Array.prototype.some() // is at least one person 19 or older? 21 | // Array.prototype.every() // is everyone 19 or older? 22 | 23 | const isAdult = people.some(function(person){ 24 | const currentYear = (new Date()).getFullYear(); 25 | if(currentYear - person.year >= 19){ 26 | return true; 27 | } 28 | }); 29 | console.table(isAdult); 30 | 31 | //Arrow function 32 | const isAdult2 = people.some(person => ((new Date()).getFullYear()) - person.year >= 19); 33 | console.table(isAdult2); 34 | 35 | //Arrow function 36 | const alladults = people.every(person => ((new Date()).getFullYear()) - person.year >= 19); 37 | console.table(alladults); 38 | 39 | // Array.prototype.find() 40 | // Find is like filter, but instead returns just the one you are looking for 41 | // find the comment with the ID of 823423 42 | 43 | 44 | const comment = comments.find(function(comment){ 45 | if(comment.id === 823423){ 46 | return true; 47 | } 48 | }); 49 | console.table(comment); 50 | 51 | //Arrow function 52 | const comment2 = comments.find(comment=> comment.id === 823423); 53 | console.table(comment2); 54 | 55 | 56 | // Array.prototype.findIndex() 57 | // Find the comment with this ID 58 | // delete the comment with the ID of 823423 59 | 60 | const index = comments.findIndex(comment => comment.id === 823423); 61 | console.table(index); 62 | 63 | //As this is at index so splice is used to remove the element 64 | comments.splice(index, 1); 65 | 66 | console.table(comments); 67 | 68 | const newComments = [ 69 | ...comments.slice(0, index), //Spreading the array from 0 index 70 | ...comments.slice(index + 1) //to last index one by one 71 | ]; 72 | console.table(newComments); -------------------------------------------------------------------------------- /08 - Fun with HTML5 Canvas/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML5 Canvas 6 | 7 | 8 | 9 | 10 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /08 - Fun with HTML5 Canvas/script.js: -------------------------------------------------------------------------------- 1 | const canvas = document.querySelector('#draw'); 2 | const ctx = canvas.getContext('2d'); 3 | canvas.width = window.innerWidth; 4 | canvas.height = window.innerHeight; 5 | ctx.strokeStyle = '#BADA55'; 6 | ctx.lineJoin = 'round'; 7 | ctx.lineCap = 'round'; 8 | ctx.lineWidth = 100; 9 | // ctx.globalCompositeOperation = 'multiply'; 10 | 11 | let isDrawing = false; 12 | let lastX = 0; 13 | let lastY = 0; 14 | let hue = 0; 15 | let direction = true; 16 | 17 | function draw(e) { 18 | if (!isDrawing) return; // stop the fn from running when they are not moused down 19 | console.log(e); 20 | ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`; 21 | ctx.beginPath(); 22 | // start from 23 | ctx.moveTo(lastX, lastY); 24 | // go to 25 | ctx.lineTo(e.offsetX, e.offsetY); 26 | ctx.stroke(); 27 | [lastX, lastY] = [e.offsetX, e.offsetY]; 28 | 29 | hue++; 30 | if (hue >= 360) { 31 | hue = 0; 32 | } 33 | if (ctx.lineWidth >= 200 || ctx.lineWidth <= 1) { 34 | direction = !direction; 35 | } 36 | 37 | if(direction) { 38 | ctx.lineWidth--; 39 | } else { 40 | ctx.lineWidth++; 41 | } 42 | 43 | } 44 | 45 | canvas.addEventListener('mousedown', (e) => { 46 | isDrawing = true; 47 | [lastX, lastY] = [e.offsetX, e.offsetY]; 48 | }); 49 | 50 | 51 | canvas.addEventListener('mousemove', draw); 52 | canvas.addEventListener('mouseup', () => isDrawing = false); 53 | canvas.addEventListener('mouseout', () => isDrawing = false); 54 | -------------------------------------------------------------------------------- /09 - Dev Tools Domination/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Console Tricks! 6 | 7 | 8 | 9 | 10 |

    ×BREAK×DOWN×

    11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /09 - Dev Tools Domination/sript.js: -------------------------------------------------------------------------------- 1 | const dogs = [{ name: 'Tomi', age: 2 }, { name: 'Moti', age: 8 }]; 2 | 3 | function makeGreen() { 4 | const p = document.querySelector('p'); 5 | p.style.color = '#BADA55'; 6 | p.style.fontSize = '50px'; 7 | } 8 | 9 | // Regular 10 | console.log('hello'); 11 | // Interpolated 12 | console.log('Hello I am a %s string!', 'tada'); 13 | // Styled 14 | console.log('%c I am some great text', 'font-size:50px; background:red; text-shadow: 5px 6px 0 blue'); 15 | // warning! 16 | console.warn('OH NOOO'); 17 | // Error :| 18 | console.error('error nub fix this'); 19 | // Info 20 | console.info('NUtech is a Great University'); 21 | // Testing 22 | const p = document.querySelector('p'); 23 | console.assert(p.classList.contains('ouch'), 'That is wrong!'); 24 | // clearing 25 | // console.clear(); 26 | // Viewing DOM Elements 27 | console.log(p); 28 | // Grouping together 29 | dogs.forEach(dog => { 30 | console.groupCollapsed(`${dog.name}`); 31 | console.log(`This is ${dog.name}`); 32 | console.log(`${dog.name} is ${dog.age} years old`); 33 | console.log(`${dog.name} is ${dog.age * 7} dog years old`); 34 | console.groupEnd(`${dog.name}`); 35 | }); 36 | console.table(dogs) 37 | // counting 38 | 39 | console.count('Noob'); 40 | console.count('NUb') 41 | // timing 42 | console.time('fetching data'); 43 | fetch('https://api.github.com/users/wesbos') 44 | .then(data => data.json()) 45 | .then(data => { 46 | console.timeEnd('fetching data'); 47 | console.log(data); 48 | } 49 | ); 50 | 51 | -------------------------------------------------------------------------------- /10 - Hold Shift and Check Checkboxes/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hold Shift to Check Multiple Checkboxes 6 | 7 | 8 | 9 | 54 | 60 |
    61 |
    62 | 63 |

    This is an inbox layout.

    64 |
    65 |
    66 | 67 |

    Check one item

    68 |
    69 |
    70 | 71 |

    Hold down your Shift key

    72 |
    73 |
    74 | 75 |

    Check a lower item

    76 |
    77 |
    78 | 79 |

    Everything in between should also be set to checked

    80 |
    81 |
    82 | 83 |

    Try to do it without any libraries

    84 |
    85 |
    86 | 87 |

    Just regular JavaScript

    88 |
    89 |
    90 | 91 |

    Good Luck!

    92 |
    93 |
    94 | 95 |

    Don't forget to tweet your result!

    96 |
    97 |
    98 | 99 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /10 - Hold Shift and Check Checkboxes/script.js: -------------------------------------------------------------------------------- 1 | const checkBoxes = document.querySelectorAll('.inbox input[type="checkbox"]'); 2 | 3 | let lastChecked; 4 | function handleCheck(e) { 5 | // console.log(e); 6 | let inBetween = false; 7 | if(e.shiftKey && this.checked) { 8 | checkBoxes.forEach(checkbox => { 9 | console.log(checkbox); 10 | if(checkbox === this || checkbox === lastChecked) { 11 | inBetween = !inBetween; 12 | console.log('Starting to check them in between!'); 13 | } 14 | if(inBetween) { 15 | checkbox.checked = true; 16 | } 17 | }); 18 | } 19 | 20 | 21 | lastChecked = this; 22 | } 23 | checkBoxes.forEach(checkbox => checkbox.addEventListener('click', handleCheck)); -------------------------------------------------------------------------------- /11 - Custom Video Player/652333414.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/11 - Custom Video Player/652333414.mp4 -------------------------------------------------------------------------------- /11 - Custom Video Player/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML Video Player 6 | 7 | 8 | 9 | 10 | 11 |
    12 | 13 | 14 |
    15 |
    16 |
    17 |
    18 | 19 | 20 | 21 | 22 | 23 |
    24 |
    25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /11 - Custom Video Player/scripts.js: -------------------------------------------------------------------------------- 1 | /* Get Our Elements */ 2 | const player = document.querySelector('.player'); 3 | const video = player.querySelector('.viewer'); 4 | const progress = player.querySelector('.progress'); 5 | const progressBar = player.querySelector('.progress__filled'); 6 | const toggle = player.querySelector('.toggle'); 7 | const skipButtons = player.querySelectorAll('[data-skip]'); 8 | const ranges = player.querySelectorAll('.player__slider'); 9 | 10 | /* Build out functions */ 11 | function togglePlay() { 12 | const method = video.paused ? 'play' : 'pause'; 13 | video[method](); 14 | } 15 | 16 | function updateButton() { 17 | const icon = this.paused ? '►' : '❚ ❚'; 18 | console.log(icon); 19 | toggle.textContent = icon; 20 | } 21 | 22 | function skip() { 23 | video.currentTime += parseFloat(this.dataset.skip); 24 | } 25 | 26 | function handleRangeUpdate() { 27 | video[this.name] = this.value; 28 | } 29 | 30 | function handleProgress() { 31 | const percent = (video.currentTime / video.duration) * 100; 32 | progressBar.style.flexBasis = `${percent}%`; 33 | } 34 | 35 | function scrub(e) { 36 | const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration; 37 | video.currentTime = scrubTime; 38 | } 39 | 40 | /* Hook up the event listeners */ 41 | video.addEventListener('click', togglePlay); 42 | video.addEventListener('play', updateButton); 43 | video.addEventListener('pause', updateButton); 44 | video.addEventListener('timeupdate', handleProgress); 45 | 46 | toggle.addEventListener('click', togglePlay); 47 | skipButtons.forEach(button => button.addEventListener('click', skip)); 48 | ranges.forEach(range => range.addEventListener('change', handleRangeUpdate)); 49 | ranges.forEach(range => range.addEventListener('mousemove', handleRangeUpdate)); 50 | 51 | let mousedown = false; 52 | progress.addEventListener('click', scrub); 53 | progress.addEventListener('mousemove', (e) => mousedown && scrub(e)); 54 | progress.addEventListener('mousedown', () => mousedown = true); 55 | progress.addEventListener('mouseup', () => mousedown = false); 56 | -------------------------------------------------------------------------------- /11 - Custom Video Player/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | } 4 | 5 | *, *:before, *:after { 6 | box-sizing: inherit; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | padding: 0; 12 | display: flex; 13 | background: #7A419B; 14 | min-height: 100vh; 15 | background: linear-gradient(135deg, #7c1599 0%,#921099 48%,#7e4ae8 100%); 16 | background-size: cover; 17 | align-items: center; 18 | justify-content: center; 19 | } 20 | 21 | .player { 22 | max-width: 750px; 23 | border: 5px solid rgba(0,0,0,0.2); 24 | box-shadow: 0 0 20px rgba(0,0,0,0.2); 25 | position: relative; 26 | font-size: 0; 27 | overflow: hidden; 28 | } 29 | 30 | /* This css is only applied when fullscreen is active. */ 31 | .player:fullscreen { 32 | max-width: none; 33 | width: 100%; 34 | } 35 | 36 | .player:-webkit-full-screen { 37 | max-width: none; 38 | width: 100%; 39 | } 40 | 41 | .player__video { 42 | width: 100%; 43 | } 44 | 45 | .player__button { 46 | background: none; 47 | border: 0; 48 | line-height: 1; 49 | color: white; 50 | text-align: center; 51 | outline: 0; 52 | padding: 0; 53 | cursor: pointer; 54 | max-width: 50px; 55 | } 56 | 57 | .player__button:focus { 58 | border-color: #ffc600; 59 | } 60 | 61 | .player__slider { 62 | width: 10px; 63 | height: 30px; 64 | } 65 | 66 | .player__controls { 67 | display: flex; 68 | position: absolute; 69 | bottom: 0; 70 | width: 100%; 71 | transform: translateY(100%) translateY(-5px); 72 | transition: all .3s; 73 | flex-wrap: wrap; 74 | background: rgba(0,0,0,0.1); 75 | } 76 | 77 | .player:hover .player__controls { 78 | transform: translateY(0); 79 | } 80 | 81 | .player:hover .progress { 82 | height: 15px; 83 | } 84 | 85 | .player__controls > * { 86 | flex: 1; 87 | } 88 | 89 | .progress { 90 | flex: 10; 91 | position: relative; 92 | display: flex; 93 | flex-basis: 100%; 94 | height: 5px; 95 | transition: height 0.3s; 96 | background: rgba(0,0,0,0.5); 97 | cursor: ew-resize; 98 | } 99 | 100 | .progress__filled { 101 | width: 50%; 102 | background: #ffc600; 103 | flex: 0; 104 | flex-basis: 50%; 105 | } 106 | 107 | /* unholy css to style input type="range" */ 108 | 109 | input[type=range] { 110 | -webkit-appearance: none; 111 | background: transparent; 112 | width: 100%; 113 | margin: 0 5px; 114 | } 115 | 116 | input[type=range]:focus { 117 | outline: none; 118 | } 119 | 120 | input[type=range]::-webkit-slider-runnable-track { 121 | width: 100%; 122 | height: 8.4px; 123 | cursor: pointer; 124 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0); 125 | background: rgba(255,255,255,0.8); 126 | border-radius: 1.3px; 127 | border: 0.2px solid rgba(1, 1, 1, 0); 128 | } 129 | 130 | input[type=range]::-webkit-slider-thumb { 131 | height: 15px; 132 | width: 15px; 133 | border-radius: 50px; 134 | background: #ffc600; 135 | cursor: pointer; 136 | -webkit-appearance: none; 137 | margin-top: -3.5px; 138 | box-shadow:0 0 2px rgba(0,0,0,0.2); 139 | } 140 | 141 | input[type=range]:focus::-webkit-slider-runnable-track { 142 | background: #bada55; 143 | } 144 | 145 | input[type=range]::-moz-range-track { 146 | width: 100%; 147 | height: 8.4px; 148 | cursor: pointer; 149 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0); 150 | background: #ffffff; 151 | border-radius: 1.3px; 152 | border: 0.2px solid rgba(1, 1, 1, 0); 153 | } 154 | 155 | input[type=range]::-moz-range-thumb { 156 | box-shadow: 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(13, 13, 13, 0); 157 | height: 15px; 158 | width: 15px; 159 | border-radius: 50px; 160 | background: #ffc600; 161 | cursor: pointer; 162 | } 163 | -------------------------------------------------------------------------------- /12 - Key Sequence Detection/cornify.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | _______ ,-----. .-------. ,---. .--..-./`) ________ ____ __ 4 | / __ \ .' .-, '. | _ _ \ | \ | |\ .-.')| | \ \ / / 5 | | ,_/ \__) / ,-.| \ _ \ | ( ' ) | | , \ | |/ `-' \| .----' \ _. / ' 6 | ,-./ ) ; \ '_ / | :|(_ o _) / | |\_ \| | `-'`"`| _|____ _( )_ .' 7 | \ '_ '`) | _`,/ \ _/ || (_,_).' __ | _( )_\ | .---. |_( )_ | ___(_ o _)' 8 | > (_) ) __: ( '\_/ \ ;| |\ \ | || (_ o _) | | | (_ o._)__|| |(_,_)' 9 | ( . .-'_/ )\ `"/ \ ) / | | \ `' /| (_,_)\ | | | |(_,_) | `-' / 10 | `-'`-' / '. \_/``".' | | \ / | | | | | | | | \ / 11 | `._____.' '-----' ''-' `'-' '--' '--' '---' '---' `-..-' 12 | 13 | This script has been modified by @wesbos because 14 | https://twitter.com/wesbos/status/1657012836403388416 15 | 16 | */ 17 | 18 | var cornify_count = 0; 19 | var cornify_add = function (options) { 20 | // Track how often we cornified. 21 | cornify_count += 1; 22 | 23 | // Prepare our lovely variables. 24 | var cornify_url = "https://www.cornify.com/"; 25 | var numType = "px"; 26 | var heightRandom = Math.random() * 0.75; 27 | var windowHeight = 768; 28 | var windowWidth = 1024; 29 | var height = 0; 30 | var width = 0; 31 | var de = document.documentElement; 32 | var transform = "translate(-50%, -50%)"; 33 | var showGrandUnicorn = cornify_count == 15; 34 | 35 | // Create a container for our 'corn or 'bow. 36 | var div = document.createElement("div"); 37 | div.style.position = "fixed"; 38 | div.className = "__cornify_unicorn"; 39 | div.style.zIndex = 143143; 40 | div.style.outline = 0; 41 | div.onclick = cornify_add; // Click for more magic. 42 | 43 | // Get the window width and height - requires some cross browser checking. 44 | if (typeof window.innerHeight == "number") { 45 | windowHeight = window.innerHeight; 46 | windowWidth = window.innerWidth; 47 | } else if (de && de.clientHeight) { 48 | windowHeight = de.clientHeight; 49 | windowWidth = de.clientWidth; 50 | } else { 51 | numType = "%"; 52 | height = Math.round(height * 100) + "%"; 53 | } 54 | 55 | if (showGrandUnicorn) { 56 | // Clicking 15 times summons the grand unicorn - which is centered on the screen. 57 | div.style.top = "50%"; 58 | div.style.left = "50%"; 59 | div.style.zIndex = 143143143; 60 | } else { 61 | // Otherwise we randomize the position. 62 | div.style.top = Math.round(Math.random() * 100) + "%"; 63 | div.style.left = Math.round(Math.random() * 100) + "%"; 64 | 65 | transform += " rotate(" + Math.round(Math.random() * 10 - 5) + "deg)"; 66 | } 67 | 68 | // Create the image element. 69 | var img = document.createElement("img"); 70 | img.style.opacity = 0; 71 | img.style.transition = "all .1s linear"; 72 | img.alt = "A lovely unicorn or rainbow"; 73 | img.onload = function () { 74 | img.style.opacity = 1; 75 | }; 76 | 77 | // Used as a cache buster so the browser makes a new request every time instead of usign the previous, cached one. 78 | var currentTime = new Date(); 79 | var submitTime = currentTime.getTime(); 80 | 81 | if (showGrandUnicorn) { 82 | // Caching doesn't matter for the Grand Unicorn. 83 | submitTime = 0; 84 | } 85 | 86 | // Construct our unicorn & rainbow request. 87 | var url = `https://www.cornify.com/corns/${ 88 | Math.random() > 0.5 ? "r" : "u" 89 | }${Math.ceil(Math.random() * 7)}.gif`; 90 | 91 | // Add younicorns if requested. 92 | if (options && (options.y || options.younicorns)) { 93 | url += "&y=" + (options.y ? options.y : options.younicorns); 94 | 95 | if (Math.random() > 0.5) { 96 | // Flip horizontally at random. 97 | if (transform.length > 0) { 98 | transform += " scaleX(-1)"; 99 | } 100 | } 101 | } 102 | 103 | div.style.transform = transform; 104 | div.style.MozTransform = transform; 105 | div.style.webkitTransform = transform; 106 | 107 | img.setAttribute("src", url); 108 | 109 | // Add a nice hover wigggle. 110 | img.style.transition = "all .1s linear"; 111 | 112 | div.onmouseover = function () { 113 | var size = 1 + Math.round(Math.random() * 10) / 100; 114 | var angle = Math.round(Math.random() * 20 - 10); 115 | var result = "rotate(" + angle + "deg) scale(" + size + "," + size + ")"; 116 | img.style.transform = result; 117 | img.style.MozTransform = result; 118 | img.style.webkitTransform = result; 119 | }; 120 | 121 | div.onmouseout = function () { 122 | var size = 0.9 + Math.round(Math.random() * 10) / 100; 123 | var angle = Math.round(Math.random() * 6 - 3); 124 | var result = "rotate(" + angle + "deg) scale(" + size + "," + size + ")"; 125 | img.style.transform = result; 126 | img.style.MozTransform = result; 127 | img.style.webkitTransform = result; 128 | }; 129 | 130 | // Append our container DIV to the page. 131 | var body = document.getElementsByTagName("body")[0]; 132 | body.appendChild(div); 133 | div.appendChild(img); 134 | 135 | // Hooray - now we have a sparkly unicorn (or rainbow) on the page. Another cornification well done. Congrats! 136 | 137 | // When clicking 5 times, add a custom stylesheet to make the page look awesome. 138 | if (cornify_count == 5) { 139 | var cssExisting = document.getElementById("__cornify_css"); 140 | 141 | if (!cssExisting) { 142 | var head = document.getElementsByTagName("head")[0]; 143 | var css = document.createElement("link"); 144 | css.id = "__cornify_css"; 145 | css.type = "text/css"; 146 | css.rel = "stylesheet"; 147 | css.href = "https://www.cornify.com/css/cornify.css"; 148 | css.media = "screen"; 149 | head.appendChild(css); 150 | } 151 | cornify_replace(); 152 | } 153 | 154 | cornify_updatecount(); 155 | 156 | // Trigger an event on the document. 157 | var event = new Event("cornify"); 158 | document.dispatchEvent(event); 159 | }; 160 | 161 | // Tracks how often we cornified. 162 | var cornify_updatecount = function () { 163 | var id = "__cornify_count"; 164 | var p = document.getElementById(id); 165 | 166 | if (p == null) { 167 | var p = document.createElement("p"); 168 | p.id = id; 169 | p.style.position = "fixed"; 170 | p.style.bottom = "5px"; 171 | p.style.left = "0px"; 172 | p.style.right = "0px"; 173 | p.style.zIndex = "1000000000"; 174 | p.style.color = "#ff00ff"; 175 | p.style.textAlign = "center"; 176 | p.style.fontSize = "24px"; 177 | p.style.fontFamily = "'Comic Sans MS', 'Comic Sans', 'Marker Felt', serif"; // Only the best! 178 | p.style.textTransform = "uppercase"; 179 | var body = document.getElementsByTagName("body")[0]; 180 | body.appendChild(p); 181 | } 182 | 183 | if (cornify_count == 1) { 184 | p.innerHTML = "You cornified!"; 185 | } else { 186 | p.innerHTML = "You cornified " + cornify_count + " times!"; 187 | } 188 | 189 | // Stores our count in a cookie for our next session. 190 | cornify_setcookie("cornify", cornify_count + "", 1000); 191 | }; 192 | 193 | var cornify_setcookie = function (name, value, days) { 194 | var d = new Date(); 195 | d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000); 196 | var expires = "expires=" + d.toGMTString(); 197 | document.cookie = name + "=" + value + "; " + expires; 198 | }; 199 | 200 | var cornify_getcookie = function (cname) { 201 | var name = cname + "="; 202 | var ca = document.cookie.split(";"); 203 | for (var i = 0; i < ca.length; i++) { 204 | var c = ca[i].trim(); 205 | if (c.indexOf(name) == 0) { 206 | return c.substring(name.length, c.length); 207 | } 208 | } 209 | return ""; 210 | }; 211 | 212 | // Retrieve our click count from the cookie when we start up. 213 | cornify_count = parseInt(cornify_getcookie("cornify")); 214 | if (isNaN(cornify_count)) { 215 | cornify_count = 0; 216 | } 217 | 218 | // Adds happy words at the beginning of all headers on the page. 219 | var cornify_replace = function () { 220 | // Replace text. 221 | var hc = 6; 222 | var hs; 223 | var h; 224 | var k; 225 | var words = [ 226 | "Happy", 227 | "Sparkly", 228 | "Glittery", 229 | "Fun", 230 | "Magical", 231 | "Lovely", 232 | "Cute", 233 | "Charming", 234 | "Amazing", 235 | "Wonderful", 236 | ]; 237 | while (hc >= 1) { 238 | hs = document.getElementsByTagName("h" + hc); 239 | for (k = 0; k < hs.length; k++) { 240 | h = hs[k]; 241 | h.innerHTML = 242 | words[Math.floor(Math.random() * words.length)] + " " + h.innerHTML; 243 | } 244 | hc -= 1; 245 | } 246 | }; 247 | 248 | // Adds happy words at the beginning of all headers on the page. 249 | var cornify_replace = function () { 250 | var headerTypeIndex = 6; 251 | var headerElements; 252 | var headerElement; 253 | var i; 254 | var magicalWords = [ 255 | "Happy", 256 | "Sparkly", 257 | "Glittery", 258 | "Fun", 259 | "Magical", 260 | "Lovely", 261 | "Cute", 262 | "Charming", 263 | "Amazing", 264 | "Wonderful", 265 | ]; 266 | 267 | while (headerTypeIndex >= 1) { 268 | headerElements = document.getElementsByTagName("h" + headerTypeIndex); 269 | 270 | for (i = 0; i < headerElements.length; i++) { 271 | headerElement = headerElements[i]; 272 | headerElement.innerHTML = 273 | magicalWords[Math.floor(Math.random() * magicalWords.length)] + 274 | " " + 275 | headerElement.innerHTML; 276 | } 277 | 278 | headerTypeIndex -= 1; 279 | } 280 | }; 281 | 282 | // Clicking the rainbow cupcake button makes all the unicorns 283 | // disappear (should only be used in an emergency, since it's sad). 284 | var cornify_click_cupcake_button = function () { 285 | var doc = document; 286 | 287 | var corns = doc.getElementsByClassName("__cornify_unicorn"); 288 | if (corns) { 289 | for (var i = 0; i < corns.length; i++) { 290 | corns[i].parentNode.removeChild(corns[i]); 291 | } 292 | } 293 | 294 | // Remove our counter. 295 | var button = doc.getElementById("__cornify_count"); 296 | if (button) { 297 | button.parentNode.removeChild(button); 298 | } 299 | 300 | // Remove the cupcake button. 301 | var button = doc.getElementById("__cornify_cupcake_button"); 302 | if (button) { 303 | button.parentNode.removeChild(button); 304 | } 305 | 306 | var event = new Event("cornify-clear"); 307 | document.dispatchEvent(event); 308 | }; 309 | 310 | // Add the rainbow cupcake button to the page. 311 | var cornify_add_cupcake_button = function () { 312 | var id = "__cornify_cupcake_button"; 313 | var doc = document; 314 | var button = doc.getElementById(id); 315 | 316 | if (!button) { 317 | button = doc.createElement("div"); 318 | button.id = id; 319 | button.onclick = cornify_click_cupcake_button; 320 | button.style.position = "fixed"; 321 | button.style.top = "10px"; 322 | button.style.right = "10px"; 323 | button.style.zIndex = 2147483640; 324 | button.setAttribute("aria-label", "Hide unicorns and rainbows"); 325 | 326 | var image = document.createElement("img"); 327 | image.src = "https://www.cornify.com/assets/cornify-cupcake-button.png"; 328 | image.alt = "Cupcake button"; 329 | image.width = 50; 330 | image.height = 50; 331 | image.style.width = "50px !important"; 332 | image.style.height = "50px !important"; 333 | image.style.display = "block !important"; 334 | image.style.cursor = "pointer !important"; 335 | image.style.margin = "0 !important"; 336 | image.style.padding = "0 !important"; 337 | button.appendChild(image); 338 | 339 | doc.getElementsByTagName("body")[0].appendChild(button); 340 | } 341 | }; 342 | 343 | // Adapted from http://www.snaptortoise.com/konami-js/ 344 | var cornami = { 345 | input: "", 346 | pattern: "38384040373937396665", 347 | clear: setTimeout("cornami.clear_input()", 5000), 348 | load: function () { 349 | window.document.onkeydown = function (event) { 350 | if (cornami.input == cornami.pattern) { 351 | cornify_add(); 352 | clearTimeout(cornami.clear); 353 | return; 354 | } else { 355 | cornami.input += event.keyCode; 356 | if (cornami.input == cornami.pattern) { 357 | cornify_add(); 358 | } 359 | clearTimeout(cornami.clear); 360 | cornami.clear = setTimeout("cornami.clear_input()", 5000); 361 | } 362 | }; 363 | }, 364 | clear_input: function () { 365 | cornami.input = ""; 366 | clearTimeout(cornami.clear); 367 | }, 368 | }; 369 | 370 | cornami.load(); 371 | -------------------------------------------------------------------------------- /12 - Key Sequence Detection/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Key Detection 6 | 7 | 8 | 9 | 10 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /13 - Slide in on Scroll/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Slide 6 | 7 | 8 | 9 | 10 |
    11 | 12 |

    Slide in on Scroll

    13 | 14 |

    Consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariaturlores sunt esse magni, ut, dignissimos.

    15 |

    Lorem ipsum cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    16 |

    Adipisicing elit. Tempore tempora rerum..

    17 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    18 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    19 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    20 | 21 | 22 | 23 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates, deserunt facilis et iste corrupti omnis tenetur est. Iste ut est dicta dolor itaque adipisci, dolorum minima, veritatis earum provident error molestias. Ratione magni illo sint vel velit ut excepturi consectetur suscipit, earum modi accusamus voluptatem nostrum, praesentium numquam, reiciendis voluptas sit id quisquam. Consequatur in quis reprehenderit modi perspiciatis necessitatibus saepe, quidem, suscipit iure natus dignissimos ipsam, eligendi deleniti accusantium, rerum quibusdam fugit perferendis et optio recusandae sed ratione. Culpa, dolorum reprehenderit harum ab voluptas fuga, nisi eligendi natus maiores illum quas quos et aperiam aut doloremque optio maxime fugiat doloribus. Eum dolorum expedita quam, nesciunt

    24 | 25 | 26 | 27 |

    at provident praesentium atque quas rerum optio dignissimos repudiandae ullam illum quibusdam. Vel ad error quibusdam, illo ex totam placeat. Quos excepturi fuga, molestiae ea quisquam minus, ratione dicta consectetur officia omnis, doloribus voluptatibus? Veniam ipsum veritatis architecto, provident quas consequatur doloremque quam quidem earum expedita, ad delectus voluptatum, omnis praesentium nostrum qui aspernatur ea eaque adipisci et cumque ab? Ea voluptatum dolore itaque odio. Eius minima distinctio harum, officia ab nihil exercitationem. Tempora rem nemo nam temporibus molestias facilis minus ipsam quam doloribus consequatur debitis nesciunt tempore officiis aperiam quisquam, molestiae voluptates cum, fuga culpa. Distinctio accusamus quibusdam, tempore perspiciatis dolorum optio facere consequatur quidem ullam beatae architecto, ipsam sequi officiis dignissimos amet impedit natus necessitatibus tenetur repellendus dolor rem! Dicta dolorem, iure, facilis illo ex nihil ipsa amet officia, optio temporibus eum autem odit repellendus nisi. Possimus modi, corrupti error debitis doloribus dicta libero earum, sequi porro ut excepturi nostrum ea voluptatem nihil culpa? Ullam expedita eligendi obcaecati reiciendis velit provident omnis quas qui in corrupti est dolore facere ad hic, animi soluta assumenda consequuntur reprehenderit! Voluptate dolor nihil veniam laborum voluptas nisi pariatur sed optio accusantium quam consectetur, corrupti, sequi et consequuntur, excepturi doloremque. Tempore quis velit corporis neque fugit non sequi eaque rem hic. Facere, inventore, aspernatur. Accusantium modi atque, asperiores qui nobis soluta cumque suscipit excepturi possimus doloremque odit saepe perferendis temporibus molestiae nostrum voluptatum quis id sint quidem nesciunt culpa. Rerum labore dolor beatae blanditiis praesentium explicabo velit optio esse aperiam similique, voluptatem cum, maiores ipsa tempore. Reiciendis sed culpa atque inventore, nam ullam enim expedita consectetur id velit iusto alias vitae explicabo nemo neque odio reprehenderit soluta sint eaque. Aperiam, qui ut tenetur, voluptate doloremque officiis dicta quaerat voluptatem rerum natus magni. Eum amet autem dolor ullam.

    28 | 29 | 30 | 31 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis

    32 | 33 | 34 |

    laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    35 | 36 | 37 | 38 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    39 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    40 | 41 | 42 | 43 | 44 |
    45 | 46 | 47 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /13 - Slide in on Scroll/script.js: -------------------------------------------------------------------------------- 1 | function debounce(func, wait = 20, immediate = true) { 2 | var timeout; 3 | return function() { 4 | var context = this, args = arguments; 5 | var later = function() { 6 | timeout = null; 7 | if (!immediate) func.apply(context, args); 8 | }; 9 | var callNow = immediate && !timeout; 10 | clearTimeout(timeout); 11 | timeout = setTimeout(later, wait); 12 | if (callNow) func.apply(context, args); 13 | }; 14 | } 15 | 16 | const sliderImages = document.querySelectorAll('.slide-in'); 17 | function checkSlide(e) { 18 | console.count(e); 19 | sliderImages.forEach(sliderImage => { 20 | const slideInAt = (window.scrollY + window.innerHeight) - sliderImage.height / 2; 21 | 22 | const imageBottom = sliderImage.offsetTop + sliderImage.height; 23 | const isHalfShown = slideInAt > sliderImage.offsetTop; 24 | const isNotScrolledPast = window.scrollY < imageBottom; 25 | 26 | if (isHalfShown && isNotScrolledPast) { 27 | sliderImage.classList.add('active'); 28 | } 29 | else { 30 | sliderImage.classList.remove('active'); 31 | } 32 | 33 | }); 34 | } 35 | window.addEventListener('scroll', debounce(checkSlide)); -------------------------------------------------------------------------------- /14 - JavaScript References VS Copying/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JS Reference VS Copy 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /14 - JavaScript References VS Copying/script.js: -------------------------------------------------------------------------------- 1 | // start with strings, numbers and booleans 2 | let age = 100; 3 | let age2 = age; 4 | console.log(age, age2); 5 | age = 200; 6 | console.log(age, age2); 7 | let name = 'Abdullah'; 8 | let name2 = name; 9 | console.log(name, name2); 10 | name = 'Sultan'; 11 | console.log(name, name2); 12 | 13 | // Let's say we have an array 14 | const players = ['Abdullah', 'Sultan', 'Mehdi', 'Moeez']; 15 | 16 | // and we want to make a copy of it. 17 | const team = players; 18 | team[3] = 'Hassan'; 19 | console.log(players,team); 20 | 21 | // You might think we can just do something like this: 22 | // however what happens when we update that array? 23 | team.push('Hamza'); 24 | console.log(players,team); 25 | 26 | 27 | // now here is the problem! 28 | 29 | // Why? It's because that is an array reference, not an array copy. They both point to the same array! 30 | 31 | // So, how do we fix this? We take a copy instead! 32 | 33 | const team2 = players.slice(2,3); 34 | console.log(team2); 35 | //copy is sliced but not the original array 36 | 37 | console.log(players); 38 | 39 | team2[1] = 'Zohaib'; 40 | team2.push('Wahab'); 41 | console.log(team2); 42 | console.log(players); 43 | // one way 44 | 45 | // or create a new array and concat the old one in 46 | const team3 = [].concat(players); 47 | console.log(team3); 48 | // or use the new ES6 Spread 49 | const team4 = [...players]; 50 | team4[3] = 'Moeez'; 51 | console.log(team4); 52 | // now when we update it, the original one isn't changed 53 | 54 | // The same thing goes for objects, let's say we have a person object 55 | 56 | // with Objects 57 | const person = { 58 | name: 'Abdullah', 59 | age: 19 60 | }; 61 | 62 | // and think we make a copy: 63 | const captain = person; 64 | captain.number = 99; 65 | 66 | // how do we take a copy instead? 67 | const cap2 = Object.assign({}, person, {number: 99, age: 12}); //overwirting age 68 | console.log(cap2); 69 | 70 | // We will hopefully soon see the object ...spread 71 | const cap3 = {...person}; 72 | console.log(cap3); 73 | // Things to note - this is only 1 level deep - both for Arrays and Objects. lodash has a cloneDeep method, but you should think twice before using it. 74 | 75 | const abdullah = { 76 | name: 'Abdullah', 77 | age: 19, 78 | social: { 79 | twitter: '@abdullah', 80 | facebook: 'abdullah.ch' 81 | } 82 | }; 83 | console.log(abdullah); 84 | 85 | const dev = Object.assign({}, abdullah); 86 | console.log(dev); 87 | abdullah.social.twitter = 'abdullahch225'; 88 | console.log(dev); -------------------------------------------------------------------------------- /15 - LocalStorage/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LocalStorage 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 |
    18 |

    LOCAL TAPAS

    19 |

    20 | 23 |
    24 | 25 | 26 |
    27 |
    28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /15 - LocalStorage/oh-la-la.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/15 - LocalStorage/oh-la-la.jpeg -------------------------------------------------------------------------------- /15 - LocalStorage/script.js: -------------------------------------------------------------------------------- 1 | const addItems = document.querySelector('.add-items'); 2 | const itemsList = document.querySelector('.plates'); 3 | const items = []; 4 | 5 | function addItem(e) { 6 | e.preventDefault(); 7 | const text = (this.querySelector('[name=item]')).value; 8 | const item = { 9 | text, 10 | done: false 11 | }; 12 | items.push(item); 13 | populateList(items, itemsList); 14 | localStorage.setItem('items', JSON.stringify(items)); 15 | this.reset(); 16 | } 17 | 18 | function populateList(plates = [], platesList) { 19 | platesList.innerHTML = plates.map((plate, i) => { 20 | return ` 21 |
  • 22 | 23 | 24 |
  • 25 | `; 26 | }).join(''); 27 | } 28 | 29 | function toggleDone(e) { 30 | if (!e.target.matches('input')) return; // skip this unless it's an input 31 | const el = e.target; 32 | const index = el.dataset.index; 33 | items[index].done = !items[index].done; 34 | localStorage.setItem('items', JSON.stringify(items)); 35 | populateList(items, itemsList); 36 | } 37 | 38 | addItems.addEventListener('submit', addItem); 39 | itemsList.addEventListener('click', toggleDone); 40 | 41 | populateList(items, itemsList); 42 | -------------------------------------------------------------------------------- /15 - LocalStorage/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | background: url("oh-la-la.jpeg") center no-repeat; 4 | background-size: cover; 5 | min-height: 100vh; 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | text-align: center; 10 | font-family: Futura, "Trebuchet MS", Arial, sans-serif; 11 | } 12 | 13 | *, 14 | *:before, 15 | *:after { 16 | box-sizing: inherit; 17 | } 18 | 19 | svg { 20 | fill: white; 21 | background: rgba(0, 0, 0, 0.1); 22 | padding: 20px; 23 | border-radius: 50%; 24 | width: 200px; 25 | margin-bottom: 50px; 26 | } 27 | 28 | .wrapper { 29 | padding: 20px; 30 | max-width: 350px; 31 | background: rgba(255, 255, 255, 0.95); 32 | box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1); 33 | } 34 | 35 | h2 { 36 | text-align: center; 37 | margin: 0; 38 | font-weight: 200; 39 | } 40 | 41 | .plates { 42 | margin: 0; 43 | padding: 0; 44 | text-align: left; 45 | list-style: none; 46 | } 47 | 48 | .plates li { 49 | border-bottom: 1px solid rgba(0, 0, 0, 0.2); 50 | padding: 10px 0; 51 | font-weight: 100; 52 | display: flex; 53 | } 54 | 55 | .plates label { 56 | flex: 1; 57 | cursor: pointer; 58 | } 59 | 60 | .plates input { 61 | display: none; 62 | } 63 | 64 | .plates input + label:before { 65 | content: "⬜️"; 66 | margin-right: 10px; 67 | } 68 | 69 | .plates input:checked + label:before { 70 | content: "🌮"; 71 | } 72 | 73 | .add-items { 74 | margin-top: 20px; 75 | } 76 | 77 | .add-items input { 78 | padding: 10px; 79 | outline: 0; 80 | border: 1px solid rgba(0, 0, 0, 0.1); 81 | } 82 | -------------------------------------------------------------------------------- /16 - Mouse Move Shadow/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mouse Shadow 6 | 7 | 8 | 9 | 10 |
    11 |

    Abdullah Assi

    12 |
    13 | 14 | 38 | 39 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /16 - Mouse Move Shadow/script.js: -------------------------------------------------------------------------------- 1 | const hero = document.querySelector('.hero'); 2 | const text = hero.querySelector('h1'); 3 | 4 | const walk = 100; // 100px 5 | function shadow(e){ 6 | const { offsetWidth:width, offsetHeight:height} =hero; 7 | let { offsetX: x, offsetY: y } = e; 8 | if (this!==e.target){ 9 | x=x+e.target.offsetLeft; 10 | y=y+e.target.offsetTop; 11 | } 12 | console.log(x,y); 13 | const xWalk = Math.round((x/width*walk)-(walk/2)); 14 | const yWalk = Math.round((y/height*walk)-(walk/2)); 15 | console.log(xWalk,yWalk); 16 | text.style.textShadow = `${xWalk}px ${yWalk}px 0 rgba(0,0,0,0.3)`; 17 | } 18 | 19 | hero.addEventListener('mousemove', shadow); -------------------------------------------------------------------------------- /17 - Follow Along Link Highlighter/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Nav Tricks 6 | 7 | 8 | 9 | 10 | 11 | 20 | 21 |
    22 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Est explicabo unde natus necessitatibus esse obcaecati distinctio, aut itaque, qui vitae!

    23 |

    Aspernatur sapiente quae sint soluta modi, atque praesentium laborum pariatur earum quaerat cupiditate consequuntur facilis ullam dignissimos, aperiam quam veniam.

    24 |

    Cum ipsam quod, incidunt sit ex tempore placeat maxime corrupti possimus veritatis ipsum fugit recusandae est doloremque? Hic, quibusdam, nulla.

    25 |

    Esse quibusdam, ad, ducimus cupiditate nulla, quae magni odit totam ut consequatur eveniet sunt quam provident sapiente dicta neque quod.

    26 |

    Aliquam dicta sequi culpa fugiat consequuntur pariatur optio ad minima, maxime odio, distinctio magni impedit tempore enim repellendus repudiandae quas!

    27 |
    28 | 29 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /17 - Follow Along Link Highlighter/script.js: -------------------------------------------------------------------------------- 1 | const triggers = document.querySelectorAll('a'); 2 | const highlight = document.createElement('span'); 3 | highlight.classList.add('highlight'); 4 | document.body.append(highlight); 5 | 6 | function highlightLink(){ 7 | console.log(this); 8 | const linkCoords = this.getBoundingClientRect(); 9 | console.log(linkCoords); 10 | highlight.style.width = `${linkCoords.width}px`; 11 | highlight.style.height = `${linkCoords.height}px`; 12 | highlight.style.transform = `translate(${linkCoords.left + window.scrollX}px, ${linkCoords.top + window.scrollY}px)`; 13 | 14 | } 15 | triggers.forEach(a => a.addEventListener('mouseenter', highlightLink)); -------------------------------------------------------------------------------- /17 - Follow Along Link Highlighter/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | } 4 | 5 | *, *:before, *:after { 6 | box-sizing: inherit; 7 | } 8 | 9 | body { 10 | min-height: 100vh; 11 | margin: 0; /* Important! */ 12 | font-family: sans-serif; 13 | background: 14 | linear-gradient(45deg, hsla(340, 100%, 55%, 1) 0%, hsla(340, 100%, 55%, 0) 70%), 15 | linear-gradient(135deg, hsla(225, 95%, 50%, 1) 10%, hsla(225, 95%, 50%, 0) 80%), 16 | linear-gradient(225deg, hsla(140, 90%, 50%, 1) 10%, hsla(140, 90%, 50%, 0) 80%), 17 | linear-gradient(315deg, hsla(35, 95%, 55%, 1) 100%, hsla(35, 95%, 55%, 0) 70%); 18 | } 19 | 20 | .wrapper { 21 | margin: 0 auto; 22 | max-width: 500px; 23 | font-size: 20px; 24 | line-height: 2; 25 | position: relative; 26 | } 27 | 28 | a { 29 | text-decoration: none; 30 | color: black; 31 | background: rgba(0,0,0,0.05); 32 | border-radius: 5px; 33 | } 34 | 35 | .highlight { 36 | transition: all .6s; 37 | border-bottom: 2px solid white; 38 | position: absolute; 39 | top: 0; 40 | background: white; 41 | left: 0; 42 | z-index: -1; 43 | border-radius: 5px; 44 | display: block; 45 | box-shadow: 0 0 10px rgba(0,0,0,0.2); 46 | } 47 | 48 | .menu { 49 | padding: 0; 50 | display: flex; 51 | list-style: none; 52 | justify-content: center; 53 | margin:100px 0; 54 | } 55 | 56 | .menu a { 57 | display: inline-block; 58 | padding: 5px; 59 | margin: 0 20px; 60 | color: black; 61 | } 62 | -------------------------------------------------------------------------------- /18 - Speech Synthesis/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Speech Synthesis 6 | 7 | 8 | 9 | 10 | 11 | 12 |
    13 | 14 |

    The VoiceNUb

    15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
    31 | 32 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /18 - Speech Synthesis/script.js: -------------------------------------------------------------------------------- 1 | const msg = new SpeechSynthesisUtterance(); 2 | let voices = []; 3 | const voicesDropdown = document.querySelector('[name="voice"]'); 4 | const options = document.querySelectorAll('[type="range"], [name="text"]'); 5 | const speakButton = document.querySelector('#speak'); 6 | const stopButton = document.querySelector('#stop'); 7 | 8 | msg.text = document.querySelector('[name="text"]').value; 9 | 10 | function populateVoices(){ 11 | voices = this.getVoices(); 12 | const voiceOptions = voices 13 | .filter(voice => voice.lang.includes('en')) 14 | .map(voice => ``) 15 | .join(''); 16 | voicesDropdown.innerHTML = voiceOptions; 17 | 18 | } 19 | 20 | function setVoice(){ 21 | msg.voice = voices.find(voice => voice.name === this.value); 22 | toggle(); 23 | } 24 | 25 | function toggle(startOver = true){ 26 | speechSynthesis.cancel(); 27 | if(startOver){ 28 | speechSynthesis.speak(msg); 29 | } 30 | } 31 | 32 | function setOption(){ 33 | msg[this.name] = this.value; 34 | toggle(); 35 | } 36 | 37 | speechSynthesis.addEventListener('voiceschanged', populateVoices); 38 | voicesDropdown.addEventListener('change', setVoice); 39 | options.forEach(option => option.addEventListener('change', setOption)); 40 | speakButton.addEventListener('click', toggle); 41 | stopButton.addEventListener('click', () => toggle(false)); 42 | -------------------------------------------------------------------------------- /18 - Speech Synthesis/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 10px; 3 | box-sizing: border-box; 4 | } 5 | 6 | *, *:before, *:after { 7 | box-sizing: inherit; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | padding: 0; 13 | font-family: sans-serif; 14 | background-color: #3BC1AC; 15 | display: flex; 16 | min-height: 100vh; 17 | align-items: center; 18 | 19 | background-image: 20 | radial-gradient(circle at 100% 150%, #c13b3b 24%, #42D2BB 25%, #42D2BB 28%, #3BC1AC 29%, #3BC1AC 36%, #42D2BB 36%, #42D2BB 40%, transparent 40%, transparent), 21 | radial-gradient(circle at 0 150%, #3BC1AC 24%, #42D2BB 25%, #42D2BB 28%, #3BC1AC 29%, #3BC1AC 36%, #42D2BB 36%, #42D2BB 40%, transparent 40%, transparent), 22 | radial-gradient(circle at 50% 100%, #42D2BB 10%, #3BC1AC 11%, #3BC1AC 23%, #42D2BB 24%, #42D2BB 30%, #3BC1AC 31%, #3BC1AC 43%, #42D2BB 44%, #42D2BB 50%, #3BC1AC 51%, #3BC1AC 63%, #42D2BB 64%, #42D2BB 71%, transparent 71%, transparent), 23 | radial-gradient(circle at 100% 50%, #42D2BB 5%, #3BC1AC 6%, #3BC1AC 15%, #42D2BB 16%, #42D2BB 20%, #3BC1AC 21%, #3BC1AC 30%, #42D2BB 31%, #42D2BB 35%, #3BC1AC 36%, #3BC1AC 45%, #42D2BB 46%, #42D2BB 49%, transparent 50%, transparent), 24 | radial-gradient(circle at 0 50%, #42D2BB 5%, #3BC1AC 6%, #3BC1AC 15%, #42D2BB 16%, #42D2BB 20%, #3BC1AC 21%, #3BC1AC 30%, #42D2BB 31%, #42D2BB 35%, #3BC1AC 36%, #3BC1AC 45%, #42D2BB 46%, #42D2BB 49%, transparent 50%, transparent); 25 | background-size:100px 50px; 26 | } 27 | 28 | .voiceinator { 29 | padding: 2rem; 30 | width: 50rem; 31 | margin: 0 auto; 32 | border-radius: 1rem; 33 | position: relative; 34 | background: white; 35 | overflow: hidden; 36 | z-index: 1; 37 | box-shadow: 0 0 5px 5px rgba(0,0,0,0.1); 38 | } 39 | 40 | h1 { 41 | width: calc(100% + 4rem); 42 | margin: -2rem 0 2rem -2rem; 43 | padding: .5rem; 44 | background: #00ffee; 45 | border-bottom: 5px solid #F3C010; 46 | text-align: center; 47 | font-size: 5rem; 48 | font-weight: 100; 49 | font-family: 'Pacifico', cursive; 50 | text-shadow: 3px 3px 0 #10ebf3; 51 | } 52 | 53 | .voiceinator input, 54 | .voiceinator button, 55 | .voiceinator select, 56 | .voiceinator textarea { 57 | width: 100%; 58 | display: block; 59 | margin: 10px 0; 60 | padding: 10px; 61 | border: 0; 62 | font-size: 2rem; 63 | background: #F7F7F7; 64 | outline: 0; 65 | } 66 | 67 | textarea { 68 | height: 20rem; 69 | } 70 | 71 | .voiceinator button { 72 | background: #6200ff; 73 | border: 0; 74 | width: 49%; 75 | float: left; 76 | font-family: 'Pacifico', cursive; 77 | margin-bottom: 0; 78 | font-size: 2rem; 79 | border-bottom: 5px solid #F3C010; 80 | cursor: pointer; 81 | position: relative; 82 | } 83 | 84 | .voiceinator button:active { 85 | top: 2px; 86 | } 87 | 88 | .voiceinator button:nth-of-type(1) { 89 | margin-right: 2%; 90 | } 91 | -------------------------------------------------------------------------------- /19 - Stripe Follow Along Nav/Untitled design (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/19 - Stripe Follow Along Nav/Untitled design (2).png -------------------------------------------------------------------------------- /19 - Stripe Follow Along Nav/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Follow Along Nav 7 | 8 | 9 |

    Cool

    10 | 79 | 80 | 81 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /19 - Stripe Follow Along Nav/script.js: -------------------------------------------------------------------------------- 1 | const triggers = document.querySelectorAll('.cool > li'); 2 | const background = document.querySelector('.dropdownBackground'); 3 | const nav = document.querySelector('.top'); 4 | 5 | function handleEnter() { 6 | this.classList.add('trigger-enter'); 7 | setTimeout(() => this.classList.contains('trigger-enter') && this.classList.add('trigger-enter-active'), 150); 8 | background.classList.add('open'); 9 | 10 | const dropdown = this.querySelector('.dropdown'); 11 | const dropdownCoords = dropdown.getBoundingClientRect(); 12 | const navCoords = nav.getBoundingClientRect(); 13 | 14 | const coords = { 15 | height: dropdownCoords.height, 16 | width: dropdownCoords.width, 17 | top: dropdownCoords.top - navCoords.top, 18 | left: dropdownCoords.left - navCoords.left 19 | }; 20 | 21 | background.style.setProperty('width', `${coords.width}px`); 22 | background.style.setProperty('height', `${coords.height}px`); 23 | background.style.setProperty('transform', `translate(${coords.left}px, ${coords.top}px)`); 24 | } 25 | 26 | function handleLeave() { 27 | this.classList.remove('trigger-enter', 'trigger-enter-active'); 28 | background.classList.remove('open'); 29 | } 30 | 31 | triggers.forEach(trigger => trigger.addEventListener('mouseenter', handleEnter)); 32 | triggers.forEach(trigger => trigger.addEventListener('mouseleave', handleLeave)); -------------------------------------------------------------------------------- /19 - Stripe Follow Along Nav/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | font-family: "Arial Rounded MT Bold", "Helvetica Rounded", Arial, sans-serif; 4 | } 5 | 6 | *, *:before, *:after { 7 | box-sizing: inherit; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | min-height: 100vh; 13 | background: url(wallpaperflare.com_wallpaper_2.jpg) center center; 14 | /* linear-gradient(45deg, hsla(340, 100%, 55%, 1) 0%, hsla(340, 100%, 55%, 0) 70%), 15 | linear-gradient(135deg, hsla(225, 95%, 50%, 1) 10%, hsla(225, 95%, 50%, 0) 80%), 16 | linear-gradient(225deg, hsla(140, 90%, 50%, 1) 10%, hsla(140, 90%, 50%, 0) 80%), 17 | linear-gradient(315deg, hsla(35, 95%, 55%, 1) 100%, hsla(35, 95%, 55%, 0) 70%); */ 18 | } 19 | 20 | h2 { 21 | margin-top: 0; 22 | padding-top: .8em; 23 | } 24 | 25 | nav { 26 | position: relative; 27 | perspective: 600px; 28 | } 29 | 30 | .cool > li > a { 31 | color: rgb(255, 0, 0); 32 | text-decoration: none; 33 | font-size: 20px; 34 | font-weight: 700; 35 | letter-spacing: 1px; 36 | background: rgba(0,0,0,0.2); 37 | padding: 10px 20px; 38 | display: inline-block; 39 | margin: 20px; 40 | border-radius: 5px; 41 | } 42 | 43 | nav ul { 44 | list-style: none; 45 | margin: 0; 46 | padding: 0; 47 | display: flex; 48 | justify-content: center; 49 | } 50 | 51 | .cool > li { 52 | position: relative; 53 | display: flex; 54 | justify-content: center; 55 | } 56 | 57 | .dropdown { 58 | opacity: 0; 59 | position: absolute; 60 | overflow: hidden; 61 | padding: 20px; 62 | top: -20px; 63 | border-radius: 2px; 64 | transition: all 0.5s; 65 | transform: translateY(100px); 66 | will-change: opacity; 67 | display: none; 68 | } 69 | 70 | .trigger-enter .dropdown { 71 | display: block; 72 | } 73 | 74 | .trigger-enter-active .dropdown { 75 | opacity: 1; 76 | } 77 | 78 | .dropdownBackground { 79 | width: 100px; 80 | height: 100px; 81 | position: absolute; 82 | background: #fff; 83 | border-radius: 4px; 84 | box-shadow: 0 50px 100px rgba(50,50,93,.1), 0 15px 35px rgba(50,50,93,.15), 0 5px 15px rgba(0,0,0,.1); 85 | transition: all 0.3s, opacity 0.1s, transform 0.2s; 86 | transform-origin: 50% 0; 87 | display: flex; 88 | justify-content: center; 89 | opacity:0; 90 | } 91 | 92 | .dropdownBackground.open { 93 | opacity: 1; 94 | } 95 | 96 | .arrow { 97 | position: absolute; 98 | width: 20px; 99 | height: 20px; 100 | display: block; 101 | background: white; 102 | transform: translateY(-50%) rotate(45deg); 103 | } 104 | 105 | .bio { 106 | min-width: 500px; 107 | display: flex; 108 | justify-content: center; 109 | align-items: center; 110 | line-height: 1.7; 111 | } 112 | 113 | .bio img { 114 | float: left; 115 | margin-right: 20px; 116 | } 117 | 118 | .courses { 119 | min-width: 300px; 120 | } 121 | 122 | .courses li { 123 | padding: 10px 0; 124 | display: block; 125 | border-bottom: 1px solid rgba(0,0,0,0.2); 126 | } 127 | 128 | .dropdown a { 129 | text-decoration: none; 130 | color: #ff0000; 131 | } 132 | 133 | a.button { 134 | background: black; 135 | display: block; 136 | padding: 10px; 137 | color: white; 138 | margin-bottom: 10px; 139 | } 140 | 141 | /* Matches Twitter, TWITTER, twitter, tWitter, TWiTTeR... */ 142 | .button[href*=twitter] { background: #019FE9; } 143 | .button[href*=facebook] { background: #3B5998; } 144 | .button[href*=Portfolio] { background: #ff0000; } -------------------------------------------------------------------------------- /19 - Stripe Follow Along Nav/wallpaperflare.com_wallpaper_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdullahAssi/JavaScript-Projects/2d4f93d37e03d41fd06a3b865e6277a4c097fb51/19 - Stripe Follow Along Nav/wallpaperflare.com_wallpaper_2.jpg -------------------------------------------------------------------------------- /20 - Sticky Nav/index-START.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sticky Nav 6 | 7 | 8 | 9 | 10 |
    11 |

    A story about getting lost.

    12 |
    13 | 14 | 24 | 25 |
    26 | 27 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    28 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    29 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    30 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    31 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    32 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    33 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    34 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    35 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    36 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

    37 | 38 | 39 | 40 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates, deserunt facilis et iste corrupti omnis tenetur est. Iste ut est dicta dolor itaque adipisci, dolorum minima, veritatis earum provident error molestias. Ratione magni illo sint vel velit ut excepturi consectetur suscipit, earum modi accusamus voluptatem nostrum, praesentium numquam, reiciendis voluptas sit id quisquam. Consequatur in quis reprehenderit modi perspiciatis necessitatibus saepe, quidem, suscipit iure natus dignissimos ipsam, eligendi deleniti accusantium, rerum quibusdam fugit perferendis et optio recusandae sed ratione. Culpa, dolorum reprehenderit harum ab voluptas fuga, nisi eligendi natus maiores illum quas quos et aperiam aut doloremque optio maxime fugiat doloribus. Eum dolorum expedita quam, nesciunt

    41 | 42 | 43 | 44 |

    at provident praesentium atque quas rerum optio dignissimos repudiandae ullam illum quibusdam. Vel ad error quibusdam, illo ex totam placeat. Quos excepturi fuga, molestiae ea quisquam minus, ratione dicta consectetur officia omnis, doloribus voluptatibus? Veniam ipsum veritatis architecto, provident quas consequatur doloremque quam quidem earum expedita, ad delectus voluptatum, omnis praesentium nostrum qui aspernatur ea eaque adipisci et cumque ab? Ea voluptatum dolore itaque odio. Eius minima distinctio harum, officia ab nihil exercitationem. Tempora rem nemo nam temporibus molestias facilis minus ipsam quam doloribus consequatur debitis nesciunt tempore officiis aperiam quisquam, molestiae voluptates cum, fuga culpa. Distinctio accusamus quibusdam, tempore perspiciatis dolorum optio facere consequatur quidem ullam beatae architecto, ipsam sequi officiis dignissimos amet impedit natus necessitatibus tenetur repellendus dolor rem! Dicta dolorem, iure, facilis illo ex nihil ipsa amet officia, optio temporibus eum autem odit repellendus nisi. Possimus modi, corrupti error debitis doloribus dicta libero earum, sequi porro ut excepturi nostrum ea voluptatem nihil culpa? Ullam expedita eligendi obcaecati reiciendis velit provident omnis quas qui in corrupti est dolore facere ad hic, animi soluta assumenda consequuntur reprehenderit! Voluptate dolor nihil veniam laborum voluptas nisi pariatur sed optio accusantium quam consectetur, corrupti, sequi et consequuntur, excepturi doloremque. Tempore quis velit corporis neque fugit non sequi eaque rem hic. Facere, inventore, aspernatur. Accusantium modi atque, asperiores qui nobis soluta cumque suscipit excepturi possimus doloremque odit saepe perferendis temporibus molestiae nostrum voluptatum quis id sint quidem nesciunt culpa. Rerum labore dolor beatae blanditiis praesentium explicabo velit optio esse aperiam similique, voluptatem cum, maiores ipsa tempore. Reiciendis sed culpa atque inventore, nam ullam enim expedita consectetur id velit iusto alias vitae explicabo nemo neque odio reprehenderit soluta sint eaque. Aperiam, qui ut tenetur, voluptate doloremque officiis dicta quaerat voluptatem rerum natus magni. Eum amet autem dolor ullam.

    45 | 46 | 47 | 48 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    49 | 50 | 51 | 52 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    53 |

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    54 |
    55 | 56 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /20 - Sticky Nav/script.js: -------------------------------------------------------------------------------- 1 | const nav = document.querySelector('#main'); 2 | const topOfNav = nav.offsetTop; 3 | 4 | 5 | function fixNav() { 6 | if (window.scrollY >= topOfNav) { 7 | document.body.style.paddingTop = nav.offsetHeight + 'px'; 8 | document.body.classList.add('fixed-nav'); 9 | } else { 10 | document.body.style.paddingTop = 0; 11 | document.body.classList.remove('fixed-nav'); 12 | } 13 | } 14 | 15 | 16 | window.addEventListener('scroll', fixNav); 17 | 18 | -------------------------------------------------------------------------------- /20 - Sticky Nav/style-START.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | background: #eeeeee; 4 | font-family: 'helvetica neue'; 5 | font-size: 20px; 6 | font-weight: 200; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | } 12 | 13 | *, *:before, *:after { 14 | box-sizing: inherit; 15 | } 16 | 17 | .site-wrap { 18 | max-width: 700px; 19 | margin: 70px auto; 20 | background: white; 21 | padding: 40px; 22 | text-align: justify; 23 | box-shadow: 0 0 10px 5px rgba(0, 0, 0, 0.05); 24 | transform: scale(0.98); 25 | transition: transform 0.5s; 26 | } 27 | 28 | body.fixed-nav .site-wrap { 29 | transform: scale(1); 30 | } 31 | 32 | header { 33 | text-align: center; 34 | height: 50vh; 35 | background: url(https://source.unsplash.com/GKN6rpDr0EI/960x640) bottom center no-repeat; 36 | background-size: cover; 37 | display: flex; 38 | align-items: center; 39 | justify-content: center; 40 | } 41 | 42 | h1 { 43 | color: white; 44 | font-size: 7vw; 45 | text-shadow: 3px 4px 0 rgba(0,0,0,0.2); 46 | } 47 | 48 | nav { 49 | background: black; 50 | top: 0; 51 | width: 100%; 52 | transition:all 0.5s; 53 | position: relative; 54 | z-index: 1; 55 | } 56 | 57 | /* Nav Game */ 58 | body.fixed-nav nav { 59 | position: fixed; 60 | box-shadow: 0 5px 0 rgba(0,0,0,0.1); 61 | } 62 | 63 | nav ul { 64 | margin: 0; 65 | padding: 0; 66 | list-style: none; 67 | display: flex; 68 | } 69 | 70 | nav li { 71 | flex: 1; 72 | text-align: center; 73 | display: flex; 74 | justify-content: center; 75 | align-items: center; 76 | } 77 | 78 | li.logo { 79 | max-width: 0; 80 | overflow: hidden; 81 | background: white; 82 | transition: all 0.5s; 83 | font-weight: 600; 84 | font-size: 30px; 85 | } 86 | 87 | li.logo a { 88 | color: black; 89 | } 90 | 91 | 92 | /* logo game on scroll */ 93 | 94 | .fixed-nav li.logo { 95 | max-width: 500px; 96 | } 97 | 98 | nav a { 99 | text-decoration: none; 100 | padding: 20px; 101 | display: inline-block; 102 | color: white; 103 | transition: all 0.2s; 104 | text-transform: uppercase; 105 | } 106 | -------------------------------------------------------------------------------- /Digital Clock/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Digital Clock 10 | 11 | 12 |
    13 |
    14 |
    15 |
    16 |
    06 17 |
    18 |
    19 |
    :
    20 |
    21 |
    17 22 |
    23 |
    24 |
    :
    25 |
    26 |
    20 27 |
    28 |
    29 |
    30 |
    31 | Hours 32 | Minutes 33 | Seconds 34 |
    35 |
    36 |
    37 | 39 | 40 | -------------------------------------------------------------------------------- /Digital Clock/script.js: -------------------------------------------------------------------------------- 1 | let hr = document.getElementById("hr"); 2 | let min = document.getElementById("mn"); 3 | let sec = document.getElementById("sc"); 4 | 5 | 6 | setInterval(()=>{ 7 | let currentTime = new Date(); 8 | hr.innerHTML = (currentTime.getHours()<10?"0":"") + currentTime.getHours(); 9 | min.innerHTML = (currentTime.getMinutes()<10?"0":"")+currentTime.getMinutes(); 10 | sec.innerHTML = (currentTime.getSeconds()<10?"0":"")+currentTime.getSeconds(); 11 | },1000); 12 | 13 | 14 | -------------------------------------------------------------------------------- /Digital Clock/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | body{ 7 | display: flex; 8 | flex-direction: column; 9 | align-items: center; 10 | justify-content: center; 11 | min-height: 100vh; 12 | background: linear-gradient(45deg,#08001f,#3124a1); 13 | } 14 | 15 | .hero{ 16 | position: relative; 17 | width: 60%; 18 | min-width: 100vh; 19 | /* background: linear-gradient(270deg,#08001f,#2b17e4); */ 20 | color: #fff; 21 | background: rgba(53, 7, 56, 0.263); 22 | backdrop-filter: blur(90px); 23 | } 24 | .container{ 25 | position: relative; 26 | width: 100%; 27 | min-width: 100vh; 28 | display: flex; 29 | align-items: center; 30 | justify-content: center; 31 | flex-direction: column; 32 | } 33 | .clock{ 34 | display: flex; 35 | /* margin-top: 11rem; */ 36 | font-size: 150px; 37 | } 38 | .hour{ 39 | margin: 1.5rem; 40 | } 41 | .min{ 42 | margin: 1.5rem; 43 | } 44 | .sec{ 45 | margin: 1.5rem; 46 | } 47 | .clock>span{ 48 | 49 | margin: 0 0.5rem;font: 1em sans-serif; 50 | } 51 | .text{ 52 | display: flex; 53 | justify-content: space-around; 54 | width: 100%; 55 | font-size: 20px; 56 | font-family: cursive; 57 | margin-top: -2rem; 58 | margin-bottom: 2rem; 59 | } 60 | 61 | --------------------------------------------------------------------------------