@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,1808 @@
1
+ /* base framework module */
2
+ (function()
3
+ {
4
+ "use strict";
5
+
6
+ /**
7
+ * This will get the data attribute settings.
8
+ *
9
+ * @param {object} settings
10
+ * @return {object}
11
+ */
12
+ var setupAttrSettings = function(settings)
13
+ {
14
+ var attributes = {};
15
+ if(!settings && typeof settings !== 'object')
16
+ {
17
+ return attributes;
18
+ }
19
+
20
+ settings = base.cloneObject(settings);
21
+
22
+ for(var prop in settings)
23
+ {
24
+ if(settings.hasOwnProperty(prop))
25
+ {
26
+ var setting = settings[prop];
27
+ if(typeof setting !== 'function')
28
+ {
29
+ attributes[prop] = setting;
30
+ delete settings[prop];
31
+ }
32
+ }
33
+ }
34
+ return attributes;
35
+ };
36
+
37
+ var DataUtils =
38
+ {
39
+ deepDataPattern: /(\w+)|(?:\[(\d)\))/g,
40
+
41
+ /**
42
+ * This will check if a string has deep data.
43
+ *
44
+ * @param {string} str
45
+ * @return {bool}
46
+ */
47
+ hasDeepData: function(str)
48
+ {
49
+ return (str.indexOf('.') !== -1 || str.indexOf('[') !== -1);
50
+ },
51
+
52
+ /**
53
+ * This will get the deep data segments
54
+ * @param {string} str
55
+ * @return {array}
56
+ */
57
+ getSegments: function(str)
58
+ {
59
+ var pattern = this.deepDataPattern;
60
+ return str.match(pattern);
61
+ }
62
+ };
63
+
64
+ var BasicData = base.Class.extend(
65
+ {
66
+ isData: true,
67
+
68
+ /**
69
+ * @constructor
70
+ * @param {object} [settings]
71
+ */
72
+ constructor: function(settings)
73
+ {
74
+ this.dirty = false;
75
+ this.links = {};
76
+
77
+ this._init();
78
+ this.setup();
79
+
80
+ /* this will setup the event sub for
81
+ one way binding */
82
+ this.eventSub = new base.DataPubSub();
83
+
84
+ /* this will set the construct attributes */
85
+ var attributes = setupAttrSettings(settings);
86
+ this.set(attributes);
87
+ },
88
+
89
+ setup: function()
90
+ {
91
+ this.stage = {};
92
+ },
93
+
94
+ /**
95
+ * @member {string} dataTypeId
96
+ */
97
+ dataTypeId: 'bd',
98
+
99
+ /**
100
+ * This will setup the number and unique id of the data object.
101
+ * @protected
102
+ */
103
+ _init: function()
104
+ {
105
+ var constructor = this.constructor;
106
+ this._dataNumber = (typeof constructor._dataNumber === 'undefined')? constructor._dataNumber = 0 : (++constructor._dataNumber);
107
+
108
+ var dataId = this.dataTypeId + '-';
109
+ this._id = dataId + this._dataNumber;
110
+ this._dataId = this._id + ':';
111
+ },
112
+
113
+ /**
114
+ * This will get the data id.
115
+ * @return {string}
116
+ */
117
+ getDataId: function()
118
+ {
119
+ return this._id;
120
+ },
121
+
122
+ /**
123
+ * This is a placeholder.
124
+ */
125
+ remove: function()
126
+ {
127
+
128
+ },
129
+
130
+ /**
131
+ * This will setup a one way bind.
132
+ *
133
+ * @param {string} attrName
134
+ * @param {function} callBack
135
+ * @return {string} The subscription token.
136
+ */
137
+ on: function(attrName, callBack)
138
+ {
139
+ var message = attrName + ':change';
140
+ var token = this.eventSub.on(message, callBack);
141
+ return token;
142
+ },
143
+
144
+ /**
145
+ * This will unbind from a one way bind.
146
+ *
147
+ * @param {string} attrName
148
+ * @param {string} token
149
+ */
150
+ off: function(attrName, token)
151
+ {
152
+ var message = attrName + ':change';
153
+ this.eventSub.off(message, token);
154
+ },
155
+
156
+ /**
157
+ * This will set the attribute value.
158
+ *
159
+ * @protected
160
+ * @param {string} attr
161
+ * @param {*} val
162
+ * @param {object} committer
163
+ */
164
+ _setAttr: function(attr, val, committer)
165
+ {
166
+ var prevValue = this.stage[attr];
167
+ if(val === prevValue)
168
+ {
169
+ return false;
170
+ }
171
+
172
+ this.stage[attr] = val;
173
+
174
+ committer = committer || this;
175
+
176
+ /* this will publish the data to the data binder
177
+ to update any ui elements that are subscribed */
178
+ this._publish(attr, val, committer, prevValue);
179
+ },
180
+
181
+ /**
182
+ * This will set the data value of an attribute or attributes.
183
+ *
184
+ * @param {string} key
185
+ * @param {*} value
186
+ *
187
+ * or
188
+ *
189
+ * @param {object} data
190
+ * @return {object} this
191
+ */
192
+ set: function()
193
+ {
194
+ var args = arguments;
195
+ if(typeof args[0] === 'object')
196
+ {
197
+ var items = args[0],
198
+ committer = args[1],
199
+ stopMerge = args[2];
200
+
201
+ for(var attr in items)
202
+ {
203
+ if(items.hasOwnProperty(attr))
204
+ {
205
+ var item = items[attr];
206
+ if(typeof item === 'function')
207
+ {
208
+ continue;
209
+ }
210
+ this._setAttr(attr, item, committer, stopMerge);
211
+ }
212
+ }
213
+ }
214
+ else
215
+ {
216
+ this._setAttr(args[0], args[1], args[2], args[3]);
217
+ }
218
+ return this;
219
+ },
220
+
221
+ /**
222
+ * This will get the model data.
223
+ */
224
+ getModelData: function()
225
+ {
226
+ return this.stage;
227
+ },
228
+
229
+ /**
230
+ * This will toggle a bool attribute.
231
+ *
232
+ * @param {string} attr
233
+ * @return {object} this
234
+ */
235
+ toggle: function(attr)
236
+ {
237
+ if(typeof attr === 'undefined')
238
+ {
239
+ return;
240
+ }
241
+
242
+ this.set(attr, !this.get(attr));
243
+ return this;
244
+ },
245
+
246
+ /**
247
+ * This will increment an attribute.
248
+ *
249
+ * @param {string} attr
250
+ * @return {object} this
251
+ */
252
+ increment: function(attr)
253
+ {
254
+ if(typeof attr === 'undefined')
255
+ {
256
+ return;
257
+ }
258
+
259
+ var val = this.get(attr);
260
+ this.set(attr, ++val);
261
+ return this;
262
+ },
263
+
264
+ /**
265
+ * This will decrement an attribute.
266
+ *
267
+ * @param {string} attr
268
+ * @return {object} this
269
+ */
270
+ decrement: function(attr)
271
+ {
272
+ if(typeof attr === 'undefined')
273
+ {
274
+ return;
275
+ }
276
+
277
+ var val = this.get(attr);
278
+ this.set(attr, --val);
279
+ return this;
280
+ },
281
+
282
+ /**
283
+ * This will set the key value if it is null.
284
+ *
285
+ * @param {string} key
286
+ * @param {mixed} value
287
+ * @return {object} this
288
+ */
289
+ ifNull: function(key, value)
290
+ {
291
+ if(this.get(key) === null)
292
+ {
293
+ this.set(key, value);
294
+ }
295
+ return this;
296
+ },
297
+
298
+ /**
299
+ * This will set the data local storage key.
300
+ *
301
+ * @param {string} key
302
+ */
303
+ setKey: function(key)
304
+ {
305
+ this.key = key;
306
+ },
307
+
308
+ /**
309
+ * This will restore the data from local storage.
310
+ *
311
+ * @param {mixed} defaultValue
312
+ * @returns {bool|void}
313
+ */
314
+ resume: function(defaultValue)
315
+ {
316
+ var key = this.key;
317
+ if(!key)
318
+ {
319
+ return false;
320
+ }
321
+
322
+ var data;
323
+ var value = localStorage.getItem(key);
324
+ if(value === null)
325
+ {
326
+ if(defaultValue)
327
+ {
328
+ data = defaultValue;
329
+ }
330
+ }
331
+ else
332
+ {
333
+ data = JSON.parse(value);
334
+ }
335
+
336
+ this.set(data);
337
+ },
338
+
339
+ /**
340
+ * This will store the data to the local stoage under
341
+ * the storage key.
342
+ *
343
+ * @returns {bool|void}
344
+ */
345
+ store: function()
346
+ {
347
+ var key = this.key;
348
+ if(!key)
349
+ {
350
+ return false;
351
+ }
352
+
353
+ var data = this.get();
354
+ if(!data)
355
+ {
356
+ return false;
357
+ }
358
+
359
+ var value = JSON.stringify(data);
360
+ localStorage.setItem(key, value);
361
+ },
362
+
363
+ /**
364
+ * This will delete an attribute.
365
+ *
366
+ * @param {object} obj
367
+ * @param {string} attr
368
+ * @return {*}
369
+ */
370
+ _deleteAttr: function(obj, attr)
371
+ {
372
+ delete obj[attr];
373
+ },
374
+
375
+ /**
376
+ * This will delete a property value or the model data.
377
+ *
378
+ * @param {string} [attrName]
379
+ * @return {*}
380
+ */
381
+ delete: function(attrName)
382
+ {
383
+ if(typeof attrName !== 'undefined')
384
+ {
385
+ this._deleteAttr(this.stage, attrName);
386
+ return;
387
+ }
388
+
389
+ // this will clear the stage and attributes
390
+ this.setup();
391
+ },
392
+
393
+ /**
394
+ * This will get the value of an attribute.
395
+ *
396
+ * @param {object} obj
397
+ * @param {string} attr
398
+ * @return {*}
399
+ */
400
+ _getAttr: function(obj, attr)
401
+ {
402
+ return obj[attr];
403
+ },
404
+
405
+ /**
406
+ * This will get a property value or the model data.
407
+ *
408
+ * @param {string} [attrName]
409
+ * @return {*}
410
+ */
411
+ get: function(attrName)
412
+ {
413
+ if(typeof attrName !== 'undefined')
414
+ {
415
+ return this._getAttr(this.stage, attrName);
416
+ }
417
+ else
418
+ {
419
+ return this.getModelData();
420
+ }
421
+ },
422
+
423
+ /**
424
+ * This will link a data source property to another data source.
425
+ *
426
+ * @param {object} data
427
+ * @param {string|object} attr
428
+ * @param {string} alias
429
+ * @return {string|array}
430
+ */
431
+ link: function(data, attr, alias)
432
+ {
433
+ // this will get the data source attrs if sending a whole data object
434
+ if(arguments.length === 1 && data.isData === true)
435
+ {
436
+ attr = data.get();
437
+ }
438
+
439
+ if(typeof attr !== 'object')
440
+ {
441
+ return this.remoteLink(data, attr, alias);
442
+ }
443
+
444
+ var tokens = [];
445
+ for(var prop in attr)
446
+ {
447
+ if(attr.hasOwnProperty(prop) === false)
448
+ {
449
+ continue;
450
+ }
451
+
452
+ tokens.push(this.remoteLink(data, prop));
453
+ }
454
+ return tokens;
455
+ },
456
+
457
+ /**
458
+ * This will link a remote data source by property.
459
+ *
460
+ * @param {object} data
461
+ * @param {string} attr
462
+ * @param {string} alias
463
+ * @return {string}
464
+ */
465
+ remoteLink: function(data, attr, alias)
466
+ {
467
+ var childAttr = alias || attr;
468
+ var value = data.get(attr);
469
+ if(typeof value !== 'undefined' && this.get(attr) !== value)
470
+ {
471
+ this.set(attr, value);
472
+ }
473
+
474
+ var self = this;
475
+ var token = data.on(attr, function(propValue, committer)
476
+ {
477
+ if(committer === self)
478
+ {
479
+ return false;
480
+ }
481
+
482
+ self.set(childAttr, propValue, data);
483
+ });
484
+
485
+ this.addLink(token, data);
486
+
487
+ var remoteToken = this.on(childAttr, function(propValue, committer)
488
+ {
489
+ if(committer === data)
490
+ {
491
+ return false;
492
+ }
493
+
494
+ data.set(attr, propValue, self);
495
+ });
496
+
497
+ data.addLink(remoteToken, this);
498
+ return token;
499
+ },
500
+
501
+ /**
502
+ * This will add a link token to the links array.
503
+ *
504
+ * @param {string} token
505
+ * @param {object} data
506
+ */
507
+ addLink: function(token, data)
508
+ {
509
+ this.links[token] = data;
510
+ },
511
+
512
+ /**
513
+ * This will remove a link or all links.
514
+ *
515
+ * @param {string} [token]
516
+ */
517
+ unlink: function(token)
518
+ {
519
+ if(token)
520
+ {
521
+ this.removeLink(token);
522
+ return;
523
+ }
524
+
525
+ var links = this.links;
526
+ if(links.length)
527
+ {
528
+ for(var i = 0, length = links.length; i < length; i++)
529
+ {
530
+ this.removeLink(links[i], false);
531
+ }
532
+ this.links = [];
533
+ }
534
+ },
535
+
536
+ /**
537
+ * This will remove the linked subscription.
538
+ *
539
+ * @param {string} token
540
+ * @param {bool} removeFromLinks
541
+ */
542
+ removeLink: function(token, removeFromLinks)
543
+ {
544
+ var data = this.links[token];
545
+ if(data)
546
+ {
547
+ data.off(token);
548
+ }
549
+
550
+ if(removeFromLinks === false)
551
+ {
552
+ return;
553
+ }
554
+
555
+ delete this.links[token];
556
+ }
557
+ });
558
+
559
+ var DataBinder = base.DataBinder;
560
+
561
+
562
+ /**
563
+ * Data
564
+ *
565
+ * This will create a new data object that can be used to
566
+ * bind elements to values.
567
+ * @class
568
+ * @augments BasicData
569
+ */
570
+ var Data = BasicData.extend(
571
+ {
572
+ /**
573
+ * This will setup the stage and attributes object.
574
+ */
575
+ setup: function()
576
+ {
577
+ this.attributes = {};
578
+ this.stage = {};
579
+ },
580
+
581
+ /**
582
+ * This will update an attribute value.
583
+ *
584
+ * @protected
585
+ * @param {object} obj
586
+ * @param {string} attr
587
+ * @param {*} val
588
+ */
589
+ _updateAttr: function(obj, attr, val)
590
+ {
591
+ var utils = DataUtils;
592
+ /* this will check if we need to update
593
+ deep nested data */
594
+ if(utils.hasDeepData(attr))
595
+ {
596
+ var prop,
597
+ props = utils.getSegments(attr),
598
+ length = props.length,
599
+ end = length - 1;
600
+
601
+ for (var i = 0; i < length; i++)
602
+ {
603
+ prop = props[i];
604
+
605
+ /* this will add the value to the last prop */
606
+ if(i === end)
607
+ {
608
+ obj[prop] = val;
609
+ break;
610
+ }
611
+
612
+ if (obj[prop] === undefined)
613
+ {
614
+ /* this will check to setup a new object
615
+ or an array if the prop is a number */
616
+ obj[prop] = isNaN(prop)? {} : [];
617
+ }
618
+ obj = obj[prop];
619
+ }
620
+ }
621
+ else
622
+ {
623
+ obj[attr] = val;
624
+ }
625
+ },
626
+
627
+ /**
628
+ * This will set the attribute value.
629
+ *
630
+ * @protected
631
+ * @param {string} attr
632
+ * @param {*} val
633
+ * @param {object} committer
634
+ * @param {boolean} stopMerge
635
+ */
636
+ _setAttr: function(attr, val, committer, stopMerge)
637
+ {
638
+ if(typeof val !== 'object' && val === this.get(attr))
639
+ {
640
+ return;
641
+ }
642
+
643
+ /* this will check to update the model based on who
644
+ updated it. if the data binder updated the data only
645
+ the stage data is updated */
646
+ if(!committer && stopMerge !== true)
647
+ {
648
+ /* this will update the attribute data because
649
+ it was updated outside the data binder */
650
+ this._updateAttr(this.attributes, attr, val);
651
+ }
652
+ else
653
+ {
654
+ if(this.dirty === false)
655
+ {
656
+ this.dirty = true;
657
+ }
658
+ }
659
+
660
+ this._updateAttr(this.stage, attr, val);
661
+
662
+ /* this will publish the data to the data binder
663
+ to update any ui elements that are subscribed */
664
+ committer = committer || this;
665
+ this._publish(attr, val, committer);
666
+ },
667
+
668
+ /**
669
+ * This will link a data attr object to another data object.
670
+ *
671
+ * @param {object} data
672
+ * @param {string} attr
673
+ */
674
+ linkAttr: function(data, attr)
675
+ {
676
+ var value = data.get(attr);
677
+ if(value)
678
+ {
679
+ for(var prop in value)
680
+ {
681
+ if(value.hasOwnProperty(prop))
682
+ {
683
+ this.link(data, attr + '.' + prop, prop);
684
+ }
685
+ }
686
+ }
687
+ },
688
+
689
+ /**
690
+ * This will create a new data source by scoping the parent
691
+ * data attr and linking the two sources.
692
+ *
693
+ * @param {string} attr
694
+ * @param {object} [constructor]
695
+ * @returns {object}
696
+ */
697
+ scope: function(attr, constructor)
698
+ {
699
+ var value = this.get(attr);
700
+ if(!value)
701
+ {
702
+ return false;
703
+ }
704
+
705
+ constructor = constructor || this.constructor;
706
+ var data = new constructor(value);
707
+
708
+ /* this will link the new data to the parent attr */
709
+ data.linkAttr(this, attr);
710
+ return data;
711
+ },
712
+
713
+ /**
714
+ * This will splice a value from an array and set
715
+ * the result.
716
+ *
717
+ * @param {string} attr
718
+ * @param {int} index
719
+ * @return {object} this
720
+ */
721
+ splice: function(attr, index)
722
+ {
723
+ this.delete(attr + '[' + index + ']');
724
+ this.refresh(attr);
725
+
726
+ return this;
727
+ },
728
+
729
+ /**
730
+ * This will add a value to an array and set the result.
731
+ *
732
+ * @param {string} attr
733
+ * @param {mixed} value
734
+ * @return {object} this
735
+ */
736
+ push: function(attr, value)
737
+ {
738
+ var currentValue = this.get(attr);
739
+ if(Array.isArray(currentValue) === false)
740
+ {
741
+ currentValue = [];
742
+ }
743
+
744
+ currentValue.push(value);
745
+ this.set(attr, currentValue);
746
+ return this;
747
+ },
748
+
749
+ /**
750
+ * This will add a value to an array and set the result.
751
+ *
752
+ * @param {string} attr
753
+ * @param {mixed} value
754
+ * @return {object} this
755
+ */
756
+ unshift: function(attr, value)
757
+ {
758
+ var currentValue = this.get(attr);
759
+ if(Array.isArray(currentValue) === false)
760
+ {
761
+ currentValue = [];
762
+ }
763
+
764
+ currentValue.unshift(value);
765
+ this.set(attr, currentValue);
766
+ return this;
767
+ },
768
+
769
+ /**
770
+ * This will add a value to an array and set the result.
771
+ *
772
+ * @param {string} attr
773
+ * @return {mixed} this
774
+ */
775
+ shift: function(attr)
776
+ {
777
+ var currentValue = this.get(attr);
778
+ if(Array.isArray(currentValue) === false)
779
+ {
780
+ return null;
781
+ }
782
+
783
+ var value = currentValue.shift();
784
+ this.set(attr, currentValue);
785
+ return value;
786
+ },
787
+
788
+ /**
789
+ * This will pop the last value from an array and set the result.
790
+ *
791
+ * @param {string} attr
792
+ * @return {mixed}
793
+ */
794
+ pop: function(attr)
795
+ {
796
+ var currentValue = this.get(attr);
797
+ if(Array.isArray(currentValue) === false)
798
+ {
799
+ return null;
800
+ }
801
+
802
+ var value = currentValue.pop();
803
+ this.set(attr, currentValue);
804
+ return value;
805
+ },
806
+
807
+ /**
808
+ * This will refresh the value.
809
+ *
810
+ * @param {string} attr
811
+ * @return {object} this
812
+ */
813
+ refresh: function(attr)
814
+ {
815
+ this.set(attr, this.get(attr));
816
+
817
+ return this;
818
+ },
819
+
820
+ /**
821
+ * This will publish an update to the data binder.
822
+ *
823
+ * @protected
824
+ * @param {string} attr
825
+ * @param {*} val
826
+ * @param {*} committer
827
+ */
828
+ _publish: function(attr, val, committer)
829
+ {
830
+ this.publish(attr, val, committer);
831
+ },
832
+
833
+ /**
834
+ * This will publish deep and simple data to the data binder.
835
+ *
836
+ * @protected
837
+ * @param {string} attr
838
+ * @param {*} val
839
+ * @param {object} committer
840
+ */
841
+ publishDeep: function(attr, val, committer)
842
+ {
843
+ var utils = DataUtils;
844
+ if(utils.hasDeepData(attr))
845
+ {
846
+ var prop,
847
+ props = utils.getSegments(attr),
848
+ length = props.length,
849
+ end = length - 1;
850
+
851
+ /* the path is a string equivalent of the javascript dot notation path
852
+ of the object being published. */
853
+ var path = '',
854
+ obj = this.stage;
855
+ for (var i = 0; i < length; i++)
856
+ {
857
+ prop = props[i];
858
+
859
+ /* we need to setup the object to go to the next level
860
+ of the data object before calling the next property. */
861
+ obj = obj[prop];
862
+
863
+ if (i > 0)
864
+ {
865
+ /* this will add the property to the path based on if its an
866
+ object property or an array. */
867
+ if(isNaN(prop))
868
+ {
869
+ path += '.' + prop;
870
+ }
871
+ }
872
+ else
873
+ {
874
+ path = prop;
875
+ }
876
+
877
+ var publish;
878
+ if(i === end)
879
+ {
880
+ /* if the loop is on the last pass it only needs to publish
881
+ the val. */
882
+ publish = val;
883
+ }
884
+ else
885
+ {
886
+ /* we only want to publish the modified branches. we need to
887
+ get the next property in the props array and create a publish
888
+ object or array with the next property value. */
889
+ var nextProp = props[i + 1];
890
+ if(isNaN(nextProp) === false)
891
+ {
892
+ path += '[' + nextProp + ']';
893
+ continue;
894
+ }
895
+
896
+ var nextAttr = {};
897
+ nextAttr[nextProp] = obj[nextProp];
898
+ publish = nextAttr;
899
+ }
900
+
901
+ this.publish(path, publish, committer);
902
+ }
903
+ }
904
+ else
905
+ {
906
+ this.publish(attr, val, committer);
907
+ }
908
+ },
909
+
910
+ /**
911
+ * This will publish an update to the data binder.
912
+ *
913
+ * @protected
914
+ * @param {string} pathString
915
+ * @param {*} obj
916
+ * @param {*} committer
917
+ */
918
+ publish: function(pathString, obj, committer)
919
+ {
920
+ pathString = pathString || "";
921
+ this._publishAttr(pathString, obj, committer);
922
+
923
+ if(obj && typeof obj === 'object')
924
+ {
925
+ var subPath, value;
926
+ if(Array.isArray(obj))
927
+ {
928
+ var length = obj.length;
929
+ for(var i = 0; i < length; i++)
930
+ {
931
+ value = obj[i];
932
+ subPath = pathString + '[' + i + ']';
933
+ this._checkPublish(subPath, value, committer);
934
+ }
935
+ }
936
+ else
937
+ {
938
+ for(var prop in obj)
939
+ {
940
+ if(obj.hasOwnProperty(prop))
941
+ {
942
+ value = obj[prop];
943
+ subPath = pathString + '.' + prop;
944
+ this._checkPublish(subPath, value, committer);
945
+ }
946
+ }
947
+ }
948
+ }
949
+ },
950
+
951
+ _checkPublish: function(subPath, val, committer)
952
+ {
953
+ if(!val || typeof val !== 'object')
954
+ {
955
+ this._publishAttr(subPath, val, committer);
956
+ }
957
+ else
958
+ {
959
+ this.publish(subPath, val, committer);
960
+ }
961
+ },
962
+
963
+ /**
964
+ * This will publish an update on an attribute.
965
+ *
966
+ * @protected
967
+ * @param {string} subPath
968
+ * @param {*} val
969
+ * @param {object} committer
970
+ */
971
+ _publishAttr: function(subPath, val, committer)
972
+ {
973
+ /* save path and value */
974
+ DataBinder.publish(this._dataId + subPath, val, committer);
975
+
976
+ var message = subPath + ':change';
977
+ this.eventSub.publish(message, val, committer);
978
+ },
979
+
980
+ /**
981
+ * This will merge the attribute with the stage.
982
+ * @protected
983
+ */
984
+ mergeStage: function()
985
+ {
986
+ /* this will clone the stage object to the
987
+ attribute object */
988
+ this.attributes = base.cloneObject(this.stage);
989
+ this.dirty = false;
990
+ },
991
+
992
+ /**
993
+ * This will get the model data.
994
+ */
995
+ getModelData: function()
996
+ {
997
+ this.mergeStage();
998
+ return this.attributes;
999
+ },
1000
+
1001
+ /**
1002
+ * This will revert the stage back to the previous attributes.
1003
+ */
1004
+ revert: function()
1005
+ {
1006
+ /* this will reset the stage to the previous
1007
+ attributes */
1008
+ this.set(this.attributes);
1009
+ this.dirty = false;
1010
+ },
1011
+
1012
+ /**
1013
+ * This will delete an attribute.
1014
+ *
1015
+ * @param {object} obj
1016
+ * @param {string} attr
1017
+ * @return {*}
1018
+ */
1019
+ _deleteAttr: function(obj, attr)
1020
+ {
1021
+ var utils = DataUtils;
1022
+ if(utils.hasDeepData(attr))
1023
+ {
1024
+ var props = utils.getSegments(attr),
1025
+ length = props.length,
1026
+ end = length - 1;
1027
+
1028
+ for (var i = 0; i < length; i++)
1029
+ {
1030
+ var prop = props[i];
1031
+ var propValue = obj[prop];
1032
+ if (propValue !== undefined)
1033
+ {
1034
+ if(i === end)
1035
+ {
1036
+ if(base.isArray(obj))
1037
+ {
1038
+ obj.splice(prop, 1);
1039
+ break;
1040
+ }
1041
+
1042
+ delete obj[prop];
1043
+ break;
1044
+ }
1045
+ obj = propValue;
1046
+ }
1047
+ else
1048
+ {
1049
+ break;
1050
+ }
1051
+ }
1052
+ }
1053
+ else
1054
+ {
1055
+ delete obj[attr];
1056
+ }
1057
+ },
1058
+
1059
+ /**
1060
+ * This will get the value of an attribute.
1061
+ *
1062
+ * @param {object} obj
1063
+ * @param {string} attr
1064
+ * @return {*}
1065
+ */
1066
+ _getAttr: function(obj, attr)
1067
+ {
1068
+ var utils = DataUtils;
1069
+ if(utils.hasDeepData(attr))
1070
+ {
1071
+ var props = utils.getSegments(attr),
1072
+ length = props.length,
1073
+ end = length - 1;
1074
+
1075
+ for (var i = 0; i < length; i++)
1076
+ {
1077
+ var prop = props[i];
1078
+ var propValue = obj[prop];
1079
+ if (propValue !== undefined)
1080
+ {
1081
+ obj = propValue;
1082
+
1083
+ if(i === end)
1084
+ {
1085
+ return obj;
1086
+ }
1087
+ }
1088
+ else
1089
+ {
1090
+ break;
1091
+ }
1092
+ }
1093
+
1094
+ return undefined;
1095
+ }
1096
+ else
1097
+ {
1098
+ return obj[attr];
1099
+ }
1100
+ }
1101
+ });
1102
+
1103
+ var DeepData = Data.extend(
1104
+ {
1105
+ /**
1106
+ * This will publish an update to the data binder.
1107
+ *
1108
+ * @protected
1109
+ * @param {string} attr
1110
+ * @param {*} val
1111
+ * @param {*} committer
1112
+ */
1113
+ _publish: function(attr, val, committer)
1114
+ {
1115
+ this.publishDeep(attr, val, committer);
1116
+ }
1117
+ });
1118
+
1119
+ base.DeepData = DeepData;
1120
+
1121
+ /**
1122
+ * SimpleData
1123
+ *
1124
+ * This will extend Data to add a simple data object
1125
+ * that doesn't allow deep nested data.
1126
+ * @class
1127
+ * @augments BasicData
1128
+ */
1129
+ var SimpleData = BasicData.extend(
1130
+ {
1131
+ /**
1132
+ * This will publish an update to the data binder.
1133
+ *
1134
+ * @override
1135
+ * @protected
1136
+ * @param {string} attr
1137
+ * @param {*} val
1138
+ * @param {*} committer
1139
+ * @param {*} prevValue
1140
+ */
1141
+ _publish: function(attr, val, committer, prevValue)
1142
+ {
1143
+ var message = attr + ':change';
1144
+ this.eventSub.publish(message, val, committer);
1145
+
1146
+ committer = committer || this;
1147
+
1148
+ DataBinder.publish(this._dataId + attr, val, committer);
1149
+ }
1150
+ });
1151
+
1152
+ base.extend.Data = Data;
1153
+ base.extend.SimpleData = SimpleData;
1154
+
1155
+ /**
1156
+ * Model
1157
+ *
1158
+ * This will extend Data to add a model that can specify
1159
+ * a service that connects to a remote source.
1160
+ */
1161
+ var Model = Data.extend(
1162
+ {
1163
+ /**
1164
+ * @constructor
1165
+ * @param {object} [settings]
1166
+ */
1167
+ constructor: function(settings)
1168
+ {
1169
+ Data.call(this, settings);
1170
+
1171
+ this.initialize();
1172
+
1173
+ /**
1174
+ * @member {object} xhr The model service.
1175
+ */
1176
+ this.xhr = null;
1177
+ },
1178
+
1179
+ /**
1180
+ * This adds a method to call if you want the model
1181
+ * to do something when its initialized.
1182
+ */
1183
+ initialize: function()
1184
+ {
1185
+
1186
+ }
1187
+ });
1188
+
1189
+ /**
1190
+ * This will get the defaults from the settings.
1191
+ *
1192
+ * @param {object} settings
1193
+ * @return {object}
1194
+ */
1195
+ var setupDefaultAttr = function(settings)
1196
+ {
1197
+ var attributes = {};
1198
+ if(!settings || typeof settings !== 'object')
1199
+ {
1200
+ return attributes;
1201
+ }
1202
+
1203
+ var defaults = settings.defaults;
1204
+ if(!defaults)
1205
+ {
1206
+ return attributes;
1207
+ }
1208
+
1209
+ for(var prop in defaults)
1210
+ {
1211
+ if(defaults.hasOwnProperty(prop))
1212
+ {
1213
+ var attr = defaults[prop];
1214
+ if(typeof attr !== 'function')
1215
+ {
1216
+ attributes[prop] = attr;
1217
+ }
1218
+ }
1219
+ }
1220
+ delete settings.defaults;
1221
+ return attributes;
1222
+ };
1223
+
1224
+ /**
1225
+ * This will get the xhr settings.
1226
+ *
1227
+ * @param {object} settings
1228
+ * @return {object}
1229
+ */
1230
+ var getXhr = function(settings)
1231
+ {
1232
+ if(!settings || typeof settings.xhr !== 'object')
1233
+ {
1234
+ return {};
1235
+ }
1236
+
1237
+ var settingsXhr = settings.xhr,
1238
+ xhr = base.createObject(settingsXhr);
1239
+ delete settings.xhr;
1240
+ return xhr;
1241
+ };
1242
+
1243
+ /* this will track the number of model types */
1244
+ var modelTypeNumber = 0;
1245
+
1246
+ /**
1247
+ * This will extend the model to a child model.
1248
+ *
1249
+ * @static
1250
+ * @param {object} settings
1251
+ * @return {object} The new model.
1252
+ */
1253
+ Model.extend = function(settings)
1254
+ {
1255
+ var parent = this,
1256
+ xhr = getXhr(settings),
1257
+ modelService = this.prototype.xhr.extend(xhr);
1258
+
1259
+ settings = settings || {};
1260
+
1261
+ /* this will setup the default attribute settings for
1262
+ the model */
1263
+ var defaultAttributes = setupDefaultAttr(settings),
1264
+ model = function(instanceSettings)
1265
+ {
1266
+ /* this will get the instance attributes that
1267
+ the model will set as attribute data */
1268
+ var instanceAttr = setupAttrSettings(instanceSettings);
1269
+
1270
+ /* we want to extend the default attr with the
1271
+ instance attr before we set the data and call
1272
+ the parent constructor */
1273
+ instanceAttr = base.extendObject(defaultAttributes, instanceAttr);
1274
+ parent.call(this, instanceAttr);
1275
+
1276
+ /* this will setup the model service and
1277
+ pass the new model instance to the service */
1278
+ this.xhr = new modelService(this);
1279
+ };
1280
+
1281
+ /* this will extend the model and add the static
1282
+ methods to the new object */
1283
+ var extended = model.prototype = base.extendClass(this.prototype, settings);
1284
+ extended.constructor = model;
1285
+ extended.xhr = modelService;
1286
+
1287
+ /* this will assign a unique id to the model type */
1288
+ extended.dataTypeId = 'bm' + (modelTypeNumber++);
1289
+
1290
+ /* this will extend the static methods */
1291
+ base.extendObject(parent, model);
1292
+ return model;
1293
+ };
1294
+
1295
+ base.extend.Model = Model;
1296
+
1297
+ /**
1298
+ * ModelService
1299
+ *
1300
+ * This will create a new model service.
1301
+ * @class
1302
+ */
1303
+ var ModelService = base.Class.extend(
1304
+ {
1305
+ /**
1306
+ * @constructor
1307
+ * @param {object} model
1308
+ */
1309
+ constructor: function(model)
1310
+ {
1311
+ /**
1312
+ * @member {object} model
1313
+ */
1314
+ this.model = model;
1315
+
1316
+ this.url = '';
1317
+ this.init();
1318
+ },
1319
+
1320
+ init: function()
1321
+ {
1322
+ var model = this.model;
1323
+ if(model && model.url)
1324
+ {
1325
+ this.url = model.url;
1326
+ }
1327
+ },
1328
+
1329
+ validateCallBack: null,
1330
+
1331
+ /**
1332
+ * This will check if the model is valid.
1333
+ *
1334
+ * @return {boolean}
1335
+ */
1336
+ isValid: function()
1337
+ {
1338
+ var result = this.validate();
1339
+ if(result !== false)
1340
+ {
1341
+ var callBack = this.validateCallBack;
1342
+ if(typeof callBack === 'function')
1343
+ {
1344
+ callBack(result);
1345
+ }
1346
+ }
1347
+ return result;
1348
+ },
1349
+
1350
+ /**
1351
+ * This should be overriden to validate the model
1352
+ * before submitting.
1353
+ *
1354
+ * @return {boolean}
1355
+ */
1356
+ validate: function()
1357
+ {
1358
+ return true;
1359
+ },
1360
+
1361
+ /**
1362
+ * This can be overriden to add default params
1363
+ * with each request.
1364
+ *
1365
+ * @protected
1366
+ * @return {string}
1367
+ */
1368
+ getDefaultParams: function()
1369
+ {
1370
+ return '';
1371
+ },
1372
+
1373
+ /**
1374
+ * This will setup the request params.
1375
+ *
1376
+ * @protected
1377
+ * @param {(string|object)} params
1378
+ * @return {(string|object)}
1379
+ */
1380
+ setupParams: function(params)
1381
+ {
1382
+ var defaults = this.getDefaultParams();
1383
+ params = this.addParams(params, defaults);
1384
+ return params;
1385
+ },
1386
+
1387
+ /**
1388
+ * This will convert an object to a string.
1389
+ *
1390
+ * @protected
1391
+ * @param {object} object
1392
+ * @return {string}
1393
+ */
1394
+ objectToString: function(object)
1395
+ {
1396
+ var params = [];
1397
+ for (var prop in object)
1398
+ {
1399
+ if(object.hasOwnProperty(prop))
1400
+ {
1401
+ params.push(prop + '=' + object[prop]);
1402
+ }
1403
+ }
1404
+ return params.join('&');
1405
+ },
1406
+
1407
+ /**
1408
+ * This will add the params.
1409
+ *
1410
+ * @protected
1411
+ * @param {*} params
1412
+ * @param {*} addingParams
1413
+ * @return {(string|object)}
1414
+ */
1415
+ addParams: function(params, addingParams)
1416
+ {
1417
+ params = params || {};
1418
+ if(typeof params === 'string')
1419
+ {
1420
+ params = base.parseQueryString(params, false);
1421
+ }
1422
+
1423
+ if(!addingParams)
1424
+ {
1425
+ return (!this._isFormData(params))? this.objectToString(params) : params;
1426
+ }
1427
+
1428
+ if(typeof addingParams === 'string')
1429
+ {
1430
+ addingParams = base.parseQueryString(addingParams, false);
1431
+ }
1432
+
1433
+ if(this._isFormData(params))
1434
+ {
1435
+ for(var key in addingParams)
1436
+ {
1437
+ if(addingParams.hasOwnProperty(key))
1438
+ {
1439
+ params.append(key, addingParams[key]);
1440
+ }
1441
+ }
1442
+ }
1443
+ else
1444
+ {
1445
+ params = base.extendObject(params, addingParams);
1446
+ params = this.objectToString(params);
1447
+ }
1448
+
1449
+ return params;
1450
+ },
1451
+
1452
+ /**
1453
+ * @member {string} objectType The return type.
1454
+ */
1455
+ objectType: 'item',
1456
+
1457
+ /**
1458
+ * This will get the model by id.
1459
+ *
1460
+ * @param {string} [instanceParams]
1461
+ * @param {function} [callBack]
1462
+ * @return {object}
1463
+ */
1464
+ get: function(instanceParams, callBack)
1465
+ {
1466
+ var id = this.model.get('id'),
1467
+ params = 'op=get' +
1468
+ '&id=' + id;
1469
+
1470
+ var model = this.model,
1471
+ self = this;
1472
+ return this._get('', params, instanceParams, callBack, function(response)
1473
+ {
1474
+ if(response)
1475
+ {
1476
+ /* this will update the model with the get request
1477
+ response */
1478
+ var object = self.getObject(response);
1479
+ if(object)
1480
+ {
1481
+ model.set(object);
1482
+ }
1483
+ }
1484
+ });
1485
+ },
1486
+
1487
+ /**
1488
+ * This will get the object from the response.
1489
+ *
1490
+ * @protected
1491
+ * @param {object} response
1492
+ * @return {object}
1493
+ */
1494
+ getObject: function(response)
1495
+ {
1496
+ /* this will update the model with the get request
1497
+ response */
1498
+ var object = response[this.objectType] || response;
1499
+ return object || false;
1500
+ },
1501
+
1502
+ /**
1503
+ * This will return a string with the model data json encoded.
1504
+ *
1505
+ * @protected
1506
+ * @return {string}
1507
+ */
1508
+ setupObjectData: function()
1509
+ {
1510
+ var item = this.model.get();
1511
+ return this.objectType + '=' + base.prepareJsonUrl(item);
1512
+ },
1513
+
1514
+ /**
1515
+ * This will add or update the model.
1516
+ *
1517
+ * @param {string} [instanceParams]
1518
+ * @param {function} [callBack]
1519
+ * @return {object}
1520
+ */
1521
+ setup: function(instanceParams, callBack)
1522
+ {
1523
+ if(!this.isValid())
1524
+ {
1525
+ return false;
1526
+ }
1527
+
1528
+ var params = 'op=setup' +
1529
+ '&' + this.setupObjectData();
1530
+
1531
+ /* this will add the instance params with the
1532
+ method params */
1533
+ params = this.addParams(params, instanceParams, instanceParams);
1534
+
1535
+ return this._put('', params, callBack);
1536
+ },
1537
+
1538
+ /**
1539
+ * This will add the model.
1540
+ *
1541
+ * @param {string} [instanceParams]
1542
+ * @param {function} [callBack]
1543
+ * @return {object}
1544
+ */
1545
+ add: function(instanceParams, callBack)
1546
+ {
1547
+ if(!this.isValid())
1548
+ {
1549
+ return false;
1550
+ }
1551
+
1552
+ var params = 'op=add' +
1553
+ '&' + this.setupObjectData();
1554
+
1555
+ return this._post('', params, instanceParams, callBack);
1556
+ },
1557
+
1558
+ /**
1559
+ * This will update the model.
1560
+ *
1561
+ * @param {string} [instanceParams]
1562
+ * @param {function} [callBack]
1563
+ * @return {object}
1564
+ */
1565
+ update: function(instanceParams, callBack)
1566
+ {
1567
+ if(!this.isValid())
1568
+ {
1569
+ return false;
1570
+ }
1571
+
1572
+ var params = 'op=update' +
1573
+ '&' + this.setupObjectData();
1574
+
1575
+ return this._patch('', params, instanceParams, callBack);
1576
+ },
1577
+
1578
+ /**
1579
+ * This will delete the model.
1580
+ *
1581
+ * @param {string} [instanceParams]
1582
+ * @param {function} [callBack]
1583
+ * @return {object}
1584
+ */
1585
+ delete: function(instanceParams, callBack)
1586
+ {
1587
+ var id = this.model.get('id'),
1588
+ params = 'op=delete' +
1589
+ '&id=' + id;
1590
+
1591
+ return this._delete('', params, instanceParams, callBack);
1592
+ },
1593
+
1594
+ /**
1595
+ * This will list rows of the model.
1596
+ *
1597
+ * @param {string} [instanceParams]
1598
+ * @param {function} [callBack]
1599
+ * @param {int} start
1600
+ * @param {int} count
1601
+ * @param {string} filter
1602
+ * @return {object}
1603
+ */
1604
+ all: function(instanceParams, callBack, start, count, filter)
1605
+ {
1606
+ filter = filter || '';
1607
+ start = !isNaN(start)? start : 0;
1608
+ count = !isNaN(count)? count : 50;
1609
+
1610
+ var params = 'op=all' +
1611
+ '&option=' + filter +
1612
+ '&start=' + start +
1613
+ '&stop=' + count;
1614
+
1615
+ return this._get('', params, instanceParams, callBack);
1616
+ },
1617
+
1618
+ getUrl: function(url)
1619
+ {
1620
+ var baseUrl = this.url;
1621
+ if(!url)
1622
+ {
1623
+ return baseUrl;
1624
+ }
1625
+
1626
+ if(url[0] === '?')
1627
+ {
1628
+ return baseUrl + url;
1629
+ }
1630
+
1631
+ return baseUrl += '/' + url;
1632
+ },
1633
+
1634
+ /**
1635
+ * This will make an ajax request.
1636
+ *
1637
+ * @param {string} url
1638
+ * @param {string} method
1639
+ * @param {(string|object)} params
1640
+ * @param {function} callBack
1641
+ * @param {function} [requestCallBack]
1642
+ * @param {object}
1643
+ */
1644
+ setupRequest: function(url, method, params, callBack, requestCallBack)
1645
+ {
1646
+ var self = this,
1647
+ settings = {
1648
+ url: this.getUrl(url),
1649
+ method: method,
1650
+ params: params,
1651
+ completed: function(response, xhr)
1652
+ {
1653
+ if(typeof requestCallBack === 'function')
1654
+ {
1655
+ requestCallBack(response);
1656
+ }
1657
+
1658
+ self.getResponse(response, callBack, xhr);
1659
+ }
1660
+ };
1661
+
1662
+ var overrideHeader = this._isFormData(params);
1663
+ if(overrideHeader)
1664
+ {
1665
+ settings.headers = {};
1666
+ }
1667
+
1668
+ return base.ajax(settings);
1669
+ },
1670
+
1671
+ _isFormData: function(data)
1672
+ {
1673
+ return data instanceof FormData;
1674
+ },
1675
+
1676
+ /**
1677
+ * This will make an ajax request.
1678
+ *
1679
+ * @param {(string|object)} params
1680
+ * @param {string} instanceParams
1681
+ * @param {function} callBack
1682
+ * @param {function} [requestCallBack]
1683
+ * @param {object}
1684
+ */
1685
+ request: function(params, instanceParams, callBack, requestCallBack)
1686
+ {
1687
+ return this._request('', 'POST', params, instanceParams, callBack, requestCallBack);
1688
+ },
1689
+
1690
+ /**
1691
+ * This will make a GET request.
1692
+ *
1693
+ * @param {string} url
1694
+ * @param {(string|object)} params
1695
+ * @param {string} instanceParams
1696
+ * @param {function} callBack
1697
+ * @param {function} [requestCallBack]
1698
+ * @param {object}
1699
+ */
1700
+ _get: function(url, params, instanceParams, callBack, requestCallBack)
1701
+ {
1702
+ params = this.setupParams(params);
1703
+ params = this.addParams(params, instanceParams);
1704
+
1705
+ url = url || '';
1706
+
1707
+ if(params)
1708
+ {
1709
+ url += '?' + params;
1710
+ }
1711
+
1712
+ return this.setupRequest(url, "GET", '', callBack, requestCallBack);
1713
+ },
1714
+
1715
+ /**
1716
+ * This will make a POST request.
1717
+ *
1718
+ * @param {string} url
1719
+ * @param {(string|object)} params
1720
+ * @param {string} instanceParams
1721
+ * @param {function} callBack
1722
+ * @param {function} [requestCallBack]
1723
+ * @param {object}
1724
+ */
1725
+ _post: function(url, params, instanceParams, callBack, requestCallBack)
1726
+ {
1727
+ return this._request(url, 'POST', params, instanceParams, callBack, requestCallBack);
1728
+ },
1729
+
1730
+ /**
1731
+ * This will make a PUT request.
1732
+ *
1733
+ * @param {string} url
1734
+ * @param {(string|object)} params
1735
+ * @param {string} instanceParams
1736
+ * @param {function} callBack
1737
+ * @param {function} [requestCallBack]
1738
+ * @param {object}
1739
+ */
1740
+ _put: function(url, params, instanceParams, callBack, requestCallBack)
1741
+ {
1742
+ return this._request(url, 'PUT', params, instanceParams, callBack, requestCallBack);
1743
+ },
1744
+
1745
+ /**
1746
+ * This will make a PATCH request.
1747
+ *
1748
+ * @param {string} url
1749
+ * @param {(string|object)} params
1750
+ * @param {string} instanceParams
1751
+ * @param {function} callBack
1752
+ * @param {function} [requestCallBack]
1753
+ * @param {object}
1754
+ */
1755
+ _patch: function(url, params, instanceParams, callBack, requestCallBack)
1756
+ {
1757
+ return this._request(url, 'PATCH', params, instanceParams, callBack, requestCallBack);
1758
+ },
1759
+
1760
+ /**
1761
+ * This will make a DELETE request.
1762
+ *
1763
+ * @param {string} url
1764
+ * @param {(string|object)} params
1765
+ * @param {string} instanceParams
1766
+ * @param {function} callBack
1767
+ * @param {function} [requestCallBack]
1768
+ * @param {object}
1769
+ */
1770
+ _delete: function(url, params, instanceParams, callBack, requestCallBack)
1771
+ {
1772
+ return this._request(url, 'DELETE', params, instanceParams, callBack, requestCallBack);
1773
+ },
1774
+
1775
+ /**
1776
+ * This will make an ajax request.
1777
+ *
1778
+ * @param {string} url
1779
+ * @param {string} method
1780
+ * @param {(string|object)} params
1781
+ * @param {string} instanceParams
1782
+ * @param {function} callBack
1783
+ * @param {function} [requestCallBack]
1784
+ * @param {object}
1785
+ */
1786
+ _request: function(url, method, params, instanceParams, callBack, requestCallBack)
1787
+ {
1788
+ params = this.setupParams(params);
1789
+ params = this.addParams(params, instanceParams);
1790
+
1791
+ return this.setupRequest(url, method, params, callBack, requestCallBack);
1792
+ },
1793
+
1794
+ getResponse: function(response, callBack, xhr)
1795
+ {
1796
+ /* this will check to return the response
1797
+ to the callBack function */
1798
+ if(typeof callBack === 'function')
1799
+ {
1800
+ callBack(response, xhr);
1801
+ }
1802
+ }
1803
+ });
1804
+
1805
+ /* we need to add the service object to the
1806
+ model prototype as the xhr service */
1807
+ Model.prototype.xhr = ModelService;
1808
+ })();