1
+ let root = document . getElementById ( "root" ) ;
2
+
3
+
4
+ class List {
5
+ constructor ( place , title = "To-Do" ) {
6
+ this . place = place ;
7
+ this . title = title ;
8
+ this . cardArray = [ ] ;
9
+ this . render ( ) ;
10
+ }
11
+
12
+ addToDo ( ) {
13
+ let text = this . input . value ;
14
+ if ( text . trim ( ) !== "" ) {
15
+ this . cardArray . push ( new Card ( text , this . div , this ) ) ;
16
+ this . input . value = "" ;
17
+ }
18
+ }
19
+
20
+ render ( ) {
21
+ this . createListElement ( ) ;
22
+ this . place . append ( this . listElement ) ;
23
+ }
24
+
25
+ createListElement ( ) {
26
+ this . listElement = document . createElement ( 'div' ) ;
27
+ this . listElement . classList . add ( "todoList" ) ;
28
+
29
+ this . h2 = document . createElement ( 'h2' ) ;
30
+ this . h2 . innerText = this . title ;
31
+
32
+ this . input = document . createElement ( 'input' ) ;
33
+ this . input . classList . add ( "comment" ) ;
34
+
35
+ this . button = document . createElement ( 'button' ) ;
36
+ this . button . innerText = 'Add' ;
37
+ this . button . classList . add ( "btn-save" ) ;
38
+ this . button . addEventListener ( 'click' , this . addToDo . bind ( this ) ) ;
39
+
40
+ this . div = document . createElement ( 'div' ) ;
41
+
42
+ this . listElement . append ( this . h2 , this . input , this . button , this . div ) ;
43
+ }
44
+ }
45
+
46
+ class ToDo extends List {
47
+ constructor ( place , title ) {
48
+ super ( place , title ) ;
49
+ }
50
+ }
51
+
52
+ class Doing extends List {
53
+ constructor ( place , title ) {
54
+ super ( place , title ) ;
55
+ }
56
+ }
57
+
58
+ class Done extends List {
59
+ constructor ( place , title ) {
60
+ super ( place , title ) ;
61
+ }
62
+ }
63
+
64
+
65
+ class Card {
66
+ constructor ( text , place , list ) {
67
+ this . text = text ;
68
+ this . place = place ;
69
+ this . list = list ;
70
+ this . state = {
71
+ description : "Click to write a description..." ,
72
+ comments : [ ]
73
+ } ;
74
+ this . render ( ) ;
75
+ }
76
+
77
+ render ( ) {
78
+ this . card = document . createElement ( 'div' ) ;
79
+ this . card . classList . add ( "card" ) ;
80
+
81
+ this . p = document . createElement ( 'p' ) ;
82
+ this . p . innerText = this . text ;
83
+
84
+ this . deleteButton = document . createElement ( 'button' ) ;
85
+ this . deleteButton . innerText = "X" ;
86
+ this . deleteButton . addEventListener ( 'click' , ( ) => {
87
+ this . deleteCard ( ) ;
88
+ } ) ;
89
+
90
+ this . card . append ( this . p , this . deleteButton ) ;
91
+ this . place . append ( this . card ) ;
92
+ this . card . addEventListener ( 'click' , this . showMenu . bind ( this ) ) ;
93
+ }
94
+
95
+ deleteCard ( ) {
96
+ this . card . remove ( ) ;
97
+ let index = this . list . cardArray . indexOf ( this ) ;
98
+ if ( index !== - 1 ) {
99
+ this . list . cardArray . splice ( index , 1 ) ;
100
+ }
101
+ }
102
+
103
+ showMenu ( ) {
104
+
105
+ //Create elements
106
+ this . menu = document . createElement ( "div" ) ;
107
+ this . menuContainer = document . createElement ( "div" ) ;
108
+ this . menuTitle = document . createElement ( "div" ) ;
109
+ this . menuDescription = document . createElement ( "div" ) ;
110
+ this . commentsInput = document . createElement ( "input" ) ;
111
+ this . commentsButton = document . createElement ( 'button' ) ;
112
+ this . menuComments = document . createElement ( "div" ) ;
113
+
114
+
115
+ //Add class names
116
+ this . menu . className = "menu" ;
117
+ this . menuContainer . className = "menuContainer" ;
118
+ this . menuTitle . className = "menuTitle" ;
119
+ this . menuDescription . className = "menuDescription" ;
120
+ this . menuComments . className = "menuComments" ;
121
+ this . commentsInput . className = "commentsInput comment" ;
122
+ this . commentsButton . className = "commentsButton btn-save" ;
123
+
124
+ //Add inner Text
125
+ this . commentsButton . innerText = "Add" ;
126
+ this . commentsInput . placeholder = "Write a comment..." ;
127
+
128
+ //Event listeners
129
+ this . menuContainer . addEventListener ( 'click' , ( e ) => {
130
+ console . log ( e . target ) ;
131
+ if ( e . target . classList . contains ( "menuContainer" ) ) {
132
+ this . menuContainer . remove ( ) ;
133
+ }
134
+ } ) ;
135
+
136
+ this . commentsButton . addEventListener ( 'click' , ( ) => {
137
+ if ( this . commentsInput . value != "" ) {
138
+ this . state . comments . push ( this . commentsInput . value ) ;
139
+ this . renderComments ( ) ;
140
+ this . commentsInput . value = "" ;
141
+ }
142
+ } )
143
+
144
+ //Append
145
+ this . menu . append ( this . menuTitle ) ;
146
+ this . menu . append ( this . menuDescription ) ;
147
+ this . menu . append ( this . commentsInput ) ;
148
+ this . menu . append ( this . commentsButton ) ;
149
+ this . menu . append ( this . menuComments ) ;
150
+ this . menuContainer . append ( this . menu ) ;
151
+ root . append ( this . menuContainer ) ;
152
+
153
+ this . editableDescription = new EditableText ( this . state . description , this . menuDescription , this , "description" , "textarea" ) ;
154
+ this . editableTitle = new EditableText ( this . state . text , this . menuTitle , this , "text" , "input" ) ;
155
+
156
+ this . renderComments ( ) ;
157
+ }
158
+
159
+ renderComments ( ) {
160
+
161
+ let currentCommentsDOM = Array . from ( this . menuComments . childNodes ) ;
162
+
163
+ currentCommentsDOM . forEach ( commentDOM => {
164
+ commentDOM . remove ( ) ;
165
+ } ) ;
166
+
167
+ this . state . comments . forEach ( comment => {
168
+ new Comment ( comment , this . menuComments , this ) ;
169
+ } ) ;
170
+ }
171
+ }
172
+
173
+ class EditableText {
174
+ constructor ( text , place , card , property , typeOfInput ) {
175
+ this . text = text ;
176
+ this . place = place ;
177
+ this . card = card ;
178
+ this . property = property ;
179
+ this . typeOfInput = typeOfInput ;
180
+ this . render ( ) ;
181
+ }
182
+
183
+ render ( ) {
184
+ this . div = document . createElement ( "div" ) ;
185
+ this . p = document . createElement ( "p" ) ;
186
+
187
+ this . p . innerText = this . text ;
188
+
189
+ this . p . addEventListener ( 'click' , ( ) => {
190
+ this . showEditableTextArea . call ( this ) ;
191
+ } ) ;
192
+
193
+ this . div . append ( this . p ) ;
194
+ this . place . append ( this . div ) ;
195
+ }
196
+
197
+ showEditableTextArea ( ) {
198
+ let oldText = this . text ;
199
+
200
+ this . input = document . createElement ( this . typeOfInput ) ;
201
+ this . saveButton = document . createElement ( "button" ) ;
202
+
203
+ this . p . remove ( ) ;
204
+ this . input . value = oldText ;
205
+ this . saveButton . innerText = "Save" ;
206
+ this . saveButton . className = "btn-save" ;
207
+ this . input . classList . add ( "comment" ) ;
208
+
209
+ this . saveButton . addEventListener ( 'click' , ( ) => {
210
+ this . text = this . input . value ;
211
+ this . card . state [ this . property ] = this . input . value ;
212
+ if ( this . property == "text" ) {
213
+ this . card . p . innerText = this . input . value ;
214
+ }
215
+ this . div . remove ( ) ;
216
+ this . render ( ) ;
217
+ } ) ;
218
+
219
+ function clickSaveButton ( event , object ) {
220
+ // Number 13 is the "Enter" key on the keyboard
221
+ if ( event . keyCode === 13 ) {
222
+ // Cancel the default action, if needed
223
+ event . preventDefault ( ) ;
224
+ // Trigger the button element with a click
225
+ object . saveButton . click ( ) ;
226
+ }
227
+ }
228
+
229
+ this . input . addEventListener ( "keyup" , ( e ) => {
230
+ if ( this . typeOfInput == "input" ) {
231
+ clickSaveButton ( e , this ) ;
232
+ }
233
+ } ) ;
234
+
235
+ this . div . append ( this . input ) ;
236
+
237
+ if ( this . typeOfInput == "textarea" ) {
238
+ this . div . append ( this . saveButton ) ;
239
+ }
240
+
241
+ this . input . select ( ) ;
242
+ }
243
+
244
+ }
245
+
246
+ class Comment {
247
+ constructor ( text , place , card ) {
248
+ this . text = text ;
249
+ this . place = place ;
250
+ this . card = card ;
251
+ this . render ( ) ;
252
+ }
253
+
254
+ render ( ) {
255
+ this . div = document . createElement ( 'div' ) ;
256
+ this . div . className = "comment" ;
257
+ this . div . innerText = this . text ;
258
+
259
+ this . place . append ( this . div ) ;
260
+ }
261
+ }
262
+
263
+
264
+
265
+ //-------------main------------
266
+
267
+ let addTodoListInput = document . getElementById ( "addTodoListInput" ) ;
268
+ let addTodoListButton = document . getElementById ( "addTodoListButton" ) ;
269
+
270
+ addTodoListButton . addEventListener ( 'click' , ( ) => {
271
+ if ( addTodoListInput . value . trim ( ) !== "" ) {
272
+ new ToDo ( root , addTodoListInput . value ) ; // Use user-provided title
273
+ addTodoListInput . value = "" ;
274
+ }
275
+ } ) ;
276
+
277
+ let todoList1 = new ToDo ( root ) ; // Default title "To-Do"
278
+ let todoList2 = new Doing ( root , "Doing" ) ; // Custom title "In Progress"
279
+ let todoList3 = new Done ( root , "Done" ) ; // Custom title "Completed"
0 commit comments