├── Autocomplete_using_tries
├── index.css
├── index.html
├── index.js
└── trie.js
├── OpaqueCalendar
├── calendar.js
├── index.css
├── index.html
└── index.js
├── README.md
└── WindowSwitcher_using_linkedlist
├── LinkedList.js
├── index.css
├── index.html
└── index.js
/Autocomplete_using_tries/index.css:
--------------------------------------------------------------------------------
1 | .top{
2 | margin-top: 50px;
3 | }
4 |
5 | .clickable{
6 | cursor: pointer;
7 | }
--------------------------------------------------------------------------------
/Autocomplete_using_tries/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 | Autocomplete Application
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Autocomplete_using_tries/index.js:
--------------------------------------------------------------------------------
1 | const items = [
2 | "apple",
3 | "apricot",
4 | "banana",
5 | "pear",
6 | "guava",
7 | "cherry",
8 | "orange",
9 | "pineapple",
10 | "mango",
11 | "grapes",
12 | "blueberry",
13 | "raspberry",
14 | "melon",
15 | "blackberry",
16 | "plum",
17 | "kiwi",
18 | "peach",
19 | "strawberry",
20 | "avocado"
21 | ];
22 |
23 | const root = new makeNode('\0');
24 | for (const item of items)
25 | add(item, 0, root);
26 |
27 | const text_box = document.getElementById("text-box");
28 | const list = document.getElementById("list");
29 |
30 | function handler(e) {
31 | const str = e.target.value;
32 | const predictions = search(str, 0, root);
33 |
34 | console.log(predictions);
35 |
36 | list.innerHTML = "";
37 | for (const prediction of predictions)
38 | list.innerHTML += `${str}${prediction.substring(str.length)}`;
39 |
40 | }
41 |
42 | function handleClick(e) {
43 | text_box.value = e.innerText;
44 | }
45 |
46 | handler({ target: { value: "" } });
47 |
48 |
49 | text_box.addEventListener("keyup", handler);
--------------------------------------------------------------------------------
/Autocomplete_using_tries/trie.js:
--------------------------------------------------------------------------------
1 | function makeNode(ch) {
2 | this.ch = ch;
3 | this.isTerminal = false;
4 | this.map = {};
5 | this.words = [];
6 | }
7 |
8 | function add(str, i, root) {
9 |
10 | if (i === str.length) {
11 | root.isTerminal = true;
12 | return;
13 | }
14 |
15 | if (!root.map[str[i]])
16 | root.map[str[i]] = new makeNode(str[i]);
17 |
18 | root.words.push(str);
19 | add(str, i + 1, root.map[str[i]]);
20 | }
21 |
22 | function search(str, i, root) {
23 | if (i === str.length)
24 | return root.words;
25 |
26 | if (!root.map[str[i]])
27 | return [];
28 | return search(str, i + 1, root.map[str[i]]);
29 |
30 | }
--------------------------------------------------------------------------------
/OpaqueCalendar/calendar.js:
--------------------------------------------------------------------------------
1 | function getBusySlots(appointments) {
2 | if (appointments.length === 0) return appointments;
3 |
4 | const mergedApps = [];
5 |
6 | let curr = appointments[0];
7 |
8 | for (let i = 1; i < appointments.length; i++) {
9 | if (doesIntersect(curr, appointments[i])) {
10 | curr[1] = Math.max(curr[1], appointments[i][1]);
11 | } else {
12 | mergedApps.push(curr);
13 | curr = appointments[i];
14 | }
15 | }
16 |
17 | mergedApps.push(curr);
18 |
19 | return mergedApps;
20 | }
21 |
22 | function doesIntersect(ap1, ap2) {
23 | return ap1[1] >= ap2[0];
24 | }
25 |
26 | function getFullCalendar(busySlots) {
27 | if (busySlots.length === 0) return [0, 24, 0];
28 |
29 | const cal = [];
30 | if (busySlots[0][0] > 0) cal.push([0, busySlots[0][0], 0]);
31 |
32 | for (let i = 0; i < busySlots.length - 1; i++) {
33 | const slot = busySlots[i];
34 | cal.push([...slot, 1]);
35 | cal.push([slot[1], busySlots[i + 1][0], 0]);
36 | }
37 |
38 | cal.push([...busySlots[busySlots.length - 1], 1]);
39 |
40 | if (busySlots[busySlots.length - 1][1] < 24)
41 | cal.push([busySlots[busySlots.length - 1][1], 24, 0]);
42 |
43 | return cal;
44 | }
45 |
--------------------------------------------------------------------------------
/OpaqueCalendar/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | text-align: center;
3 | margin: 0px;
4 | font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Grande",
5 | "Lucida Sans", Arial, sans-serif;
6 | }
7 |
8 | h1 {
9 | padding-bottom: 50px;
10 | }
11 |
12 | #list {
13 | list-style-type: none;
14 | width: 50%;
15 | text-align: center;
16 | margin-left: 25%;
17 | padding: 0px;
18 | }
19 |
20 | #list > li {
21 | text-align: center;
22 | border: 1px solid white;
23 | margin: 0px auto 0px;
24 | border-radius: 5px;
25 | }
26 |
--------------------------------------------------------------------------------
/OpaqueCalendar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | My Calendar
8 |
9 |
10 | Varun's Calendar
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/OpaqueCalendar/index.js:
--------------------------------------------------------------------------------
1 | const appointments = [
2 | [7, 9],
3 | [9, 10],
4 | [12, 16],
5 | [13, 14],
6 | [14.5, 15.5],
7 | [21, 22],
8 | ];
9 |
10 | const list = document.getElementById("list");
11 |
12 | list.innerHTML += `12 am`;
13 |
14 | for (let slot of getFullCalendar(getBusySlots(appointments))) {
15 | list.innerHTML += `
18 | `;
19 |
20 | list.innerHTML += `${slot[1] % 12 === 0 ? 12 : slot[1] % 12} ${
21 | slot[1] >= 12 && slot[1] < 24 ? "pm" : "am"
22 | }`;
23 | }
24 |
25 | const fullCal = getBusySlots(appointments);
26 | console.log(fullCal);
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Javascript-Applications
2 | This is the repository for the youtube series you can find [here](Link_here).
3 |
4 | ## Installation
5 | You can run these applications by simply cloning this repository or downloading it via github and then starting a http server in the root directory and clicking on the application you wanna run. I use the [`http-server`](https://www.npmjs.com/package/http-server) utility to do this.
6 |
7 | 
8 |
9 | ## Contributing
10 | You are more than welcome to hack any of the applications here and add features or improve the UI. If you have any ideas about which application I should do next, please feel free to open an issue and we can discuss more. Happy coding! :D
11 |
--------------------------------------------------------------------------------
/WindowSwitcher_using_linkedlist/LinkedList.js:
--------------------------------------------------------------------------------
1 | function Linkedlist() {
2 | function Node(content) {
3 | this.content = content;
4 | this.next = this;
5 | this.prev = this;
6 | }
7 |
8 | this.head = null;
9 | this.tail = null;
10 |
11 | this.add = function(content) {
12 | if (!this.head) {
13 | this.head = this.tail = new Node(content);
14 | }
15 | else {
16 | this.tail.next = new Node(content);
17 | this.tail.next.prev = this.tail;
18 | this.tail = this.tail.next;
19 | this.tail.next = this.head;
20 | this.head.prev = this.tail;
21 | }
22 | }
23 |
24 | this.move_to_front = function(node) {
25 | if (node === this.head) {
26 | return;
27 | }
28 |
29 | let temp = this.head;
30 | let isTailNode = false;
31 |
32 | while (temp.next !== node)
33 | temp = temp.next;
34 |
35 | if (temp.next === this.tail)
36 | isTailNode = true;
37 |
38 | if(!isTailNode){
39 | temp.next = node.next;
40 | node.next.prev = temp;
41 | }
42 | else{
43 | this.tail = this.tail.prev;
44 | }
45 |
46 | node.next = this.head;
47 | this.head.prev = node;
48 | this.head = node;
49 | this.tail.next = this.head;
50 | this.head.prev = this.tail;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/WindowSwitcher_using_linkedlist/index.css:
--------------------------------------------------------------------------------
1 | body{
2 | text-align: center;
3 | }
4 |
5 | #box{
6 | text-align: center;
7 | }
8 |
9 | .sel{
10 | color: red;
11 | background-color: rgb(202, 199, 199) !important;
12 | }
13 |
14 | #tab-switcher{
15 | margin-top: 40px;
16 | }
17 |
18 | li > img{
19 | height: 3rem;
20 | text-align: center;
21 | }
--------------------------------------------------------------------------------
/WindowSwitcher_using_linkedlist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 | Window Switcher
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
21 |
Card title
22 |
23 |
24 |
25 |
26 |
27 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/WindowSwitcher_using_linkedlist/index.js:
--------------------------------------------------------------------------------
1 | const box = document.getElementById("box");
2 | const title = document.getElementById("title");
3 | const image = document.getElementById("image");
4 | const tab_switcher = document.getElementById("tab-switcher");
5 |
6 | const list = new Linkedlist();
7 |
8 | const data = [
9 | { title: "Chrome", value: "This is a window that contains chrome", url: "https://cdn.vox-cdn.com/thumbor/eG32HnbPci_k88_8A_HXS3-pnB8=/1400x1050/filters:format(jpeg)/cdn.vox-cdn.com/uploads/chorus_asset/file/6676117/chromelogo.0.jpg" },
10 | { title: "VS code", value: "This is a window that contains VS Code", url: "https://user-images.githubusercontent.com/49339/32078127-102bbcfe-baa6-11e7-8ab9-b04dcad2035e.png" },
11 | { title: "Sublime", value: "This is a window that contains Sublime text 2", url: "https://cdn.dribbble.com/users/533705/screenshots/3811091/sublime-icon.png" },
12 | { title: "Final Cut", value: "This is a window that contains Final Cur Pro X", url: "https://i.pcmag.com/imagery/reviews/00FaQZAwQoZwxbFpiehSYlN-21.fit_scale.size_1028x578.v_1569473012.png" },
13 | { title: "Photos", value: "This is a window that contains Photos", url: "https://i.pcmag.com/imagery/reviews/01JBzqHYl37ch2AaT3qOR9H-10.fit_scale.size_1028x578.v_1569475171.png" },
14 | { title: "Calendar", value: "This is a window that contains Calendar", url: "https://cdn4.iconfinder.com/data/icons/small-n-flat/24/calendar-512.png" },
15 | { title: "Maps", value: "This is a window that contains Maps", url: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/AppleMaps_logo.svg/1200px-AppleMaps_logo.svg.png" }
16 | ];
17 |
18 |
19 | for (let i in data)
20 | list.add({ id: i });
21 |
22 |
23 | tab_switcher.hidden = true;
24 | let tabbable = false;
25 |
26 | let point, children, offset;
27 |
28 | setState();
29 |
30 | document.addEventListener('keydown', function(e) {
31 | console.log(e);
32 | if (e.key === "Control") {
33 | tabbable = true;
34 | point = list.head;
35 | }
36 | if ((e.key === "f" || e.key === "b") && tabbable) {
37 | tab_switcher.hidden = false;
38 | let key = e.key; // store current pressed key.
39 | let dataSize = data.length; // store total size of data array
40 |
41 | children[offset].classList.remove("sel");
42 |
43 | point = key === "f" ? point.next : point.prev;
44 | offset = key === "f" ? ((offset + 1) % dataSize) : offset ? ((offset - 1) % dataSize) : (dataSize - 1);
45 | children[offset].classList.add("sel");
46 | }
47 | });
48 |
49 |
50 | document.addEventListener("keyup", function(e) {
51 | if (e.key === "Control") {
52 | tabbable = false;
53 | list.move_to_front(point);
54 | tab_switcher.hidden = true;
55 | setState();
56 | }
57 | });
58 |
59 |
60 | function setState() {
61 | image.src = data[list.head.content.id].url;
62 | title.innerHTML = data[list.head.content.id].title;
63 | box.innerHTML = data[list.head.content.id].value;
64 |
65 | tab_switcher.innerHTML = "";
66 |
67 | let temp = list.head;
68 |
69 | do{
70 | tab_switcher.innerHTML += `
${data[temp.content.id].title}
`;
71 | temp = temp.next;
72 | }while(temp !== list.head);
73 |
74 | children = tab_switcher.childNodes;
75 | children[0].classList.add("sel");
76 | offset = 0;
77 |
78 | }
--------------------------------------------------------------------------------