-
Notifications
You must be signed in to change notification settings - Fork 0
/
script_26.txt
1567 lines (1322 loc) · 60.4 KB
/
script_26.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
____________________________________________________________________________
26_score_keeper_code_along________________________________________________26
____________________________________________________________________________
Next up we're going to get a little practice using the DOM manipulation content we've learned, working with events, HTML and some basic CSS. We're going to wrap it all together and make this simple ping pong scorekeeping widget. It's very straightforward, a two player game, each player has a button +1 player one and +1 player two and a reset button. We can select what we want to play up to. We add a point and the score changes on the page. When the playing to score is reached, the numbers change color showing in green the player who won and in green the player who lost. With the reset button we can start all over. That's it.
(If you want, you can try to do this on your own as homework.)
We have some styling in here as well. For this project we'll use another CSS framework that is not Bootstrap, but another similar tool called Bulma.
So let's get into it. Let's open our scorekeeper_starte/index.html and add in our app.js script.
<body>
<script src="app.js"></script>
</body>
let's also add an h1 called "0 to 0":
<body>
<h1>0 to 0</h1>
<script src="app.js"></script>
</body>
before we go any further let's discuss how this is going to work, where we are updating just one number out of this h1.And then we're applying a class to make something green just to one number and not the other. If we have the h1 with the markup just as it is now, it's going to be very difficult. So we need a way to single out the two zeros and then select them and change them using JavaScript. We're going to use a span for that:
<body>
<h1><span>0</span> to <span>0</span></h1>
<script src="app.js"></script>
</body>
That's what a span is supposed to do, wrap a single inline content that we can then single out. So we'll wrap the 0's in a span and we'll now give them each an id like p1Display and p2Display
<body>
<h1><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<script src="app.js"></script>
</body>
And now let's add three buttons text +1 Player One, +1 Player Two and Reset respectively. Let's also give them and id of p1Button, p2Button and reset.
<body>
<h1><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<button id="p1Button">+1 Player One</button>
<button id="p2Button">+1 Player Two</button>
<button id="reset">Reset</button>
<script src="app.js"></script>
</body>
now we have the bare minimum. Now we can get the logic to work for our buttons. Let's assume we're playing to five and hardcode that to begin with. Now let's move to our scorekeeper_starter/app.js and add in an alert('sometghin') to test if it's connected.
alert('hello')
it is. Now what we whant to do is begin by selecting the buttons and the doing something when we click on the buttons. So let's select them up top:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
Now let's add an event listener for click and in our callback function let's alert something to see if it works:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
p1Button.addEventListener('click', function(){
alert('clicked')
})
and it works. Now let's talk about the logic that we want to do. When we click on player one, we want ot take whatever the current score is for player one and add one to it and then update this span to have that new score. So we need to keep track of whatever the current score is for player one. So let's have a variable do that for us:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
let p1Score = 0;
p1Button.addEventListener('click', function(){
p1Score += 1;
})
so when we click on the p1Button we should have a score increase. Now we want to update what we see in our span. So let's select the spans from our h1 too:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
p1Button.addEventListener('click', function(){
p1Score += 1;
})
now all we need to do is change that span's text:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
p1Button.addEventListener('click', function(){
p1Score += 1;
p1Display.textContent = p1Score
})
now if we click, we add one to our p1 score and then it updates our display and it looks like it's working. Now we also need to pay attention to what we're playing to. We're going to start by playing to 5. So let's make a variable called winningScore = 5;
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let winningScore = 5;
p1Button.addEventListener('click', function(){
p1Score += 1;
p1Display.textContent = p1Score
})
Now inside the p1Button event listener we could do something like if Player1 score is no equal to winning score, increase the Player1 score and update the p1Display span:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let winningScore = 5;
p1Button.addEventListener('click', function(){
if(p1Score !== winningScore){
p1Score += 1;
p1Display.textContent = p1Score
}
})
now it stops when we reach five. We can now duplicate this logic for player 2:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
p1Button.addEventListener('click', function(){
if(p1Score !== winningScore){
p1Score += 1;
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(p2Score !== winningScore){
p2Score += 1;
p2Display.textContent = p2Score;
}
})
now if we get with player 1 to five for example, we can still add points to player 2. That's not really what we want. So we want to make it that if any of player 1 or 2 make it to 5, we are done increasing the score. To make that work we need to keep track of that winningScore like we arleady are doing, but also we need to track wheather if any of the player has reached it. Another way of saying it is we need to know wheather we are still playing the game or not. It's just a yes or a no. So we would need a boolean for that. So let's make one named isGameOver and let's initialize it with false:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(p1Score !== winningScore){
p1Score += 1;
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(p2Score !== winningScore){
p2Score += 1;
p2Display.textContent = p2Score;
}
})
now we need to add more logic to our event listeners. So if anybody hits five, we're going to set isGameOver to true. So inside our callback functions we're going to rewrite our code a bit:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(p2Score !== winningScore){
p2Score += 1;
p2Display.textContent = p2Score;
}
})
so now we look for isGameOver. If it is false, !false gives us true, we will increase the p1Score. After increasing the p1Score, we check if it's the winningScore already, in which case we set isGameOver to true so that we cannot increase p1Score anyore. And at the end of the first if we update the textContent with the p1Score. Inside the p1Score === winningScore if statement we will also add in the class styling for our elements later on. So let's now duplicate the code from player one and adapt it to player too as well:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
Now let's make our reset button reset the game. So let's first select it:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
now we need to add an event listener on our click for the reset button and the first thing we'll do in our callback function is set isGameOver to false, second we'll set player one and two's score to 0:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
resetButton.addEventListener('click', function(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
})
now we also need to update the display when we reset:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
resetButton.addEventListener('click', function(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
})
so that's working. Now we can add in our select, so that we can play to a different range, so that we can set a different winning score. We'll just begin by adding in a select befor our buttons in our index.html and we'll give it an id of "playto":
<body>
<h1><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<select name="" id="playto">
</select>
<button id="p1Button">+1 Player One</button>
<button id="p2Button">+1 Player Two</button>
<button id="reset">Reset</button>
<script src="app.js"></script>
</body>
now we need to give it some options. We need to specify a value attribute and then the inner text for the option that the user sees. So let's do 3, 4, 5, 6, 7 up to 11:
<body>
<h1><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<select name="" id="playto">
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
</select>
<button id="p1Button">+1 Player One</button>
<button id="p2Button">+1 Player Two</button>
<button id="reset">Reset</button>
<script src="app.js"></script>
</body>
now all we want to do is, when we make a change in our play to select, we want to make sure our winning score is set to whatever that value is. We also want to reset the game, so that the user cannot change the playto mid-game. So we go to our app.js and we will select our playto and add an event listener to it on 'change', also let's add an alert first to see if it works to its callback function:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
const winningScoreSelect = document.querySelector('#playto')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
winningScoreSelect = addEventListener('change', function(){
alert('CHANGE!')
})
resetButton.addEventListener('click', function(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
})
so it works. The next thing we need to figure out is how to get the value out. The easiest option is to reference "this". Then we have access to the value. Let's test this out in our alert with this.value:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
const winningScoreSelect = document.querySelector('#playto')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
winningScoreSelect = addEventListener('change', function(){
alert(this.value)
})
resetButton.addEventListener('click', function(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
})
So this gives us a number and unfortunately, it's not quite as easy as updating the winning score, because it's going to be a string. So we need to convert it into a number using parseInt. So we'll do something like:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
const winningScoreSelect = document.querySelector('#playto')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
winningScoreSelect = addEventListener('change', function(){
winningScore = parseInt(this.value)
})
resetButton.addEventListener('click', function(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
})
now this should update whatever the winning score variable is. Now we need to reset the values for p1Score and p2Score. We could copy the code from the resetButton, but the better approach here is to move the code from it to a separate function called reset() that we can call in both callbacks:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
const winningScoreSelect = document.querySelector('#playto')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
}
p2Display.textContent = p2Score;
}
})
winningScoreSelect = addEventListener('change', function(){
winningScore = parseInt(this.value);
reset();
})
resetButton.addEventListener('click', reset)
function reset(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
}
for the reset button we pass it in as a callback function and we do not call it directly. It will be called when the time has come. On the other hand in winningScoreSelect, we call the function directly because it is already in an anonymous callback function. Now if we change the select to another number, it should reset our scores.
Now all that we have left is adding in a color to whoever wins and loses. Now as we mentioned before, we're going to use a CSS framework called Bulma and it comes with classes to make things red and green. But for now we'll just come up with a class name in our index.html that we'll remove later so that we don't make a new stylesheet. So we'll add an inline <style></style> element in our head with two classes: .winner and .loser with color: green and red respectively:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Score Keeper</title>
<style>
.winner{
color: green;
}
.loser{
color: red
}
</style>
</head>
What we want to do now is when someone wins, meaning p1Score is equal to winningScore or p2Score is equal to winningScore, we want to add the appropiate class to each one with classList.add:
so we can do that with:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
const winningScoreSelect = document.querySelector('#playto')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
p1Display.classList.add('winner');
p2Display.classList.add('loser');
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
p1Display.classList.add('loser');
p2Display.classList.add('winner');
}
p2Display.textContent = p2Score;
}
})
winningScoreSelect = addEventListener('change', function(){
winningScore = parseInt(this.value);
reset();
})
resetButton.addEventListener('click', reset)
function reset(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
}
Alright. But the reset is not working for the class. So let's call classList.remove in the reset function:
const p1Button = document.querySelector('#p1Button')
const p2Button = document.querySelector('#p2Button')
const resetButton = document.querySelector('#reset')
const p1Display = document.querySelector('#p1Display')
const p2Display = document.querySelector('#p2Display')
const winningScoreSelect = document.querySelector('#playto')
let p1Score = 0;
let p2Score = 0;
let winningScore = 5;
let isGameOver = false;
p1Button.addEventListener('click', function(){
if(!isGameOver){
p1Score += 1;
if(p1Score === winningScore){
isGameOver = true;
p1Display.classList.add('winner');
p2Display.classList.add('loser');
}
p1Display.textContent = p1Score;
}
})
p2Button.addEventListener('click', function(){
if(!isGameOver){
p2Score += 1;
if(p2Score === winningScore){
isGameOver = true;
p1Display.classList.add('loser');
p2Display.classList.add('winner');
}
p2Display.textContent = p2Score;
}
})
winningScoreSelect = addEventListener('change', function(){
winningScore = parseInt(this.value);
reset();
})
resetButton.addEventListener('click', reset)
function reset(){
isGameOver = false;
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
p1Display.classList.remove('winner', 'loser');
p2Display.classList.remove('winner', 'loser');
}
nice, now it also works if we reset via the select playto number.
Now we'll introduce Bulma. Bulm is essentially a full-blown CSS framework that we can use to replace something like Bootstrap. It's very simple to pick up, the terminology a bit simpler than Bootstrap. The styles are a bit different. It's nice and customizable. It does not force us to use something like jquery, which Bootstrap has for a very long time, or popper.js, another dependency of Bootstrap. These were the driving forces for Bulma, not having those dependencies. So if we look at the documentation https://bulma.io/documentation/ it's broken down into Helpers, Form, Elements and Components. Components includes things like cards, very similar to Bootstrap. We're going to use a card to make our scorekeeper. Now we need to include it in our app. So if we go to overview > start https://bulma.io/documentation/overview/start/ we just need that min css file:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
So let's put that at the top of our index.html in the head tag:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Score Keeper</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
</head>
now we should see some changes to our page. The next thing we're going to do is go on the documentation to a card: https://bulma.io/documentation/components/card/ then from there let's copy a card (the second last one to be more exact):
<div class="card">
<header class="card-header">
<p class="card-header-title">
Component
</p>
<button class="card-header-icon" aria-label="more options">
<span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</header>
<div class="card-content">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris.
<a href="#">@bulmaio</a>. <a href="#">#css</a> <a href="#">#responsive</a>
<br>
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
and just paste it into our document at the top of body. And it's super wide. Now we need to figure out how we can control that. This is very different from how Bootstrap works, but it's the same concept of dividing up space, although the class names are different. If we go to columns > basics https://bulma.io/documentation/columns/basics/ it says we need a column container and as many columns elements as we want. In addition we can change the size of a single column, using one of the following classes: is-half, is-quarter etc. (see website https://bulma.io/documentation/columns/sizes/ for more info). We don't use things as in bootstrap like column-6 or column-md-5. So we'll first cut the card we just inserted out and make a div container with another div columns inside it. Inside the columns div we'll make another column div:
<div class="container">
<div class="columns">
<div class="column">
</div>
</div>
</div>
now let's paste the card inside the column div.
<div class="container">
<div class="columns">
<div class="column">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Component
</p>
<button class="card-header-icon" aria-label="more options">
<span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</header>
<div class="card-content">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris.
<a href="#">@bulmaio</a>. <a href="#">#css</a> <a href="#">#responsive</a>
<br>
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
now if we want to go halfway across we can use the class "column is-half" on the column div:
<div class="container">
<div class="columns">
<div class="column is-half">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Component
</p>
<button class="card-header-icon" aria-label="more options">
<span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</header>
<div class="card-content">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris.
<a href="#">@bulmaio</a>. <a href="#">#css</a> <a href="#">#responsive</a>
<br>
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
Now to center it, we can use one of the offset classes https://bulma.io/documentation/columns/sizes/ like in the docs. So if our card is 50% that means it's half and we want it to be centered, we would need to put one quarter on the left and one quarter on the right. For that we would need to add in "column is-half is-offset-one-quarter":
<div class="container">
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Component
</p>
<button class="card-header-icon" aria-label="more options">
<span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</header>
<div class="card-content">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris.
<a href="#">@bulmaio</a>. <a href="#">#css</a> <a href="#">#responsive</a>
<br>
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
Next up we can begin adding our content inside the card. So let's start wit hthe card header and replace that with "Ping Pong Score Keeper". We're also going to delete the button tag that comes after the paragraph:
<div class="container">
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Ping Pong Score Keeper
</p>
</header>
<div class="card-content">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris.
<a href="#">@bulmaio</a>. <a href="#">#css</a> <a href="#">#responsive</a>
<br>
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
Now we have the div's class="card-content" and inside it div with class "content". We'll delete everything inside that div and we'll put inside our h1 tag.
<div class="container">
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Ping Pong Score Keeper
</p>
</header>
<div class="card-content">
<div class="content">
<h1><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
now we have inside our score display. Our h1 itself is going to have a new typography class from Bulma. So if we go Helpers > Typograpy https://bulma.io/documentation/helpers/typography-helpers/ we can see that there are seven sizes that Bulma offers. We also have elements > title https://bulma.io/documentation/elements/title/ from which we will use "title is-1" on our h1 as a class:
<div class="container">
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Ping Pong Score Keeper
</p>
</header>
<div class="card-content">
<div class="content">
<h1 class="title is-1"><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
in the div after our h1 we can put a paragraph with a class of subtitle that says: Use the buttons below to keep score
<div class="container">
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Ping Pong Score Keeper
</p>
</header>
<div class="card-content">
<div class="content">
<h1 class="title is-1"><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<p class="subtitle">Use the buttons below to keep score</p>
</div>
</div>
<footer class="card-footer">
<a href="#" class="card-footer-item">Save</a>
<a href="#" class="card-footer-item">Edit</a>
<a href="#" class="card-footer-item">Delete</a>
</footer>
</div>
</div>
</div>
</div>
Now let's get our buttons in the card where we have Save, Edit and Delete. They are all anchor tags with card-footer-item class, which we will keep, but we'll make them buttons instead. In elements > button we can se how we can make a button in Bulma: https://bulma.io/documentation/elements/button/ we just use the actual word "button" as our class. We can also change the color of the button just as in Boostrap and also their size. So let's add in our first button with class "is-primary button card-footer-item" and take the id from our first player 1 button of "p1Button" and add it too. The text inside the button will say "+1 Player One":
<div class="container">
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Ping Pong Score Keeper
</p>
</header>
<div class="card-content">
<div class="content">
<h1 class="title is-1"><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<p class="subtitle">Use the buttons below to keep score</p>