├── 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 |
15 |
16 |

Autocomplete Application

17 |
18 |
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 | ![](https://i.imgur.com/p0UCFp8.png) 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 |
    28 | 31 |
    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 | } --------------------------------------------------------------------------------