├── .firebaserc ├── .gitignore ├── .vscode └── settings.json ├── 404.html ├── app ├── app.js └── sorting-algorithms.js ├── assets ├── github-logo.svg ├── linkedin.svg ├── style.css └── style.scss ├── firebase.json ├── index.html ├── package.json ├── preview.png └── readme.md /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "sorting-visualizer-js" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | public 3 | package-lock.json 4 | .firebase -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.background": "#273023", 4 | "titleBar.activeBackground": "#374332", 5 | "titleBar.activeForeground": "#F8FAF8" 6 | } 7 | } -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page Not Found 7 | 8 | 23 | 24 | 25 |
26 |

404

27 |

Page Not Found

28 |

The specified file was not found on this website. Please check the URL for mistakes and try again.

29 |

Why am I seeing this?

30 |

This page was generated by the Firebase Command-Line Interface. To modify it, edit the 404.html file in your project's configured public directory.

31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | import * as sorting from './sorting-algorithms.js'; 2 | 3 | console.log(sorting); 4 | 5 | function getElements(elements) { 6 | let obj = {}; 7 | elements.forEach(element => { 8 | obj[element] = document.getElementById(element) 9 | }); 10 | 11 | return obj; 12 | } 13 | 14 | 15 | var barsData = []; 16 | var barsDataCopy = []; 17 | 18 | const { barsElement, sliderElement, toggleAnimationBtn, stopAnimationBtn, generateArrayBtn, arraySizeSliderElement, animationSpeedSliderElement, sortingAlgorithms } = getElements(['barsElement', 'sliderElement', 'toggleAnimationBtn', 'stopAnimationBtn', 'generateArrayBtn', 'arraySizeSliderElement', 'animationSpeedSliderElement', 'sortingAlgorithms']); 19 | 20 | var ANIMATION_SPEED = 1; 21 | var ARRAY_SIZE = 150; 22 | // var WIDTH = window.visualViewport.width; 23 | 24 | let interval; 25 | 26 | sliderElement.addEventListener('input', (e) => { 27 | // console.log(e.target.value); 28 | renderFrame(e.target.value) 29 | }) 30 | 31 | arraySizeSliderElement.addEventListener('input', (e) => { 32 | ARRAY_SIZE = e.target.value; 33 | genArray(); 34 | }) 35 | 36 | animationSpeedSliderElement.addEventListener('input', (e) => { 37 | ANIMATION_SPEED = e.target.value; 38 | if (isPlaying !== null) { 39 | pauseAnimation(); 40 | runAnimation(); 41 | } 42 | }) 43 | 44 | // /** 45 | // * Draw bards 46 | // * @param {*} data 47 | // * @param {*} compare 48 | // */ 49 | // function renderBars(data, compare = []) { 50 | 51 | // barsElement.innerHTML = data.map((item, i) => ` 52 | //
${item}
53 | // `).join(""); 54 | // } 55 | 56 | /** 57 | * Set slider position 58 | */ 59 | function setSlider(position) { 60 | 61 | if (position >= animationFrames.length) { 62 | togglePlay(); 63 | return; 64 | } 65 | 66 | sliderElement.value = position; 67 | renderFrame(position) 68 | } 69 | /** 70 | * Generate random data 71 | */ 72 | function genArray() { 73 | animationFrames = []; 74 | barsData = []; 75 | let min = 1; 76 | let max = window.innerHeight - 250; 77 | 78 | for (let i = 0; i < ARRAY_SIZE; i++) { 79 | barsData.push((Math.random() * (max - min) + min)); 80 | } 81 | barsDataCopy = barsData.slice(); 82 | sort(); 83 | // renderFrame({ arr: barsData }); 84 | setSlider(0); 85 | } 86 | 87 | /** 88 | * Sort the array and generate animated frames based on selected sorting algorithm 89 | */ 90 | function sort() { 91 | // console.log(barsData); 92 | barsData = barsDataCopy.slice(0); 93 | 94 | let result = sorting[sortingAlgorithms.value](barsData); 95 | animationFrames = result.animationFrames; 96 | renderBars = result.renderBars; 97 | sliderElement.setAttribute('max', animationFrames.length - 1); 98 | setSlider(sliderElement.value); 99 | } 100 | 101 | 102 | /** 103 | * Render bars 104 | * @param {*} param 105 | */ 106 | function renderFrame(index) { 107 | barsElement.innerHTML = renderBars(index); 108 | // barsElement.innerHTML = frame.arr.map((bar, index) => renderBars(bar, index, frame)).join(""); 109 | } 110 | 111 | /** 112 | * Play Animation 113 | */ 114 | function runAnimation() { 115 | // animationFrames.forEach((frame, i) => { 116 | // setTimeout(() => { 117 | // // renderFrame(frame); 118 | // setSlider(i) 119 | // }, ANIMATION_SPEED * (i + 1)) 120 | // }) 121 | 122 | isPlaying = true; 123 | toggleAnimationBtn.children[0].className = 'mdi mdi-pause'; 124 | 125 | let i = sliderElement.value; 126 | interval = setInterval(() => { 127 | // renderFrame(animationFrames[i]) 128 | setSlider(i++); 129 | 130 | }, ANIMATION_SPEED) 131 | } 132 | 133 | function stopAnimation() { 134 | pauseAnimation(); 135 | setSlider(0) 136 | } 137 | 138 | /** 139 | * Pauses the animation 140 | */ 141 | function pauseAnimation() { 142 | clearInterval(interval); 143 | 144 | isPlaying = false; 145 | toggleAnimationBtn.children[0].className = 'mdi mdi-play'; 146 | } 147 | 148 | 149 | var animationFrames = []; 150 | var renderBars; 151 | 152 | 153 | var isPlaying = null; 154 | function togglePlay() { 155 | if (isPlaying) { 156 | pauseAnimation(); 157 | } else { 158 | runAnimation(); 159 | } 160 | } 161 | 162 | genArray(); 163 | 164 | toggleAnimationBtn.onclick = togglePlay; 165 | stopAnimationBtn.onclick = stopAnimation; 166 | generateArrayBtn.onclick = genArray; 167 | 168 | sortingAlgorithms.onchange = () => { 169 | // genArray(); 170 | sort(); 171 | }; -------------------------------------------------------------------------------- /app/sorting-algorithms.js: -------------------------------------------------------------------------------- 1 | 2 | export function mergeSort(barsData) { 3 | var animationFrames = []; 4 | var sorted = []; 5 | function addFrame({ compare = [], orderedIndex, start, mid, end }) { 6 | animationFrames.push({ 7 | arr: barsData.slice(0), 8 | compare, 9 | orderedIndex, 10 | start, 11 | mid, 12 | end, 13 | // sorted: start == 0 && end == barsData.length ? sorted.slice() : [] 14 | }) 15 | } 16 | 17 | function mergeSort(arr, start, end) { 18 | if (start < end) { 19 | 20 | let mid = parseInt((start + end) / 2); 21 | mergeSort(arr, start, mid) 22 | mergeSort(arr, mid + 1, end) 23 | 24 | merge(arr, start, mid, end) 25 | } 26 | } 27 | 28 | function merge(arr, start, mid, end) { 29 | 30 | // console.log(arguments); 31 | 32 | let arr2 = arr.slice(0); 33 | let i = start, j = mid + 1; 34 | let k = start; 35 | // arr.splice(start - 1, 0, 0) 36 | while (i <= mid && j <= end) { 37 | addFrame({ compare: [k, j], start, mid, end }) 38 | if (arr2[i] <= arr2[j]) { 39 | addFrame({ compare: [k, j], orderedIndex: k, start, mid, end }) 40 | arr[k++] = arr2[i++] 41 | // renderBarsSlowly([i, j]) 42 | } 43 | else { 44 | addFrame({ compare: [k, j], orderedIndex: j, start, mid, end }) 45 | // arr[k++] = arr2[j++] 46 | 47 | arr.splice(j, 1) 48 | arr.splice(k++, 0, arr2[j++]) 49 | 50 | // addFrame({ compare: [i, j - 1], orderedIndex: i }) 51 | } 52 | 53 | } 54 | 55 | while (i <= mid) { 56 | addFrame({ compare: [k, j], start, mid, end }) 57 | arr[k++] = arr2[i++] 58 | // renderBarsSlowly([i, j]) 59 | } 60 | 61 | while (j <= end) { 62 | addFrame({ compare: [k, j], start, mid, end }) 63 | // arr[k++] = arr2[j++] 64 | arr.splice(j, 1) 65 | arr.splice(k++, 0, arr2[j++]) 66 | // renderBarsSlowly([i, j]) 67 | } 68 | } 69 | 70 | addFrame({}) 71 | mergeSort(barsData, 0, barsData.length - 1) 72 | addFrame({ start: 0, mid: (barsData.length - 1) / 2, end: barsData.length - 1 }) 73 | 74 | return { 75 | animationFrames, 76 | renderBars: (frameIndex) => { 77 | let frame = animationFrames[frameIndex]; 78 | return frame.arr.map((bar, index) => { 79 | let { arr, compare = [], orderedIndex, start, mid, end } = frame 80 | return ` 81 |
82 | `}).join("") 83 | } 84 | }; 85 | } 86 | 87 | 88 | export function quickSort(barsData) { 89 | var animationFrames = []; 90 | function addFrame({ compare = [], pivot, low, high, swap }) { 91 | // console.log(arguments); 92 | // debugger 93 | // let parentArgs = addFrame.caller.arguments; 94 | animationFrames.push({ 95 | arr: barsData.slice(), 96 | compare, 97 | pivot, 98 | low, 99 | high, 100 | sorted: sorted.slice(), 101 | swap 102 | }) 103 | // return await delay(); 104 | } 105 | 106 | function swap(i, j) { 107 | let temp = barsData[i]; 108 | barsData[i] = barsData[j]; 109 | barsData[j] = temp; 110 | } 111 | function partition(low, high) { 112 | let pivot = barsData[high]; 113 | let i = (low - 1); 114 | 115 | addFrame({ low, high, pivot: high }) 116 | let j; 117 | for (j = low; j < high; j++) { 118 | // addFrame({ low, high, pivot: high, compare: [i, j] }) 119 | 120 | if (barsData[j] <= pivot) { 121 | addFrame({ low, high, pivot: high, compare: [i, j], swap: [j] }) 122 | i++; 123 | addFrame({ low, high, pivot: high, compare: [i, j], swap: [i, j] }) 124 | swap(i, j) 125 | addFrame({ low, high, pivot: high, compare: [i, j] }) 126 | } 127 | else 128 | addFrame({ low, high, pivot: high, compare: [i, j] }) 129 | } 130 | addFrame({ low, high, pivot: high, compare: [i, j], swap: [i + 1, high] }) 131 | swap(i + 1, high) 132 | addFrame({ low, high, pivot: i + 1, compare: [i, j] }) 133 | return (i + 1); 134 | } 135 | 136 | var sorted = []; 137 | function quickSort(low, high) { 138 | if (low < high) { 139 | let pi = partition(low, high); 140 | sorted.push(pi); 141 | quickSort(low, pi - 1); 142 | quickSort(pi + 1, high); 143 | } else { 144 | sorted.push(low, high) 145 | } 146 | } 147 | 148 | addFrame({}) 149 | quickSort(0, barsData.length - 1); 150 | addFrame({}) 151 | 152 | return { 153 | animationFrames, 154 | renderBars: (frameIndex) => { 155 | let frame = animationFrames[frameIndex]; 156 | return frame.arr.map((bar, index) => { 157 | let { compare = [], pivot, low, high, swap = [], sorted } = frame 158 | return ` 159 |
160 | `}).join("") 161 | } 162 | }; 163 | 164 | } 165 | -------------------------------------------------------------------------------- /assets/github-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /assets/linkedin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /assets/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "Jura", sans-serif; } 3 | 4 | body { 5 | background-color: #28293d; 6 | color: #fff; } 7 | 8 | .page-wrapper { 9 | display: flex; 10 | flex-direction: column; 11 | flex-wrap: wrap; 12 | height: calc(100vh - 16px); 13 | margin: 0; 14 | padding: 0 50px; } 15 | 16 | #barsElement { 17 | display: flex; 18 | justify-content: center; 19 | flex-grow: 1; 20 | padding-top: 20px; 21 | width: 100%; } 22 | 23 | .bar { 24 | /* border: 2px solid black; */ 25 | background: #9dbff8; 26 | width: 20px; 27 | margin-right: 1px; 28 | position: relative; 29 | border-radius: 18px; } 30 | 31 | .un-ordered { 32 | background: red; } 33 | 34 | .sorted { 35 | background: #05c270; } 36 | 37 | .ordered { 38 | background: #05c270; } 39 | 40 | input.slider { 41 | width: 100%; } 42 | 43 | .start:before { 44 | content: "\F061F"; 45 | position: absolute; 46 | top: -24px; 47 | left: -2px; 48 | color: #fff; 49 | display: inline-block; 50 | font: normal normal normal 24px/1 "Material Design Icons"; 51 | font-size: inherit; 52 | text-rendering: auto; 53 | line-height: inherit; 54 | -webkit-font-smoothing: antialiased; 55 | -moz-osx-font-smoothing: grayscale; 56 | font-size: x-large; } 57 | 58 | .end:before { 59 | content: "\F0620"; 60 | position: absolute; 61 | top: -24px; 62 | right: -2px; 63 | color: #fff; 64 | display: inline-block; 65 | font: normal normal normal 24px/1 "Material Design Icons"; 66 | font-size: inherit; 67 | text-rendering: auto; 68 | line-height: inherit; 69 | -webkit-font-smoothing: antialiased; 70 | -moz-osx-font-smoothing: grayscale; 71 | font-size: x-large; } 72 | 73 | .comparing { 74 | display: flex; 75 | justify-content: center; } 76 | .comparing::after { 77 | content: "\F005D"; 78 | position: absolute; 79 | bottom: -23px; 80 | z-index: 10; 81 | color: #93ff5b; 82 | display: inline-block; 83 | font: normal normal normal 24px/1 "Material Design Icons"; 84 | font-size: inherit; 85 | text-rendering: auto; 86 | line-height: inherit; 87 | -webkit-font-smoothing: antialiased; 88 | -moz-osx-font-smoothing: grayscale; 89 | font-size: x-large; } 90 | 91 | /* .mid { 92 | border-top: 20px solid pink; 93 | margin-top: -20px; 94 | } */ 95 | .toolbar { 96 | display: flex; 97 | justify-content: center; 98 | padding: 15px 0; 99 | align-items: center; } 100 | 101 | .toolbar-top > * { 102 | margin-right: 30px; } 103 | 104 | .toolbar-bottom > button:first-child { 105 | margin-right: 7px; } 106 | 107 | /* .bottom { 108 | } */ 109 | .animation-speed > div { 110 | display: flex; 111 | align-items: center; 112 | margin-top: 5px; } 113 | .animation-speed > div > *:not(:first-child) { 114 | margin-left: 10px; } 115 | 116 | .pivot { 117 | /* border: 2px solid red; */ 118 | background: #ffac00; } 119 | 120 | .swap { 121 | background-color: #f13737; } 122 | 123 | .btn { 124 | padding: 10px; 125 | border: none; 126 | border-radius: 10px; 127 | cursor: pointer; } 128 | .btn-primary { 129 | background-color: #3568d4; 130 | color: #fff; 131 | box-shadow: 0px 5px 13px 0px #1f58d18c; } 132 | .btn-primary-outline { 133 | border: 1px solid #3568d4; 134 | color: #fff; 135 | box-shadow: 0px 5px 13px 0px #1f58d18c; 136 | background-color: transparent; } 137 | .btn-secondary { 138 | background-color: #28c328; 139 | color: #fff; 140 | box-shadow: 0px 5px 13px 0px #1fd13d8c; } 141 | .btn-rounded { 142 | border-radius: 100px; } 143 | 144 | select { 145 | padding: 9px 5px; 146 | border-radius: 10px; 147 | border: 1px solid #3568d4; 148 | color: #fff; 149 | box-shadow: 0px 5px 13px 0px #1f58d18c; 150 | background-color: transparent; 151 | cursor: pointer; } 152 | select option { 153 | color: #000; } 154 | 155 | /* The slider itself */ 156 | .slider { 157 | -webkit-appearance: none; 158 | /* Override default CSS styles */ 159 | appearance: none; 160 | width: 100%; 161 | /* Full-width */ 162 | height: 5px; 163 | /* Specified height */ 164 | background: #d3d3d3b7; 165 | /* Grey background */ 166 | outline: none; 167 | /* Remove outline */ 168 | -webkit-transition: 0.2s; 169 | /* 0.2 seconds transition on hover */ 170 | transition: background 0.2s; 171 | cursor: pointer; 172 | /* Mouse-over effects */ 173 | /* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */ } 174 | .slider:hover { 175 | background: #d3d3d3; } 176 | .slider::-webkit-slider-thumb { 177 | -webkit-appearance: none; 178 | /* Override default look */ 179 | appearance: none; 180 | width: 15px; 181 | /* Set a specific slider handle width */ 182 | height: 15px; 183 | /* Slider handle height */ 184 | background: #3568d4; 185 | /* Green background */ 186 | cursor: pointer; 187 | /* Cursor on hover */ 188 | border-radius: 50px; 189 | box-shadow: 0px 5px 13px 0px #1f58d18c; } 190 | .slider::-moz-range-thumb { 191 | width: 15px; 192 | /* Set a specific slider handle width */ 193 | height: 15px; 194 | /* Slider handle height */ 195 | background: #3568d4; 196 | /* Green background */ 197 | cursor: pointer; 198 | /* Cursor on hover */ 199 | border-radius: 50px; 200 | box-shadow: 0px 5px 13px 0px #1f58d18c; } 201 | 202 | .credits { 203 | position: fixed; 204 | right: 0; 205 | top: 50%; 206 | transform: translateY(-50%); 207 | background-color: #fff; 208 | box-shadow: 0 0 8px 3px #0a0a0a5c; 209 | padding: 5px; 210 | border-top-left-radius: 10px; 211 | border-bottom-left-radius: 10px; } 212 | .credits > div { 213 | transition: all .1s; } 214 | .credits > div img { 215 | width: 20px; 216 | height: 20px; } 217 | .credits > div:not(:first-child) { 218 | margin-top: 5px; } 219 | .credits > div:hover { 220 | transform: scale(1.1); } 221 | 222 | @supports (-ms-ime-align: auto) { 223 | .slider-container { 224 | width: 200px; } 225 | .bottom .slider-container { 226 | width: 800px; 227 | margin: 0 auto; } 228 | .slider { 229 | background-color: #fff; } } 230 | -------------------------------------------------------------------------------- /assets/style.scss: -------------------------------------------------------------------------------- 1 | $color-dark-1: #28293d; 2 | $color-blue: #3568d4; 3 | 4 | @mixin mdi-icon { 5 | display: inline-block; 6 | font: normal normal normal 24px/1 "Material Design Icons"; 7 | font-size: inherit; 8 | text-rendering: auto; 9 | line-height: inherit; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | * { 15 | font-family: "Jura", sans-serif; 16 | } 17 | body { 18 | background-color: $color-dark-1; 19 | color: #fff; 20 | } 21 | 22 | .page-wrapper { 23 | display: flex; 24 | flex-direction: column; 25 | flex-wrap: wrap; 26 | height: calc(100vh - 16px); 27 | margin: 0; 28 | padding: 0 50px; 29 | } 30 | #barsElement { 31 | display: flex; 32 | justify-content: center; 33 | flex-grow: 1; 34 | padding-top: 20px; 35 | width: 100%; 36 | } 37 | 38 | .bar { 39 | /* border: 2px solid black; */ 40 | background: #9dbff8; 41 | width: 20px; 42 | margin-right: 1px; 43 | position: relative; 44 | border-radius: 18px; 45 | } 46 | 47 | .un-ordered { 48 | background: red; 49 | } 50 | 51 | .sorted { 52 | background: #05c270; 53 | } 54 | .ordered { 55 | background: #05c270; 56 | } 57 | 58 | input.slider { 59 | width: 100%; 60 | } 61 | 62 | .start { 63 | // border-top: 20px solid #f819f1 !important; 64 | // margin-top: -20px; 65 | &:before { 66 | content: "\F061F"; 67 | position: absolute; 68 | top: -24px; 69 | left: -2px; 70 | color: #fff; 71 | @include mdi-icon(); 72 | font-size: x-large; 73 | } 74 | } 75 | 76 | .end { 77 | // border-top: 20px solid #f819f1 !important; 78 | // margin-top: -20px; 79 | &:before { 80 | content: "\F0620"; 81 | position: absolute; 82 | top: -24px; 83 | right: -2px; 84 | color: #fff; 85 | @include mdi-icon(); 86 | font-size: x-large; 87 | } 88 | } 89 | 90 | .comparing { 91 | // border-bottom: 20px solid #ff5b5b; 92 | display: flex; 93 | justify-content: center; 94 | &::after { 95 | content: "\F005D"; 96 | position: absolute; 97 | bottom: -23px; 98 | z-index: 10; 99 | // right: 0; 100 | color: #93ff5b; 101 | @include mdi-icon(); 102 | font-size: x-large; 103 | } 104 | } 105 | /* .mid { 106 | border-top: 20px solid pink; 107 | margin-top: -20px; 108 | } */ 109 | 110 | .toolbar { 111 | display: flex; 112 | justify-content: center; 113 | padding: 15px 0; 114 | align-items: center; 115 | } 116 | 117 | .toolbar-top > * { 118 | margin-right: 30px; 119 | } 120 | 121 | .toolbar-bottom > button:first-child { 122 | margin-right: 7px; 123 | } 124 | 125 | // .toolbar-bottom button:hover { 126 | // /* transform: scale(1.1); */ 127 | // box-shadow: 0 2px 5px 3px #00000040; 128 | // } 129 | 130 | // .toolbar-bottom button:active { 131 | // transform: scale(0.9); 132 | // box-shadow: 0 2px 5px 3px #00000040; 133 | // } 134 | 135 | // .btn-toggle { 136 | // background-color: #1e76dc; 137 | // margin-right: 10px; 138 | // } 139 | // .btn-stop { 140 | // background-color: #28c328; 141 | // } 142 | 143 | /* .bottom { 144 | } */ 145 | 146 | .animation-speed > div { 147 | display: flex; 148 | align-items: center; 149 | margin-top: 5px; 150 | 151 | > *:not(:first-child) { 152 | margin-left: 10px; 153 | } 154 | } 155 | 156 | .pivot { 157 | /* border: 2px solid red; */ 158 | background: #ffac00; 159 | } 160 | .swap { 161 | background-color: #f13737; 162 | } 163 | 164 | .btn { 165 | padding: 10px; 166 | border: none; 167 | border-radius: 10px; 168 | cursor: pointer; 169 | &-primary { 170 | background-color: $color-blue; 171 | color: #fff; 172 | box-shadow: 0px 5px 13px 0px #1f58d18c; 173 | } 174 | &-primary-outline { 175 | border: 1px solid $color-blue; 176 | color: #fff; 177 | box-shadow: 0px 5px 13px 0px #1f58d18c; 178 | background-color: transparent; 179 | } 180 | &-secondary { 181 | background-color: #28c328; 182 | color: #fff; 183 | box-shadow: 0px 5px 13px 0px #1fd13d8c; 184 | } 185 | &-rounded { 186 | border-radius: 100px; 187 | } 188 | } 189 | 190 | select { 191 | padding: 9px 5px; 192 | border-radius: 10px; 193 | border: 1px solid $color-blue; 194 | color: #fff; 195 | box-shadow: 0px 5px 13px 0px #1f58d18c; 196 | background-color: transparent; 197 | cursor: pointer; 198 | 199 | option { 200 | color: #000; 201 | } 202 | } 203 | 204 | /* The slider itself */ 205 | .slider { 206 | -webkit-appearance: none; /* Override default CSS styles */ 207 | appearance: none; 208 | width: 100%; /* Full-width */ 209 | height: 5px; /* Specified height */ 210 | background: #d3d3d3b7; /* Grey background */ 211 | outline: none; /* Remove outline */ 212 | // opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */ 213 | -webkit-transition: 0.2s; /* 0.2 seconds transition on hover */ 214 | transition: background 0.2s; 215 | cursor: pointer; 216 | /* Mouse-over effects */ 217 | &:hover { 218 | // opacity: 1; /* Fully shown on mouse-over */ 219 | background: #d3d3d3; 220 | } 221 | 222 | /* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */ 223 | &::-webkit-slider-thumb { 224 | -webkit-appearance: none; /* Override default look */ 225 | appearance: none; 226 | width: 15px; /* Set a specific slider handle width */ 227 | height: 15px; /* Slider handle height */ 228 | background: $color-blue; /* Green background */ 229 | cursor: pointer; /* Cursor on hover */ 230 | border-radius: 50px; 231 | box-shadow: 0px 5px 13px 0px #1f58d18c; 232 | } 233 | 234 | &::-moz-range-thumb { 235 | width: 15px; /* Set a specific slider handle width */ 236 | height: 15px; /* Slider handle height */ 237 | background: $color-blue; /* Green background */ 238 | cursor: pointer; /* Cursor on hover */ 239 | border-radius: 50px; 240 | box-shadow: 0px 5px 13px 0px #1f58d18c; 241 | } 242 | } 243 | 244 | // CREDITS 245 | .credits { 246 | position: fixed; 247 | right: 0; 248 | top: 50%; 249 | transform: translateY(-50%); 250 | background-color: #fff; 251 | // border: 1px solid blue; 252 | box-shadow: 0 0 8px 3px #0a0a0a5c; 253 | padding: 5px; 254 | border-top-left-radius: 10px; 255 | border-bottom-left-radius: 10px; 256 | 257 | > div{ 258 | transition: all .1s; 259 | img{ 260 | width: 20px; 261 | height: 20px; 262 | } 263 | 264 | &:not(:first-child){ 265 | margin-top: 5px; 266 | } 267 | 268 | &:hover{ 269 | transform: scale(1.1); 270 | } 271 | } 272 | } 273 | 274 | // CROSS-BROWSER COMPATIBILITY 275 | // MS Edge 276 | @supports (-ms-ime-align: auto) { 277 | .slider-container { 278 | width: 200px; 279 | } 280 | .bottom { 281 | .slider-container { 282 | width: 800px; 283 | margin: 0 auto; 284 | } 285 | } 286 | 287 | .slider { 288 | background-color: #fff; 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sort Visualizer 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 | Github 23 | 24 |
25 |
26 | 27 | LinkedIn 28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 | 36 | 37 |
38 | 39 | 40 |
41 | 42 | 43 |
44 | 45 |
46 | Fast 47 | 48 | Slow 49 |
50 |
51 | 52 | 53 | 57 |
58 | 59 |
60 | 61 |
62 |
63 | 64 |
65 | 66 |
67 | 70 | 73 | 74 |
75 |
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 85 | 86 | 87 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sorting-visualizer", 3 | "version": "1.0.0", 4 | "description": "Sorting algorithms visualizer in Vanilla JavaScript", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "cs": "node-sass assets/style.scss assets/style.css -w" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/abdulsohailmohd/sorting-visualizer.git" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/abdulsohailmohd/sorting-visualizer/issues" 19 | }, 20 | "homepage": "https://github.com/abdulsohailmohd/sorting-visualizer#readme", 21 | "devDependencies": { 22 | "node-sass": "^4.14.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sohail-js/sorting-visualizer/cc9114dec5ff438c7730f9f03759bcf7e3c114cd/preview.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Sorting Visualizer :fire: 2 | Sorting algorithms visualizer in Vanilla JavaScript 3 | 4 | ![preview](preview.png) 5 | 6 | ## Live Demo :star: 7 | https://sorting-visualizer-js.firebaseapp.com/ --------------------------------------------------------------------------------