@base-framework/base 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/base.min.js +1 -0
  2. package/es5/base.js +2968 -0
  3. package/es5/modules/ajax.js +663 -0
  4. package/es5/modules/animation.js +188 -0
  5. package/es5/modules/animations.js +1080 -0
  6. package/es5/modules/atom.js +65 -0
  7. package/es5/modules/component.js +1310 -0
  8. package/es5/modules/data-binder.js +1131 -0
  9. package/es5/modules/data.js +1808 -0
  10. package/es5/modules/date.js +525 -0
  11. package/es5/modules/form-validator.js +324 -0
  12. package/es5/modules/history.js +126 -0
  13. package/es5/modules/html-builder.js +461 -0
  14. package/es5/modules/layout.js +1679 -0
  15. package/es5/modules/mouse.js +124 -0
  16. package/es5/modules/nav-link.js +123 -0
  17. package/es5/modules/olderversions/animations-ease.js +1095 -0
  18. package/es5/modules/olderversions/animations-update.js +1048 -0
  19. package/es5/modules/olderversions/base-animations.js +636 -0
  20. package/es5/modules/olderversions/base-component-class.js +100 -0
  21. package/es5/modules/olderversions/base-data-binder-1.js +407 -0
  22. package/es5/modules/olderversions/base-data-binder-class.js +358 -0
  23. package/es5/modules/olderversions/base-layout-parser-class.js +172 -0
  24. package/es5/modules/olderversions/base-mode-1.js +777 -0
  25. package/es5/modules/olderversions/base-model-class.js +585 -0
  26. package/es5/modules/olderversions/data-binder/element-binding/base-data-binder-class.js +358 -0
  27. package/es5/modules/olderversions/data-binder/element-binding/base-model-class.js +585 -0
  28. package/es5/modules/olderversions/data-binder/model-binding/base-data-binder-class.js +353 -0
  29. package/es5/modules/olderversions/data-binder/model-binding/base-model-class.js +604 -0
  30. package/es5/modules/olderversions/data-binder-update-watcher.js +640 -0
  31. package/es5/modules/olderversions/data-tracker.js +187 -0
  32. package/es5/modules/olderversions/event-update.js +666 -0
  33. package/es5/modules/olderversions/nav-link.js +119 -0
  34. package/es5/modules/olderversions/router-with-templates-1.js +785 -0
  35. package/es5/modules/olderversions/router-with-templates.js +701 -0
  36. package/es5/modules/prototypes/ajax.js +657 -0
  37. package/es5/modules/prototypes/atom.js +65 -0
  38. package/es5/modules/prototypes/component.js +972 -0
  39. package/es5/modules/prototypes/data-binder.js +1089 -0
  40. package/es5/modules/prototypes/data.js +1290 -0
  41. package/es5/modules/prototypes/html-builder.js +414 -0
  42. package/es5/modules/prototypes/layout.js +879 -0
  43. package/es5/modules/router.js +1680 -0
  44. package/es5/modules/state.js +274 -0
  45. package/es6/.jshintrc +3 -0
  46. package/es6/base.js +41 -0
  47. package/es6/core.js +1 -0
  48. package/es6/data-tracker.js +351 -0
  49. package/es6/events.js +602 -0
  50. package/es6/legacy/es5/base.js +2968 -0
  51. package/es6/legacy/es5/modules/ajax.js +663 -0
  52. package/es6/legacy/es5/modules/animation.js +188 -0
  53. package/es6/legacy/es5/modules/animations.js +1080 -0
  54. package/es6/legacy/es5/modules/atom.js +65 -0
  55. package/es6/legacy/es5/modules/component.js +1310 -0
  56. package/es6/legacy/es5/modules/data-binder.js +1131 -0
  57. package/es6/legacy/es5/modules/data.js +1808 -0
  58. package/es6/legacy/es5/modules/date.js +525 -0
  59. package/es6/legacy/es5/modules/form-validator.js +324 -0
  60. package/es6/legacy/es5/modules/history.js +126 -0
  61. package/es6/legacy/es5/modules/html-builder.js +461 -0
  62. package/es6/legacy/es5/modules/layout.js +1679 -0
  63. package/es6/legacy/es5/modules/mouse.js +124 -0
  64. package/es6/legacy/es5/modules/nav-link.js +123 -0
  65. package/es6/legacy/es5/modules/olderversions/animations-ease.js +1095 -0
  66. package/es6/legacy/es5/modules/olderversions/animations-update.js +1048 -0
  67. package/es6/legacy/es5/modules/olderversions/base-animations.js +636 -0
  68. package/es6/legacy/es5/modules/olderversions/base-component-class.js +100 -0
  69. package/es6/legacy/es5/modules/olderversions/base-data-binder-1.js +407 -0
  70. package/es6/legacy/es5/modules/olderversions/base-data-binder-class.js +358 -0
  71. package/es6/legacy/es5/modules/olderversions/base-layout-parser-class.js +172 -0
  72. package/es6/legacy/es5/modules/olderversions/base-mode-1.js +777 -0
  73. package/es6/legacy/es5/modules/olderversions/base-model-class.js +585 -0
  74. package/es6/legacy/es5/modules/olderversions/data-binder/element-binding/base-data-binder-class.js +358 -0
  75. package/es6/legacy/es5/modules/olderversions/data-binder/element-binding/base-model-class.js +585 -0
  76. package/es6/legacy/es5/modules/olderversions/data-binder/model-binding/base-data-binder-class.js +353 -0
  77. package/es6/legacy/es5/modules/olderversions/data-binder/model-binding/base-model-class.js +604 -0
  78. package/es6/legacy/es5/modules/olderversions/data-binder-update-watcher.js +640 -0
  79. package/es6/legacy/es5/modules/olderversions/data-tracker.js +187 -0
  80. package/es6/legacy/es5/modules/olderversions/event-update.js +666 -0
  81. package/es6/legacy/es5/modules/olderversions/nav-link.js +119 -0
  82. package/es6/legacy/es5/modules/olderversions/router-with-templates-1.js +785 -0
  83. package/es6/legacy/es5/modules/olderversions/router-with-templates.js +701 -0
  84. package/es6/legacy/es5/modules/prototypes/ajax.js +657 -0
  85. package/es6/legacy/es5/modules/prototypes/atom.js +65 -0
  86. package/es6/legacy/es5/modules/prototypes/component.js +972 -0
  87. package/es6/legacy/es5/modules/prototypes/data-binder.js +1089 -0
  88. package/es6/legacy/es5/modules/prototypes/data.js +1290 -0
  89. package/es6/legacy/es5/modules/prototypes/html-builder.js +414 -0
  90. package/es6/legacy/es5/modules/prototypes/layout.js +879 -0
  91. package/es6/legacy/es5/modules/router.js +1680 -0
  92. package/es6/legacy/es5/modules/state.js +274 -0
  93. package/es6/main.js +1331 -0
  94. package/es6/modules/ajax/ajax.js +514 -0
  95. package/es6/modules/animation/animation.js +236 -0
  96. package/es6/modules/animations/animation-controller.js +231 -0
  97. package/es6/modules/animations/animation.js +64 -0
  98. package/es6/modules/animations/attr-movement.js +66 -0
  99. package/es6/modules/animations/css-movement.js +170 -0
  100. package/es6/modules/animations/movement.js +131 -0
  101. package/es6/modules/animations/value.js +187 -0
  102. package/es6/modules/atom/atom.js +54 -0
  103. package/es6/modules/component/component.js +230 -0
  104. package/es6/modules/component/event-helper.js +119 -0
  105. package/es6/modules/component/jot.js +144 -0
  106. package/es6/modules/component/state-helper.js +262 -0
  107. package/es6/modules/component/unit.js +551 -0
  108. package/es6/modules/data/attrs.js +40 -0
  109. package/es6/modules/data/basic-data.js +500 -0
  110. package/es6/modules/data/data-utils.js +29 -0
  111. package/es6/modules/data/data.js +3 -0
  112. package/es6/modules/data/deep-data.js +541 -0
  113. package/es6/modules/data/model-service.js +528 -0
  114. package/es6/modules/data/model.js +133 -0
  115. package/es6/modules/data/simple-data.js +33 -0
  116. package/es6/modules/data-binder/connection-tracker.js +113 -0
  117. package/es6/modules/data-binder/connection.js +16 -0
  118. package/es6/modules/data-binder/data-binder.js +352 -0
  119. package/es6/modules/data-binder/data-pub-sub.js +141 -0
  120. package/es6/modules/data-binder/data-source.js +56 -0
  121. package/es6/modules/data-binder/element-source.js +219 -0
  122. package/es6/modules/data-binder/one-way-connection.js +46 -0
  123. package/es6/modules/data-binder/one-way-source.js +43 -0
  124. package/es6/modules/data-binder/source.js +36 -0
  125. package/es6/modules/data-binder/two-way-connection.js +75 -0
  126. package/es6/modules/data-binder/two-way-source.js +41 -0
  127. package/es6/modules/date/date.js +544 -0
  128. package/es6/modules/history/history.js +89 -0
  129. package/es6/modules/html-builder/html-builder.js +434 -0
  130. package/es6/modules/import/import.js +390 -0
  131. package/es6/modules/layout/layout-builder.js +1269 -0
  132. package/es6/modules/layout/layout-parser.js +134 -0
  133. package/es6/modules/layout/watcher-helper.js +282 -0
  134. package/es6/modules/mouse/mouse.js +114 -0
  135. package/es6/modules/router/component-helper.js +163 -0
  136. package/es6/modules/router/history-controller.js +216 -0
  137. package/es6/modules/router/nav-link.js +124 -0
  138. package/es6/modules/router/route.js +401 -0
  139. package/es6/modules/router/router.js +789 -0
  140. package/es6/modules/router/utils.js +31 -0
  141. package/es6/modules/state/state-target.js +91 -0
  142. package/es6/modules/state/state.js +171 -0
  143. package/es6/package-lock.json +13 -0
  144. package/es6/package.json +28 -0
  145. package/es6/shared/objects.js +99 -0
  146. package/legacy/es5/base.js +2968 -0
  147. package/legacy/es5/modules/ajax.js +663 -0
  148. package/legacy/es5/modules/animation.js +188 -0
  149. package/legacy/es5/modules/animations.js +1080 -0
  150. package/legacy/es5/modules/atom.js +65 -0
  151. package/legacy/es5/modules/component.js +1310 -0
  152. package/legacy/es5/modules/data-binder.js +1131 -0
  153. package/legacy/es5/modules/data.js +1808 -0
  154. package/legacy/es5/modules/date.js +525 -0
  155. package/legacy/es5/modules/form-validator.js +324 -0
  156. package/legacy/es5/modules/history.js +126 -0
  157. package/legacy/es5/modules/html-builder.js +461 -0
  158. package/legacy/es5/modules/layout.js +1679 -0
  159. package/legacy/es5/modules/mouse.js +124 -0
  160. package/legacy/es5/modules/nav-link.js +123 -0
  161. package/legacy/es5/modules/olderversions/animations-ease.js +1095 -0
  162. package/legacy/es5/modules/olderversions/animations-update.js +1048 -0
  163. package/legacy/es5/modules/olderversions/base-animations.js +636 -0
  164. package/legacy/es5/modules/olderversions/base-component-class.js +100 -0
  165. package/legacy/es5/modules/olderversions/base-data-binder-1.js +407 -0
  166. package/legacy/es5/modules/olderversions/base-data-binder-class.js +358 -0
  167. package/legacy/es5/modules/olderversions/base-layout-parser-class.js +172 -0
  168. package/legacy/es5/modules/olderversions/base-mode-1.js +777 -0
  169. package/legacy/es5/modules/olderversions/base-model-class.js +585 -0
  170. package/legacy/es5/modules/olderversions/data-binder/element-binding/base-data-binder-class.js +358 -0
  171. package/legacy/es5/modules/olderversions/data-binder/element-binding/base-model-class.js +585 -0
  172. package/legacy/es5/modules/olderversions/data-binder/model-binding/base-data-binder-class.js +353 -0
  173. package/legacy/es5/modules/olderversions/data-binder/model-binding/base-model-class.js +604 -0
  174. package/legacy/es5/modules/olderversions/data-binder-update-watcher.js +640 -0
  175. package/legacy/es5/modules/olderversions/data-tracker.js +187 -0
  176. package/legacy/es5/modules/olderversions/event-update.js +666 -0
  177. package/legacy/es5/modules/olderversions/nav-link.js +119 -0
  178. package/legacy/es5/modules/olderversions/router-with-templates-1.js +785 -0
  179. package/legacy/es5/modules/olderversions/router-with-templates.js +701 -0
  180. package/legacy/es5/modules/prototypes/ajax.js +657 -0
  181. package/legacy/es5/modules/prototypes/atom.js +65 -0
  182. package/legacy/es5/modules/prototypes/component.js +972 -0
  183. package/legacy/es5/modules/prototypes/data-binder.js +1089 -0
  184. package/legacy/es5/modules/prototypes/data.js +1290 -0
  185. package/legacy/es5/modules/prototypes/html-builder.js +414 -0
  186. package/legacy/es5/modules/prototypes/layout.js +879 -0
  187. package/legacy/es5/modules/router.js +1680 -0
  188. package/legacy/es5/modules/state.js +274 -0
  189. package/package.json +8 -3
  190. package/update +16 -0
@@ -0,0 +1,434 @@
1
+ import {base} from '../../core.js';
2
+ import {dataBinder} from '../data-binder/data-binder.js';
3
+
4
+ const dataTracker = base.dataTracker;
5
+
6
+ const NORMALIZED_NAMES =
7
+ {
8
+ class: 'className',
9
+ text: 'textContent',
10
+ for: 'htmlFor',
11
+ readonly: 'readOnly',
12
+ maxlength: 'maxLength',
13
+ cellspacing: 'cellSpacing',
14
+ rowspan: 'rowSpan',
15
+ colspan: 'colSpan',
16
+ tabindex: 'tabIndex',
17
+ celpadding: 'cellPadding',
18
+ useMap: 'useMap',
19
+ frameborder: 'frameBorder',
20
+ contenteditable: 'contentEditable'
21
+ };
22
+
23
+ /**
24
+ * This will get the javascript property name.
25
+ *
26
+ * @param {string} prop
27
+ * @return {string}
28
+ */
29
+ export const normalizeAttr = (prop) =>
30
+ {
31
+ return NORMALIZED_NAMES[prop] || prop;
32
+ };
33
+
34
+ /**
35
+ * This will remove on from a property.
36
+ *
37
+ * @param {string} prop
38
+ * @return {string}
39
+ */
40
+ export const removeEventPrefix = (prop) =>
41
+ {
42
+ if(typeof prop === 'string' && prop.substring(0, 2) === 'on')
43
+ {
44
+ return prop.substring(2);
45
+ }
46
+ return prop;
47
+ };
48
+
49
+ /**
50
+ * htmlBuilder
51
+ *
52
+ * This will create an html builder object that can create
53
+ * and remove dom elements.
54
+ * @class
55
+ */
56
+ export class htmlBuilder
57
+ {
58
+ /**
59
+ * This will create a new element.
60
+ *
61
+ * @param {string} nodeName The node name.
62
+ * @param {object} attrObject The node attributes.
63
+ * @param {object} container The node container.
64
+ * @param {boolean} [prepend=false] Add to the begining of the container.
65
+ * @return {object} The new element.
66
+ */
67
+ create(nodeName, attrObject, container, prepend)
68
+ {
69
+ let obj = document.createElement(nodeName);
70
+ this._addElementAttrs(obj, attrObject);
71
+
72
+ /* we want to check if the new element should be
73
+ added to the begining or end */
74
+ if(prepend === true)
75
+ {
76
+ this.prepend(container, obj);
77
+ }
78
+ else
79
+ {
80
+ this.append(container, obj);
81
+ }
82
+ return obj;
83
+ }
84
+
85
+ /**
86
+ * This will add the element attributes.
87
+ *
88
+ * @protected
89
+ * @param {object} obj
90
+ * @param {object} attrObject
91
+ */
92
+ _addElementAttrs(obj, attrObject)
93
+ {
94
+ /* we want to check if we have attrributes to add */
95
+ if(!attrObject || typeof attrObject !== 'object')
96
+ {
97
+ return false;
98
+ }
99
+
100
+ /* we need to add the type if set to stop ie
101
+ from removing the value if set after the value is
102
+ added */
103
+ let type = attrObject.type;
104
+ if(typeof type !== 'undefined')
105
+ {
106
+ base.setAttr(obj, 'type', type);
107
+ }
108
+
109
+ /* we want to add each attr to the obj */
110
+ for(var prop in attrObject)
111
+ {
112
+ /* we have already added the type so we need to
113
+ skip if the prop is type */
114
+ if(attrObject.hasOwnProperty(prop) === false || prop === 'type')
115
+ {
116
+ continue;
117
+ }
118
+
119
+ var attrPropValue = attrObject[prop];
120
+
121
+ /* we want to check to add the attr settings
122
+ by property name */
123
+ if(prop === 'innerHTML')
124
+ {
125
+ obj.innerHTML = attrPropValue;
126
+ }
127
+ else if(prop.substring(4, 1) === '-')
128
+ {
129
+ // this will handle data and aria attributes
130
+ base.setAttr(obj, prop, attrPropValue);
131
+ }
132
+ else
133
+ {
134
+ this.addAttr(obj, prop, attrPropValue);
135
+ }
136
+ }
137
+ }
138
+
139
+ /**
140
+ * This will add html to an element.
141
+ *
142
+ * @param {object} obj
143
+ * @param {string} content
144
+ */
145
+ addHtml(obj, content)
146
+ {
147
+ if(typeof content !== 'undefined' && content !== '')
148
+ {
149
+ /* we need to check if we are adding inner
150
+ html content or just a string */
151
+ let pattern = /(?:<[a-z][\s\S]*>)/i;
152
+ if(pattern.test(content))
153
+ {
154
+ /* html */
155
+ obj.innerHTML = content;
156
+ }
157
+ else
158
+ {
159
+ /* string */
160
+ obj.textContent = content;
161
+ }
162
+ }
163
+ }
164
+
165
+ /**
166
+ * This will add an element attribute.
167
+ *
168
+ * @param {object} obj
169
+ * @param {object} attr
170
+ * @param {string} value
171
+ */
172
+ addAttr(obj, attr, value)
173
+ {
174
+ if(value === '' || !attr)
175
+ {
176
+ return false;
177
+ }
178
+
179
+ /* we want to check to add a value or an event listener */
180
+ let type = typeof value;
181
+ if(type === 'function')
182
+ {
183
+ /* this will add the event using the base events
184
+ so the event is tracked */
185
+ attr = removeEventPrefix(attr);
186
+ base.addListener(attr, obj, value);
187
+ }
188
+ else
189
+ {
190
+ let attrName = normalizeAttr(attr);
191
+ obj[attrName] = value;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * This will create a doc fragment.
197
+ *
198
+ * @return {object}
199
+ */
200
+ createDocFragment()
201
+ {
202
+ return document.createDocumentFragment();
203
+ }
204
+
205
+ /**
206
+ * This will create a text node.
207
+ *
208
+ * @param {string} text
209
+ * @param {object} container
210
+ * @return {object}
211
+ */
212
+ createTextNode(text, container)
213
+ {
214
+ let obj = document.createTextNode(text);
215
+
216
+ if(container)
217
+ {
218
+ this.append(container, obj);
219
+ }
220
+ return obj;
221
+ }
222
+
223
+ /**
224
+ * This will create a text node.
225
+ *
226
+ * @param {string} text
227
+ * @param {object} container
228
+ * @return {object}
229
+ */
230
+ createCommentNode(text, container)
231
+ {
232
+ let obj = document.createComment(text);
233
+
234
+ if(container)
235
+ {
236
+ this.append(container, obj);
237
+ }
238
+ return obj;
239
+ }
240
+
241
+ /**
242
+ * This will create the options on a select.
243
+ *
244
+ * @param {object} selectElem
245
+ * @param {array} optionArray
246
+ * @param {string} [defaultValue]
247
+ */
248
+ setupSelectOptions(selectElem, optionArray, defaultValue)
249
+ {
250
+ if(!selectElem || typeof selectElem !== 'object')
251
+ {
252
+ return false;
253
+ }
254
+
255
+ if(!optionArray || !optionArray.length)
256
+ {
257
+ return false;
258
+ }
259
+
260
+ /* create each option then add it to the select */
261
+ for(var n = 0, maxLength = optionArray.length; n < maxLength; n++)
262
+ {
263
+ var settings = optionArray[n];
264
+ var option = selectElem.options[n] = new Option(settings.label, settings.value);
265
+
266
+ /* we can select an option if a default value
267
+ has been sumbitted */
268
+ if(defaultValue !== null && option.value == defaultValue)
269
+ {
270
+ option.selected = true;
271
+ }
272
+ }
273
+ }
274
+
275
+ /**
276
+ * This will remove an elements data.
277
+ *
278
+ * @param {object} ele
279
+ */
280
+ removeElementData(ele)
281
+ {
282
+ /* we want to do a recursive remove child
283
+ removal */
284
+ let children = ele.childNodes;
285
+ if(children)
286
+ {
287
+ let length = children.length - 1;
288
+ for(var i = length; i >= 0; i--)
289
+ {
290
+ var child = children[i];
291
+ if(child)
292
+ {
293
+ /* this will remove the child element data
294
+ before the parent is removed */
295
+ this.removeElementData(child);
296
+ }
297
+ }
298
+ }
299
+
300
+ dataTracker.remove(ele);
301
+
302
+ let bound = ele.bindId;
303
+ if(bound)
304
+ {
305
+ /* this will check to remove any data bindings
306
+ to the element */
307
+ dataBinder.unbind(ele);
308
+ }
309
+ }
310
+
311
+ /**
312
+ * This will remove an element and its data.
313
+ *
314
+ * @param {object} obj
315
+ */
316
+ removeElement(obj)
317
+ {
318
+ let container;
319
+
320
+ if(!obj || !(container = obj.parentNode))
321
+ {
322
+ return this;
323
+ }
324
+
325
+ /* this will remove all element data and binding
326
+ and remove from the parent container */
327
+ this.removeElementData(obj);
328
+ container.removeChild(obj);
329
+
330
+ return this;
331
+ }
332
+
333
+ /**
334
+ * This will remove an element.
335
+ *
336
+ * @param {object} child
337
+ */
338
+ removeChild(child)
339
+ {
340
+ this.removeElement(child);
341
+ }
342
+
343
+ /**
344
+ * This will remove all elements from the container.
345
+ *
346
+ * @param {object} container
347
+ */
348
+ removeAll(container)
349
+ {
350
+ if(typeof container === 'object')
351
+ {
352
+ let children = container.childNodes;
353
+ for(var child in children)
354
+ {
355
+ if(children.hasOwnProperty(child))
356
+ {
357
+ this.removeElementData(children[child]);
358
+ }
359
+ }
360
+ container.innerHTML = '';
361
+ }
362
+ }
363
+
364
+ /**
365
+ * This change the parent of an element.
366
+ *
367
+ * @param {object} child
368
+ * @param {object} newParent
369
+ */
370
+ changeParent(child, newParent)
371
+ {
372
+ newParent.appendChild(child);
373
+ }
374
+
375
+ /**
376
+ * This will append a child element.
377
+ *
378
+ * @param {object} parent
379
+ * @param {object} child
380
+ */
381
+ append(parent, child)
382
+ {
383
+ switch(typeof parent)
384
+ {
385
+ case "object":
386
+ break;
387
+ case "undefined":
388
+ parent = document.body;
389
+ break;
390
+ }
391
+
392
+ parent.appendChild(child);
393
+ }
394
+
395
+ /**
396
+ * This will prepend a child element.
397
+ *
398
+ * @param {object} parent
399
+ * @param {object} child
400
+ * @param {object} [optionalNode]
401
+ */
402
+ prepend(parent, child, optionalNode)
403
+ {
404
+ switch(typeof parent)
405
+ {
406
+ case "object":
407
+ break;
408
+ case "undefined":
409
+ parent = document.body;
410
+ break;
411
+ }
412
+
413
+ var node = optionalNode || parent.firstChild;
414
+ parent.insertBefore(child, node);
415
+ }
416
+
417
+ /**
418
+ * This will clone an element.
419
+ *
420
+ * @param {object} node
421
+ * @param {boolean} deepCopy
422
+ * @return {object}
423
+ */
424
+ clone(node, deepCopy)
425
+ {
426
+ if(!node || typeof node !== 'object')
427
+ {
428
+ return false;
429
+ }
430
+
431
+ deepCopy = deepCopy || false;
432
+ return node.cloneNode(deepCopy);
433
+ }
434
+ }