@@ -4,140 +4,110 @@ import { Bar } from "../components/Bar"
44import { ChartWrapper } from "../components/ChartWrapper"
55import { SortButton } from "../components/SortButton"
66import { generateNewBarHeights } from "../utils/index"
7+ import { Grid } from "@geist-ui/react"
78
89/**
910 * Tailwind class of the active bar
1011 */
11- const ACTIVE_BAR_CLASS = "bg-black "
12+ const ACTIVE_BAR_COLOR = "#111 "
1213
1314/**
1415 * Tailwind class of the default bar
1516 */
16- const DEFAULT_BAR_CLASS = "bg-red-600 "
17+ const INACTIVE_BAR_COLOR = "#ff1a1a "
1718
1819/**
1920 * Sorting speed in miliseconds
2021 */
2122const SORTING_SPEED = 50
2223
23- interface changeElementClassParam {
24- add ?: string
25- remove ?: string
26- }
27-
2824/**
29- * Change an element's classList, can be adding or removing item from classList depending on the
30- * 2nd param's properties
31- * @param element A bar DOM element which will be modified
32- * @param operations An object containing 2 optional property, add and remove. The presence
33- * of one or both of it will determine what kind of operation will be done to the classList
25+ * Change element backgroundColor to a given value
26+ * @param element The DOM element
27+ * @param toColor The value in which the background color will be changed to
3428 */
35- const changeElementClass = (
36- element : Element ,
37- operations : changeElementClassParam
38- ) : void => {
39- let isAdd = operations . add
40- let isRemove = operations . remove
41- let isRemoveAndAdd = isRemove && isAdd
42-
43- if ( isRemoveAndAdd ) {
44- element . classList . remove ( operations . remove )
45- element . classList . add ( operations . add )
46- } else if ( isAdd ) {
47- element . classList . add ( operations . add )
48- } else if ( isRemove ) {
49- element . classList . remove ( operations . remove )
50- }
29+ const changeBarColor = ( element : HTMLElement , toColor : string ) : void => {
30+ element . style . backgroundColor = toColor
5131}
5232
5333/**
5434 * Revert each bar in the given collection bars from active bar to default bar
5535 * @param bars HTMLCollection of bar elements
5636 */
57- const revertBarsColor = ( bars : Element [ ] ) : void => {
37+ const revertBarsColor = ( bars : HTMLElement [ ] ) : void => {
5838 for ( const bar of bars ) {
59- changeElementClass ( bar , {
60- add : DEFAULT_BAR_CLASS ,
61- remove : ACTIVE_BAR_CLASS ,
62- } )
39+ changeBarColor ( bar , INACTIVE_BAR_COLOR )
6340 }
6441}
6542
6643/**
67- * Turn 2 previously active bars back into default bars
44+ * Turn 2 previously active bars back into inactive bars
6845 * @param prevBarsIndexes Previous bars' indexes in the current DOM
69- * @param barDomElements Array/HTMLCollection of the bar's DOM elemnt
46+ * @param bars Array/HTMLCollection of the bar's DOM elemnt
7047 */
7148const revertPreviousBarsColors = (
7249 prevBarsIndexes : [ number , number ] ,
73- barDomElements : HTMLCollectionOf < Element >
50+ bars : HTMLCollectionOf < HTMLElement >
7451) : void => {
7552 let [ prevBar1Idx , prevBar2Idx ] = prevBarsIndexes
7653
77- let prevActiveBar1 = barDomElements [ prevBar1Idx ]
78- let prevActiveBar2 = barDomElements [ prevBar2Idx ]
54+ let prevActiveBar1 = bars [ prevBar1Idx ]
55+ let prevActiveBar2 = bars [ prevBar2Idx ]
7956
8057 let previousActiveBars = [ prevActiveBar1 , prevActiveBar2 ]
8158
8259 revertBarsColor ( previousActiveBars )
8360}
8461
85- type BarToActiveBar = { element : Element ; newHeight : number }
62+ type BarToActiveBar = { element : HTMLElement ; newHeight : number }
8663
8764/**
88- * Turn each bar element in the bars param into an active bar
65+ * Turn each bar in the given array into an active bar, then set the height of it
66+ * to the given newHeight property
8967 * @param bars Array of object, each item is an object containing the element which
9068 * will be changed and the new height for that element
9169 */
9270const makeBarsActive = ( bars : BarToActiveBar [ ] ) : void => {
9371 for ( const bar of bars ) {
94- changeElementClass ( bar . element , {
95- add : ACTIVE_BAR_CLASS ,
96- remove : DEFAULT_BAR_CLASS ,
97- } )
98-
99- // @ts -ignore
72+ changeBarColor ( bar . element , ACTIVE_BAR_COLOR )
10073 bar . element . style . height = `${ bar . newHeight } %`
10174 }
10275}
10376
10477/**
105- * Turn every bar in the DOM into an active bar (black bar) one by one, from first bar to last bar
106- * @param barsEl Array/HTML Collection of the bar's DOM elements
78+ * Turn every bar in the given array into an active bar one by one, from first bar to last bar
79+ * @param bars Array/HTML Collection of the bar's DOM elements
10780 */
108- const postSortAnimation = ( barsEl : HTMLCollectionOf < Element > ) : void => {
109- for ( let s = 0 ; s < barsEl . length ; s ++ ) {
81+ const postSortAnimation = ( bars : HTMLCollectionOf < HTMLElement > ) : void => {
82+ for ( let n = 0 ; n < bars . length ; n ++ ) {
11083 setTimeout ( ( ) => {
111- let sThBar = barsEl [ s ]
84+ let nThBar = bars [ n ]
11285
113- changeElementClass ( sThBar , {
114- remove : DEFAULT_BAR_CLASS ,
115- add : ACTIVE_BAR_CLASS ,
116- } )
117- } , s * 10 )
86+ changeBarColor ( nThBar , ACTIVE_BAR_COLOR )
87+ } , n * 10 )
11888 }
11989}
12090
121- const animateSelectionSort = ( bars : number [ ] ) : void => {
122- const [ arrayStates , animationSequence ] = selectionSort ( bars )
123- const barDomElements = document . getElementsByClassName ( "bar" )
91+ const animateSelectionSort = ( barHeights : number [ ] , postSortFunc ?: ( ) => void ) : void => {
92+ const [ arrayStates , animationSequence ] = selectionSort ( barHeights )
93+ const bars = document . getElementsByClassName ( "bar" ) as HTMLCollectionOf < HTMLElement >
12494
12595 for ( let i = 0 ; i < animationSequence . length ; i ++ ) {
12696 let firstIteration = i === 0
12797 let lastIteration = i === animationSequence . length - 1
12898
12999 const [ bar1Idx , bar2Idx ] = animationSequence [ i ]
130100
131- const activeBar1 = barDomElements [ bar1Idx ]
132- const activeBar2 = barDomElements [ bar2Idx ]
101+ const activeBar1 = bars [ bar1Idx ]
102+ const activeBar2 = bars [ bar2Idx ]
133103
134104 const activeBar1Height = arrayStates [ i ] [ bar2Idx ]
135105 const activeBar2Height = arrayStates [ i ] [ bar1Idx ]
136106
137107 setTimeout ( ( ) => {
138108 if ( ! firstIteration ) {
139109 let prevAnimationSequence = animationSequence [ i - 1 ]
140- revertPreviousBarsColors ( prevAnimationSequence , barDomElements )
110+ revertPreviousBarsColors ( prevAnimationSequence , bars )
141111 }
142112
143113 let barsToActiveBars : BarToActiveBar [ ] = [
@@ -154,11 +124,18 @@ const animateSelectionSort = (bars: number[]): void => {
154124 makeBarsActive ( barsToActiveBars )
155125
156126 if ( lastIteration ) {
127+ // Revert the last bar to an inactive bar
157128 setTimeout ( ( ) => {
158129 let lastBar = activeBar1
159130 revertBarsColor ( [ lastBar ] )
160131
161- postSortAnimation ( barDomElements )
132+ // Because this animate function executes asynchronous function (setTimeout)
133+ // if we wanted to do something right after this function is done running,
134+ // we have to put the code inside the setTimeout and set it to run at the last iteration.
135+ // Otherwise, the code will be executed before the setTimeouts get
136+ // executed (because it is asynchronous).
137+ postSortAnimation ( bars )
138+ if ( postSortFunc ) postSortFunc ( )
162139 } , SORTING_SPEED )
163140 }
164141 } , i * SORTING_SPEED )
@@ -167,21 +144,32 @@ const animateSelectionSort = (bars: number[]): void => {
167144
168145const Home : React . FC = ( ) => {
169146 const [ barHeights , setBarHeights ] = useState ( [ ] )
147+ const [ sortState , setSortState ] = useState < "Sort" | "Sorting" | "Sorted" > ( "Sort" )
170148
171149 const bars = barHeights . map ( ( heightValue , idx ) => (
172150 < Bar key = { idx } height = { heightValue } />
173151 ) )
174152
175153 useEffect ( ( ) => {
176- const newBarHeights = generateNewBarHeights ( 150 )
154+ const newBarHeights = generateNewBarHeights ( 100 )
177155 setBarHeights ( newBarHeights )
178156 } , [ ] )
179157
180158 return (
181- < div className = "h-screen mt-8 mx-auto" >
182- < ChartWrapper bars = { bars } />
183- < SortButton clickAction = { ( ) => animateSelectionSort ( barHeights ) } />
184- </ div >
159+ < Grid . Container justify = "center" style = { { height : "100vh" } } >
160+ < Grid xs = { 24 } style = { { paddingTop : "40px" } } >
161+ < ChartWrapper bars = { bars } />
162+ </ Grid >
163+ < Grid xs = { 24 } >
164+ < SortButton
165+ sortState = { sortState }
166+ clickAction = { ( ) => {
167+ setSortState ( "Sorting" )
168+ animateSelectionSort ( barHeights , ( ) => setSortState ( "Sorted" ) )
169+ } }
170+ />
171+ </ Grid >
172+ </ Grid . Container >
185173 )
186174}
187175
0 commit comments