├── .gitignore
├── 01-JS-Drum-Kit
├── index.html
├── package.json
├── sounds
│ ├── boom.wav
│ ├── clap.wav
│ ├── hihat.wav
│ ├── kick.wav
│ ├── openhat.wav
│ ├── ride.wav
│ ├── snare.wav
│ ├── tink.wav
│ └── tom.wav
└── src
│ ├── index.js
│ └── styles.css
├── 02-JS-CSS-Clock
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 03-CSS-Variables
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 04-Array-Cardio-1
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 05-Flex-Gallery
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 06-Type-Ahead
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 07-Array-Cardio-2
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 08-HTML5-Canvas
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 09-Dev-Tools
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 10-Multiple-Check-Shift
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 11-Custom-Video-Player
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 12-Key-Sequence-Detection
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 13-Slide-In-On-Scroll
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 14-JS-Reference-Vs-Copy
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 15-Localstorage
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 16-Mousemove-Shadow
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 17-Sort-Without-Articles
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 18-Add-Time-With-Reduce
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 19-Webcam-Fun
├── .cache
│ ├── 19
│ │ └── 2a340c057017172252c7a98c05d581.json
│ ├── 57
│ │ └── 730c4c4fbb17905544f6301244eb4f.json
│ ├── 99
│ │ └── 9d1e0ef9756b6671230ebd5667ef53.json
│ ├── 1c
│ │ └── bbc204f36037adc9e7df523c6762b0.json
│ ├── ce
│ │ └── cfe6d71944082b11df6af23fa13790.json
│ └── eb
│ │ └── 359863811fcd8b8e7c1af4f52a0b8b.json
├── dist
│ ├── index.html
│ ├── src.a2b27638.js
│ ├── src.a2b27638.js.map
│ ├── styles.dd855970.css
│ ├── styles.dd855970.css.map
│ ├── styles.dd855970.js
│ └── styles.dd855970.js.map
├── index.html
├── package-lock.json
├── package.json
├── snap.mp3
└── src
│ ├── index.js
│ └── styles.css
├── 20-Speech-Recognition
├── index.html
├── package-lock.json
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 21-Geolocation
├── index.html
├── package-lock.json
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 22-Follow-Along-Link
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 23-Speech-Synthesis
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 24-Sticky-Nav
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 25-EventCapture-Propogation-Bubbling
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 26-Stripe-Nav
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 27-Click-Drag-Scroll
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 28-Video-Speed-Controller
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 29-Countdown-Timer
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── 30-Whack-A-Mole
├── index.html
├── package.json
└── src
│ ├── index.js
│ └── styles.css
├── LICENSE
├── README.md
├── assets
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── asteroids.jpg
├── celebration.png
├── dirt.svg
├── fancy-pants.jpg
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
├── green-goblin.png
├── manifest.json
├── mole.svg
├── ocean.jpg
├── og.png
├── plaid.jpg
├── shattered-island.gif
├── special-delivery.jpg
└── wild-sea.png
├── common.css
├── index.html
├── package-lock.json
├── package.json
├── sitemap.xml
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 | dist
35 | .cache
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # TypeScript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 |
62 | # next.js build output
63 | .next
64 |
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JS Drum Kit
6 |
7 |
8 |
12 |
17 |
23 |
29 |
30 |
31 |
32 |
33 |
#1
34 |
of JavaScript30
35 |
36 |
37 |
38 |
JS Drum Kit
39 |
40 |
41 | A
42 | clap
43 |
44 |
45 | S
46 | hihat
47 |
48 |
49 | D
50 | kick
51 |
52 |
53 | F
54 | openhat
55 |
56 |
57 | G
58 | boom
59 |
60 |
61 | H
62 | ride
63 |
64 |
65 | J
66 | snare
67 |
68 |
69 | K
70 | tom
71 |
72 |
73 | L
74 | tink
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "01-js-drum-kit",
3 | "version": "1.0.0",
4 | "description": "Simple Parcel Sandbox",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/boom.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/boom.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/clap.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/clap.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/hihat.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/hihat.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/kick.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/kick.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/openhat.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/openhat.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/ride.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/ride.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/snare.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/snare.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/tink.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/tink.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/sounds/tom.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/01-JS-Drum-Kit/sounds/tom.wav
--------------------------------------------------------------------------------
/01-JS-Drum-Kit/src/index.js:
--------------------------------------------------------------------------------
1 | const keyCodes = {
2 | 'A': 65,
3 | 'S': 83,
4 | 'D': 68,
5 | 'F': 70,
6 | 'G': 71,
7 | 'H': 72,
8 | 'J': 74,
9 | 'K': 75,
10 | 'L': 76,
11 | };
12 |
13 | function removeTransition(e) {
14 | if (e.propertyName !== 'transform') return;
15 | e.target.classList.remove('playing');
16 | }
17 |
18 | function playSound(e) {
19 | const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
20 | const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
21 | if (!audio) return;
22 |
23 | key.classList.add('playing');
24 | audio.currentTime = 0;
25 | audio.play();
26 | }
27 |
28 | function playSoundOnTouch(e) {
29 | // console.log(e);
30 | const audio = document.querySelector(`audio[data-key="${keyCodes[e.path[0].innerText]}"]`);
31 | const key = document.querySelector(`div[data-key="${keyCodes[e.path[0].innerText]}"]`);
32 | if (!audio) return;
33 |
34 | key.classList.add('playing');
35 | audio.currentTime = 0;
36 | audio.play();
37 | }
38 |
39 | const keys = Array.from(document.querySelectorAll('.key'));
40 | keys.forEach((key) => {
41 | key.addEventListener('transitionend', removeTransition);
42 | key.addEventListener('touchstart', playSoundOnTouch, false);
43 | key.addEventListener('click', playSoundOnTouch);
44 | });
45 | window.addEventListener('keydown', playSound);
46 |
--------------------------------------------------------------------------------
/02-JS-CSS-Clock/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JS + CSS Clock
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#2
30 |
of JavaScript30
31 |
32 |
33 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/02-JS-CSS-Clock/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parcel-sandbox",
3 | "version": "1.0.0",
4 | "description": "Simple Parcel Sandbox",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | }
15 | }
--------------------------------------------------------------------------------
/02-JS-CSS-Clock/src/index.js:
--------------------------------------------------------------------------------
1 | const secondHand = document.querySelector(".second-hand");
2 | const minuteHand = document.querySelector(".min-hand");
3 | const hourHand = document.querySelector(".hour-hand");
4 |
5 | function setDate() {
6 | const now = new Date();
7 |
8 | const seconds = now.getSeconds();
9 | const secondDegrees = (seconds / 60) * 360 + 90;
10 | secondHand.style.transform = `rotate(${secondDegrees}deg)`;
11 |
12 | const minutes = now.getMinutes();
13 | const minuteDegrees = (minutes / 60) * 360 + 90;
14 | minuteHand.style.transform = `rotate(${minuteDegrees}deg)`;
15 |
16 | const hours = now.getHours();
17 | const hourDegrees = (hours / 12) * 360 + 90;
18 | hourHand.style.transform = `rotate(${hourDegrees}deg)`;
19 | }
20 |
21 | setInterval(setDate, 1000);
22 |
--------------------------------------------------------------------------------
/02-JS-CSS-Clock/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | /* background: #018ded; */
3 | background-color: #018ded;
4 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%2313042b' fill-opacity='0.1' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E");
5 | font-family: "helvetica neue";
6 | text-align: center;
7 | font-size: 10px;
8 | }
9 | body {
10 | margin: 0;
11 | font-size: 2rem;
12 | display: flex;
13 | flex: 1;
14 | min-height: 100vh;
15 | align-items: center;
16 | }
17 | .clock {
18 | width: 30rem;
19 | height: 30rem;
20 | border: 20px solid white;
21 | border-radius: 50%;
22 | margin: 50px auto;
23 | position: relative;
24 | padding: 2rem;
25 | box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1), inset 0 0 0 3px #efefef,
26 | inset 0 0 10px black, 0 0 10px rgba(0, 0, 0, 0.2);
27 | }
28 | .clock-face {
29 | position: relative;
30 | width: 100%;
31 | height: 100%;
32 | transform: translateY(-3px); /* account for the height of the clock hands */
33 | }
34 | .hand {
35 | width: 50%;
36 | height: 6px;
37 | background: black;
38 | position: absolute;
39 | top: 50%;
40 | transform-origin: 100%;
41 | transform: rotate(90deg);
42 | transition: all 0.05s;
43 | transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
44 | border-radius: 5px;
45 | }
46 |
47 | .hour-hand {
48 | width: 25%;
49 | margin-left: 25%;
50 | background: rgb(0, 255, 221);
51 | }
52 |
53 | .min-hand {
54 | width: 40%;
55 | margin-left: 10%;
56 | background: rgb(128, 51, 0);
57 | }
58 |
59 | .inner-circle {
60 | top: 50%;
61 | position: absolute;
62 | margin-left: 48%;
63 | width: 10px;
64 | height: 10px;
65 | border: 3px solid balck;
66 | border-radius: 50%;
67 | background: white;
68 | }
69 |
--------------------------------------------------------------------------------
/03-CSS-Variables/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Scoped CSS Variables and JS
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#3
30 |
of JavaScript30
31 |
32 |
33 | Update CSS Variables with JS
34 |
35 |
36 | Spacing:
37 |
46 |
47 | Blur:
48 |
57 |
58 | Base Color
59 |
60 |
61 | Border Radius:
62 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/03-CSS-Variables/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parcel-sandbox",
3 | "version": "1.0.0",
4 | "description": "Simple Parcel Sandbox",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | }
15 | }
--------------------------------------------------------------------------------
/03-CSS-Variables/src/index.js:
--------------------------------------------------------------------------------
1 | const inputs = document.querySelectorAll(".controls input");
2 |
3 | function handleUpdate() {
4 | const suffix = this.dataset.sizing || "";
5 | document.documentElement.style.setProperty(
6 | `--${this.name}`,
7 | this.value + suffix
8 | );
9 | }
10 |
11 | inputs.forEach(input => input.addEventListener("change", handleUpdate));
12 | inputs.forEach(input => input.addEventListener("mousemove", handleUpdate));
13 |
--------------------------------------------------------------------------------
/03-CSS-Variables/src/styles.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --base: #ffc600;
3 | --spacing: 10px;
4 | --blur: 10px;
5 | --border-radius: 10px;
6 | }
7 |
8 | body {
9 | text-align: center;
10 | background-image: url('../../assets/fancy-pants.jpg');
11 | background-color: #242329;
12 | color: white;
13 | font-family: 'helvetica neue', sans-serif;
14 | font-weight: 100;
15 | font-size: 50px;
16 | }
17 | .controls {
18 | margin-bottom: 50px;
19 | }
20 | input {
21 | width: 100px;
22 | }
23 |
24 | img {
25 | padding: var(--spacing);
26 | background: var(--base);
27 | filter: blur(var(--blur));
28 | border-radius: var(--border-radius);
29 | background-size: cover;
30 | }
31 |
32 | .hl {
33 | color: var(--base);
34 | }
35 |
--------------------------------------------------------------------------------
/04-Array-Cardio-1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Array Cardio 💪
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#4
30 |
of JavaScript30
31 |
32 |
33 | Psst: have a look at the JavaScript Console 💁
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/04-Array-Cardio-1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "array-cardio",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/04-Array-Cardio-1/src/index.js:
--------------------------------------------------------------------------------
1 | const inventors = [
2 | { first: "Albert", last: "Einstein", year: 1879, passed: 1955 },
3 | { first: "Isaac", last: "Newton", year: 1643, passed: 1727 },
4 | { first: "Galileo", last: "Galilei", year: 1564, passed: 1642 },
5 | { first: "Marie", last: "Curie", year: 1867, passed: 1934 },
6 | { first: "Johannes", last: "Kepler", year: 1571, passed: 1630 },
7 | { first: "Nicolaus", last: "Copernicus", year: 1473, passed: 1543 },
8 | { first: "Max", last: "Planck", year: 1858, passed: 1947 },
9 | { first: "Katherine", last: "Blodgett", year: 1898, passed: 1979 },
10 | { first: "Ada", last: "Lovelace", year: 1815, passed: 1852 },
11 | { first: "Sarah E.", last: "Goode", year: 1855, passed: 1905 },
12 | { first: "Lise", last: "Meitner", year: 1878, passed: 1968 },
13 | { first: "Hanna", last: "Hammarström", year: 1829, passed: 1909 }
14 | ];
15 |
16 | const people = [
17 | "Beck, Glenn",
18 | "Becker, Carl",
19 | "Beckett, Samuel",
20 | "Beddoes, Mick",
21 | "Beecher, Henry",
22 | "Beethoven, Ludwig",
23 | "Begin, Menachem",
24 | "Belloc, Hilaire",
25 | "Bellow, Saul",
26 | "Benchley, Robert",
27 | "Benenson, Peter",
28 | "Ben-Gurion, David",
29 | "Benjamin, Walter",
30 | "Benn, Tony",
31 | "Bennington, Chester",
32 | "Benson, Leana",
33 | "Bent, Silas",
34 | "Bentsen, Lloyd",
35 | "Berger, Ric",
36 | "Bergman, Ingmar",
37 | "Berio, Luciano",
38 | "Berle, Milton",
39 | "Berlin, Irving",
40 | "Berne, Eric",
41 | "Bernhard, Sandra",
42 | "Berra, Yogi",
43 | "Berry, Halle",
44 | "Berry, Wendell",
45 | "Bethea, Erin",
46 | "Bevan, Aneurin",
47 | "Bevel, Ken",
48 | "Biden, Joseph",
49 | "Bierce, Ambrose",
50 | "Biko, Steve",
51 | "Billings, Josh",
52 | "Biondo, Frank",
53 | "Birrell, Augustine",
54 | "Black, Elk",
55 | "Blair, Robert",
56 | "Blair, Tony",
57 | "Blake, William"
58 | ];
59 |
60 | // Array.protot ype.filter()
61 | // 1. Filter the list of inventors for those who were born in the 1500's
62 | const fifteen = inventors.filter(
63 | inventor => inventor.year >= 1500 && inventor.year < 1600
64 | );
65 | console.table(fifteen);
66 |
67 | // Array.prototype.map()
68 | // 2. Give us an array of the inventors' first and last names
69 | const fullNames = inventors.map(
70 | inventor => `${inventor.first} ${inventor.last}`
71 | );
72 | console.log(fullNames);
73 |
74 | // Array.prototype.sort()
75 | // 3. Sort the inventors by birthdate, oldest to youngest
76 | const sorted = inventors.sort((a, b) => (a.year > b.year ? 1 : -1));
77 | console.table(sorted);
78 |
79 | // Array.prototype.reduce()
80 | // 4. How many years did all the inventors live?
81 | const totalYears = inventors.reduce(
82 | (total, inventor) => total + (inventor.passed - inventor.year),
83 | 0
84 | );
85 | console.log(totalYears);
86 |
87 | // 5. Sort the inventors by years lived
88 | const oldest = inventors.sort((a, b) => {
89 | const lastGuy = a.passed - a.year;
90 | const nextGuy = b.passed - b.year;
91 | return lastGuy > nextGuy ? -1 : 1;
92 | });
93 | console.table(oldest);
94 |
95 | // 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name
96 | // https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris
97 |
98 | // const category = document.querySelector(".mw-category");
99 |
100 | // const links = category.querySelectorAll('a');
101 | // the above returns a NodeList, not an array. NodeList is like an array but doesn't contain all of the array methods.
102 | // We can convert to array in two ways.
103 | //1. const links = [...category.querySelectorAll('a')]
104 | //2. below
105 |
106 | // const links = Array.from(category.querySelectorAll("a"));
107 |
108 | // const de = links
109 | // .map(link => link.textContent)
110 | // .filter(streetName => streetName.includes("de"));
111 |
112 | // 7. sort Exercise
113 | // Sort the people alphabetically by last name
114 | const alpha = people.sort((lastOne, nextOne) => {
115 | const [aLast, aFirst] = lastOne.split(", ");
116 | const [bLast, bFirst] = nextOne.split(", ");
117 | return aLast > bLast ? 1 : -1;
118 | });
119 | console.log(alpha);
120 |
121 | // 8. Reduce Exercise
122 | // Sum up the instances of each of these
123 | const data = [
124 | "car",
125 | "car",
126 | "truck",
127 | "truck",
128 | "bike",
129 | "walk",
130 | "car",
131 | "van",
132 | "bike",
133 | "walk",
134 | "car",
135 | "van",
136 | "car",
137 | "truck"
138 | ];
139 |
140 | const transportation = data.reduce((obj, item) => {
141 | if (!obj[item]) {
142 | obj[item] = 0;
143 | }
144 | obj[item]++;
145 | return obj;
146 | }, {});
147 |
148 | console.log(transportation);
149 |
--------------------------------------------------------------------------------
/04-Array-Cardio-1/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-image: url('../../assets/wild-sea.png');
3 | background-color: #FFA23B;
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | height: 100vh;
8 | font-family: monospace;
9 | font-size: large;
10 | font-weight: bolder;
11 | }
--------------------------------------------------------------------------------
/05-Flex-Gallery/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flex Panels 💪 - JavaScript30 - Ayush Gupta
6 |
11 |
12 |
13 |
18 |
24 |
30 |
31 |
32 |
33 |
34 |
#5
35 |
of JavaScript30
36 |
37 |
38 |
39 |
40 |
Hey
41 |
Let's
42 |
Dance
43 |
44 |
45 |
Give
46 |
Take
47 |
Receive
48 |
49 |
50 |
Experience
51 |
It
52 |
Today
53 |
54 |
55 |
Give
56 |
All
57 |
You can
58 |
59 |
60 |
Life
61 |
In
62 |
Motion
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/05-Flex-Gallery/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flex-panel-gallery",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/05-Flex-Gallery/src/index.js:
--------------------------------------------------------------------------------
1 | const panels = document.querySelectorAll(".panel");
2 |
3 | function toggleOpen() {
4 | this.classList.toggle("open");
5 | }
6 |
7 | function toggleActive(e) {
8 | // this.classList.toggle("open-active");
9 | //we didn't used above statement as there are multiple transition events happening.
10 | if (e.propertyName.includes("flex")) {
11 | this.classList.toggle("open-active");
12 | }
13 | }
14 |
15 | panels.forEach(panel => panel.addEventListener("click", toggleOpen));
16 | panels.forEach(panel => panel.addEventListener("transitionend", toggleActive));
17 |
--------------------------------------------------------------------------------
/05-Flex-Gallery/src/styles.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 | body {
10 | margin: 0;
11 | }
12 |
13 | *,
14 | *:before,
15 | *:after {
16 | box-sizing: inherit;
17 | }
18 |
19 | .panels {
20 | min-height: 100vh;
21 | overflow: hidden;
22 | display: flex;
23 | }
24 |
25 | .panel {
26 | background: #6b0f9c;
27 | box-shadow: inset 0 0 0 5px rgba(255, 255, 255, 0.1);
28 | color: white;
29 | text-align: center;
30 | align-items: center;
31 | /* Safari transitionend event.propertyName === flex */
32 | /* Chrome + FF transitionend event.propertyName === flex-grow */
33 | transition: 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), background 0.2s;
35 | font-size: 20px;
36 | background-size: cover;
37 | background-position: center;
38 | flex: 1;
39 | display: flex;
40 | flex-direction: column;
41 | justify-content: center;
42 | }
43 |
44 | .panel1 {
45 | background-image: url(https://source.unsplash.com/gYl-UtwNg_I/1500x1500);
46 | }
47 | .panel2 {
48 | background-image: url(https://source.unsplash.com/rFKUFzjPYiQ/1500x1500);
49 | }
50 | .panel3 {
51 | 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);
52 | }
53 | .panel4 {
54 | background-image: url(https://source.unsplash.com/ITjiVXcwVng/1500x1500);
55 | }
56 | .panel5 {
57 | background-image: url(https://source.unsplash.com/3MNzGlQM7qs/1500x1500);
58 | }
59 |
60 | /* Flex Children */
61 | .panel > * {
62 | margin: 0;
63 | width: 100%;
64 | transition: transform 0.5s;
65 | flex: 1 0 auto;
66 | display: flex;
67 | justify-content: center;
68 | align-items: center;
69 | }
70 |
71 | .panel > *:first-child {
72 | transform: translateY(-100%);
73 | }
74 | .panel.open-active > *:first-child {
75 | transform: translateY(0);
76 | }
77 | .panel > *:last-child {
78 | transform: translateY(100%);
79 | }
80 | .panel.open-active > *:last-child {
81 | transform: translateY(0);
82 | }
83 |
84 | .panel p {
85 | text-transform: uppercase;
86 | font-family: "Amatic SC", cursive;
87 | text-shadow: 0 0 4px rgba(0, 0, 0, 0.72), 0 0 14px rgba(0, 0, 0, 0.45);
88 | font-size: 2em;
89 | }
90 |
91 | .panel p:nth-child(2) {
92 | font-size: 4em;
93 | }
94 | .panel.open {
95 | font-size: 40px;
96 | flex: 5;
97 | }
98 |
--------------------------------------------------------------------------------
/06-Type-Ahead/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Type Ahead 👀 - JavaScript30 by Ayush Gupta
5 |
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
#6
31 |
of JavaScript30
32 |
33 |
34 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/06-Type-Ahead/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ajax-type-ahead",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/06-Type-Ahead/src/index.js:
--------------------------------------------------------------------------------
1 | const endpoint =
2 | "https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json";
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 | const regex = new RegExp(wordToMatch, "gi");
12 | return place.city.match(regex) || place.state.match(regex);
13 | });
14 | }
15 |
16 | function numberWithCommas(x) {
17 | return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
18 | }
19 |
20 | function displayMatches() {
21 | const matchArray = findMatches(this.value, cities);
22 | const html = matchArray
23 | .map(place => {
24 | const regex = new RegExp(this.value, "gi");
25 | const cityName = place.city.replace(
26 | regex,
27 | `${this.value} `
28 | );
29 | const stateName = place.state.replace(
30 | regex,
31 | `${this.value} `
32 | );
33 |
34 | return `
35 |
36 | ${cityName}, ${stateName}
37 | ${numberWithCommas(place.population)}
38 |
39 | `;
40 | })
41 | .join("");
42 | suggestions.innerHTML = html;
43 | }
44 |
45 | const searchInput = document.querySelector(".search");
46 | const suggestions = document.querySelector(".suggestions");
47 |
48 | searchInput.addEventListener("change", displayMatches);
49 | searchInput.addEventListener("keyup", displayMatches);
50 |
--------------------------------------------------------------------------------
/06-Type-Ahead/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | background-image: url('../../assets/special-delivery.jpg');
4 | background-color: #D8C547;
5 | font-family: "helvetica neue";
6 | font-size: 20px;
7 | font-weight: 200;
8 | }
9 |
10 | *,
11 | *:before,
12 | *:after {
13 | box-sizing: inherit;
14 | }
15 |
16 | input {
17 | width: 100%;
18 | padding: 20px;
19 | }
20 |
21 | .search-form {
22 | max-width: 400px;
23 | margin: 50px auto;
24 | }
25 |
26 | input.search {
27 | margin: 0;
28 | text-align: center;
29 | outline: 0;
30 | border: 10px solid #f7f7f7;
31 | width: 120%;
32 | left: -10%;
33 | position: relative;
34 | top: 10px;
35 | z-index: 2;
36 | border-radius: 5px;
37 | font-size: 40px;
38 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.19);
39 | }
40 |
41 | .suggestions {
42 | margin: 0;
43 | padding: 0;
44 | position: relative;
45 | /*perspective: 20px;*/
46 | }
47 |
48 | .suggestions li {
49 | background: white;
50 | list-style: none;
51 | border-bottom: 1px solid #d8d8d8;
52 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.14);
53 | margin: 0;
54 | padding: 20px;
55 | transition: background 0.2s;
56 | display: flex;
57 | justify-content: space-between;
58 | text-transform: capitalize;
59 | }
60 |
61 | .suggestions li:nth-child(even) {
62 | transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001);
63 | background: linear-gradient(to bottom, #ffffff 0%, #efefef 100%);
64 | }
65 |
66 | .suggestions li:nth-child(odd) {
67 | transform: perspective(100px) rotateX(-3deg) translateY(3px);
68 | background: linear-gradient(to top, #ffffff 0%, #efefef 100%);
69 | }
70 |
71 | span.population {
72 | font-size: 15px;
73 | }
74 |
75 | .hl {
76 | background: #ffc600;
77 | }
78 |
--------------------------------------------------------------------------------
/07-Array-Cardio-2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Array Cardio 💪💪 - JavaScript30 by Ayush Gupta
5 |
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
#7
31 |
of JavaScript30
32 |
33 |
34 | Psst: have a look at the JavaScript Console 💁
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/07-Array-Cardio-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "array-cardio-2",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/07-Array-Cardio-2/src/index.js:
--------------------------------------------------------------------------------
1 | // ## Array Cardio Day 2
2 | const people = [
3 | { name: "Wes", year: 1988 },
4 | { name: "Kait", year: 1986 },
5 | { name: "Irv", year: 1970 },
6 | { name: "Lux", year: 2015 }
7 | ];
8 | const comments = [
9 | { text: "Love this!", id: 523423 },
10 | { text: "Super good", id: 823423 },
11 | { text: "You are the best", id: 2039842 },
12 | { text: "Ramen is my fav food ever", id: 123523 },
13 | { text: "Nice Nice Nice!", id: 542328 }
14 | ];
15 | // Some and Every Checks
16 | // Array.prototype.some() // is at least one person 19 or older?
17 | const isAdult = people.some(
18 | person => new Date().getFullYear() - person.year >= 19
19 | );
20 | console.log({ isAdult });
21 |
22 | // Array.prototype.every() // is everyone 19 or older?
23 | const allAdults = people.every(
24 | person => new Date().getFullYear() - person.year >= 19
25 | );
26 | console.log({ allAdults });
27 |
28 | // Array.prototype.find()
29 | // Find is like filter, but instead returns just the one you are looking for
30 | // find the comment with the ID of 823423
31 | const comment = comments.find(comment => comment.id === 823423);
32 | console.log(comment);
33 |
34 | // Array.prototype.findIndex()
35 | // Find the comment with this ID
36 | const index = comments.findIndex(comment => comment.id === 823423);
37 |
38 | // delete the comment with the ID of 823423
39 |
40 | // comments.splice(index, 1);
41 | // console.table(comments);
42 |
43 | const newComments = [...comments.slice(0, index), ...comments.slice(index + 1)];
44 | console.table(newComments);
45 |
--------------------------------------------------------------------------------
/07-Array-Cardio-2/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-image: url('../../assets/green-goblin.png');
3 | background-color: #8AAA00;
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | height: 100vh;
8 | font-family: monospace;
9 | font-size: large;
10 | font-weight: bolder;
11 | }
--------------------------------------------------------------------------------
/08-HTML5-Canvas/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HTML5 Canvas - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
#8
31 |
of JavaScript30
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/08-HTML5-Canvas/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "html5-canvas",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/08-HTML5-Canvas/src/index.js:
--------------------------------------------------------------------------------
1 | const canvas = document.querySelector("#draw");
2 | const context = canvas.getContext("2d");
3 | canvas.width = window.innerWidth;
4 | canvas.height = window.innerHeight;
5 | context.font = "8px";
6 | context.fillText("Start Painting", window.innerWidth / 2, 50);
7 | context.strokeStyle = "#BADA55";
8 | context.lineJoin = "round";
9 | context.lineCap = "round";
10 | context.lineWidth = 0;
11 | context.globalCompositeOperation = "lighten";
12 |
13 | let isDrawing = false;
14 | let lastX = 0;
15 | let lastY = 0;
16 | let hue = 0;
17 | let direction = true;
18 | function draw(e) {
19 | //stop fxn from running when not mouse downed
20 | if (!isDrawing) return;
21 | // console.log(e);
22 | context.strokeStyle = `hsl(${hue++}, 100%, 50%)`;
23 | context.beginPath();
24 | //start from
25 | context.moveTo(lastX, lastY);
26 | //go to
27 | context.lineTo(e.offsetX, e.offsetY);
28 | context.stroke();
29 | [lastX, lastY] = [e.offsetX, e.offsetY];
30 |
31 | if (hue >= 360) {
32 | hue = 0;
33 | }
34 | if (context.lineWidth >= 100 || context.lineWidth <= 1) {
35 | direction = !direction;
36 | }
37 | if (direction) {
38 | context.lineWidth++;
39 | } else {
40 | context.lineWidth--;
41 | }
42 | }
43 |
44 | canvas.addEventListener("mousemove", draw);
45 | canvas.addEventListener("mousedown", e => {
46 | isDrawing = true;
47 | [lastX, lastY] = [e.offsetX, e.offsetY];
48 | });
49 | canvas.addEventListener("mouseup", () => (isDrawing = false));
50 | canvas.addEventListener("mouseout", () => (isDrawing = false));
51 | // canvas.addEventListener("mouseover", () => (isDrawing = true));
52 |
--------------------------------------------------------------------------------
/08-HTML5-Canvas/src/styles.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | margin: 0;
4 | }
5 |
--------------------------------------------------------------------------------
/09-Dev-Tools/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dev Tools - JavaScript30 by Ayush Gupta
5 |
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
#9
31 |
of JavaScript30
32 |
33 |
34 | × DON'T×CLICK ×
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/09-Dev-Tools/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "devtools-tricks",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/09-Dev-Tools/src/index.js:
--------------------------------------------------------------------------------
1 | const dogs = [{ name: 'Snickers', age: 2 }, { name: 'hugo', age: 8 }];
2 |
3 | function makeGreen() {
4 | const p = document.querySelector('p');
5 | p.style.color = '#BADA55';
6 | p.style.fontSize = '50px';
7 | p.innerText = "x GO, HAVE A LOOK AT CONSOLE x"
8 | }
9 |
10 | // Regular
11 | console.log("hello");
12 | // Interpolated
13 | console.log("Hello I am a %s string!", "💩");
14 | // Styled
15 | console.log('%c I am some great text', 'font-size:50px; background:red; text-shadow: 10px 10px 0 blue')
16 | // warning!
17 | console.warn("OH NOOO");
18 | // Error :|
19 | console.error("Shit!");
20 | // Info
21 | console.info("Crocodiles eat 3-4 people per year");
22 | // Testing
23 | const p = document.querySelector("p");
24 | console.assert(p.classList.contains("ouch"), "That is wrong!");
25 | // clearing
26 | console.clear();
27 | // Viewing DOM Elements
28 | console.log(p);
29 | console.dir(p);
30 | console.clear();
31 | // Grouping together
32 | dogs.forEach(dog => {
33 | console.groupCollapsed(`${dog.name}`);
34 | console.log(`This is ${dog.name}`);
35 | console.log(`${dog.name} is ${dog.age} years old`);
36 | console.log(`${dog.name} is ${dog.age * 7} dog years old`);
37 | console.groupEnd(`${dog.name}`);
38 | });
39 | // counting
40 | console.count("Ayush");
41 | console.count("Ayush");
42 | console.count("Gupta");
43 | console.count("Gupta");
44 | console.count("Ayush");
45 | console.count("Gupta");
46 | console.count("Ayush");
47 | console.count("Gupta");
48 | console.count("Gupta");
49 | console.count("Gupta");
50 | console.count("Gupta");
51 | console.count("Gupta");
52 | // timing
53 | console.time("fetching data");
54 | fetch("https://api.github.com/users/gupta-ji6")
55 | .then(data => data.json())
56 | .then(data => {
57 | console.timeEnd("fetching data");
58 | console.log(data);
59 | });
60 | console.table(dogs);
61 |
--------------------------------------------------------------------------------
/10-Multiple-Check-Shift/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hold Shift to Check Multiple Checkboxes - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
31 |
32 |
33 |
#10
34 |
of JavaScript30
35 |
36 |
37 |
38 |
39 |
40 |
This is an inbox layout.
41 |
42 |
43 |
44 |
Check one item
45 |
46 |
47 |
48 |
Hold down your Shift key
49 |
50 |
51 |
52 |
Check a lower item
53 |
54 |
55 |
56 |
Everything in between should also be set to checked
57 |
58 |
59 |
60 |
Try to do it without any libraries
61 |
62 |
63 |
64 |
Just regular JavaScript
65 |
66 |
67 |
68 |
Good Luck!
69 |
70 |
71 |
72 |
Don't forget to tweet your result!
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/10-Multiple-Check-Shift/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multiple-check-with-shift",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/10-Multiple-Check-Shift/src/index.js:
--------------------------------------------------------------------------------
1 | const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]');
2 |
3 | let lastChecked;
4 |
5 | function handleCheck(e) {
6 | // check if they had shiift key down and they are checking it, not unchecking it
7 | let inBetween = false;
8 | if (e.shiftKey && this.checked) {
9 | // loop over every single checkbox
10 | checkboxes.forEach(checkbox => {
11 | if (checkbox === this || checkbox === lastChecked) {
12 | inBetween = !inBetween;
13 | }
14 |
15 | if (inBetween) {
16 | checkbox.checked = true;
17 | }
18 | });
19 | }
20 | lastChecked = this;
21 | }
22 |
23 | checkboxes.forEach(checkbox => checkbox.addEventListener("click", handleCheck));
24 |
--------------------------------------------------------------------------------
/10-Multiple-Check-Shift/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-family: sans-serif;
3 | background: #CBDEE6;
4 | background-image: url('../../assets/plaid.jpg');
5 | }
6 | .inbox {
7 | max-width: 400px;
8 | margin: 50px auto;
9 | background: white;
10 | border-radius: 5px;
11 | box-shadow: 10px 10px 0 rgba(0,0,0,0.1);
12 | }
13 | .item {
14 | display: flex;
15 | align-items: center;
16 | border-bottom: 1px solid #F1F1F1;
17 | }
18 | .item:last-child {
19 | border-bottom: 0;
20 | }
21 | input:checked + p {
22 | background: #F9F9F9;
23 | text-decoration: line-through;
24 | }
25 | input[type="checkbox"] {
26 | margin: 20px;
27 | }
28 | p {
29 | margin: 0;
30 | padding: 20px;
31 | transition: background 0.2s;
32 | flex: 1;
33 | font-family:'helvetica neue';
34 | font-size: 20px;
35 | font-weight: 200;
36 | border-left: 1px solid #D1E2FF;
37 | }
--------------------------------------------------------------------------------
/11-Custom-Video-Player/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HTML Video Player - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#11
30 |
of JavaScript30
31 |
32 |
33 |
34 |
38 |
39 |
40 |
43 |
►
44 |
53 |
62 |
« 10s
63 |
25s »
64 |
FullScreen
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/11-Custom-Video-Player/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "custom-htm5-player",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/11-Custom-Video-Player/src/index.js:
--------------------------------------------------------------------------------
1 | // Get 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 | const fullScreen = player.querySelector(".player__fullscreen");
10 |
11 | // Build Functions
12 | function togglePlay() {
13 | const method = video.paused ? "play" : "pause";
14 | video[method]();
15 | // if(video.paused) {
16 | // video.play();
17 | // } else {
18 | // video.pause();
19 | // }
20 | }
21 |
22 | function updateButton() {
23 | const icon = this.paused ? "►" : "Pause";
24 | toggle.textContent = icon;
25 | }
26 |
27 | function skip() {
28 | video.currentTime += parseFloat(this.dataset.skip);
29 | }
30 |
31 | function handleRangeChange() {
32 | video[this.name] = this.value;
33 | console.log(this.value);
34 | console.log(this.name);
35 | }
36 |
37 | function handleProgress() {
38 | const percent = (video.currentTime / video.duration) * 100;
39 | progressBar.style.flexBasis = `${percent}%`;
40 | }
41 |
42 | function scrub(e) {
43 | const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
44 | video.currentTime = scrubTime;
45 | }
46 |
47 | function handleFullscreen() {
48 | if (!isFull) {
49 | fullScreen.textContent = "Exit Fullscreen";
50 | if (player.requestFullscreen) {
51 | player.requestFullscreen();
52 | } else if (player.mozRequestFullScreen) {
53 | /* Firefox */
54 | player.mozRequestFullScreen();
55 | } else if (player.webkitRequestFullscreen) {
56 | /* Chrome, Safari and Opera */
57 | player.webkitRequestFullscreen();
58 | } else if (player.msRequestFullscreen) {
59 | /* IE/Edge */
60 | player.msRequestFullscreen();
61 | }
62 | } else if (isFull) {
63 | fullScreen.textContent = "Fullscreen";
64 |
65 | if (document.exitFullscreen) {
66 | document.exitFullscreen();
67 | } else if (document.webkitCancelFullScreen) {
68 | document.webkitCancelFullScreen();
69 | } else if (player.mozCancelFullScreen) {
70 | player.mozCancelFullScreen();
71 | } else if (player.msCancelFullScreen) {
72 | player.msCancelFullScreen();
73 | }
74 | }
75 | isFull = !isFull;
76 | }
77 |
78 | // Add evenet listeners
79 | video.addEventListener("click", togglePlay);
80 | video.addEventListener("play", updateButton);
81 | video.addEventListener("pause", updateButton);
82 | video.addEventListener("timeupdate", handleProgress);
83 | toggle.addEventListener("click", togglePlay);
84 |
85 | skipButtons.forEach(button => button.addEventListener("click", skip));
86 |
87 | ranges.forEach(range => range.addEventListener("change", handleRangeChange));
88 |
89 | let mousedown = false;
90 | progress.addEventListener("click", scrub);
91 | progress.addEventListener("mousemove", e => mousedown && scrub(e));
92 | progress.addEventListener("mousedown", () => (mousedown = true));
93 | progress.addEventListener("mouseup", () => (mousedown = false));
94 | let isFull = false;
95 | fullScreen.addEventListener("click", handleFullscreen);
96 |
--------------------------------------------------------------------------------
/11-Custom-Video-Player/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | }
4 |
5 | *,
6 | *:before,
7 | *:after {
8 | box-sizing: inherit;
9 | }
10 |
11 | body {
12 | margin: 0;
13 | padding: 0;
14 | display: flex;
15 | background: #7a419b;
16 | min-height: 100vh;
17 | /* background: linear-gradient(135deg, #7c1599 0%, #921099 48%, #7e4ae8 100%); */
18 | background-color: #9B39A8;
19 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 28' width='56' height='28'%3E%3Cpath fill='%23ebeaec' fill-opacity='0.18' d='M56 26v2h-7.75c2.3-1.27 4.94-2 7.75-2zm-26 2a2 2 0 1 0-4 0h-4.09A25.98 25.98 0 0 0 0 16v-2c.67 0 1.34.02 2 .07V14a2 2 0 0 0-2-2v-2a4 4 0 0 1 3.98 3.6 28.09 28.09 0 0 1 2.8-3.86A8 8 0 0 0 0 6V4a9.99 9.99 0 0 1 8.17 4.23c.94-.95 1.96-1.83 3.03-2.63A13.98 13.98 0 0 0 0 0h7.75c2 1.1 3.73 2.63 5.1 4.45 1.12-.72 2.3-1.37 3.53-1.93A20.1 20.1 0 0 0 14.28 0h2.7c.45.56.88 1.14 1.29 1.74 1.3-.48 2.63-.87 4-1.15-.11-.2-.23-.4-.36-.59H26v.07a28.4 28.4 0 0 1 4 0V0h4.09l-.37.59c1.38.28 2.72.67 4.01 1.15.4-.6.84-1.18 1.3-1.74h2.69a20.1 20.1 0 0 0-2.1 2.52c1.23.56 2.41 1.2 3.54 1.93A16.08 16.08 0 0 1 48.25 0H56c-4.58 0-8.65 2.2-11.2 5.6 1.07.8 2.09 1.68 3.03 2.63A9.99 9.99 0 0 1 56 4v2a8 8 0 0 0-6.77 3.74c1.03 1.2 1.97 2.5 2.79 3.86A4 4 0 0 1 56 10v2a2 2 0 0 0-2 2.07 28.4 28.4 0 0 1 2-.07v2c-9.2 0-17.3 4.78-21.91 12H30zM7.75 28H0v-2c2.81 0 5.46.73 7.75 2zM56 20v2c-5.6 0-10.65 2.3-14.28 6h-2.7c4.04-4.89 10.15-8 16.98-8zm-39.03 8h-2.69C10.65 24.3 5.6 22 0 22v-2c6.83 0 12.94 3.11 16.97 8zm15.01-.4a28.09 28.09 0 0 1 2.8-3.86 8 8 0 0 0-13.55 0c1.03 1.2 1.97 2.5 2.79 3.86a4 4 0 0 1 7.96 0zm14.29-11.86c1.3-.48 2.63-.87 4-1.15a25.99 25.99 0 0 0-44.55 0c1.38.28 2.72.67 4.01 1.15a21.98 21.98 0 0 1 36.54 0zm-5.43 2.71c1.13-.72 2.3-1.37 3.54-1.93a19.98 19.98 0 0 0-32.76 0c1.23.56 2.41 1.2 3.54 1.93a15.98 15.98 0 0 1 25.68 0zm-4.67 3.78c.94-.95 1.96-1.83 3.03-2.63a13.98 13.98 0 0 0-22.4 0c1.07.8 2.09 1.68 3.03 2.63a9.99 9.99 0 0 1 16.34 0z'%3E%3C/path%3E%3C/svg%3E");
20 | align-items: center;
21 | justify-content: center;
22 | }
23 |
24 | .player {
25 | max-width: 750px;
26 | border: 5px solid rgba(0, 0, 0, 0.2);
27 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
28 | position: relative;
29 | font-size: 0;
30 | overflow: hidden;
31 | }
32 |
33 | /* This css is only applied when fullscreen is active. */
34 | .player:fullscreen {
35 | max-width: none;
36 | width: 100%;
37 | }
38 |
39 | .player:-webkit-full-screen {
40 | max-width: none;
41 | width: 100%;
42 | }
43 |
44 | .player__video {
45 | width: 100%;
46 | }
47 |
48 | .player__button {
49 | background: none;
50 | border: 0;
51 | line-height: 1;
52 | color: white;
53 | text-align: center;
54 | outline: 0;
55 | padding: 0;
56 | cursor: pointer;
57 | max-width: 50px;
58 | }
59 |
60 | .player__button:focus {
61 | border-color: #9B39A8;
62 | }
63 |
64 | .player__slider {
65 | width: 10px;
66 | height: 30px;
67 | }
68 |
69 | .player__controls {
70 | display: flex;
71 | position: absolute;
72 | bottom: 0;
73 | width: 100%;
74 | transform: translateY(100%) translateY(-5px);
75 | transition: all 0.3s;
76 | flex-wrap: wrap;
77 | background: rgba(0, 0, 0, 0.1);
78 | }
79 |
80 | .player:hover .player__controls {
81 | transform: translateY(0);
82 | }
83 |
84 | .player:hover .progress {
85 | height: 15px;
86 | }
87 |
88 | .player__controls > * {
89 | flex: 1;
90 | }
91 |
92 | .progress {
93 | flex: 10;
94 | position: relative;
95 | display: flex;
96 | flex-basis: 100%;
97 | height: 5px;
98 | transition: height 0.3s;
99 | background: rgba(0, 0, 0, 0.5);
100 | cursor: ew-resize;
101 | }
102 |
103 | .progress__filled {
104 | width: 50%;
105 | background: #9B39A8;
106 | flex: 0;
107 | flex-basis: 50%;
108 | }
109 |
110 | /* unholy css to style input type="range" */
111 |
112 | input[type='range'] {
113 | -webkit-appearance: none;
114 | background: transparent;
115 | width: 100%;
116 | margin: 0 5px;
117 | }
118 |
119 | input[type='range']:focus {
120 | outline: none;
121 | }
122 |
123 | input[type='range']::-webkit-slider-runnable-track {
124 | width: 100%;
125 | height: 8.4px;
126 | cursor: pointer;
127 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
128 | background: rgba(255, 255, 255, 0.8);
129 | border-radius: 1.3px;
130 | border: 0.2px solid rgba(1, 1, 1, 0);
131 | }
132 |
133 | input[type='range']::-webkit-slider-thumb {
134 | height: 15px;
135 | width: 15px;
136 | border-radius: 50px;
137 | background: #9B39A8;
138 | cursor: pointer;
139 | -webkit-appearance: none;
140 | margin-top: -3.5px;
141 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
142 | }
143 |
144 | input[type='range']:focus::-webkit-slider-runnable-track {
145 | background: #bada55;
146 | }
147 |
148 | input[type='range']::-moz-range-track {
149 | width: 100%;
150 | height: 8.4px;
151 | cursor: pointer;
152 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
153 | background: #ffffff;
154 | border-radius: 1.3px;
155 | border: 0.2px solid rgba(1, 1, 1, 0);
156 | }
157 |
158 | input[type='range']::-moz-range-thumb {
159 | box-shadow: 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(13, 13, 13, 0);
160 | height: 15px;
161 | width: 15px;
162 | border-radius: 50px;
163 | background: #9B39A8;
164 | cursor: pointer;
165 | }
166 |
--------------------------------------------------------------------------------
/12-Key-Sequence-Detection/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Key Detection - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#12
30 |
of JavaScript30
31 |
32 |
33 |
34 |
🎊 Type my nickname for a surprise! 🎊
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/12-Key-Sequence-Detection/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "key-sequence-detection",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {
11 | "confetti-js": "0.0.16"
12 | },
13 | "devDependencies": {
14 | "@babel/core": "7.2.0",
15 | "parcel-bundler": "^1.6.1"
16 | },
17 | "keywords": []
18 | }
19 |
--------------------------------------------------------------------------------
/12-Key-Sequence-Detection/src/index.js:
--------------------------------------------------------------------------------
1 | // import ConfettiGenerator from "confetti-js";
2 | const pressed = [];
3 | const secretCode = "guptaji";
4 | console.info(`Hint: Type ${secretCode} on your keyboard`);
5 | let confettiSettings = { target: "my-canvas", animate: true,size: 4, clock: 100 };
6 |
7 | window.addEventListener("keyup", e => {
8 | pressed.push(e.key);
9 | pressed.splice(-secretCode.length - 1, pressed.length - secretCode.length);
10 | console.log(pressed);
11 | if (pressed.join("").includes(secretCode)) {
12 | var confetti = new ConfettiGenerator(confettiSettings);
13 | confetti.render();
14 | } else {
15 | var confettii = new ConfettiGenerator(confettiSettings);
16 | confettii.clear();
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/12-Key-Sequence-Detection/src/styles.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | background-image: url('../../assets/ocean.jpg');
4 | background-color: #1e1e1e;
5 | height: 100vh;
6 | }
7 |
8 | .title {
9 | position: absolute;
10 | width: 60vw;;
11 | left: 20vw;
12 | right: 20vw;
13 | margin-top: 10vh;
14 | color: white;
15 | font-family: monospace;
16 | text-align: center;
17 | }
18 |
--------------------------------------------------------------------------------
/13-Slide-In-On-Scroll/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "slide-in-on-scroll",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/13-Slide-In-On-Scroll/src/index.js:
--------------------------------------------------------------------------------
1 | function debounce(func, wait = 20, immediate = true) {
2 | var timeout;
3 | return function() {
4 | var context = this,
5 | args = arguments;
6 | var later = function() {
7 | timeout = null;
8 | if (!immediate) func.apply(context, args);
9 | };
10 | var callNow = immediate && !timeout;
11 | clearTimeout(timeout);
12 | timeout = setTimeout(later, wait);
13 | if (callNow) func.apply(context, args);
14 | };
15 | }
16 |
17 | const sliderImages = document.querySelectorAll(".slide-in");
18 |
19 | function checkSlide(e) {
20 | sliderImages.forEach(sliderImage => {
21 | //half way through the image
22 | const slideInAt =
23 | window.scrollY + window.innerHeight - sliderImage.height / 2;
24 | // bottom of the image for when you scroll up
25 | const imageBottom = sliderImage.offsetTop + sliderImage.height;
26 | const isHalfShown = slideInAt > sliderImage.offsetTop;
27 | const isNotScrollPast = window.scrollY < imageBottom;
28 | if (isHalfShown && isNotScrollPast) {
29 | sliderImage.classList.add("active");
30 | } else {
31 | sliderImage.classList.remove("active");
32 | }
33 | });
34 | }
35 |
36 | window.addEventListener("scroll", debounce(checkSlide));
37 |
--------------------------------------------------------------------------------
/13-Slide-In-On-Scroll/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | background-color: #2a7966;
4 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.2'%3E%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
5 | font-family: 'helvetica neue';
6 | font-size: 20px;
7 | font-weight: 200;
8 | }
9 |
10 | body {
11 | margin: 0;
12 | }
13 |
14 | *,
15 | *:before,
16 | *:after {
17 | box-sizing: inherit;
18 | }
19 | h1 {
20 | margin-top: 0;
21 | }
22 | .site-wrap {
23 | max-width: 700px;
24 | margin: 100px auto;
25 | background: white;
26 | padding: 40px;
27 | text-align: justify;
28 | }
29 | .align-left {
30 | float: left;
31 | margin-right: 20px;
32 | }
33 | .align-right {
34 | float: right;
35 | margin-left: 20px;
36 | }
37 | .slide-in {
38 | opacity: 0;
39 | transition: all 0.5s;
40 | }
41 | .align-left.slide-in {
42 | transform: translateX(-30%) scale(0.95);
43 | }
44 |
45 | .align-right.slide-in {
46 | transform: translateX(30%) scale(0.95);
47 | }
48 | .slide-in.active {
49 | opacity: 1;
50 | transform: translateX(0%) scale(1);
51 | }
52 |
--------------------------------------------------------------------------------
/14-JS-Reference-Vs-Copy/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JS Reference VS Copy - JavaScript30 by Ayush Gupta
5 |
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
#14
31 |
of JavaScript30
32 |
33 |
34 | Have a look at the source code for understanding reference vs copy in JS.
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/14-JS-Reference-Vs-Copy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-reference-vs-copy",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/14-JS-Reference-Vs-Copy/src/index.js:
--------------------------------------------------------------------------------
1 | // start with strings, numbers and booleans
2 |
3 | // let age = 100;
4 | // let age2 = age;
5 | // console.log(age, age2);
6 |
7 | // age = 200;
8 | // console.log(age, age2);
9 |
10 | // let name = 'Wes';
11 | // let name2 = name;
12 | // console.log(name, name2);
13 |
14 | // name = 'wesley';
15 | // console.log(name, name2);
16 |
17 | // Let's say we have an array
18 |
19 | const players = ["Wes", "Sarah", "Ryan", "Poppy"];
20 |
21 | // and we want to make a copy of it.
22 |
23 | const team = players;
24 | console.log(players, team);
25 |
26 | // You might think we can just do something like this:
27 |
28 | // team[3] = 'Lux';
29 |
30 | // however what happens when we update that array?
31 | // now here is the problem!
32 | // oh no - we have edited the original array too!
33 | // Why? It's because that is an array reference, not an array copy. They both point to the same array!
34 | // So, how do we fix this? We take a copy instead!
35 |
36 | const team2 = players.slice();
37 |
38 | // one way
39 | // or create a new array and concat the old one in
40 |
41 | const team3 = [].concat(players);
42 |
43 | // or use the new ES6 Spread
44 |
45 | const team4 = [...players];
46 | team4[3] = "heeee hawww";
47 |
48 | console.log(team4);
49 | const team5 = Array.from(players);
50 |
51 | // now when we update it, the original one isn't changed
52 | // The same thing goes for objects, let's say we have a person object
53 | // with Objects
54 |
55 | const person = {
56 | name: "Wes Bos",
57 | age: 80
58 | };
59 |
60 | // and think we make a copy:
61 |
62 | // const captain = person;
63 | // captain.number = 99;
64 |
65 | // how do we take a copy instead?
66 |
67 | const cap2 = Object.assign({}, person, { number: 99, age: 12 });
68 | console.log(cap2);
69 |
70 | // We will hopefully soon see the object ...spread
71 | // const cap3 = {...person};
72 | // 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.
73 |
74 | const ayush = {
75 | name: "Ayush",
76 | age: 23,
77 | social: {
78 | twitter: "@_guptaji_",
79 | facebook: "guptaji.6"
80 | }
81 | };
82 |
83 | console.clear();
84 | console.log(ayush);
85 |
86 | const dev = Object.assign({}, ayush);
87 | const dev2 = JSON.parse(JSON.stringify(ayush));
88 |
--------------------------------------------------------------------------------
/15-Localstorage/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | LocalStorage - JavaScript30 by Ayush Gupta
5 |
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
32 |
33 |
34 |
35 |
#15
36 |
of JavaScript30
37 |
38 |
39 |
40 |
50 |
51 |
54 |
57 |
60 |
63 |
66 |
67 |
68 |
69 |
70 |
71 |
LOCAL TAPAS
72 |
73 |
74 | Loading Tapas...
75 |
76 |
80 |
81 | Check All
82 | Delete All
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/15-Localstorage/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "localstorage-event-deligation",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/15-Localstorage/src/index.js:
--------------------------------------------------------------------------------
1 | const addItems = document.querySelector(".add-items");
2 | const itemsList = document.querySelector(".plates");
3 | let items = JSON.parse(localStorage.getItem("items")) || [];
4 | const deleteBtn = document.querySelector(".delete");
5 | const checkBtn = document.querySelector(".check-uncheck");
6 |
7 | function addItem(e) {
8 | e.preventDefault();
9 | const text = this.querySelector("[name = item]").value;
10 | const item = {
11 | text,
12 | done: false
13 | };
14 | items.push(item);
15 | populateList(items, itemsList);
16 | localStorage.setItem("items", JSON.stringify(items));
17 | this.reset();
18 | }
19 |
20 | function populateList(plates = [], platesList) {
21 | platesList.innerHTML = plates
22 | .map((plate, i) => {
23 | return `
24 |
25 |
28 | ${plate.text}
29 |
30 | `;
31 | })
32 | .join("");
33 | }
34 |
35 | // event delegation is done here
36 | // instead of listening to clicks on /itemsList, we're listening it on it's parent ul
37 | function toggleDone(e) {
38 | if (!e.target.matches("input")) return; //skip this if the item we're clicking is not input
39 | const el = e.target;
40 | const index = el.dataset.index;
41 | items[index].done = !items[index].done;
42 | localStorage.setItem("items", JSON.stringify(items));
43 | populateList(items, itemsList);
44 | }
45 |
46 | function deleteAll() {
47 | if (window.confirm("Are you sure you want to delete all items?")) {
48 | itemsList.innerHTML = ` Loading Tapas... `;
49 | items = [];
50 | localStorage.removeItem("items");
51 | }
52 | }
53 |
54 | let isChecked = false;
55 | function checkOrUncheckAll() {
56 | if (!isChecked) {
57 | items.map(item => {
58 | return (item.done = true);
59 | });
60 | populateList(items, itemsList);
61 | checkBtn.textContent = "Uncheck All";
62 | } else {
63 | items.map(item => {
64 | return (item.done = false);
65 | });
66 | populateList(items, itemsList);
67 | checkBtn.textContent = "Check All";
68 | }
69 | isChecked = !isChecked;
70 | }
71 |
72 | addItems.addEventListener("submit", addItem);
73 | itemsList.addEventListener("click", toggleDone);
74 | deleteBtn.addEventListener("click", deleteAll);
75 | checkBtn.addEventListener("click", checkOrUncheckAll);
76 |
77 | populateList(items, itemsList);
78 |
--------------------------------------------------------------------------------
/15-Localstorage/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | background-color: #184d47;
4 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80' width='80' height='80'%3E%3Cpath fill='%2396bb7c' fill-opacity='0.16' d='M14 16H9v-2h5V9.87a4 4 0 1 1 2 0V14h5v2h-5v15.95A10 10 0 0 0 23.66 27l-3.46-2 8.2-2.2-2.9 5a12 12 0 0 1-21 0l-2.89-5 8.2 2.2-3.47 2A10 10 0 0 0 14 31.95V16zm40 40h-5v-2h5v-4.13a4 4 0 1 1 2 0V54h5v2h-5v15.95A10 10 0 0 0 63.66 67l-3.47-2 8.2-2.2-2.88 5a12 12 0 0 1-21.02 0l-2.88-5 8.2 2.2-3.47 2A10 10 0 0 0 54 71.95V56zm-39 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm40-40a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM15 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm40 40a2 2 0 1 0 0-4 2 2 0 0 0 0 4z'%3E%3C/path%3E%3C/svg%3E");
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: #eebb4d;
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 #96bb7c;
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 |
83 | .btn-group button {
84 | margin-top: 20px;
85 | padding: 10px;
86 | outline: 0;
87 | border: 1px solid rgba(0, 0, 0, 0.1);
88 | }
89 |
90 | .delete, .check-uncheck {
91 | background-color: #184d47;
92 | color: #d6efc7;
93 | }
94 |
95 | input[type="submit"] {
96 | background-color: #eebb4d;
97 | }
98 |
99 | input[type="text"] {
100 | border: 1px solid #96bb7c;
101 | }
102 |
--------------------------------------------------------------------------------
/16-Mousemove-Shadow/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mouse Shadow - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#16
30 |
of JavaScript30
31 |
32 |
33 |
34 |
🔥WOAH!
35 | Pro Tip: The text above is editable ;-)
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/16-Mousemove-Shadow/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-mouse-move-effect",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/16-Mousemove-Shadow/src/index.js:
--------------------------------------------------------------------------------
1 | const hero = document.querySelector(".hero");
2 | const text = hero.querySelector("h1");
3 | const walk = 30; //100px
4 |
5 | function shadow(e) {
6 | const { offsetWidth: width, offsetHeight: height } = hero;
7 | let { offsetX: x, offsetY: y } = e;
8 |
9 | if (this !== e.target) {
10 | x += e.target.offsetLeft;
11 | y += e.target.offsetTop;
12 | }
13 |
14 | const xWalk = Math.round((x / width) * walk - walk / 2);
15 | const yWalk = Math.round((y / height) * walk - walk / 2);
16 |
17 | text.style.textShadow = `
18 | ${xWalk}px ${yWalk}px 0 rgba(255, 0, 255, 0.7),
19 | ${xWalk * -1}px ${yWalk}px 0 rgba(0, 255, 255, 0.7),
20 | ${yWalk}px ${xWalk * -1}px 0 rgba(0, 255, 0, 0.7),
21 | ${yWalk * -1}px ${xWalk}px 0 rgba(0, 0, 255, 0.7)
22 | `;
23 | }
24 |
25 | hero.addEventListener("mousemove", shadow);
26 |
--------------------------------------------------------------------------------
/16-Mousemove-Shadow/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | color: white;
3 | font-family: sans-serif;
4 | }
5 | body {
6 | margin: 0;
7 | background-image: url('../../assets/celebration.png');
8 | }
9 | .hero {
10 | min-height: 100vh;
11 | display: flex;
12 | justify-content: center;
13 | align-items: center;
14 | flex-direction: column;
15 | color: white;
16 | }
17 | h1 {
18 | text-shadow: 10px 10px 0 rgba(0, 0, 0, 1);
19 | font-size: 100px;
20 | }
21 |
22 | h7{
23 | color: lightcoral;
24 | font-family: monospace;
25 | }
26 |
--------------------------------------------------------------------------------
/17-Sort-Without-Articles/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Sort Without Articles - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#17
30 |
of JavaScript30
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/17-Sort-Without-Articles/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sort-without-articles",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": [
16 | "javascript30",
17 | "javascript"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/17-Sort-Without-Articles/src/index.js:
--------------------------------------------------------------------------------
1 | const bands = [
2 | "The Plot in You",
3 | "The Devil Wears Prada",
4 | "Pierce the Veil",
5 | "Norma Jean",
6 | "The Bled",
7 | "Say Anything",
8 | "The Midway State",
9 | "We Came as Romans",
10 | "Counterparts",
11 | "Oh, Sleeper",
12 | "A Skylit Drive",
13 | "Anywhere But Here",
14 | "An Old Dog"
15 | ];
16 |
17 | function strip(bandName) {
18 | return bandName.replace(/^(a |the |an )/i, "").trim();
19 | }
20 |
21 | const sortBandsByAsc = bands.sort((a, b) => (strip(a) < strip(b) ? -1 : 1));
22 |
23 | let bandsCopy = [...bands];
24 | const sortBandsByDesc = bandsCopy.sort((a, b) =>
25 | strip(a) > strip(b) ? -1 : 1
26 | );
27 |
28 | const sortBtn = document.querySelector("#sort-btn");
29 | let sortByAsc = true;
30 |
31 | document.querySelector("#bands").innerHTML = sortBandsByAsc
32 | .map(band => `${band} `)
33 | .join("");
34 |
35 | sortBtn.addEventListener("click", () => {
36 | sortByAsc = !sortByAsc;
37 | if (sortByAsc) {
38 | document.querySelector("#bands").innerHTML = sortBandsByAsc
39 | .map(band => `${band} `)
40 | .join("");
41 | sortBtn.textContent = "Sort by Descending";
42 | } else {
43 | document.querySelector("#bands").innerHTML = sortBandsByDesc
44 | .map(band => `${band} `)
45 | .join("");
46 | sortBtn.textContent = "Sort by Ascending";
47 | }
48 | });
49 |
--------------------------------------------------------------------------------
/17-Sort-Without-Articles/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: sans-serif;
4 | background: url('../../assets/asteroids.jpg');
5 | display: flex;
6 | align-items: center;
7 | flex-direction: column;
8 | min-height: 100vh;
9 | padding: 30px;
10 | }
11 |
12 | #bands {
13 | list-style: inside square;
14 | font-size: 20px;
15 | background: #fb7813;
16 | width: 500px;
17 | margin: auto;
18 | padding: 0;
19 | box-shadow: 0 0 0 20px rgba(0, 0, 0, 0.05);
20 | }
21 |
22 | #bands li {
23 | border-bottom: 1px solid #efefef;
24 | padding: 20px;
25 | color: #f7f7ee;
26 | }
27 |
28 | #bands li:last-child {
29 | border-bottom: 0;
30 | }
31 |
32 | a {
33 | color: #ffc600;
34 | text-decoration: none;
35 | }
36 |
--------------------------------------------------------------------------------
/18-Add-Time-With-Reduce/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Add Time With Reduce - JavaScript30 by Ayush Gupta
5 |
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
#18
31 |
of JavaScript30
32 |
33 |
34 |
35 |
36 | Video 01
37 |
38 |
39 | Video 02
40 |
41 |
42 | Video 03
43 |
44 |
45 | Video 04
46 |
47 |
48 | Video 05
49 |
50 |
51 | Video 06
52 |
53 |
54 | Video 07
55 |
56 |
57 | Video 08
58 |
59 |
60 | Video 09
61 |
62 |
63 | Video 10
64 |
65 |
66 | Video 11
67 |
68 |
69 | Video 12
70 |
71 |
72 | Video 13
73 |
74 |
75 | Video 14
76 |
77 |
78 | Video 15
79 |
80 |
81 | Video 16
82 |
83 |
84 | Video 17
85 |
86 |
87 | Video 18
88 |
89 |
90 | Video 19
91 |
92 |
93 | Video 20
94 |
95 |
96 | Video 21
97 |
98 |
99 | Video 22
100 |
101 |
102 | Video 23
103 |
104 |
105 | Video 24
106 |
107 |
108 | Video 25
109 |
110 |
111 | Video 26
112 |
113 |
114 | Video 27
115 |
116 |
117 | Video 28
118 |
119 |
120 | Video 29
121 |
122 |
123 | Video 30
124 |
125 |
126 | Video 31
127 |
128 |
129 | Video 32
130 |
131 |
132 | Video 33
133 |
134 |
135 | Video 34
136 |
137 |
138 | Video 35
139 |
140 |
141 | Video 36
142 |
143 |
144 | Video 37
145 |
146 |
147 | Video 38
148 |
149 |
150 | Video 39
151 |
152 |
153 | Video 40
154 |
155 |
156 | Video 41
157 |
158 |
159 | Video 42
160 |
161 |
162 | Video 43
163 |
164 |
165 | Video 44
166 |
167 |
168 | Video 45
169 |
170 |
171 | Video 46
172 |
173 |
174 | Video 47
175 |
176 |
177 | Video 48
178 |
179 |
180 | Video 49
181 |
182 |
183 | Video 50
184 |
185 |
186 | Video 51
187 |
188 |
189 | Video 52
190 |
191 |
192 | Video 53
193 |
194 |
195 | Video 54
196 |
197 |
198 | Video 55
199 |
200 |
201 | Video 56
202 |
203 |
204 | Video 57
205 |
206 |
207 | Video 58
208 |
209 |
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/18-Add-Time-With-Reduce/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "add-time-reduce",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/18-Add-Time-With-Reduce/src/index.js:
--------------------------------------------------------------------------------
1 | const timeNodes = Array.from(document.querySelectorAll("[data-time]"));
2 |
3 | const seconds = timeNodes
4 | .map(node => node.dataset.time)
5 | .map(timeCode => {
6 | const [mins, secs] = timeCode.split(":").map(parseFloat);
7 | return mins * 60 + secs;
8 | })
9 | .reduce((total, vidSeconds) => total + vidSeconds);
10 |
11 | let secondsLeft = seconds;
12 | const hours = Math.floor(secondsLeft / 3600);
13 | secondsLeft %= 3600;
14 |
15 | const mins = Math.floor(secondsLeft / 60);
16 | secondsLeft %= 60;
17 |
18 | console.log(hours, mins, secondsLeft);
19 |
--------------------------------------------------------------------------------
/18-Add-Time-With-Reduce/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #2f2519;
3 | color: #fa7d09;
4 | font-family: sans-serif;
5 | display: flex;
6 | justify-content: center;
7 | }
--------------------------------------------------------------------------------
/19-Webcam-Fun/.cache/57/730c4c4fbb17905544f6301244eb4f.json:
--------------------------------------------------------------------------------
1 | {"id":"index.html","dependencies":[{"name":"./src/styles.css","dynamic":true,"resolved":"/home/ayushgupta/Documents/JavaScript30/19-Webcam-Fun/src/styles.css","parent":"/home/ayushgupta/Documents/JavaScript30/19-Webcam-Fun/index.html"},{"name":"./src/index.js","dynamic":true,"resolved":"/home/ayushgupta/Documents/JavaScript30/19-Webcam-Fun/src/index.js","parent":"/home/ayushgupta/Documents/JavaScript30/19-Webcam-Fun/index.html"}],"generated":{"html":"\n\n \n \n Get User Media Code Along! \n \n \n \n \n\n \n\n \n \n\n"},"sourceMaps":null,"error":null,"hash":"0da55d9ca1167c4e022366da3e6eefcb","cacheData":{}}
--------------------------------------------------------------------------------
/19-Webcam-Fun/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webcam Fun - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
#18
17 |
of JavaScript30
18 |
19 |
20 |
21 |
PhotoBooth
22 |
Take Photo
23 |
41 |
42 |
43 |
44 |
45 | Click to download
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/19-Webcam-Fun/dist/src.a2b27638.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["src/index.js"],"names":["video","document","querySelector","canvas","ctx","getContext","strip","snap","getVideo","navigator","mediaDevices","getUserMedia","audio","then","localMediaStream","console","log","srcObject","play","catch","err","error","paintToCanvas","width","videoWidth","height","videoHeight","style","cssText","setInterval","drawImage","pixels","getImageData","rgbSplit","globalAlpha","putImageData","greenScreen","levels","querySelectorAll","forEach","input","name","value","i","data","length","red","green","blue","alpha","rmin","gmin","bmin","rmax","gmax","bmax","takePhoto","currentTime","toDataURL","link","createElement","href","setAttribute","innerHTML","insertBefore","firstChild","redEffect","addEventListener"],"mappings":"AAAA,IAAMA,KAAK,GAAGC,QAAQ,CAACC,aAAT,CAAuB,SAAvB,CAAd;AACA,IAAMC,MAAM,GAAGF,QAAQ,CAACC,aAAT,CAAuB,QAAvB,CAAf;AACA,IAAME,GAAG,GAAGD,MAAM,CAACE,UAAP,CAAkB,IAAlB,CAAZ;AACA,IAAMC,KAAK,GAAGL,QAAQ,CAACC,aAAT,CAAuB,QAAvB,CAAd;AACA,IAAMK,IAAI,GAAGN,QAAQ,CAACC,aAAT,CAAuB,OAAvB,CAAb;;AAEA,SAASM,QAAT,GAAoB;AAClBC,EAAAA,SAAS,CAACC,YAAV,CACGC,YADH,CACgB;AAAEX,IAAAA,KAAK,EAAE,IAAT;AAAeY,IAAAA,KAAK,EAAE;AAAtB,GADhB,EAEGC,IAFH,CAEQ,UAAAC,gBAAgB,EAAI;AACxBC,IAAAA,OAAO,CAACC,GAAR,CAAYF,gBAAZ;AACAd,IAAAA,KAAK,CAACiB,SAAN,GAAkBH,gBAAlB;AACAd,IAAAA,KAAK,CAACkB,IAAN;AACD,GANH,EAOGC,KAPH,CAOS,UAAAC,GAAG,EAAI;AACZL,IAAAA,OAAO,CAACM,KAAR,CAAc,aAAd,EAA6BD,GAA7B;AACD,GATH;AAUD;;AAED,SAASE,aAAT,GAAyB;AACvB,MAAMC,KAAK,GAAGvB,KAAK,CAACwB,UAApB;AACA,MAAMC,MAAM,GAAGzB,KAAK,CAAC0B,WAArB;AACA1B,EAAAA,KAAK,CAAC2B,KAAN,CAAYC,OAAZ,GACE;;wCADF;AAIAzB,EAAAA,MAAM,CAACoB,KAAP,GAAeA,KAAf;AACApB,EAAAA,MAAM,CAACsB,MAAP,GAAgBA,MAAhB;AAEA,SAAOI,WAAW,CAAC,YAAM;AACvBzB,IAAAA,GAAG,CAAC0B,SAAJ,CAAc9B,KAAd,EAAqB,CAArB,EAAwB,CAAxB,EAA2BuB,KAA3B,EAAkCE,MAAlC,EADuB,CAEvB;;AACA,QAAIM,MAAM,GAAG3B,GAAG,CAAC4B,YAAJ,CAAiB,CAAjB,EAAoB,CAApB,EAAuBT,KAAvB,EAA8BE,MAA9B,CAAb,CAHuB,CAIvB;AACA;;AAEAM,IAAAA,MAAM,GAAGE,QAAQ,CAACF,MAAD,CAAjB;AACA3B,IAAAA,GAAG,CAAC8B,WAAJ,GAAkB,GAAlB,CARuB,CAUvB;;AACA9B,IAAAA,GAAG,CAAC+B,YAAJ,CAAiBJ,MAAjB,EAAyB,CAAzB,EAA4B,CAA5B,EAXuB,CAYvB;AACD,GAbiB,EAaf,EAbe,CAAlB;AAcD;;AAED,SAASK,WAAT,CAAqBL,MAArB,EAA6B;AAC3B,MAAMM,MAAM,GAAG,EAAf;AAEApC,EAAAA,QAAQ,CAACqC,gBAAT,CAA0B,YAA1B,EAAwCC,OAAxC,CAAgD,UAAAC,KAAK,EAAI;AACvDH,IAAAA,MAAM,CAACG,KAAK,CAACC,IAAP,CAAN,GAAqBD,KAAK,CAACE,KAA3B;AACD,GAFD;;AAIA,OAAKC,CAAC,GAAG,CAAT,EAAYA,CAAC,GAAGZ,MAAM,CAACa,IAAP,CAAYC,MAA5B,EAAoCF,CAAC,GAAGA,CAAC,GAAG,CAA5C,EAA+C;AAC7CG,IAAAA,GAAG,GAAGf,MAAM,CAACa,IAAP,CAAYD,CAAC,GAAG,CAAhB,CAAN;AACAI,IAAAA,KAAK,GAAGhB,MAAM,CAACa,IAAP,CAAYD,CAAC,GAAG,CAAhB,CAAR;AACAK,IAAAA,IAAI,GAAGjB,MAAM,CAACa,IAAP,CAAYD,CAAC,GAAG,CAAhB,CAAP;AACAM,IAAAA,KAAK,GAAGlB,MAAM,CAACa,IAAP,CAAYD,CAAC,GAAG,CAAhB,CAAR;;AAEA,QACEG,GAAG,IAAIT,MAAM,CAACa,IAAd,IACAH,KAAK,IAAIV,MAAM,CAACc,IADhB,IAEAH,IAAI,IAAIX,MAAM,CAACe,IAFf,IAGAN,GAAG,IAAIT,MAAM,CAACgB,IAHd,IAIAN,KAAK,IAAIV,MAAM,CAACiB,IAJhB,IAKAN,IAAI,IAAIX,MAAM,CAACkB,IANjB,EAOE;AACA;AACAxB,MAAAA,MAAM,CAACa,IAAP,CAAYD,CAAC,GAAG,CAAhB,IAAqB,CAArB;AACD;AACF;;AAED,SAAOZ,MAAP;AACD;;AAED,SAASyB,SAAT,GAAqB;AACnB;AACAjD,EAAAA,IAAI,CAACkD,WAAL,GAAmB,CAAnB;AACAlD,EAAAA,IAAI,CAACW,IAAL;AAEA,MAAM0B,IAAI,GAAGzC,MAAM,CAACuD,SAAP,CAAiB,YAAjB,CAAb;AACA,MAAMC,IAAI,GAAG1D,QAAQ,CAAC2D,aAAT,CAAuB,GAAvB,CAAb;AACAD,EAAAA,IAAI,CAACE,IAAL,GAAYjB,IAAZ;AACAe,EAAAA,IAAI,CAACG,YAAL,CAAkB,UAAlB,EAA8B,UAA9B;AACAH,EAAAA,IAAI,CAACI,SAAL,wBAA8BnB,IAA9B;AACAtC,EAAAA,KAAK,CAAC0D,YAAN,CAAmBL,IAAnB,EAAyBrD,KAAK,CAAC2D,UAA/B;AACD;;AAED,SAASC,SAAT,CAAmBnC,MAAnB,EAA2B;AACzB,OAAK,IAAIY,EAAC,GAAG,CAAb,EAAgBA,EAAC,GAAGZ,MAAM,CAACa,IAAP,CAAYC,MAAhC,EAAwCF,EAAC,IAAI,CAA7C,EAAgD;AAC9CZ,IAAAA,MAAM,CAACa,IAAP,CAAYD,EAAC,GAAG,CAAhB,KAAsB,GAAtB,CAD8C,CACnB;;AAC3BZ,IAAAA,MAAM,CAACa,IAAP,CAAYD,EAAC,GAAG,CAAhB,KAAsB,EAAtB,CAF8C,CAEpB;;AAC1BZ,IAAAA,MAAM,CAACa,IAAP,CAAYD,EAAC,GAAG,CAAhB,KAAsB,GAAtB,CAH8C,CAGnB;AAC5B;;AACD,SAAOZ,MAAP;AACD;;AAED,SAASE,QAAT,CAAkBF,MAAlB,EAA0B;AACxB,OAAK,IAAIY,GAAC,GAAG,CAAb,EAAgBA,GAAC,GAAGZ,MAAM,CAACa,IAAP,CAAYC,MAAhC,EAAwCF,GAAC,IAAI,CAA7C,EAAgD;AAC9CZ,IAAAA,MAAM,CAACa,IAAP,CAAYD,GAAC,GAAG,GAAhB,IAAuBZ,MAAM,CAACa,IAAP,CAAYD,GAAC,GAAG,CAAhB,CAAvB,CAD8C,CACH;;AAC3CZ,IAAAA,MAAM,CAACa,IAAP,CAAYD,GAAC,GAAG,GAAhB,IAAuBZ,MAAM,CAACa,IAAP,CAAYD,GAAC,GAAG,CAAhB,CAAvB,CAF8C,CAEH;;AAC3CZ,IAAAA,MAAM,CAACa,IAAP,CAAYD,GAAC,GAAG,GAAhB,IAAuBZ,MAAM,CAACa,IAAP,CAAYD,GAAC,GAAG,CAAhB,CAAvB,CAH8C,CAGH;AAC5C;;AACD,SAAOZ,MAAP;AACD;;AAEDvB,QAAQ;AAERR,KAAK,CAACmE,gBAAN,CAAuB,SAAvB,EAAkC7C,aAAlC","file":"src.a2b27638.js","sourceRoot":"..","sourcesContent":["const video = document.querySelector(\".player\");\r\nconst canvas = document.querySelector(\".photo\");\r\nconst ctx = canvas.getContext(\"2d\");\r\nconst strip = document.querySelector(\".strip\");\r\nconst snap = document.querySelector(\".snap\");\r\n\r\nfunction getVideo() {\r\n navigator.mediaDevices\r\n .getUserMedia({ video: true, audio: false })\r\n .then(localMediaStream => {\r\n console.log(localMediaStream);\r\n video.srcObject = localMediaStream;\r\n video.play();\r\n })\r\n .catch(err => {\r\n console.error(\"Oh, NOOO!!!\", err);\r\n });\r\n}\r\n\r\nfunction paintToCanvas() {\r\n const width = video.videoWidth;\r\n const height = video.videoHeight;\r\n video.style.cssText =\r\n '-moz-transform: scale(-1, 1); \\\r\n-webkit-transform: scale(-1, 1); -o-transform: scale(-1, 1); \\\r\ntransform: scale(-1, 1); filter: FlipH;';\r\n canvas.width = width;\r\n canvas.height = height;\r\n\r\n return setInterval(() => {\r\n ctx.drawImage(video, 0, 0, width, height);\r\n // take pixels out\r\n let pixels = ctx.getImageData(0, 0, width, height);\r\n // mess with them\r\n // pixels = redEffect(pixels);\r\n\r\n pixels = rgbSplit(pixels);\r\n ctx.globalAlpha = 0.8;\r\n\r\n // put them back\r\n ctx.putImageData(pixels, 0, 0);\r\n // debugger;\r\n }, 16);\r\n}\r\n\r\nfunction greenScreen(pixels) {\r\n const levels = {};\r\n\r\n document.querySelectorAll(\".rgb input\").forEach(input => {\r\n levels[input.name] = input.value;\r\n });\r\n\r\n for (i = 0; i < pixels.data.length; i = i + 4) {\r\n red = pixels.data[i + 0];\r\n green = pixels.data[i + 1];\r\n blue = pixels.data[i + 2];\r\n alpha = pixels.data[i + 3];\r\n\r\n if (\r\n red >= levels.rmin &&\r\n green >= levels.gmin &&\r\n blue >= levels.bmin &&\r\n red <= levels.rmax &&\r\n green <= levels.gmax &&\r\n blue <= levels.bmax\r\n ) {\r\n // take it out!\r\n pixels.data[i + 3] = 0;\r\n }\r\n }\r\n\r\n return pixels;\r\n}\r\n\r\nfunction takePhoto() {\r\n // play sound\r\n snap.currentTime = 0;\r\n snap.play();\r\n\r\n const data = canvas.toDataURL(\"image/jpeg\");\r\n const link = document.createElement(\"a\");\r\n link.href = data;\r\n link.setAttribute(\"download\", \"handsome\");\r\n link.innerHTML = ` `;\r\n strip.insertBefore(link, strip.firstChild);\r\n}\r\n\r\nfunction redEffect(pixels) {\r\n for (let i = 0; i < pixels.data.length; i += 4) {\r\n pixels.data[i + 0] += 100; //r\r\n pixels.data[i + 1] -= 50; //g\r\n pixels.data[i + 2] *= 0.5; //b\r\n }\r\n return pixels;\r\n}\r\n\r\nfunction rgbSplit(pixels) {\r\n for (let i = 0; i < pixels.data.length; i += 4) {\r\n pixels.data[i - 150] = pixels.data[i + 0]; // RED\r\n pixels.data[i + 500] = pixels.data[i + 1]; // GREEN\r\n pixels.data[i - 550] = pixels.data[i + 2]; // Blue\r\n }\r\n return pixels;\r\n}\r\n\r\ngetVideo();\r\n\r\nvideo.addEventListener(\"canplay\", paintToCanvas);\r\n"]}
--------------------------------------------------------------------------------
/19-Webcam-Fun/dist/styles.dd855970.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | font-size: 10px;
4 | background-color: #f46036;
5 | background-image: url("data:image/svg+xml,%3Csvg width='80' height='80' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%232e294e' fill-opacity='0.2'%3E%3Cpath d='M50 50c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10zM10 10c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10S0 25.523 0 20s4.477-10 10-10zm10 8c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm40 40c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
6 | padding: 2vw;
7 | font-family: Arial, Helvetica, sans-serif;
8 | }
9 |
10 | *,
11 | *:before,
12 | *:after {
13 | box-sizing: inherit;
14 | }
15 |
16 | .photobooth {
17 | background: white;
18 | max-width: 150rem;
19 | margin: 2rem auto;
20 | border-radius: 2px;
21 | display: flex;
22 | flex-direction: column;
23 | justify-content: center;
24 | align-items: center;
25 | }
26 |
27 | h1 {
28 | text-align: center;
29 | font-family: 'Pacifico', cursive;
30 | color: #F46036;
31 | font-size: 48px;
32 | margin-bottom: 1vh;
33 | margin-top: 1vh;
34 | padding-top: 0;
35 | }
36 |
37 | button {
38 | height: 5vh;
39 | background-color: #2E294E;
40 | color: #fff;
41 | outline: 0;
42 | border: 0;
43 | border-radius: 0.3em;
44 | margin-bottom: 3vh;
45 | }
46 |
47 | .controls {
48 | margin-bottom: 3vh;
49 | }
50 |
51 | /*clearfix*/
52 | .photobooth:after {
53 | content: "";
54 | display: block;
55 | clear: both;
56 | }
57 |
58 | .photo {
59 | width: 100%;
60 | float: left;
61 | transform: rotateY(180deg);
62 | -webkit-transform:rotateY(180deg); /* Safari and Chrome */
63 | -moz-transform:rotateY(180deg); /* Firefox */
64 | margin-bottom: 1vh;
65 | }
66 |
67 | .player {
68 | position: absolute;
69 | top: 10px;
70 | right: 10px;
71 | width: 200px;
72 | transform: rotateY(180deg);
73 | -webkit-transform:rotateY(180deg); /* Safari and Chrome */
74 | -moz-transform:rotateY(180deg); /* Firefox */
75 | border-radius: 0.3em;
76 | }
77 |
78 | /*
79 | Strip!
80 | */
81 |
82 | .strip {
83 | padding: 2rem;
84 | }
85 |
86 | .strip img {
87 | width: 100px;
88 | overflow-x: scroll;
89 | padding: 0.8rem 0.8rem 2.5rem 0.8rem;
90 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
91 | background: white;
92 | }
93 |
94 | .strip a:nth-child(5n + 1) img {
95 | transform: rotate(10deg);
96 | }
97 | .strip a:nth-child(5n + 2) img {
98 | transform: rotate(-2deg);
99 | }
100 | .strip a:nth-child(5n + 3) img {
101 | transform: rotate(8deg);
102 | }
103 | .strip a:nth-child(5n + 4) img {
104 | transform: rotate(-11deg);
105 | }
106 | .strip a:nth-child(5n + 5) img {
107 | transform: rotate(12deg);
108 | }
109 |
110 |
111 | /*# sourceMappingURL=/styles.dd855970.css.map */
--------------------------------------------------------------------------------
/19-Webcam-Fun/dist/styles.dd855970.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["src/styles.css"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"styles.dd855970.css","sourceRoot":"..","sourcesContent":["html {\r\n box-sizing: border-box;\r\n font-size: 10px;\r\n background-color: #f46036;\r\n background-image: url(\"data:image/svg+xml,%3Csvg width='80' height='80' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%232e294e' fill-opacity='0.2'%3E%3Cpath d='M50 50c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10zM10 10c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10S0 25.523 0 20s4.477-10 10-10zm10 8c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm40 40c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E\");\r\n padding: 2vw;\r\n font-family: Arial, Helvetica, sans-serif;\r\n}\r\n\r\n*,\r\n*:before,\r\n*:after {\r\n box-sizing: inherit;\r\n}\r\n\r\n.photobooth {\r\n background: white;\r\n max-width: 150rem;\r\n margin: 2rem auto;\r\n border-radius: 2px;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\nh1 {\r\n text-align: center;\r\n font-family: 'Pacifico', cursive;\r\n color: #F46036;\r\n font-size: 48px;\r\n margin-bottom: 1vh;\r\n margin-top: 1vh;\r\n padding-top: 0;\r\n}\r\n\r\nbutton {\r\n height: 5vh;\r\n background-color: #2E294E;\r\n color: #fff;\r\n outline: 0;\r\n border: 0;\r\n border-radius: 0.3em;\r\n margin-bottom: 3vh;\r\n}\r\n\r\n.controls {\r\n margin-bottom: 3vh;\r\n}\r\n\r\n/*clearfix*/\r\n.photobooth:after {\r\n content: \"\";\r\n display: block;\r\n clear: both;\r\n}\r\n\r\n.photo {\r\n width: 100%;\r\n float: left;\r\n transform: rotateY(180deg);\r\n -webkit-transform:rotateY(180deg); /* Safari and Chrome */\r\n -moz-transform:rotateY(180deg); /* Firefox */\r\n margin-bottom: 1vh;\r\n}\r\n\r\n.player {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n width: 200px;\r\n transform: rotateY(180deg);\r\n -webkit-transform:rotateY(180deg); /* Safari and Chrome */\r\n -moz-transform:rotateY(180deg); /* Firefox */\r\n border-radius: 0.3em;\r\n}\r\n\r\n/*\r\n Strip!\r\n*/\r\n\r\n.strip {\r\n padding: 2rem;\r\n}\r\n\r\n.strip img {\r\n width: 100px;\r\n overflow-x: scroll;\r\n padding: 0.8rem 0.8rem 2.5rem 0.8rem;\r\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);\r\n background: white;\r\n}\r\n\r\n.strip a:nth-child(5n + 1) img {\r\n transform: rotate(10deg);\r\n}\r\n.strip a:nth-child(5n + 2) img {\r\n transform: rotate(-2deg);\r\n}\r\n.strip a:nth-child(5n + 3) img {\r\n transform: rotate(8deg);\r\n}\r\n.strip a:nth-child(5n + 4) img {\r\n transform: rotate(-11deg);\r\n}\r\n.strip a:nth-child(5n + 5) img {\r\n transform: rotate(12deg);\r\n}\r\n"]}
--------------------------------------------------------------------------------
/19-Webcam-Fun/dist/styles.dd855970.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["node_modules/parcel-bundler/src/builtins/bundle-url.js","node_modules/parcel-bundler/src/builtins/css-loader.js"],"names":["bundleURL","getBundleURLCached","getBundleURL","Error","err","matches","stack","match","getBaseURL","url","replace","exports","bundle","require","updateLink","link","newLink","cloneNode","onload","remove","href","split","Date","now","parentNode","insertBefore","nextSibling","cssTimeout","reloadCSS","setTimeout","links","document","querySelectorAll","i","length","module"],"mappings":"AAAA,ACAA,IDAIA,ACAAY,MAAM,GDAG,ACAAC,GDAG,IAAhB,ACAoB,CAAC,cAAD,CAApB;;ADCA,ACCA,SDDSZ,ACCAa,UAAT,CAAoBC,IAApB,EAA0B,CDD1B,GAA8B;AAC5B,ACCA,MDDI,ACCAC,CDDChB,MCCM,GDDX,ACCce,EDDE,ECCE,CAACE,SAAL,EAAd;ADAEjB,IAAAA,SAAS,GAAGE,YAAY,EAAxB;AACD,ACADc,EAAAA,OAAO,CAACE,MAAR,GAAiB,YAAY;AAC3BH,IAAAA,IAAI,CAACI,MAAL;ADCF,ACAC,GAFD,MDEOnB,SAAP;AACD;ACACgB,EAAAA,OAAO,CAACI,IAAR,GAAeL,IAAI,CAACK,IAAL,CAAUC,KAAV,CAAgB,GAAhB,EAAqB,CAArB,IAA0B,GAA1B,GAAgCC,IAAI,CAACC,GAAL,EAA/C;ADEF,ACDER,EAAAA,IAAI,CAACS,EDCEtB,QCDP,CAAgBuB,GDClB,GAAwB,MCDtB,CAA6BT,OAA7B,EAAsCD,IAAI,CAACW,WAA3C;ADEA,ACDD;ADEC,MAAI;AACF,ACDJ,IAAIC,MDCM,IAAIxB,ACDA,GAAG,EDCP,EAAN,ACDJ;ADEG,GAFD,CAEE,OAAOC,GAAP,EAAY;AACZ,ACFJ,QDEQC,CCFCuB,MDEM,GAAG,ACFlB,CDEmB,ECFE,GDEGxB,GAAG,CAACE,KAAV,EAAiBC,KAAjB,CAAuB,+DAAvB,CAAd;ACDF,MAAIoB,UAAJ,EAAgB;ADEd,ACDA,QDCItB,OAAJ,EAAa;AACX,ACDH,aDCUG,UAAU,CAACH,OAAO,CAAC,CAAD,CAAR,CAAjB;AACD;AACF,ACDDsB,EAAAA,UAAU,GAAGE,UAAU,CAAC,YAAY;AAClC,QAAIC,KAAK,GAAGC,QAAQ,CAACC,gBAAT,CAA0B,wBAA1B,CAAZ;ADEF,SAAO,GAAP;AACD,ACFG,SAAK,IAAIC,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGH,KAAK,CAACI,MAA1B,EAAkCD,CAAC,EAAnC,EAAuC;AACrC,UAAIrB,MAAM,CAACJ,UAAP,CAAkBsB,KAAK,CAACG,CAAD,CAAL,CAASb,IAA3B,MAAqCR,MAAM,CAACV,YAAP,EAAzC,EAAgE;ADGtE,ACFQY,QAAAA,CDECN,SCFS,CDElB,ACFmBsB,CDECrB,GAApB,CCFwB,CDEC,ACFAwB,CAAD,CAAN,CAAV;ADGN,ACFK,SDEE,CAAC,KAAKxB,GAAN,EAAWC,OAAX,CAAmB,sEAAnB,EAA2F,IAA3F,IAAmG,GAA1G;AACD,ACFI;;ADILC,ACFIgB,IAAAA,GDEG,CAACzB,MCFM,GAAG,GDEjB,CCFI,EDEmBD,kBAAvB;AACAU,ACFG,GATsB,EASpB,EDEE,ACXkB,CDWjBH,ACXN,UDWF,GAAqBA,UAArB;ACDC;;AAED2B,MAAM,CAACxB,OAAP,GAAiBiB,SAAjB","file":"styles.dd855970.js","sourceRoot":"..","sourcesContent":["var bundleURL = null;\nfunction getBundleURLCached() {\n if (!bundleURL) {\n bundleURL = getBundleURL();\n }\n\n return bundleURL;\n}\n\nfunction getBundleURL() {\n // Attempt to find the URL of the current script and use that as the base URL\n try {\n throw new Error;\n } catch (err) {\n var matches = ('' + err.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\\/\\/[^)\\n]+/g);\n if (matches) {\n return getBaseURL(matches[0]);\n }\n }\n\n return '/';\n}\n\nfunction getBaseURL(url) {\n return ('' + url).replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\\/\\/.+)\\/[^/]+$/, '$1') + '/';\n}\n\nexports.getBundleURL = getBundleURLCached;\nexports.getBaseURL = getBaseURL;\n","var bundle = require('./bundle-url');\n\nfunction updateLink(link) {\n var newLink = link.cloneNode();\n newLink.onload = function () {\n link.remove();\n };\n newLink.href = link.href.split('?')[0] + '?' + Date.now();\n link.parentNode.insertBefore(newLink, link.nextSibling);\n}\n\nvar cssTimeout = null;\nfunction reloadCSS() {\n if (cssTimeout) {\n return;\n }\n\n cssTimeout = setTimeout(function () {\n var links = document.querySelectorAll('link[rel=\"stylesheet\"]');\n for (var i = 0; i < links.length; i++) {\n if (bundle.getBaseURL(links[i].href) === bundle.getBundleURL()) {\n updateLink(links[i]);\n }\n }\n\n cssTimeout = null;\n }, 50);\n}\n\nmodule.exports = reloadCSS;\n"]}
--------------------------------------------------------------------------------
/19-Webcam-Fun/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webcam Fun - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
9 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
#19
31 |
of JavaScript30
32 |
33 |
34 |
35 |
PhotoBooth
36 |
Take Photo
37 |
55 |
56 |
57 |
58 |
59 | Click to download
60 |
61 |
62 |
63 |
64 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/19-Webcam-Fun/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "19-webcam-fun",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/19-Webcam-Fun/snap.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/19-Webcam-Fun/snap.mp3
--------------------------------------------------------------------------------
/19-Webcam-Fun/src/index.js:
--------------------------------------------------------------------------------
1 | const video = document.querySelector(".player");
2 | const canvas = document.querySelector(".photo");
3 | const ctx = canvas.getContext("2d");
4 | const strip = document.querySelector(".strip");
5 | const snap = document.querySelector(".snap");
6 |
7 | function getVideo() {
8 | navigator.mediaDevices
9 | .getUserMedia({ video: true, audio: false })
10 | .then(localMediaStream => {
11 | console.log(localMediaStream);
12 | video.srcObject = localMediaStream;
13 | video.play();
14 | })
15 | .catch(err => {
16 | console.error("Oh, NOOO!!!", err);
17 | });
18 | }
19 |
20 | function paintToCanvas() {
21 | const width = video.videoWidth;
22 | const height = video.videoHeight;
23 | video.style.cssText =
24 | '-moz-transform: scale(-1, 1); \
25 | -webkit-transform: scale(-1, 1); -o-transform: scale(-1, 1); \
26 | transform: scale(-1, 1); filter: FlipH;';
27 | canvas.width = width;
28 | canvas.height = height;
29 |
30 | return setInterval(() => {
31 | ctx.drawImage(video, 0, 0, width, height);
32 | // take pixels out
33 | let pixels = ctx.getImageData(0, 0, width, height);
34 | // mess with them
35 | // pixels = redEffect(pixels);
36 |
37 | pixels = rgbSplit(pixels);
38 | ctx.globalAlpha = 0.8;
39 |
40 | // put them back
41 | ctx.putImageData(pixels, 0, 0);
42 | // debugger;
43 | }, 16);
44 | }
45 |
46 | function greenScreen(pixels) {
47 | const levels = {};
48 |
49 | document.querySelectorAll(".rgb input").forEach(input => {
50 | levels[input.name] = input.value;
51 | });
52 |
53 | for (i = 0; i < pixels.data.length; i = i + 4) {
54 | red = pixels.data[i + 0];
55 | green = pixels.data[i + 1];
56 | blue = pixels.data[i + 2];
57 | alpha = pixels.data[i + 3];
58 |
59 | if (
60 | red >= levels.rmin &&
61 | green >= levels.gmin &&
62 | blue >= levels.bmin &&
63 | red <= levels.rmax &&
64 | green <= levels.gmax &&
65 | blue <= levels.bmax
66 | ) {
67 | // take it out!
68 | pixels.data[i + 3] = 0;
69 | }
70 | }
71 |
72 | return pixels;
73 | }
74 |
75 | function takePhoto() {
76 | // play sound
77 | snap.currentTime = 0;
78 | snap.play();
79 |
80 | const data = canvas.toDataURL("image/jpeg");
81 | const link = document.createElement("a");
82 | link.href = data;
83 | link.setAttribute("download", "handsome");
84 | link.innerHTML = ` `;
85 | strip.insertBefore(link, strip.firstChild);
86 | }
87 |
88 | function redEffect(pixels) {
89 | for (let i = 0; i < pixels.data.length; i += 4) {
90 | pixels.data[i + 0] += 100; //r
91 | pixels.data[i + 1] -= 50; //g
92 | pixels.data[i + 2] *= 0.5; //b
93 | }
94 | return pixels;
95 | }
96 |
97 | function rgbSplit(pixels) {
98 | for (let i = 0; i < pixels.data.length; i += 4) {
99 | pixels.data[i - 150] = pixels.data[i + 0]; // RED
100 | pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
101 | pixels.data[i - 550] = pixels.data[i + 2]; // Blue
102 | }
103 | return pixels;
104 | }
105 |
106 | getVideo();
107 |
108 | video.addEventListener("canplay", paintToCanvas);
109 |
--------------------------------------------------------------------------------
/19-Webcam-Fun/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | font-size: 10px;
4 | background-color: #f46036;
5 | background-image: url("data:image/svg+xml,%3Csvg width='80' height='80' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%232e294e' fill-opacity='0.2'%3E%3Cpath d='M50 50c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10zM10 10c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10S0 25.523 0 20s4.477-10 10-10zm10 8c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm40 40c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
6 | padding: 2vw;
7 | font-family: Arial, Helvetica, sans-serif;
8 | }
9 |
10 | *,
11 | *:before,
12 | *:after {
13 | box-sizing: inherit;
14 | }
15 |
16 | .photobooth {
17 | background: white;
18 | max-width: 150rem;
19 | margin: 2rem auto;
20 | border-radius: 2px;
21 | display: flex;
22 | flex-direction: column;
23 | justify-content: center;
24 | align-items: center;
25 | }
26 |
27 | h1 {
28 | text-align: center;
29 | font-family: 'Pacifico', cursive;
30 | color: #F46036;
31 | font-size: 48px;
32 | margin-bottom: 1vh;
33 | margin-top: 1vh;
34 | padding-top: 0;
35 | }
36 |
37 | button {
38 | height: 5vh;
39 | background-color: #2E294E;
40 | color: #fff;
41 | outline: 0;
42 | border: 0;
43 | border-radius: 0.3em;
44 | margin-bottom: 3vh;
45 | }
46 |
47 | .controls {
48 | margin-bottom: 3vh;
49 | }
50 |
51 | /*clearfix*/
52 | .photobooth:after {
53 | content: "";
54 | display: block;
55 | clear: both;
56 | }
57 |
58 | .photo {
59 | width: 100%;
60 | float: left;
61 | transform: rotateY(180deg);
62 | -webkit-transform:rotateY(180deg); /* Safari and Chrome */
63 | -moz-transform:rotateY(180deg); /* Firefox */
64 | margin-bottom: 1vh;
65 | }
66 |
67 | .player {
68 | position: absolute;
69 | top: 10px;
70 | right: 10px;
71 | width: 200px;
72 | transform: rotateY(180deg);
73 | -webkit-transform:rotateY(180deg); /* Safari and Chrome */
74 | -moz-transform:rotateY(180deg); /* Firefox */
75 | border-radius: 0.3em;
76 | }
77 |
78 | /*
79 | Strip!
80 | */
81 |
82 | .strip {
83 | padding: 2rem;
84 | }
85 |
86 | .strip img {
87 | width: 100px;
88 | overflow-x: scroll;
89 | padding: 0.8rem 0.8rem 2.5rem 0.8rem;
90 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
91 | background: white;
92 | }
93 |
94 | .strip a:nth-child(5n + 1) img {
95 | transform: rotate(10deg);
96 | }
97 | .strip a:nth-child(5n + 2) img {
98 | transform: rotate(-2deg);
99 | }
100 | .strip a:nth-child(5n + 3) img {
101 | transform: rotate(8deg);
102 | }
103 | .strip a:nth-child(5n + 4) img {
104 | transform: rotate(-11deg);
105 | }
106 | .strip a:nth-child(5n + 5) img {
107 | transform: rotate(12deg);
108 | }
109 |
--------------------------------------------------------------------------------
/20-Speech-Recognition/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Speech Detection - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#20
30 |
of JavaScript30
31 |
32 |
33 | Speak to Type
34 | P.S. Do not say any synonym of shit or else face consequences
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/20-Speech-Recognition/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "20-speech-recognition",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html",
9 | "dev": "browser-sync start --directory --server --files \"*.css, *.html, *.js\""
10 | },
11 | "dependencies": {},
12 | "devDependencies": {
13 | "@babel/core": "7.2.0",
14 | "parcel-bundler": "^1.6.1",
15 | "browser-sync": "^2.12.5 <2.27.11"
16 | },
17 | "keywords": []
18 | }
19 |
--------------------------------------------------------------------------------
/20-Speech-Recognition/src/index.js:
--------------------------------------------------------------------------------
1 | window.SpeechRecognition =
2 | window.SpeechRecognition || window.webkitSpeechRecognition;
3 |
4 | const recognition = new SpeechRecognition();
5 | recognition.interimResults = true;
6 |
7 | let p = document.createElement("p");
8 | const words = document.querySelector(".words");
9 | words.appendChild(p);
10 |
11 | recognition.addEventListener("result", e => {
12 | const transcript = Array.from(e.results)
13 | .map(result => result[0])
14 | .map(result => result.transcript)
15 | .join("");
16 |
17 | const poopScript = transcript.replace(/poop|poo|shit|java|dump/gi, "💩");
18 | p.textContent = poopScript;
19 |
20 | // p.textContent = transcript;
21 | if (e.results[0].isFinal) {
22 | p = document.createElement("p");
23 | words.appendChild(p);
24 | }
25 | });
26 |
27 | recognition.addEventListener("end", recognition.start);
28 | recognition.start();
29 |
--------------------------------------------------------------------------------
/20-Speech-Recognition/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 10px;
3 | }
4 |
5 | body {
6 | background-color: #f38181;
7 | background-image: url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 40 40' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20 20.5V18H0v-2h20v-2H0v-2h20v-2H0V8h20V6H0V4h20V2H0V0h22v20h2V0h2v20h2V0h2v20h2V0h2v20h2V0h2v20h2v2H20v-1.5zM0 20h2v20H0V20zm4 0h2v20H4V20zm4 0h2v20H8V20zm4 0h2v20h-2V20zm4 0h2v20h-2V20zm4 4h20v2H20v-2zm0 4h20v2H20v-2zm0 4h20v2H20v-2zm0 4h20v2H20v-2z' fill='%23fce38a' fill-opacity='0.25' fill-rule='evenodd'/%3E%3C/svg%3E");
8 | font-family: 'helvetica neue';
9 | font-weight: 200;
10 | font-size: 20px;
11 | display: flex;
12 | justify-content: center;
13 | flex-direction: column;
14 | font-family: sans-serif;
15 | }
16 |
17 | h1, small {
18 | color: #eaffd0;
19 | text-align: center;
20 | }
21 |
22 | .words {
23 | width: 500px;
24 | max-width: 500px;
25 | margin: 50px auto;
26 | background: #95e1d3;
27 | border-radius: 5px;
28 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.1);
29 | padding: 1rem 2rem 1rem 5rem;
30 | background: -webkit-gradient(
31 | linear,
32 | 0 0,
33 | 0 100%,
34 | from(#d9eaf3),
35 | color-stop(4%, #95e1d3)
36 | )
37 | 0 4px;
38 | background-size: 100% 3rem;
39 | position: relative;
40 | line-height: 3rem;
41 | }
42 |
43 | p {
44 | margin: 0 0 3rem;
45 | }
46 |
47 | .words:before {
48 | content: '';
49 | position: absolute;
50 | width: 4px;
51 | top: 0;
52 | left: 30px;
53 | bottom: 0;
54 | border: 1px solid;
55 | border-color: transparent #efe4e4;
56 | }
57 |
--------------------------------------------------------------------------------
/21-Geolocation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Geolocation - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
9 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
#21
31 |
of JavaScript30
32 |
33 |
34 |
45 |
46 |
50 |
51 |
55 |
59 |
63 |
67 |
71 |
72 |
73 |
74 |
75 |
76 | 0
77 | KM/H
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/21-Geolocation/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "21-geolocation",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "browser-sync start --directory --server --files \"*.css, *.html, *.js\""
8 | },
9 | "dependencies": {},
10 | "devDependencies": {
11 | "browser-sync": "^2.12.5 <2.27.11"
12 | },
13 | "keywords": []
14 | }
15 |
--------------------------------------------------------------------------------
/21-Geolocation/src/index.js:
--------------------------------------------------------------------------------
1 | const arrow = document.querySelector('.arrow');
2 | const speed = document.querySelector('.speed-value');
3 |
4 | navigator.geolocation.watchPosition((data) => {
5 | console.log(data);
6 | speed.textContent = (data.coords.speed * 3.6).toFixed(2);
7 | arrow.style.transform = `rotate(${data.coords.heading}deg)`
8 | }, (err) => {
9 | console.log(err);
10 | alert('Uh-oh, you need to allow location permission for this application to run.')
11 | });
--------------------------------------------------------------------------------
/21-Geolocation/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 100px;
3 | }
4 |
5 | body {
6 | margin: 0;
7 | font-family: sans-serif;
8 | min-height: 100vh;
9 | display: flex;
10 | justify-content: center;
11 | align-items: center;
12 | flex-direction: column;
13 | background: radial-gradient(black 15%, transparent 16%) 0 0,
14 | radial-gradient(black 15%, transparent 16%) 8px 8px,
15 | radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 0 1px,
16 | radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 8px 9px;
17 | background-color: #282828;
18 | background-size: 16px 16px;
19 | background-attachment: fixed;
20 | }
21 |
22 | .arrow {
23 | width: 250px;
24 | overflow: hidden;
25 | transition: all 0.2s;
26 | transform: rotate(0deg);
27 | display: inline-block;
28 | }
29 |
30 | h1 {
31 | color: white;
32 | font-weight: 100;
33 | font-size: 60px;
34 | display: flex;
35 | align-items: center;
36 | }
37 |
38 | .units {
39 | font-size: 15px;
40 | }
41 | /*Compass: https://thenounproject.com/search/?q=compass&i=592352*/
42 |
--------------------------------------------------------------------------------
/22-Follow-Along-Link/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 👀 Follow Along Nav - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#22
30 |
of JavaScript30
31 |
32 |
33 | Follow Along Link
34 |
35 |
42 |
43 |
44 |
45 |
46 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
47 | Est explicabo unde natus necessitatibus esse obcaecati
48 | distinctio, aut itaque, qui vitae!
49 |
50 |
51 | Aspernatur sapiente quae sint soluta modi, atque
52 | praesentium laborum pariatur earum quaerat cupiditate
53 | consequuntur facilis ullam dignissimos, aperiam quam veniam.
54 |
55 |
56 | Cum ipsam quod, incidunt sit ex tempore placeat maxime
57 | corrupti possimus veritatis ipsum fugit
58 | recusandae est doloremque? Hic, quibusdam , nulla.
59 |
60 |
61 | Esse quibusdam, ad, ducimus cupiditate nulla , quae magni
62 | odit totam ut consequatur eveniet sunt quam provident
63 | sapiente dicta neque quod.
64 |
65 |
66 | Aliquam dicta sequi culpa fugiat
67 | consequuntur pariatur optio ad minima, maxime
68 | odio , distinctio magni impedit tempore enim repellendus
69 | repudiandae quas!
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/22-Follow-Along-Link/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "follow-along-link",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/22-Follow-Along-Link/src/index.js:
--------------------------------------------------------------------------------
1 | const triggers = document.querySelectorAll("a");
2 | const highlight = document.createElement("span");
3 | highlight.classList.add("highlight");
4 | document.body.appendChild(highlight);
5 |
6 | function highlightLink() {
7 | const linkCoords = this.getBoundingClientRect();
8 | console.log(linkCoords);
9 |
10 | const coords = {
11 | width: linkCoords.width,
12 | height: linkCoords.height,
13 | top: linkCoords.top + window.scrollY,
14 | left: linkCoords.left + window.scrollX
15 | };
16 |
17 | highlight.style.width = `${coords.width}px`;
18 | highlight.style.height = `${coords.height}px`;
19 | highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;
20 | }
21 | triggers.forEach(a => a.addEventListener("mouseenter", highlightLink));
22 |
--------------------------------------------------------------------------------
/22-Follow-Along-Link/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | }
4 |
5 | *,
6 | *:before,
7 | *:after {
8 | box-sizing: inherit;
9 | }
10 |
11 | body {
12 | min-height: 100vh;
13 | margin: 0; /* Important! */
14 | font-family: sans-serif;
15 | background-color: #00adb5;
16 | background-image: url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23eeeeee' fill-opacity='0.1'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4v2c-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
17 | }
18 |
19 | h1{
20 | text-align: center;
21 | color: #eeeeee;
22 | }
23 |
24 | .wrapper {
25 | margin: 0 auto;
26 | max-width: 500px;
27 | font-size: 20px;
28 | line-height: 2;
29 | position: relative;
30 | }
31 |
32 | a {
33 | text-decoration: none;
34 | color: black;
35 | background: rgba(0, 0, 0, 0.05);
36 | border-radius: 20px;
37 | }
38 |
39 | .highlight {
40 | transition: all 0.2s;
41 | border-bottom: 2px solid #eeeeee;
42 | position: absolute;
43 | top: 0;
44 | background: #eeeeee;
45 | left: 0;
46 | z-index: -1;
47 | border-radius: 20px;
48 | display: block;
49 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
50 | }
51 |
52 | .menu {
53 | padding: 0;
54 | display: flex;
55 | list-style: none;
56 | justify-content: center;
57 | margin: 100px 0;
58 | }
59 |
60 | .menu a {
61 | display: inline-block;
62 | padding: 5px;
63 | margin: 0 20px;
64 | color: #393e46;
65 | }
66 |
--------------------------------------------------------------------------------
/23-Speech-Synthesis/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Speech Synthesis - JavaScript30 by Ayush Gupta
6 |
11 |
12 |
13 |
18 |
24 |
30 |
31 |
32 |
33 |
34 |
#23
35 |
of JavaScript30
36 |
37 |
38 |
39 |
The Voiceinator 5000
40 |
41 |
42 | Select A Voice
43 |
44 |
45 | Rate:
46 |
47 |
48 | Pitch:
49 |
50 |
51 |
52 | Stop!
53 | Speak
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/23-Speech-Synthesis/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "23-speech-synthesis",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/23-Speech-Synthesis/src/index.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 | voicesDropdown.innerHTML = voices
13 | .filter((voice) => voice.lang.includes('en'))
14 | .map(
15 | (voice) =>
16 | `${voice.name} - (${voice.lang}) `
17 | )
18 | .join('');
19 | }
20 |
21 | function setVoice() {
22 | msg.voice = voices.find((voice) => voice.name === this.value);
23 | toggle();
24 | }
25 |
26 | function toggle(startOver = true) {
27 | speechSynthesis.cancel();
28 | if (startOver) {
29 | speechSynthesis.speak(msg);
30 | }
31 | }
32 |
33 | function setOption() {
34 | msg[this.name] = this.value;
35 | toggle();
36 | }
37 |
38 | speechSynthesis.addEventListener('voiceschanged', populateVoices);
39 | voicesDropdown.addEventListener('change', setVoice);
40 | options.forEach((option) => option.addEventListener('change', setOption));
41 | speakButton.addEventListener('click', toggle);
42 | stopButton.addEventListener('click', () => toggle(false));
43 |
--------------------------------------------------------------------------------
/23-Speech-Synthesis/src/styles.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 | background-color: #ff9999;
19 | background-image: url("data:image/svg+xml,%3Csvg width='180' height='180' viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M81.28 88H68.413l19.298 19.298L81.28 88zm2.107 0h13.226L90 107.838 83.387 88zm15.334 0h12.866l-19.298 19.298L98.72 88zm-32.927-2.207L73.586 78h32.827l.5.5 7.294 7.293L115.414 87l-24.707 24.707-.707.707L64.586 87l1.207-1.207zm2.62.207L74 80.414 79.586 86H68.414zm16 0L90 80.414 95.586 86H84.414zm16 0L106 80.414 111.586 86h-11.172zm-8-6h11.173L98 85.586 92.414 80zM82 85.586L87.586 80H76.414L82 85.586zM17.414 0L.707 16.707 0 17.414V0h17.414zM4.28 0L0 12.838V0h4.28zm10.306 0L2.288 12.298 6.388 0h8.198zM180 17.414L162.586 0H180v17.414zM165.414 0l12.298 12.298L173.612 0h-8.198zM180 12.838L175.72 0H180v12.838zM0 163h16.413l.5.5 7.294 7.293L25.414 172l-8 8H0v-17zm0 10h6.613l-2.334 7H0v-7zm14.586 7l7-7H8.72l-2.333 7h8.2zM0 165.414L5.586 171H0v-5.586zM10.414 171L16 165.414 21.586 171H10.414zm-8-6h11.172L8 170.586 2.414 165zM180 163h-16.413l-7.794 7.793-1.207 1.207 8 8H180v-17zm-14.586 17l-7-7h12.865l2.333 7h-8.2zM180 173h-6.613l2.334 7H180v-7zm-21.586-2l5.586-5.586 5.586 5.586h-11.172zM180 165.414L174.414 171H180v-5.586zm-8 5.172l5.586-5.586h-11.172l5.586 5.586zM152.933 25.653l1.414 1.414-33.94 33.942-1.416-1.416 33.943-33.94zm1.414 127.28l-1.414 1.414-33.942-33.94 1.416-1.416 33.94 33.943zm-127.28 1.414l-1.414-1.414 33.94-33.942 1.416 1.416-33.943 33.94zm-1.414-127.28l1.414-1.414 33.942 33.94-1.416 1.416-33.94-33.943zM0 85c2.21 0 4 1.79 4 4s-1.79 4-4 4v-8zm180 0c-2.21 0-4 1.79-4 4s1.79 4 4 4v-8zM94 0c0 2.21-1.79 4-4 4s-4-1.79-4-4h8zm0 180c0-2.21-1.79-4-4-4s-4 1.79-4 4h8z' fill='%23ffc8c8' fill-opacity='0.43' fill-rule='evenodd'/%3E%3C/svg%3E");
20 | }
21 |
22 | .voiceinator {
23 | padding: 2rem;
24 | width: 50rem;
25 | margin: 0 auto;
26 | border-radius: 1rem;
27 | position: relative;
28 | background: white;
29 | overflow: hidden;
30 | z-index: 1;
31 | box-shadow: 0 0 5px 5px rgba(0,0,0,0.1);
32 | }
33 |
34 | h1 {
35 | width: calc(100% + 4rem);
36 | margin: -2rem 0 2rem -2rem;
37 | padding: .5rem;
38 | background: #3fc1c9;
39 | border-bottom: 5px solid #ffc8c8;
40 | text-align: center;
41 | font-size: 5rem;
42 | font-weight: 100;
43 | font-family: 'Pacifico', cursive;
44 | text-shadow: 3px 3px 0 #ffc8c8;
45 | /* color: white; */
46 | }
47 |
48 | .voiceinator input,
49 | .voiceinator button,
50 | .voiceinator select,
51 | .voiceinator textarea {
52 | width: 100%;
53 | display: block;
54 | margin: 10px 0;
55 | padding: 10px;
56 | border: 0;
57 | font-size: 2rem;
58 | background: #F7F7F7;
59 | outline: 0;
60 | }
61 |
62 | textarea {
63 | height: 20rem;
64 | }
65 |
66 | input[type="select"] {
67 |
68 | }
69 |
70 | .voiceinator button {
71 | background: #3fc1c9;
72 | border: 0;
73 | width: 49%;
74 | float: left;
75 | font-family: 'Pacifico', cursive;
76 | margin-bottom: 0;
77 | font-size: 2rem;
78 | border-bottom: 5px solid #ffc8c8;
79 | cursor: pointer;
80 | position: relative;
81 | }
82 |
83 | .voiceinator button:active {
84 | top: 2px;
85 | }
86 |
87 | .voiceinator button:nth-of-type(1) {
88 | margin-right: 2%;
89 | }
--------------------------------------------------------------------------------
/24-Sticky-Nav/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sticky-nav",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/24-Sticky-Nav/src/index.js:
--------------------------------------------------------------------------------
1 | const nav = document.querySelector("#main");
2 | const topOfNav = nav.offsetTop;
3 |
4 | function fixNav() {
5 | if (window.scrollY >= topOfNav) {
6 | document.body.style.paddingTop = nav.offsetHeight + "px";
7 | document.body.classList.add("fixed-nav");
8 | } else {
9 | document.body.style.paddingTop = 0;
10 | document.body.classList.remove("fixed-nav");
11 | }
12 | }
13 |
14 | window.addEventListener("scroll", fixNav);
15 |
--------------------------------------------------------------------------------
/24-Sticky-Nav/src/styles.css:
--------------------------------------------------------------------------------
1 | #project-tag {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | background-color: yellow;
6 | border: 1px solid transparent;
7 | /* border-radius: 0px 3px 3px 0px; */
8 | border-bottom-right-radius: 3px;
9 | color: black;
10 | font-weight: bolder;
11 | font-family: monospace;
12 | font-size: medium;
13 | height: 5vh;
14 | display: flex;
15 | flex-direction: column;
16 | justify-content: center;
17 | align-items: center;
18 | padding: 5px 15px;
19 | transition-timing-function: linear;
20 | box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
21 | }
22 |
23 | html {
24 | box-sizing: border-box;
25 | background: #444f5a;
26 | font-family: "helvetica neue";
27 | font-size: 20px;
28 | font-weight: 200;
29 | }
30 |
31 | body {
32 | margin: 0;
33 | }
34 |
35 | *,
36 | *:before,
37 | *:after {
38 | box-sizing: inherit;
39 | }
40 |
41 | .site-wrap {
42 | max-width: 700px;
43 | margin: 70px auto;
44 | background: #ff9999;
45 | padding: 40px;
46 | text-align: justify;
47 | box-shadow: 0 0 10px 5px rgba(0, 0, 0, 0.05);
48 | transform: scale(0.98);
49 | transition: transform 0.5s;
50 | }
51 |
52 | .fixed-nav .site-wrap {
53 | transform: scale(1);
54 | }
55 |
56 | header {
57 | text-align: center;
58 | height: 50vh;
59 | background: url(http://wes.io/iEgP/wow-so-deep.jpg) bottom center no-repeat;
60 | background-size: cover;
61 | display: flex;
62 | align-items: center;
63 | justify-content: center;
64 | }
65 |
66 | h1 {
67 | color: #ffc8c8;
68 | font-size: 7vw;
69 | text-shadow: 3px 4px 0 rgba(0, 0, 0, 0.2);
70 | }
71 |
72 | nav {
73 | background: #ff9999;
74 | top: 0;
75 | width: 100%;
76 | transition: all 0.5s;
77 | position: relative;
78 | z-index: 1;
79 | }
80 |
81 | .fixed-nav nav {
82 | position: fixed;
83 | box-shadow: 0 5px rgba(0, 0, 0, 0.2);
84 | }
85 |
86 | nav ul {
87 | margin: 0;
88 | padding: 0;
89 | list-style: none;
90 | display: flex;
91 | }
92 |
93 | nav li {
94 | flex: 1;
95 | text-align: center;
96 | display: flex;
97 | justify-content: center;
98 | align-items: center;
99 | }
100 |
101 | li.logo {
102 | max-width: 0;
103 | overflow: hidden;
104 | background: white;
105 | transition: all 0.5s;
106 | font-weight: 600;
107 | font-size: 30px;
108 | }
109 |
110 | .fixed-nav li.logo {
111 | max-width: 500px;
112 | }
113 |
114 | li.logo a {
115 | color: black;
116 | }
117 |
118 | nav a {
119 | text-decoration: none;
120 | padding: 20px;
121 | display: inline-block;
122 | color: white;
123 | transition: all 0.2s;
124 | text-transform: uppercase;
125 | }
126 |
--------------------------------------------------------------------------------
/25-EventCapture-Propogation-Bubbling/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Understanding JavaScript's Capture - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#25
30 |
of JavaScript30
31 |
32 |
33 | JavaScript Event Capture & Bubbling
34 |
39 |
40 | Pay Now
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/25-EventCapture-Propogation-Bubbling/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "25-eventpropogation-bubbling-once",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/25-EventCapture-Propogation-Bubbling/src/index.js:
--------------------------------------------------------------------------------
1 | const divs = document.querySelectorAll("div");
2 | const button = document.querySelector("button");
3 | function logText(e) {
4 | console.log(this.classList.value);
5 | e.stopPropagation(); // stop bubbling!
6 | console.log(this);
7 | }
8 | divs.forEach(div =>
9 | div.addEventListener("click", logText, {
10 | capture: false,
11 | once: true
12 | })
13 | );
14 | button.addEventListener(
15 | "click",
16 | () => {
17 | console.log("Click!!!");
18 | },
19 | {
20 | once: true
21 | }
22 | );
23 |
--------------------------------------------------------------------------------
/25-EventCapture-Propogation-Bubbling/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | text-align: center;
4 | font-family: monospace;
5 | color: #EFCB68;
6 | background-color: #160c28;
7 | background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%23efcb68' fill-opacity='0.17' fill-rule='evenodd'/%3E%3C/svg%3E");
8 | display: flex;
9 | justify-content: center;
10 | align-items: center;
11 | flex-direction: column;
12 | }
13 |
14 | *,
15 | *:before,
16 | *:after {
17 | box-sizing: inherit;
18 | }
19 | .one {
20 | background: #E65F5C;
21 | width: 100%;
22 | padding: 100px;
23 | border-radius: 0.3em;
24 | margin-bottom: 10px;
25 | margin-top: 5vh;
26 | }
27 | .two {
28 | background: #406E8E;
29 | width: 100%;
30 | padding: 100px;
31 | }
32 | .three {
33 | background: #0CBABA;
34 | width: 100%;
35 | padding: 100px;
36 | }
37 |
38 | button {
39 | background-color: #EFCB68;
40 | color: #160c28;
41 | border: 0;
42 | outline: 0;
43 | border-radius: 0.3em;
44 | height: 3vh;
45 | font-weight: bold;
46 | text-transform: uppercase;
47 | min-width: 15vh;
48 | }
49 |
--------------------------------------------------------------------------------
/26-Stripe-Nav/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Strip Nav - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#26
30 |
of JavaScript30
31 |
32 |
33 | Ayush Gupta
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | About Me
42 |
43 |
44 |
45 |
46 | Ayush Gupta is skilled and enthusiast about web & mobile
47 | development. He has a keen interest in designing. Photography is
48 | his passion!
49 |
50 |
51 |
52 |
53 |
54 | Projects
55 |
78 |
79 |
80 | Other Links
81 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/26-Stripe-Nav/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "26-stripe-nav",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/26-Stripe-Nav/src/index.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(() => {
8 | this.classList.contains("trigger-enter") &&
9 | this.classList.add("trigger-enter-active");
10 | }, 150);
11 | background.classList.add("open");
12 |
13 | const dropdown = this.querySelector(".dropdown");
14 | const dropdownCoords = dropdown.getBoundingClientRect();
15 | const navCoords = nav.getBoundingClientRect();
16 |
17 | const coords = {
18 | height: dropdownCoords.height,
19 | width: dropdownCoords.width,
20 | top: dropdownCoords.top - navCoords.top,
21 | left: dropdownCoords.left - navCoords.left
22 | };
23 |
24 | background.style.setProperty("width", `${coords.width}px`);
25 | background.style.setProperty("height", `${coords.height}px`);
26 | background.style.setProperty(
27 | "transform",
28 | `translate(${coords.left}px, ${coords.top}px)`
29 | );
30 | }
31 |
32 | function handleLeave() {
33 | this.classList.remove("trigger-enter", "tigger-enter-active");
34 | background.classList.remove("open");
35 | }
36 |
37 | triggers.forEach(trigger =>
38 | trigger.addEventListener("mouseenter", handleEnter)
39 | );
40 | triggers.forEach(trigger =>
41 | trigger.addEventListener("mouseleave", handleLeave)
42 | );
43 |
--------------------------------------------------------------------------------
/27-Click-Drag-Scroll/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Click and Drag - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#27
30 |
of JavaScript30
31 |
32 |
33 |
34 |
01
35 |
02
36 |
03
37 |
04
38 |
05
39 |
06
40 |
07
41 |
08
42 |
09
43 |
10
44 |
11
45 |
12
46 |
13
47 |
14
48 |
15
49 |
16
50 |
17
51 |
18
52 |
19
53 |
20
54 |
21
55 |
22
56 |
23
57 |
24
58 |
25
59 |
26
60 |
27
61 |
28
62 |
29
63 |
30
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/27-Click-Drag-Scroll/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "27-click-drag-scroll",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/27-Click-Drag-Scroll/src/index.js:
--------------------------------------------------------------------------------
1 | const slider = document.querySelector(".items");
2 | let isDown = false;
3 | let startX;
4 | let scrollLeft;
5 |
6 | slider.addEventListener("mousedown", e => {
7 | isDown = true;
8 | slider.classList.add("active");
9 | startX = e.pageX - slider.offsetLeft;
10 | scrollLeft = slider.scrollLeft;
11 | });
12 |
13 | slider.addEventListener("mouseleave", () => {
14 | isDown = false;
15 | slider.classList.remove("active");
16 | });
17 |
18 | slider.addEventListener("mouseup", () => {
19 | isDown = false;
20 | slider.classList.remove("active");
21 | });
22 |
23 | slider.addEventListener("mousemove", e => {
24 | if (!isDown) return;
25 | e.preventDefault();
26 | const x = e.pageX - slider.offsetLeft;
27 | const walk = (x - startX) * 3;
28 | slider.scrollLeft = scrollLeft - walk;
29 | });
30 |
--------------------------------------------------------------------------------
/27-Click-Drag-Scroll/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | background-color: #111111;
4 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cg fill='%23808080' fill-opacity='0.22'%3E%3Cpolygon fill-rule='evenodd' points='8 4 12 6 8 8 6 12 4 8 0 6 4 4 6 0 8 4'/%3E%3C/g%3E%3C/svg%3E");
5 |
6 | }
7 | *,
8 | *:before,
9 | *:after {
10 | box-sizing: inherit;
11 | }
12 |
13 | body {
14 | min-height: 100vh;
15 | display: flex;
16 | justify-content: center;
17 | align-items: center;
18 | font-family: sans-serif;
19 | font-size: 20px;
20 | margin: 0;
21 | }
22 |
23 | .items {
24 | height: 85vh;
25 | padding: 100px;
26 | width: 100%;
27 | border: 1px solid white;
28 | border-radius: 10px;
29 | overflow-x: scroll;
30 | overflow-y: hidden;
31 | white-space: nowrap;
32 | user-select: none;
33 | cursor: pointer;
34 | transition: all 0.2s;
35 | transform: scale(0.98);
36 | will-change: transform;
37 | position: relative;
38 | background: rgba(255, 255, 255, 0.05);
39 | font-size: 0;
40 | perspective: 500px;
41 | }
42 |
43 | .items.active {
44 | background: rgba(255, 255, 255, 0.1);
45 | cursor: grabbing;
46 | cursor: -webkit-grabbing;
47 | transform: scale(1);
48 | }
49 |
50 | .item {
51 | width: 200px;
52 | height: calc(100% - 10px);
53 | display: inline-flex;
54 | align-items: center;
55 | justify-content: center;
56 | border-radius: 10px;
57 | font-size: 80px;
58 | font-weight: 100;
59 | color: rgba(0, 0, 0, 0.15);
60 | box-shadow: inset 0 0 0 10px rgba(0, 0, 0, 0.15);
61 | }
62 |
63 | .item:nth-child(5n + 1) {
64 | background: #2f855a;
65 | }
66 | .item:nth-child(5n + 2) {
67 | background: #38a169;
68 | }
69 | .item:nth-child(5n + 3) {
70 | background: #48bb78;
71 | }
72 | .item:nth-child(5n + 4) {
73 | background: #68d391;
74 | }
75 | .item:nth-child(5n + 5) {
76 | background: #9ae6b4;
77 | }
78 |
79 | .item:nth-child(5n + 6) {
80 | background: #b83280;
81 | }
82 | .item:nth-child(5n + 7) {
83 | background: #d53f8c;
84 | }
85 | .item:nth-child(5n + 8) {
86 | background: #ed64a6;
87 | }
88 | .item:nth-child(5n + 9) {
89 | background: #f687b3;
90 | }
91 | .item:nth-child(5n + 10) {
92 | background: #fbb6ce;
93 | }
94 |
95 | .item:nth-child(5n + 11) {
96 | background: #6B46C1;
97 | }
98 | .item:nth-child(5n + 12) {
99 | background: #805AD5;
100 | }
101 | .item:nth-child(5n + 13) {
102 | background: #9F7AEA;
103 | }
104 | .item:nth-child(5n + 14) {
105 | background: #B794F4;
106 | }
107 | .item:nth-child(5n + 15) {
108 | background: #D6BCFA;
109 | }
110 |
111 | .item:nth-child(5n + 16) {
112 | background: #C05621;
113 | }
114 | .item:nth-child(5n + 17) {
115 | background: #DD6B20;
116 | }
117 | .item:nth-child(5n + 18) {
118 | background: #ED8936;
119 | }
120 | .item:nth-child(5n + 19) {
121 | background: #F6AD55;
122 | }
123 | .item:nth-child(5n + 20) {
124 | background: #FBD38D;
125 | }
126 |
127 | .item:nth-child(5n + 21) {
128 | background: #C53030;
129 | }
130 | .item:nth-child(5n + 22) {
131 | background: #E53E3E;
132 | }
133 | .item:nth-child(5n + 23) {
134 | background: #F56565;
135 | }
136 | .item:nth-child(5n + 24) {
137 | background: #FC8181;
138 | }
139 | .item:nth-child(5n + 25) {
140 | background: #FEB2B2;
141 | }
142 |
143 | .item:nth-child(5n + 26) {
144 | background: #2C7A7B;
145 | }
146 | .item:nth-child(5n + 27) {
147 | background: #319795;
148 | }
149 | .item:nth-child(5n + 28) {
150 | background: #38B2AC;
151 | }
152 | .item:nth-child(5n + 29) {
153 | background: #4FD1C5;
154 | }
155 | .item:nth-child(5n + 30) {
156 | background: #81E6D9;
157 | }
158 |
159 |
160 |
161 | .item:nth-child(even) {
162 | transform: scaleX(1.31) rotateY(40deg);
163 | }
164 | .item:nth-child(odd) {
165 | transform: scaleX(1.31) rotateY(-40deg);
166 | }
167 |
--------------------------------------------------------------------------------
/28-Video-Speed-Controller/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Video Speed Scrubber - JavaScript30 by Ayush Gupta
6 |
7 |
8 |
13 |
19 |
25 |
26 |
27 |
28 |
29 |
#28
30 |
of JavaScript30
31 |
32 |
33 | Video Speed Controller
34 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/28-Video-Speed-Controller/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "28-video-speed-controller",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
--------------------------------------------------------------------------------
/28-Video-Speed-Controller/src/index.js:
--------------------------------------------------------------------------------
1 | const speed = document.querySelector(".speed");
2 | const bar = speed.querySelector(".speed-bar");
3 | const video = document.querySelector(".flex");
4 |
5 | function handleMove(e) {
6 | const y = e.pageY - this.offsetTop;
7 | const percent = y / this.offsetHeight;
8 | const min = 0.4;
9 | const max = 6;
10 | const height = Math.round(percent * 100) + "%";
11 | bar.style.height = height;
12 |
13 | const playbackRate = percent * (max - min) + min;
14 | bar.textContent = playbackRate.toFixed(2) + "x";
15 | video.playbackRate = playbackRate;
16 | }
17 |
18 | speed.addEventListener("mousemove", handleMove);
19 |
--------------------------------------------------------------------------------
/28-Video-Speed-Controller/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | display: flex;
4 | justify-content: center;
5 | align-items: center;
6 | min-height: 100vh;
7 | background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
8 | url('http://www.lisbonazulejos.com/assets/images/svg/azulejo-26.svg');
9 | /* opacity: 0.5; */
10 | font-family: sans-serif;
11 | flex-direction: column;
12 | }
13 | h1 {
14 | color: #fff;
15 | font-size: calc(1em + 2vw);
16 | font-weight: 900;
17 | text-shadow: 4px 4px 0px #6a82fb, 7px 7px 0px rgba(0, 0, 0, 0.5);
18 | margin-bottom: 5vh;
19 | }
20 |
21 | .wrapper {
22 | width: 850px;
23 | display: flex;
24 | }
25 |
26 | video {
27 | box-shadow: 0 0 1px 3px rgba(0, 0, 0, 0.1);
28 | }
29 |
30 | .speed {
31 | background: #efefef;
32 | flex: 1;
33 | display: flex;
34 | align-items: flex-start;
35 | margin: 10px;
36 | border-radius: 50px;
37 | box-shadow: 0 0 1px 3px rgba(0, 0, 0, 0.1);
38 | overflow: hidden;
39 | }
40 |
41 | .speed-bar {
42 | width: 100%;
43 | background: #373b44; /* fallback for old browsers */
44 | background: -webkit-linear-gradient(
45 | to bottom,
46 | #4286f4,
47 | #373b44
48 | ); /* Chrome 10-25, Safari 5.1-6 */
49 | background: linear-gradient(
50 | to bottom,
51 | #4286f4,
52 | #373b44
53 | ); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
54 |
55 | cursor: grab;
56 | text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
57 | display: flex;
58 | align-items: center;
59 | justify-content: center;
60 | padding: 2px;
61 | color: white;
62 | height: 16.3%;
63 | }
64 |
--------------------------------------------------------------------------------
/29-Countdown-Timer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Countdown Timer - JavaScript30 by Ayush Gupta
6 |
11 |
12 |
17 |
23 |
29 |
30 |
31 |
32 |
33 |
#29
34 |
of JavaScript30
35 |
36 |
37 |
38 |
39 | 20 Secs
40 | Work 5
41 | Quick 15
42 | Snack 20
43 | Lunch Break
44 |
47 |
48 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/29-Countdown-Timer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "29-countdown-clock",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/29-Countdown-Timer/src/index.js:
--------------------------------------------------------------------------------
1 | let countdown;
2 | const timerDisplay = document.querySelector(".display__time-left");
3 | const endTime = document.querySelector(".display__end-time");
4 | const buttons = document.querySelectorAll("[data-time]");
5 |
6 | function timer(seconds) {
7 | // clear any existing timers
8 | clearInterval(countdown);
9 |
10 | const now = Date.now();
11 | const then = now + seconds * 1000;
12 | displayTimeLeft(seconds);
13 | displayEndTime(then);
14 |
15 | countdown = setInterval(() => {
16 | const secondsLeft = Math.round((then - Date.now()) / 1000);
17 | // check if we should stop it!
18 | if (secondsLeft < 0) {
19 | clearInterval(countdown);
20 | return;
21 | }
22 | // display it
23 | displayTimeLeft(secondsLeft);
24 | }, 1000);
25 | }
26 |
27 | function displayTimeLeft(seconds) {
28 | const minutes = Math.floor(seconds / 60);
29 | const remainderSeconds = seconds % 60;
30 | const display = `${minutes}:${
31 | remainderSeconds < 10 ? "0" : ""
32 | }${remainderSeconds}`;
33 | document.title = display;
34 | timerDisplay.textContent = display;
35 | }
36 |
37 | function displayEndTime(timestamp) {
38 | const end = new Date(timestamp);
39 | const hour = end.getHours();
40 | const adjustedHour = hour > 12 ? hour - 12 : hour;
41 | const minutes = end.getMinutes();
42 | endTime.textContent = `Be Back At ${adjustedHour}:${
43 | minutes < 10 ? "0" : ""
44 | }${minutes}`;
45 | }
46 |
47 | function startTimer() {
48 | const seconds = parseInt(this.dataset.time);
49 | timer(seconds);
50 | }
51 |
52 | buttons.forEach(button => button.addEventListener("click", startTimer));
53 | document.customForm.addEventListener("submit", function(e) {
54 | e.preventDefault();
55 | const mins = this.minutes.value;
56 | console.log(mins);
57 | timer(mins * 60);
58 | this.reset();
59 | });
60 |
--------------------------------------------------------------------------------
/29-Countdown-Timer/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | font-size: 10px;
4 | background: #2B2C34;
5 | background: url('../../assets/shattered-island.gif')
6 | }
7 |
8 | *,
9 | *:before,
10 | *:after {
11 | box-sizing: inherit;
12 | }
13 |
14 | body {
15 | margin: 0;
16 | text-align: center;
17 | font-family: "Inconsolata", monospace;
18 | }
19 |
20 | .display__time-left {
21 | font-weight: 100;
22 | font-size: 20rem;
23 | margin: 0;
24 | color: white;
25 | text-shadow: 4px 4px 0 rgba(0, 0, 0, 0.05);
26 | }
27 |
28 | .timer {
29 | display: flex;
30 | min-height: 100vh;
31 | flex-direction: column;
32 | }
33 |
34 | .timer__controls {
35 | display: flex;
36 | }
37 |
38 | .timer__controls > * {
39 | flex: 1;
40 | }
41 |
42 | .timer__controls form {
43 | flex: 1;
44 | display: flex;
45 | }
46 |
47 | .timer__controls input {
48 | flex: 1;
49 | border: 0;
50 | padding: 2rem;
51 | }
52 |
53 | .timer__button {
54 | /* background: none; */
55 | border: 0;
56 | cursor: pointer;
57 | color: white;
58 | font-size: 2rem;
59 | text-transform: uppercase;
60 | background: rgba(0, 0, 0, 0.1);
61 | border-bottom: 3px solid rgba(0, 0, 0, 0.2);
62 | border-right: 1px solid rgba(0, 0, 0, 0.2);
63 | padding: 1rem;
64 | font-family: "Inconsolata", monospace;
65 | }
66 |
67 | .timer__button:hover,
68 | .timer__button:focus {
69 | background: rgba(0, 0, 0, 0.2);
70 | outline: 0;
71 | }
72 |
73 | .color:nth-child(5n+1) {
74 | background-color: #7fb069;
75 | }
76 | .color:nth-child(5n+2) {
77 | background-color: #8963BA;
78 | }
79 | .color:nth-child(5n+3) {
80 | background-color: #E6AA68;
81 | }
82 | .color:nth-child(5n+4) {
83 | background-color: #DF6553;
84 | }
85 | .color:nth-child(5n+5) {
86 | background-color: #1FCBFF;
87 | }
88 |
89 | input {
90 | background-color: rgb(214, 214, 214);
91 | color: #000;
92 | }
93 |
94 | .display {
95 | flex: 1;
96 | display: flex;
97 | flex-direction: column;
98 | align-items: center;
99 | justify-content: center;
100 | }
101 |
102 | .display__end-time {
103 | font-size: 4rem;
104 | color: white;
105 | }
106 |
107 | #project-tag {
108 | position: absolute;
109 | bottom: 0;
110 | right: 0;
111 | background-color: yellow;
112 | border: 1px solid transparent;
113 | /* border-radius: 0px 3px 3px 0px; */
114 | border-top-left-radius: 3px;
115 | color: black;
116 | font-weight: bolder;
117 | font-family: monospace;
118 | font-size: medium;
119 | height: 6vh;
120 | display: flex;
121 | flex-direction: column;
122 | justify-content: center;
123 | align-items: center;
124 | padding: 5px 15px;
125 | transition-timing-function: linear;
126 | box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
127 | }
--------------------------------------------------------------------------------
/30-Whack-A-Mole/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Whack A Mole! - JavaScript30 by Ayush Gupta
6 |
11 |
12 |
13 |
18 |
24 |
30 |
31 |
32 |
33 |
34 |
#30
35 |
of JavaScript30
36 |
37 |
38 | Whack-a-mole!
39 | Your Score - 0
40 |
43 |
44 |
45 |
46 |
49 |
52 |
55 |
58 |
61 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/30-Whack-A-Mole/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "30-whack-a-mole",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/30-Whack-A-Mole/src/index.js:
--------------------------------------------------------------------------------
1 | const holes = document.querySelectorAll(".hole");
2 | const scoreBoard = document.querySelector(".score");
3 | const moles = document.querySelectorAll(".mole");
4 |
5 | let lastHole;
6 | let timeUp = false;
7 | let score = 0;
8 |
9 | function randomTime(min, max) {
10 | return Math.round(Math.random() * (max - min) + min);
11 | }
12 |
13 | function randomHole(holes) {
14 | const idx = Math.floor(Math.random() * holes.length);
15 | const hole = holes[idx];
16 | if (hole === lastHole) {
17 | console.log("Ah nah thats the same one bud");
18 | return randomHole(holes);
19 | }
20 | lastHole = hole;
21 | return hole;
22 | }
23 |
24 | function peep() {
25 | const time = randomTime(200, 1000);
26 | const hole = randomHole(holes);
27 | hole.classList.add("up");
28 | setTimeout(() => {
29 | hole.classList.remove("up");
30 | if (!timeUp) peep();
31 | }, time);
32 | }
33 |
34 | function startGame() {
35 | document.querySelector('.btn').textContent = 'Start Game'
36 | scoreBoard.textContent = 0;
37 | timeUp = false;
38 | score = 0;
39 | peep();
40 | setTimeout(() => {timeUp = true;
41 | document.querySelector('.btn').textContent = 'Game Over, Start again!'
42 | }, 10000);
43 | }
44 |
45 | function bonk(e) {
46 | if (!e.isTrusted) return; // cheater!
47 | score++;
48 | this.parentNode.classList.remove("up");
49 | scoreBoard.textContent = score;
50 | }
51 |
52 | moles.forEach(mole => mole.addEventListener("click", bonk));
53 |
--------------------------------------------------------------------------------
/30-Whack-A-Mole/src/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | font-size: 10px;
4 | background-color: #ffc600;
5 | background-image: url("data:image/svg+xml,%3Csvg width='42' height='44' viewBox='0 0 42 44' xmlns='http://www.w3.org/2000/svg'%3E%3Cg id='Page-1' fill='none' fill-rule='evenodd'%3E%3Cg id='brick-wall' fill='%23282828' fill-opacity='0.06'%3E%3Cpath d='M0 0h42v44H0V0zm1 1h40v20H1V1zM0 23h20v20H0V23zm22 0h20v20H22V23z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
6 | }
7 |
8 | *,
9 | *:before,
10 | *:after {
11 | box-sizing: inherit;
12 | }
13 |
14 | body {
15 | padding: 0;
16 | margin: 0;
17 | font-family: 'Amatic SC', cursive;
18 | }
19 |
20 | h1 {
21 | text-align: center;
22 | font-size: 10rem;
23 | line-height: 1;
24 | margin-bottom: 20px;
25 | margin-top: 20px;
26 | }
27 |
28 | h3 {
29 | text-align: center;
30 | font-size: 4rem;
31 | line-height: 1;
32 | }
33 |
34 | .btn-container {
35 | display: flex;
36 | justify-content: center;
37 | }
38 |
39 | .btn {
40 | top: 0;
41 | left: 0;
42 | transition: all 0.15s linear 0s;
43 | position: relative;
44 | display: inline-block;
45 | min-width: 15vw;
46 | height: 6vh;
47 | padding: 15px 25px;
48 | background-color: #754c03;
49 | text-transform: uppercase;
50 | color: #fff;
51 | font-family: sans-serif;
52 | font-size: large;
53 | font-weight: 600;
54 | letter-spacing: 1px;
55 | box-shadow: -6px 6px 0 #c79c00;
56 | text-decoration: none;
57 | text-align: center;
58 | }
59 | .btn:hover {
60 | top: 3px;
61 | left: -3px;
62 | box-shadow: -3px 3px 0 #404040;
63 | }
64 | .btn:hover::after {
65 | top: 1px;
66 | left: -2px;
67 | width: 4px;
68 | height: 4px;
69 | }
70 | .btn:hover::before {
71 | bottom: -2px;
72 | right: 1px;
73 | width: 4px;
74 | height: 4px;
75 | }
76 | .btn::after {
77 | transition: all 0.15s linear 0s;
78 | content: '';
79 | position: absolute;
80 | top: 2px;
81 | left: -4px;
82 | width: 8px;
83 | height: 8px;
84 | background-color: #404040;
85 | transform: rotate(45deg);
86 | z-index: -1;
87 | }
88 | .btn::before {
89 | transition: all 0.15s linear 0s;
90 | content: '';
91 | position: absolute;
92 | bottom: -4px;
93 | right: 2px;
94 | width: 8px;
95 | height: 8px;
96 | background-color: #404040;
97 | transform: rotate(45deg);
98 | z-index: -1;
99 | }
100 |
101 | a.btn {
102 | position: relative;
103 | }
104 |
105 | a:active.btn {
106 | top: 6px;
107 | left: -6px;
108 | box-shadow: none;
109 | }
110 | a:active.btn:before {
111 | bottom: 1px;
112 | right: 1px;
113 | }
114 | a:active.btn:after {
115 | top: 1px;
116 | left: 1px;
117 | }
118 |
119 | .score {
120 | background: rgba(255, 255, 255, 0.2);
121 | padding: 0 3rem;
122 | line-height: 1;
123 | border-radius: 1rem;
124 | font-weight: bold;
125 | font-size: 5rem;
126 | }
127 |
128 | .game {
129 | width: 600px;
130 | height: 400px;
131 | display: flex;
132 | flex-wrap: wrap;
133 | margin: 0 auto;
134 | }
135 |
136 | .hole {
137 | flex: 1 0 33.33%;
138 | overflow: hidden;
139 | position: relative;
140 | }
141 |
142 | .hole:after {
143 | display: block;
144 | background: url('../../assets/dirt.svg') bottom center no-repeat;
145 | background-size: contain;
146 | content: '';
147 | width: 100%;
148 | height: 70px;
149 | position: absolute;
150 | z-index: 2;
151 | bottom: -30px;
152 | }
153 |
154 | .mole {
155 | background: url('../../assets/mole.svg') bottom center no-repeat;
156 | background-size: 60%;
157 | position: absolute;
158 | top: 100%;
159 | width: 100%;
160 | height: 100%;
161 | transition: all 0.4s;
162 | cursor: grabbing;
163 | }
164 |
165 | .hole.up .mole {
166 | top: 0;
167 | }
168 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Ayush Gupta
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript 30 Challenge by WesBos
2 |
3 | Participating in and completing 30 day [Vanilla JS challenge (#JavaScript30)](https://javascript30.com/) by [WesBos](https://wesbos.com/).
4 |
5 | ## Todo Challenges
6 |
7 | - [x] 🥁 [JS Drum Kit](https://javascript30.ayushgupta.tech/01-JS-Drum-Kit/index.html)
8 | - [x] 🕒 [JS and CSS Clock](https://javascript30.ayushgupta.tech/02-JS-CSS-Clock/index.html)
9 | - [x] 🖼 [CSS Variables](https://javascript30.ayushgupta.tech/03-CSS-Variables/index.html)
10 | - [x] 🕺🏻 [Array Cardio Day 1](https://javascript30.ayushgupta.tech/04-Array-Cardio-1/index.html)
11 | - [x] 💪🏻 [Flex Panel Gallery](https://javascript30.ayushgupta.tech/04-Array-Cardio-1/index.html)
12 | - [x] ⌨ [Type Ahead](https://javascript30.ayushgupta.tech/06-Type-Ahead/index.html)
13 | - [x] 💃🏻 [Array Cardio Day 2](https://javascript30.ayushgupta.tech/07-Array-Cardio-2/index.html)
14 | - [x] 🌈 [Fun with HTML5 Canvas](https://javascript30.ayushgupta.tech/08-HTML5-Canvas/index.html)
15 | - [x] 🛠 [Dev Tools Domination](https://javascript30.ayushgupta.tech/09-Dev-Tools/index.html)
16 | - [x] ✔ [Hold Shift and Check Checkboxes](https://javascript30.ayushgupta.tech/10-Multiple-Check-Shift/index.html)
17 | - [x] 📽 [Custom Video Player](https://javascript30.ayushgupta.tech/11-Custom-Video-Player/index.html)
18 | - [x] 🎊 [Key Sequence Detection](https://javascript30.ayushgupta.tech/12-Key-Sequence-Detection/index.html)
19 | - [x] 🤜🏻 [Slide in on Scroll](https://javascript30.ayushgupta.tech/13-Slide-In-On-Scroll/index.html)
20 | - [x] 📋 [JavaScript References vs Copying](https://javascript30.ayushgupta.tech/14-JS-Reference-Vs-Copy/index.html)
21 | - [x] 🏪 [LocalStorage](https://javascript30.ayushgupta.tech/15-Localstorage/index.html)
22 | - [x] 🐁 [Mouse Move Shadow](https://javascript30.ayushgupta.tech/16-Mousemove-Shadow/index.html)
23 | - [x] 🗃 [Sort Without Articles](https://javascript30.ayushgupta.tech/17-Sort-Without-Articles/index.html)
24 | - [x] ➕ [Adding Up Times with Reduce](https://javascript30.ayushgupta.tech/18-Add-Time-With-Reduce/index.html)
25 | - [x] 📷 [Webcam Fun](https://javascript30.ayushgupta.tech/19-Webcam-Fun/index.html)
26 | - [x] 🗣 [Speech Detection](https://javascript30.ayushgupta.tech/20-Speech-Recognition/index.html)
27 | - [x] 📌 [Geolocation](https://javascript30.ayushgupta.tech/21-Geolocation/index.html)
28 | - [x] 🔗 [Follow Along Link Highlighter](https://javascript30.ayushgupta.tech/22-Follow-Along-Link/index.html)
29 | - [x] 💬 [Speech Synthesis](https://javascript30.ayushgupta.tech/23-Speech-Synthesis/index.html)
30 | - [x] 🍡 [Sticky Nav](https://javascript30.ayushgupta.tech/24-Sticky-Nav/index.html)
31 | - [x] 💭 [Event Capture, Propogation, Bubbling and Once](https://javascript30.ayushgupta.tech/25-EventCapture-Propogation-Bubbling/index.html)
32 | - [x] 🏃🏻♂️ [Stripe Follow Along Nav](https://javascript30.ayushgupta.tech/26-Stripe-Nav/index.html)
33 | - [x] 🎚 [Click and Drag](https://javascript30.ayushgupta.tech/27-Click-Drag-Scroll/index.html)
34 | - [x] 📹 [Video Speed Controller](https://javascript30.ayushgupta.tech/28-Video-Speed-Controller/index.html)
35 | - [x] ⏱ [Countdown Timer](https://javascript30.ayushgupta.tech/29-Countdown-Timer/index.html)
36 | - [x] 🎮 [Whack A Mole](https://javascript30.ayushgupta.tech/30-Whack-A-Mole/index.html)
37 |
38 | ## Add-Ons
39 |
40 | I have mentioned below the add-ons I added in some of the JavaScript30 projects for fun.
41 |
42 | - ✨ * - All projects
43 |
44 | Updated design of all projects because designing is therapeutic.
45 |
46 | - 🥁 #1 - JS Drum Kit
47 |
48 | Added touch & click event handling on keys
49 |
50 | - 🕒 #2 - JS and CSS Clock
51 |
52 | Changed size of clock hands & added a pivot in center
53 |
54 | - 🖼 #3 - CSS Variables
55 |
56 | Added border-radius controller
57 |
58 | - 📽 #11 - Custom Video Player
59 |
60 | Added FullScreen button
61 |
62 | - 🎊 #12 - Key Sequence Detection
63 |
64 | Added confetti options
65 |
66 | - 🏪 #15 - LocalStorage
67 |
68 | Added Check All, Uncheck All, Delete All buttons.
69 |
70 | - 📷 #19 - Webcam fun
71 |
72 | Added mirror image for video.
73 |
74 | - 🎮 #30 - Whack A Mole
75 |
76 | Notify user about game over.
--------------------------------------------------------------------------------
/assets/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/android-chrome-192x192.png
--------------------------------------------------------------------------------
/assets/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/android-chrome-512x512.png
--------------------------------------------------------------------------------
/assets/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/apple-touch-icon.png
--------------------------------------------------------------------------------
/assets/asteroids.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/asteroids.jpg
--------------------------------------------------------------------------------
/assets/celebration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/celebration.png
--------------------------------------------------------------------------------
/assets/fancy-pants.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/fancy-pants.jpg
--------------------------------------------------------------------------------
/assets/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/favicon-16x16.png
--------------------------------------------------------------------------------
/assets/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/favicon-32x32.png
--------------------------------------------------------------------------------
/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/favicon.ico
--------------------------------------------------------------------------------
/assets/green-goblin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/green-goblin.png
--------------------------------------------------------------------------------
/assets/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "JavaScript30 - Ayush Gupta",
3 | "short_name": "JavaScript30",
4 | "description": "30 day vanilla JS coding challenge by WesBos",
5 | "icons": [
6 | {
7 | "src": "android-chrome-192x192.png",
8 | "sizes": "192x192",
9 | "type": "image/png"
10 | },
11 | {
12 | "src": "android-chrome-512x512.png",
13 | "sizes": "512x512",
14 | "type": "image/png"
15 | }
16 | ],
17 | "start_url": "/?source=pwa",
18 | "theme_color": "#000000de",
19 | "background_color": "#000000de",
20 | "display": "standalone"
21 | }
22 |
--------------------------------------------------------------------------------
/assets/ocean.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/ocean.jpg
--------------------------------------------------------------------------------
/assets/og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/og.png
--------------------------------------------------------------------------------
/assets/plaid.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/plaid.jpg
--------------------------------------------------------------------------------
/assets/shattered-island.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/shattered-island.gif
--------------------------------------------------------------------------------
/assets/special-delivery.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/special-delivery.jpg
--------------------------------------------------------------------------------
/assets/wild-sea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gupta-ji6/JavaScript30/8e6c6c46dd24b61fccf350828cb5e7fcdbd4bdaf/assets/wild-sea.png
--------------------------------------------------------------------------------
/common.css:
--------------------------------------------------------------------------------
1 | .project-tag {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | background-color: yellow;
6 | border: 1px solid transparent;
7 | /* border-radius: 0px 3px 3px 0px; */
8 | border-bottom-right-radius: 3px;
9 | color: black;
10 | font-weight: bolder;
11 | font-family: monospace;
12 | font-size: medium;
13 | height: 5vh;
14 | display: flex;
15 | flex-direction: column;
16 | justify-content: center;
17 | align-items: center;
18 | padding: 5px 15px;
19 | transition-timing-function: linear;
20 | box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
21 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "JavaScript30",
3 | "version": "1.0.0",
4 | "description": "Repo for managing JavaScript30 challenge by @wesbos",
5 | "main": "README.md",
6 | "scripts": {
7 | "start": "parcel index.html --open",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {
12 | "@babel/core": "7.2.0",
13 | "parcel-bundler": "^1.6.1"
14 | },
15 | "keywords": []
16 | }
17 |
--------------------------------------------------------------------------------
/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 | https://javascript30.ayushgupta.tech/
12 | 2020-08-26T13:44:36+00:00
13 | 1.00
14 |
15 |
16 | https://javascript30.ayushgupta.tech/01-js-drum-kit/
17 | 2020-08-26T13:44:36+00:00
18 | 0.80
19 |
20 |
21 | https://javascript30.ayushgupta.tech/02-js-css-clock/
22 | 2020-08-26T13:44:36+00:00
23 | 0.80
24 |
25 |
26 | https://javascript30.ayushgupta.tech/03-css-variables/
27 | 2020-08-26T13:44:36+00:00
28 | 0.80
29 |
30 |
31 | https://javascript30.ayushgupta.tech/04-array-cardio-1/
32 | 2020-08-26T13:44:36+00:00
33 | 0.80
34 |
35 |
36 | https://javascript30.ayushgupta.tech/05-flex-gallery/
37 | 2020-08-26T13:44:36+00:00
38 | 0.80
39 |
40 |
41 | https://javascript30.ayushgupta.tech/06-type-ahead/
42 | 2020-08-26T13:44:36+00:00
43 | 0.80
44 |
45 |
46 | https://javascript30.ayushgupta.tech/07-array-cardio-2/
47 | 2020-08-26T13:44:36+00:00
48 | 0.80
49 |
50 |
51 | https://javascript30.ayushgupta.tech/08-html5-canvas/
52 | 2020-08-26T13:44:36+00:00
53 | 0.80
54 |
55 |
56 | https://javascript30.ayushgupta.tech/09-dev-tools/
57 | 2020-08-26T13:44:36+00:00
58 | 0.80
59 |
60 |
61 | https://javascript30.ayushgupta.tech/10-multiple-check-shift/
62 | 2020-08-26T13:44:36+00:00
63 | 0.80
64 |
65 |
66 | https://javascript30.ayushgupta.tech/11-custom-video-player/
67 | 2020-08-26T13:44:36+00:00
68 | 0.80
69 |
70 |
71 | https://javascript30.ayushgupta.tech/12-key-sequence-detection/
72 | 2020-08-26T13:44:36+00:00
73 | 0.80
74 |
75 |
76 | https://javascript30.ayushgupta.tech/13-slide-in-on-scroll/
77 | 2020-08-26T13:44:36+00:00
78 | 0.80
79 |
80 |
81 | https://javascript30.ayushgupta.tech/14-js-reference-vs-copy/
82 | 2020-08-26T13:44:36+00:00
83 | 0.80
84 |
85 |
86 | https://javascript30.ayushgupta.tech/15-localstorage/
87 | 2020-08-26T13:44:36+00:00
88 | 0.80
89 |
90 |
91 | https://javascript30.ayushgupta.tech/16-mousemove-shadow/
92 | 2020-08-26T13:44:36+00:00
93 | 0.80
94 |
95 |
96 | https://javascript30.ayushgupta.tech/17-sort-without-articles/
97 | 2020-08-26T13:44:36+00:00
98 | 0.80
99 |
100 |
101 | https://javascript30.ayushgupta.tech/18-add-time-with-reduce/
102 | 2020-08-26T13:44:36+00:00
103 | 0.80
104 |
105 |
106 | https://javascript30.ayushgupta.tech/19-webcam-fun/
107 | 2020-08-26T13:44:36+00:00
108 | 0.80
109 |
110 |
111 | https://javascript30.ayushgupta.tech/20-speech-recognition/
112 | 2020-08-26T13:44:36+00:00
113 | 0.80
114 |
115 |
116 | https://javascript30.ayushgupta.tech/21-geolocation/
117 | 2020-08-26T13:44:36+00:00
118 | 0.80
119 |
120 |
121 | https://javascript30.ayushgupta.tech/22-follow-along-link/
122 | 2020-08-26T13:44:36+00:00
123 | 0.80
124 |
125 |
126 | https://javascript30.ayushgupta.tech/23-speech-synthesis/
127 | 2020-08-26T13:44:36+00:00
128 | 0.80
129 |
130 |
131 | https://javascript30.ayushgupta.tech/24-sticky-nav/
132 | 2020-08-26T13:44:36+00:00
133 | 0.80
134 |
135 |
136 | https://javascript30.ayushgupta.tech/25-eventcapture-propogation-bubbling/
137 | 2020-08-26T13:44:36+00:00
138 | 0.80
139 |
140 |
141 | https://javascript30.ayushgupta.tech/26-stripe-nav/
142 | 2020-08-26T13:44:36+00:00
143 | 0.80
144 |
145 |
146 | https://javascript30.ayushgupta.tech/27-click-drag-scroll/
147 | 2020-08-26T13:44:36+00:00
148 | 0.80
149 |
150 |
151 | https://javascript30.ayushgupta.tech/28-video-speed-controller/
152 | 2020-08-26T13:44:36+00:00
153 | 0.80
154 |
155 |
156 | https://javascript30.ayushgupta.tech/29-countdown-timer/
157 | 2020-08-26T13:44:36+00:00
158 | 0.80
159 |
160 |
161 | https://javascript30.ayushgupta.tech/30-whack-a-mole/
162 | 2020-08-26T13:44:36+00:00
163 | 0.80
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --bg-color: #ebecf0;
3 | --text-color: #000000de;
4 | }
5 |
6 | body {
7 | background: var(--bg-color);
8 | margin: 30px 0px 0px 0px;
9 | display: flex;
10 | align-items: center;
11 | flex-direction: column;
12 | width: 100vw;
13 | }
14 |
15 | .title {
16 | font-family: "Molle", cursive;
17 | font-size: 50px;
18 | margin-bottom: 0;
19 | letter-spacing: 1.2px;
20 | color: var(--text-color);
21 | }
22 |
23 | .subtitle {
24 | font-family: monospace;
25 | color: var(--text-color);
26 | text-align: center;
27 | }
28 |
29 | .github-buttons {
30 | display: flex;
31 | justify-content: space-evenly;
32 | margin-bottom: 50px;
33 | flex-wrap: wrap;
34 | min-width: 30vh;
35 | flex-grow: 2;
36 | }
37 |
38 | .btn {
39 | width: 20vw !important;
40 | }
41 |
42 | .grid-container {
43 | display: grid;
44 | align-items: center;
45 | grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
46 | grid-gap: 50px;
47 | width: 80vw;
48 | visibility: hidden;
49 | }
50 |
51 | .grid-container > * {
52 | visibility: visible;
53 | transition: opacity 150ms linear 100ms, transform 150ms ease-in-out 100ms;
54 | }
55 |
56 | .grid-container:hover > * {
57 | opacity: 0.5;
58 | transform: scale(0.9);
59 | }
60 |
61 | .grid-container > *:hover {
62 | opacity: 1;
63 | transform: scale(1.02);
64 | transition-delay: 0ms, 0ms;
65 | }
66 |
67 | .items {
68 | min-height: 25vh;
69 | box-shadow: -5px -5px 20px 0 #ffffff, 5px 5px 20px 0 #aeaec0;
70 | border: 1px solid transparent;
71 | border-radius: 5px;
72 | transition: all 0.2s ease-in-out;
73 | background: #e3e6ecde;
74 | cursor: pointer;
75 | display: flex;
76 | flex-direction: column;
77 | align-items: center;
78 | justify-content: center;
79 | font-size: 20px;
80 | font-family: monospace;
81 | text-align: center;
82 | padding: 5px;
83 | }
84 |
85 | .items:hover {
86 | box-shadow: inset -2px -2px 5px #ffffff, inset 2px 2px 5px #d1d9e6;
87 | /* border-top: 2px solid #00000031; */
88 | /* border-left: 2px solid #00000031; */
89 | transition: all 0.2s ease-in-out;
90 | font-size: 22px;
91 | font-weight: bolder;
92 | }
93 |
94 | a {
95 | text-decoration: none;
96 | color: black;
97 | }
98 |
99 | .footer {
100 | height: 12vh;
101 | width: 100vw;
102 | margin-top: 5vh;
103 | display: flex;
104 | justify-content: center;
105 | align-items: center;
106 | box-shadow: inset -3px -3px 7px #000000, inset 3px 3px 7px var(--bg-color);
107 | background-color: rgb(34, 34, 34);
108 | color: var(--bg-color);
109 | font-family: monospace;
110 | font-size: 16px;
111 | }
112 |
113 | .footer > a {
114 | color: var(--bg-color);
115 | font-weight: bolder;
116 | }
117 |
--------------------------------------------------------------------------------