1
+ <!DOCTYPE html>
2
+ < html lang ="en ">
3
+ < head >
4
+ < meta charset ="UTF-8 ">
5
+ < title > Title</ title >
6
+ < script >
7
+ if ( ! ( function ( ) { return ( 'registerElement' in document
8
+ && 'import' in document . createElement ( 'link' )
9
+ && 'content' in document . createElement ( 'template' ) ) } ) ( ) ) {
10
+ let s = "<script type=\"text\/javascript\" " +
11
+ "src=\"https ://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.23/webcomponents.min.js\"" +
12
+ " > <\/script> "
13
+ document . write ( s )
14
+ }
15
+ </ script >
16
+ < script src ="../../Slim.js "> </ script >
17
+ </ head >
18
+ < body >
19
+
20
+
21
+ < script >
22
+ class ContactsModel {
23
+
24
+ constructor ( ) {
25
+ let contactsFromLocal = localStorage . getItem ( 'slim-contacts' )
26
+ if ( contactsFromLocal ) contactsFromLocal = JSON . parse ( contactsFromLocal )
27
+ this . contacts = contactsFromLocal || [ ]
28
+ }
29
+
30
+ create ( first , last ) {
31
+ let newContact = new Contact ( first , last )
32
+ this . contacts . push ( newContact )
33
+ this . sort ( )
34
+ this . save ( )
35
+ return newContact
36
+ }
37
+
38
+ save ( ) {
39
+ localStorage . setItem ( 'slim-contacts' , JSON . stringify ( this . contacts ) )
40
+ }
41
+
42
+ sort ( ) {
43
+ this . contacts = this . contacts . sort ( ( a , b ) => {
44
+ if ( a . last > b . last ) return 1
45
+ if ( b . last > a . last ) return - 1
46
+ if ( a . first > b . first ) return 1
47
+ if ( b . first > a . first ) return - 1
48
+ return 0
49
+ } )
50
+ }
51
+
52
+ remove ( contact ) {
53
+ let i = this . contacts . indexOf ( contact )
54
+ this . contacts . splice ( i , 1 )
55
+ this . save ( )
56
+ }
57
+
58
+ }
59
+
60
+ class Contact {
61
+ constructor ( first = "Moshe" , last = "Vilner" ) {
62
+ this . first = first
63
+ this . last = last
64
+ this . email = 'moshe@vilner.com'
65
+ this . phones = [ ]
66
+ }
67
+
68
+ addPhone ( phone ) {
69
+ this . phones . push ( number )
70
+ }
71
+
72
+ removePhone ( phone ) {
73
+ let i = this . phones . indexOf ( phone )
74
+ this . phones . splice ( i )
75
+ }
76
+ }
77
+
78
+ class Phone {
79
+ constructor ( type = 'Mobile' , number = '555-1234-567' ) {
80
+ this . type = type
81
+ this . number = number
82
+ }
83
+ }
84
+
85
+ window . Phone = Phone
86
+ window . Contact = Contact
87
+ window . ContactsModel = new ContactsModel ( )
88
+
89
+
90
+
91
+ /**
92
+ * Classic web component implementation
93
+ */
94
+ var SlimHeaderProto = Object . create ( HTMLElement . prototype ) ;
95
+
96
+ SlimHeaderProto . createdCallback = function ( ) {
97
+ this . innerHTML = '<h1>Slim is awesome</h1>'
98
+ this . style . width = '100%'
99
+ this . style . display = 'block'
100
+ this . style . textAlign = 'center'
101
+ }
102
+
103
+ document . registerElement ( 'slim-header' , {
104
+ prototype : SlimHeaderProto
105
+ } )
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+ /**
116
+ * Slim web component example
117
+ */
118
+ Slim . tag ( 'slim-app' , class extends Slim {
119
+
120
+
121
+ get template ( ) {
122
+ return `<div class="container"><slim-header></slim-header><slim-contacts /></div>`
123
+ }
124
+
125
+ } )
126
+
127
+
128
+ /**
129
+ * This is the wrapper for the slim-contacts application.
130
+ */
131
+ Slim . tag ( 'slim-contacts' , class SlimContacts extends Slim {
132
+
133
+ get template ( ) {
134
+ return `
135
+ <!-- header of the application, main menu -->
136
+ <div class="navbar navbar-default">
137
+ <div class="navbar-header">
138
+ <div class="navbar-brand">Slim Contacts</div>
139
+ <ul class="nav navbar-nav">
140
+ <li><a #btn_add_contact>Add Contact</a></li>
141
+ </ul>
142
+ </div>
143
+ </div>
144
+
145
+ <!-- pay attention how repeater works in slim -->
146
+ <div class="row">
147
+ <slim-contact-view slim-repeat="model.contacts"></slim-contact-view>
148
+ </div>
149
+ `
150
+ }
151
+
152
+ onCreated ( ) {
153
+ this . model = window . ContactsModel
154
+ this . btn_add_contact . onclick = ( ) => {
155
+ this . model . create ( )
156
+ this . update ( )
157
+ }
158
+
159
+ this . addEventListener ( 'removeContact' , contact => {
160
+ this . model . remove ( contact )
161
+ // this.update()
162
+ } )
163
+ }
164
+
165
+ select ( contact ) {
166
+ this . selected = contact
167
+ }
168
+
169
+ onAfterRender ( ) {
170
+ this . find ( 'slim-repeat' ) . onchange = ( ) => {
171
+ setTimeout ( ( ) => {
172
+ this . model . sort ( )
173
+ // this.update()
174
+ } , 0 )
175
+ }
176
+ }
177
+
178
+ } )
179
+
180
+
181
+
182
+ Slim . tag ( 'slim-contact-view' , class SlimContactView extends Slim {
183
+
184
+ get template ( ) {
185
+ return `
186
+ <div class="row contact-entry">
187
+ <div class="col-xs-1"><input type="button" slim-id="btnRemove" class="btn btn-xs btn-danger" value="X" /> </div>
188
+ <div class="col-xs-4"><slim-editable-input text="[[data.first]]" slim-id="inpFirst"></slim-editable-input> <slim-editable-input text="[[data.last]]" slim-id="inpLast"></slim-editable-input></div>
189
+ <div class="col-xs-3"><slim-editable-input slim-id="inpEmail"></slim-editable-input></div>
190
+ <div class="col-xs-4"><slim-phones slim-id="phones"></slim-phones></div>
191
+ </div>`
192
+ }
193
+
194
+ onCreated ( ) {
195
+ this . inpEmail . text = this . data . email
196
+ this . inpEmail . onchange = ( ) => {
197
+ this . data . email = this . inpEmail . text
198
+ }
199
+ this . inpFirst . onchange = ( ) => {
200
+ this . data . first = this . inpFirst . text
201
+ }
202
+
203
+ this . inpLast . onchange = ( ) => {
204
+ this . data . last = this . inpLast . text
205
+ }
206
+
207
+ this . btnRemove . onclick = ( ) => {
208
+ let e = new Event ( 'removeContact' , { bubbles :true } )
209
+ e . value = this . data
210
+ this . dispatchEvent ( e )
211
+ }
212
+
213
+ this . phones . data = this . data . phones
214
+ }
215
+
216
+
217
+ } )
218
+
219
+ Slim . tag ( 'slim-phones' , class extends Slim {
220
+ get template ( ) {
221
+ return `
222
+ <div class="row"><input slim-id="btnAddPhone" type="button" class="btn btn-xs btn-primary" value="+ Phone" /></div>
223
+ <div class="row"><slim-phone slim-repeat="data"></slim-phone></div>
224
+ `
225
+ }
226
+
227
+ onCreated ( ) {
228
+ this . btnAddPhone . onclick = ( ) => {
229
+ this . data . push ( new window . Phone ( ) )
230
+ this . update ( )
231
+ window . ContactsModel . save ( )
232
+ }
233
+ }
234
+ } )
235
+
236
+ Slim . tag ( 'slim-phone' , class extends Slim {
237
+ get template ( ) {
238
+ return `<div class="col-xs-6"><slim-editable-input slim-id="type"></slim-editable-input></div>
239
+ <div class="col-xs-6"><slim-editable-input slim-id="number"></slim-editable-input></div>`
240
+ }
241
+
242
+ onCreated ( ) {
243
+ this . type . text = this . data . type
244
+ this . number . text = this . data . number
245
+
246
+ this . number . onchange = ( ) => {
247
+ this . data . number = this . number . text
248
+ }
249
+
250
+ this . type . onchange = ( ) => {
251
+ this . data . type = this . type . text
252
+ }
253
+ }
254
+ } )
255
+
256
+
257
+ Slim . tag ( 'slim-editable-input' , class extends Slim {
258
+
259
+ get template ( ) {
260
+ return `<span slim-id="label" bind>[[text]]</span><input slim-id="inp" type="text" value=[[text]] />`
261
+ }
262
+
263
+ onCreated ( ) {
264
+ this . inp . style . display = 'none'
265
+ this . inp . style . position = 'absolute'
266
+ this . inp . style . left = '0'
267
+ this . inp . style . top = '0'
268
+ this . inp . onblur = this . inp . onchange = ( ) => {
269
+ this . text = this . inp . value
270
+ this . setAttribute ( 'text' , this . inp . value )
271
+ this . inp . style . display = 'none'
272
+ this . onchange ( )
273
+ }
274
+ this . label . ondblclick = ( ) => {
275
+ this . inp . style . display = 'initial'
276
+ this . inp . focus ( )
277
+ }
278
+ }
279
+
280
+ } )
281
+
282
+ </ script >
283
+
284
+ < slim-app > </ slim-app >
285
+ </ body >
286
+ </ html >
0 commit comments