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