@converse/skeletor 0.0.8 → 0.0.9

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 (42) hide show
  1. package/README.md +38 -25
  2. package/dist/skeletor.js +9232 -5096
  3. package/dist/skeletor.js.map +1 -1
  4. package/dist/skeletor.min.js +74 -3
  5. package/dist/skeletor.min.js.map +1 -1
  6. package/package.json +21 -11
  7. package/src/collection.js +540 -395
  8. package/src/drivers/sessionStorage.js +222 -219
  9. package/src/element.js +132 -82
  10. package/src/eventemitter.js +187 -0
  11. package/src/helpers.js +143 -118
  12. package/src/{main.js → index.js} +21 -17
  13. package/src/listening.js +81 -0
  14. package/src/model.js +340 -238
  15. package/src/storage.js +222 -230
  16. package/src/types/collection.d.ts +366 -0
  17. package/src/types/collection.d.ts.map +1 -0
  18. package/src/types/drivers/sessionStorage.d.ts +37 -0
  19. package/src/types/drivers/sessionStorage.d.ts.map +1 -0
  20. package/src/types/element.d.ts +115 -0
  21. package/src/types/element.d.ts.map +1 -0
  22. package/src/types/eventemitter.d.ts +93 -0
  23. package/src/types/eventemitter.d.ts.map +1 -0
  24. package/src/types/helpers.d.ts +62 -0
  25. package/src/types/helpers.d.ts.map +1 -0
  26. package/src/types/index.d.ts +19 -0
  27. package/src/types/index.d.ts.map +1 -0
  28. package/src/types/listening.d.ts +40 -0
  29. package/src/types/listening.d.ts.map +1 -0
  30. package/src/types/model.d.ts +230 -0
  31. package/src/types/model.d.ts.map +1 -0
  32. package/src/types/storage.d.ts +35 -0
  33. package/src/types/storage.d.ts.map +1 -0
  34. package/src/types/utils/events.d.ts +28 -0
  35. package/src/types/utils/events.d.ts.map +1 -0
  36. package/src/utils/events.js +174 -0
  37. package/src/drivers/sessionStorage.js~ +0 -307
  38. package/src/events.js +0 -328
  39. package/src/history.js +0 -301
  40. package/src/overview.js +0 -191
  41. package/src/router.js +0 -119
  42. package/src/view.js +0 -267
package/src/model.js CHANGED
@@ -1,157 +1,217 @@
1
- // Backbone.js 1.4.0
2
- // (c) 2010-2019 Jeremy Ashkenas and DocumentCloud
3
- // Backbone may be freely distributed under the MIT license.
4
-
5
- // Model
6
- // -----
7
- // **Models** are the basic data object in the framework --
8
- // frequently representing a row in a table in a database on your server.
9
- // A discrete chunk of data and a bunch of useful, related methods for
10
- // performing computations and transformations on that data.
11
-
12
- // Create a new model with the specified attributes. A client id (`cid`)
13
- // is automatically generated and assigned for you.
14
-
15
- import {
16
- getResolveablePromise,
17
- getSyncMethod,
18
- inherits,
19
- urlError,
20
- wrapError
21
- } from './helpers.js';
22
- import { Events } from './events.js';
23
- import clone from "lodash-es/clone.js";
24
- import defaults from "lodash-es/defaults.js";
25
- import defer from "lodash-es/defer.js";
26
- import escape from "lodash-es/escape.js";
27
- import extend from "lodash-es/extend.js";
28
- import has from "lodash-es/has.js";
29
- import invert from "lodash-es/invert.js";
30
- import isEmpty from "lodash-es/isEmpty.js";
31
- import isEqual from "lodash-es/isEqual.js";
32
- import iteratee from "lodash-es/iteratee.js";
33
- import omit from "lodash-es/omit.js";
34
- import pick from "lodash-es/pick.js";
35
- import result from "lodash-es/result.js";
36
- import uniqueId from "lodash-es/uniqueId.js";
37
-
38
-
39
- export const Model = function(attributes, options) {
40
- let attrs = attributes || {};
41
- options || (options = {});
42
- this.preinitialize.apply(this, arguments);
43
- this.cid = uniqueId(this.cidPrefix);
44
- this.attributes = {};
45
- if (options.collection) this.collection = options.collection;
46
- if (options.parse) attrs = this.parse(attrs, options) || {};
47
- const default_attrs = result(this, 'defaults');
48
- attrs = defaults(extend({}, default_attrs, attrs), default_attrs);
49
- this.set(attrs, options);
50
- this.changed = {};
51
- this.initialize.apply(this, arguments);
52
- };
53
-
54
- Model.extend = inherits;
55
-
56
- // Attach all inheritable methods to the Model prototype.
57
- Object.assign(Model.prototype, Events, {
58
-
59
- // A hash of attributes whose current and previous value differ.
60
- changed: null,
61
-
62
- // The value returned during the last failed validation.
63
- validationError: null,
64
-
65
- // The default name for the JSON `id` attribute is `"id"`. MongoDB and
66
- // CouchDB users may want to set this to `"_id"`.
67
- idAttribute: 'id',
68
-
69
- // The prefix is used to create the client id which is used to identify models locally.
70
- // You may want to override this if you're experiencing name clashes with model ids.
71
- cidPrefix: 'c',
72
-
73
- // preinitialize is an empty function by default. You can override it with a function
74
- // or object. preinitialize will run before any instantiation logic is run in the Model.
75
- preinitialize: function(){},
76
-
77
- // Initialize is an empty function by default. Override it with your own
78
- // initialization logic.
79
- initialize: function(){},
80
-
81
- // Return a copy of the model's `attributes` object.
82
- toJSON: function(options) {
1
+ import { getResolveablePromise, getSyncMethod, urlError, wrapError } from './helpers.js';
2
+ import clone from 'lodash-es/clone.js';
3
+ import defaults from 'lodash-es/defaults.js';
4
+ import defer from 'lodash-es/defer.js';
5
+ import has from 'lodash-es/has.js';
6
+ import invert from 'lodash-es/invert.js';
7
+ import isEmpty from 'lodash-es/isEmpty.js';
8
+ import isEqual from 'lodash-es/isEqual.js';
9
+ import iteratee from 'lodash-es/iteratee.js';
10
+ import omit from 'lodash-es/omit.js';
11
+ import pick from 'lodash-es/pick.js';
12
+ import result from 'lodash-es/result.js';
13
+ import uniqueId from 'lodash-es/uniqueId.js';
14
+ import EventEmitter from './eventemitter.js';
15
+
16
+ /**
17
+ * @typedef {import('./collection.js').Collection} Collection
18
+ * @typedef {Record.<string, any>} Attributes
19
+ *
20
+ * @typedef {Record.<string, any>} Options
21
+ * @property {boolean} [validate]
22
+ *
23
+ * @typedef {Record.<string, any>} ModelOptions
24
+ * @property {Collection} [collection]
25
+ * @property {boolean} [parse]
26
+ * @property {boolean} [unset]
27
+ * @property {boolean} [silent]
28
+ */
29
+
30
+ /**
31
+ * **Models** are the basic data object in the framework --
32
+ * frequently representing a row in a table in a database on your server.
33
+ * A discrete chunk of data and a bunch of useful, related methods for
34
+ * performing computations and transformations on that data.
35
+ */
36
+ class Model extends EventEmitter(Object) {
37
+ /**
38
+ * Create a new model with the specified attributes. A client id (`cid`)
39
+ * is automatically generated and assigned for you.
40
+ * @param {Attributes} [attributes]
41
+ * @param {ModelOptions} [options]
42
+ */
43
+ constructor(attributes, options) {
44
+ super();
45
+ let attrs = attributes || {};
46
+ options || (options = {});
47
+ this.preinitialize.apply(this, arguments);
48
+ this.cid = uniqueId(this.cidPrefix);
49
+ this.attributes = {};
50
+
51
+ // The value returned during the last failed validation.
52
+ this.validationError = null;
53
+
54
+ if (options.collection) this.collection = options.collection;
55
+ if (options.parse) attrs = this.parse(attrs, options) || {};
56
+
57
+ const default_attrs = result(this, 'defaults');
58
+ attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
59
+
60
+ this.set(attrs, options);
61
+
62
+ this.initialize.apply(this, arguments);
63
+
64
+ // A hash of attributes whose current and previous value differ.
65
+ this.changed = {};
66
+ }
67
+
68
+ /**
69
+ * @param {Storage} storage
70
+ */
71
+ set browserStorage(storage) {
72
+ this._browserStorage = storage;
73
+ }
74
+
75
+ /**
76
+ * @returns {Storage} storage
77
+ */
78
+ get browserStorage() {
79
+ return this._browserStorage;
80
+ }
81
+
82
+ /**
83
+ * The default name for the JSON `id` attribute is `"id"`. MongoDB and
84
+ * CouchDB users may want to set this to `"_id"` (by overriding this getter
85
+ * in a subclass).
86
+ */
87
+ // eslint-disable-next-line class-methods-use-this
88
+ get idAttribute() {
89
+ return 'id';
90
+ }
91
+
92
+ /**
93
+ * The prefix is used to create the client id which is used to identify models locally.
94
+ * You may want to override this if you're experiencing name clashes with model ids.
95
+ */
96
+ // eslint-disable-next-line class-methods-use-this
97
+ get cidPrefix() {
98
+ return 'c';
99
+ }
100
+
101
+ /**
102
+ * preinitialize is an empty function by default. You can override it with a function
103
+ * or object. preinitialize will run before any instantiation logic is run in the Model.
104
+ */
105
+ // eslint-disable-next-line class-methods-use-this
106
+ preinitialize() {}
107
+
108
+ /**
109
+ * Initialize is an empty function by default. Override it with your own
110
+ * initialization logic.
111
+ * @param {Attributes} [attrs]
112
+ * @param {ModelOptions} [options]
113
+ */
114
+ initialize(attrs, options) {}
115
+
116
+ /**
117
+ * @param {object} attrs
118
+ * @param {object} [options]
119
+ * @returns {string} The validation error message
120
+ */
121
+ validate(attrs, options) {
122
+ return '';
123
+ }
124
+
125
+ /**
126
+ * Return a copy of the model's `attributes` object.
127
+ */
128
+ toJSON() {
83
129
  return clone(this.attributes);
84
- },
130
+ }
85
131
 
86
- // Proxy `Backbone.sync` by default -- but override this if you need
87
- // custom syncing semantics for *this* particular model.
88
- sync: function(method, model, options) {
89
- return getSyncMethod(this)(method, model, options);
90
- },
132
+ /**
133
+ * Override this if you need custom syncing semantics for *this* particular model.
134
+ * @param {'create'|'update'|'patch'|'delete'|'read'} method
135
+ * @param {Model} model
136
+ * @param {Options} options
137
+ */
138
+ // eslint-disable-next-line class-methods-use-this
139
+ sync(method, model, options) {
140
+ return getSyncMethod(model)(method, model, options);
141
+ }
91
142
 
92
- // Get the value of an attribute.
93
- get: function(attr) {
143
+ /**
144
+ * Get the value of an attribute.
145
+ * @param {string} attr
146
+ */
147
+ get(attr) {
94
148
  return this.attributes[attr];
95
- },
149
+ }
96
150
 
97
- keys: function() {
151
+ keys() {
98
152
  return Object.keys(this.attributes);
99
- },
153
+ }
100
154
 
101
- values: function() {
155
+ values() {
102
156
  return Object.values(this.attributes);
103
- },
157
+ }
104
158
 
105
- pairs: function() {
159
+ pairs() {
106
160
  return this.entries();
107
- },
161
+ }
108
162
 
109
- entries: function() {
163
+ entries() {
110
164
  return Object.entries(this.attributes);
111
- },
165
+ }
112
166
 
113
- invert: function() {
167
+ invert() {
114
168
  return invert(this.attributes);
115
- },
169
+ }
116
170
 
117
- pick: function(...args) {
171
+ pick(...args) {
118
172
  if (args.length === 1 && Array.isArray(args[0])) {
119
173
  args = args[0];
120
174
  }
121
175
  return pick(this.attributes, args);
122
- },
176
+ }
123
177
 
124
- omit: function(...args) {
178
+ omit(...args) {
125
179
  if (args.length === 1 && Array.isArray(args[0])) {
126
180
  args = args[0];
127
181
  }
128
182
  return omit(this.attributes, args);
129
- },
183
+ }
130
184
 
131
- isEmpty: function() {
185
+ isEmpty() {
132
186
  return isEmpty(this.attributes);
133
- },
134
-
135
- // Get the HTML-escaped value of an attribute.
136
- escape: function(attr) {
137
- return escape(this.get(attr));
138
- },
187
+ }
139
188
 
140
- // Returns `true` if the attribute contains a value that is not null
141
- // or undefined.
142
- has: function(attr) {
189
+ /**
190
+ * Returns `true` if the attribute contains a value that is not null
191
+ * or undefined.
192
+ * @param {string} attr
193
+ */
194
+ has(attr) {
143
195
  return this.get(attr) != null;
144
- },
196
+ }
145
197
 
146
- // Special-cased proxy to lodash's `matches` method.
147
- matches: function(attrs) {
198
+ /**
199
+ * Special-cased proxy to lodash's `matches` method.
200
+ * @param {Attributes} attrs
201
+ */
202
+ matches(attrs) {
148
203
  return !!iteratee(attrs, this)(this.attributes);
149
- },
204
+ }
150
205
 
151
- // Set a hash of model attributes on the object, firing `"change"`. This is
152
- // the core primitive operation of a model, updating the data and notifying
153
- // anyone who needs to know about the change in state. The heart of the beast.
154
- set: function(key, val, options) {
206
+ /**
207
+ * Set a hash of model attributes on the object, firing `"change"`. This is
208
+ * the core primitive operation of a model, updating the data and notifying
209
+ * anyone who needs to know about the change in state. The heart of the beast.
210
+ * @param {string|Object} key
211
+ * @param {string|Object} [val]
212
+ * @param {Options} [options]
213
+ */
214
+ set(key, val, options) {
155
215
  if (key == null) return this;
156
216
 
157
217
  // Handle both `"key", value` and `{key: value}` -style arguments.
@@ -169,10 +229,10 @@ Object.assign(Model.prototype, Events, {
169
229
  if (!this._validate(attrs, options)) return false;
170
230
 
171
231
  // Extract attributes and options.
172
- const unset = options.unset;
173
- const silent = options.silent;
174
- const changes = [];
175
- const changing = this._changing;
232
+ const unset = options.unset;
233
+ const silent = options.silent;
234
+ const changes = [];
235
+ const changing = this._changing;
176
236
  this._changing = true;
177
237
 
178
238
  if (!changing) {
@@ -182,7 +242,7 @@ Object.assign(Model.prototype, Events, {
182
242
 
183
243
  const current = this.attributes;
184
244
  const changed = this.changed;
185
- const prev = this._previousAttributes;
245
+ const prev = this._previousAttributes;
186
246
 
187
247
  // For each `set` attribute, update or delete the current value.
188
248
  for (const attr in attrs) {
@@ -193,7 +253,7 @@ Object.assign(Model.prototype, Events, {
193
253
  } else {
194
254
  delete changed[attr];
195
255
  }
196
- unset ? delete current[attr] : current[attr] = val;
256
+ unset ? delete current[attr] : (current[attr] = val);
197
257
  }
198
258
 
199
259
  // Update the `id`.
@@ -212,7 +272,7 @@ Object.assign(Model.prototype, Events, {
212
272
  if (changing) return this;
213
273
  if (!silent) {
214
274
  while (this._pending) {
215
- options = this._pending;
275
+ options = /** @type {Options} */ (this._pending);
216
276
  this._pending = false;
217
277
  this.trigger('change', this, options);
218
278
  }
@@ -220,36 +280,52 @@ Object.assign(Model.prototype, Events, {
220
280
  this._pending = false;
221
281
  this._changing = false;
222
282
  return this;
223
- },
283
+ }
224
284
 
225
- // Remove an attribute from the model, firing `"change"`. `unset` is a noop
226
- // if the attribute doesn't exist.
227
- unset: function(attr, options) {
228
- return this.set(attr, undefined, extend({}, options, {unset: true}));
229
- },
285
+ /**
286
+ * Remove an attribute from the model, firing `"change"`. `unset` is a noop
287
+ * if the attribute doesn't exist.
288
+ * @param {string} attr
289
+ * @param {Options} [options]
290
+ */
291
+ unset(attr, options) {
292
+ return this.set(attr, undefined, Object.assign({}, options, { unset: true }));
293
+ }
230
294
 
231
- // Clear all attributes on the model, firing `"change"`.
232
- clear: function(options) {
295
+ /**
296
+ * Clear all attributes on the model, firing `"change"`.
297
+ * @param {Options} options
298
+ */
299
+ clear(options) {
233
300
  const attrs = {};
234
301
  for (const key in this.attributes) attrs[key] = undefined;
235
- return this.set(attrs, extend({}, options, {unset: true}));
236
- },
302
+ return this.set(attrs, Object.assign({}, options, { unset: true }));
303
+ }
237
304
 
238
- // Determine if the model has changed since the last `"change"` event.
239
- // If you specify an attribute name, determine if that attribute has changed.
240
- hasChanged: function(attr) {
305
+ /**
306
+ * Determine if the model has changed since the last `"change"` event.
307
+ * If you specify an attribute name, determine if that attribute has changed.
308
+ * @param {string} [attr]
309
+ */
310
+ hasChanged(attr) {
241
311
  if (attr == null) return !isEmpty(this.changed);
242
312
  return has(this.changed, attr);
243
- },
244
-
245
- // Return an object containing all the attributes that have changed, or
246
- // false if there are no changed attributes. Useful for determining what
247
- // parts of a view need to be updated and/or what attributes need to be
248
- // persisted to the server. Unset attributes will be set to undefined.
249
- // You can also pass an attributes object to diff against the model,
250
- // determining if there *would be* a change.
251
- changedAttributes: function(diff) {
252
- if (!diff) return this.hasChanged() ? clone(this.changed) : false;
313
+ }
314
+
315
+ /**
316
+ * Return an object containing all the attributes that have changed, or
317
+ * false if there are no changed attributes. Useful for determining what
318
+ * parts of a view need to be updated and/or what attributes need to be
319
+ * persisted to the server. Unset attributes will be set to undefined.
320
+ * You can also pass an attributes object to diff against the model,
321
+ * determining if there *would be* a change.
322
+ * @param {Object} diff
323
+ */
324
+ changedAttributes(diff) {
325
+ if (!diff) {
326
+ return this.hasChanged() ? clone(this.changed) : false;
327
+ }
328
+
253
329
  const old = this._changing ? this._previousAttributes : this.attributes;
254
330
  const changed = {};
255
331
  let hasChanged;
@@ -260,51 +336,66 @@ Object.assign(Model.prototype, Events, {
260
336
  hasChanged = true;
261
337
  }
262
338
  return hasChanged ? changed : false;
263
- },
339
+ }
264
340
 
265
- // Get the previous value of an attribute, recorded at the time the last
266
- // `"change"` event was fired.
267
- previous: function(attr) {
341
+ /**
342
+ * Get the previous value of an attribute, recorded at the time the last
343
+ * `"change"` event was fired.
344
+ * @param {string} [attr]
345
+ */
346
+ previous(attr) {
268
347
  if (attr == null || !this._previousAttributes) return null;
269
348
  return this._previousAttributes[attr];
270
- },
349
+ }
271
350
 
272
- // Get all of the attributes of the model at the time of the previous
273
- // `"change"` event.
274
- previousAttributes: function() {
351
+ /**
352
+ * Get all of the attributes of the model at the time of the previous
353
+ * `"change"` event.
354
+ */
355
+ previousAttributes() {
275
356
  return clone(this._previousAttributes);
276
- },
357
+ }
358
+
359
+ /**
360
+ * Fetch the model from the server, merging the response with the model's
361
+ * local attributes. Any changed attributes will trigger a "change" event.
362
+ * @param {Options} [options={}]
363
+ */
364
+ fetch(options={}) {
365
+ options = Object.assign({ parse: true }, options);
277
366
 
278
- // Fetch the model from the server, merging the response with the model's
279
- // local attributes. Any changed attributes will trigger a "change" event.
280
- fetch: function(options) {
281
- options = extend({parse: true}, options);
282
- const model = this;
283
367
  const success = options.success;
284
- options.success = function(resp) {
285
- const serverAttrs = options.parse ? model.parse(resp, options) : resp;
286
- if (!model.set(serverAttrs, options)) return false;
287
- if (success) success.call(options.context, model, resp, options);
288
- model.trigger('sync', model, resp, options);
368
+
369
+ options.success = (resp) => {
370
+ const serverAttrs = options.parse ? this.parse(resp, options) : resp;
371
+ if (!this.set(serverAttrs, options)) return false;
372
+ if (success) success.call(options.context, this, resp, options);
373
+ this.trigger('sync', this, resp, options);
289
374
  };
375
+
290
376
  wrapError(this, options);
291
377
  return this.sync('read', this, options);
292
- },
378
+ }
293
379
 
294
- // Set a hash of model attributes, and sync the model to the server.
295
- // If the server returns an attributes hash that differs, the model's
296
- // state will be `set` again.
297
- save: function(key, val, options) {
380
+ /**
381
+ * Set a hash of model attributes, and sync the model to the server.
382
+ * If the server returns an attributes hash that differs, the model's
383
+ * state will be `set` again.
384
+ * @param {string|Attributes} [key]
385
+ * @param {boolean|number|string|Options} [val]
386
+ * @param {Options} [options]
387
+ */
388
+ save(key, val, options) {
298
389
  // Handle both `"key", value` and `{key: value}` -style arguments.
299
390
  let attrs;
300
391
  if (key == null || typeof key === 'object') {
301
392
  attrs = key;
302
- options = val;
393
+ options = /** @type {Options} */ (val);
303
394
  } else {
304
395
  (attrs = {})[key] = val;
305
396
  }
306
397
 
307
- options = extend({validate: true, parse: true}, options);
398
+ options = Object.assign({ validate: true, parse: true }, options);
308
399
  const wait = options.wait;
309
400
  const return_promise = options.promise;
310
401
  const promise = return_promise && getResolveablePromise();
@@ -314,35 +405,36 @@ Object.assign(Model.prototype, Events, {
314
405
  // the model will be valid when the attributes, if any, are set.
315
406
  if (attrs && !wait) {
316
407
  if (!this.set(attrs, options)) return false;
317
- } else if (!this._validate(attrs, options)) {
408
+ } else if (!this._validate(/** @type {Object} */ (attrs), options)) {
318
409
  return false;
319
410
  }
320
411
 
321
412
  // After a successful server-side save, the client is (optionally)
322
413
  // updated with the server-side state.
323
- const model = this;
324
414
  const success = options.success;
325
415
  const error = options.error;
326
416
  const attributes = this.attributes;
327
- options.success = function(resp) {
417
+
418
+ options.success = (resp) => {
328
419
  // Ensure attributes are restored during synchronous saves.
329
- model.attributes = attributes;
330
- let serverAttrs = options.parse ? model.parse(resp, options) : resp;
331
- if (wait) serverAttrs = extend({}, attrs, serverAttrs);
332
- if (serverAttrs && !model.set(serverAttrs, options)) return false;
333
- if (success) success.call(options.context, model, resp, options);
334
- model.trigger('sync', model, resp, options);
420
+ this.attributes = attributes;
421
+ let serverAttrs = options.parse ? this.parse(resp, options) : resp;
422
+ if (wait) serverAttrs = Object.assign({}, attrs, serverAttrs);
423
+ if (serverAttrs && !this.set(serverAttrs, options)) return false;
424
+ if (success) success.call(options.context, this, resp, options);
425
+ this.trigger('sync', this, resp, options);
335
426
  return_promise && promise.resolve();
336
427
  };
337
- options.error = function(model, e, options) {
428
+
429
+ options.error = (model, e, options) => {
338
430
  error && error.call(options.context, model, e, options);
339
431
  return_promise && promise.reject(e);
340
- }
432
+ };
341
433
 
342
434
  wrapError(this, options);
343
435
 
344
436
  // Set temporary attributes if `{wait: true}` to properly find new ids.
345
- if (attrs && wait) this.attributes = extend({}, attributes, attrs);
437
+ if (attrs && wait) this.attributes = Object.assign({}, attributes, attrs);
346
438
 
347
439
  const method = this.isNew() ? 'create' : options.patch ? 'patch' : 'update';
348
440
  if (method === 'patch' && !options.attrs) options.attrs = attrs;
@@ -356,27 +448,28 @@ Object.assign(Model.prototype, Events, {
356
448
  } else {
357
449
  return xhr;
358
450
  }
451
+ }
359
452
 
360
- },
361
-
362
- // Destroy this model on the server if it was already persisted.
363
- // Optimistically removes the model from its collection, if it has one.
364
- // If `wait: true` is passed, waits for the server to respond before removal.
365
- destroy: function(options) {
453
+ /**
454
+ * Destroy this model on the server if it was already persisted.
455
+ * Optimistically removes the model from its collection, if it has one.
456
+ * If `wait: true` is passed, waits for the server to respond before removal.
457
+ * @param {Options} [options]
458
+ */
459
+ destroy(options) {
366
460
  options = options ? clone(options) : {};
367
- const model = this;
368
461
  const success = options.success;
369
462
  const wait = options.wait;
370
463
 
371
- const destroy = function() {
372
- model.stopListening();
373
- model.trigger('destroy', model, model.collection, options);
464
+ const destroy = () => {
465
+ this.stopListening();
466
+ this.trigger('destroy', this, this.collection, options);
374
467
  };
375
468
 
376
- options.success = function(resp) {
469
+ options.success = (resp) => {
377
470
  if (wait) destroy();
378
- if (success) success.call(options.context, model, resp, options);
379
- if (!model.isNew()) model.trigger('sync', model, resp, options);
471
+ if (success) success.call(options.context, this, resp, options);
472
+ if (!this.isNew()) this.trigger('sync', this, resp, options);
380
473
  };
381
474
 
382
475
  let xhr = false;
@@ -388,50 +481,59 @@ Object.assign(Model.prototype, Events, {
388
481
  }
389
482
  if (!wait) destroy();
390
483
  return xhr;
391
- },
392
-
393
- // Default URL for the model's representation on the server -- if you're
394
- // using Backbone's restful methods, override this to change the endpoint
395
- // that will be called.
396
- url: function() {
397
- const base =
398
- result(this, 'urlRoot') ||
399
- result(this.collection, 'url') ||
400
- urlError();
484
+ }
485
+
486
+ /**
487
+ * Default URL for the model's representation on the server -- if you're
488
+ * using Backbone's restful methods, override this to change the endpoint
489
+ * that will be called.
490
+ */
491
+ url() {
492
+ const base = result(this, 'urlRoot') || result(this.collection, 'url') || urlError();
401
493
  if (this.isNew()) return base;
402
494
  const id = this.get(this.idAttribute);
403
495
  return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id);
404
- },
496
+ }
405
497
 
406
- // **parse** converts a response into the hash of attributes to be `set` on
407
- // the model. The default implementation is just to pass the response along.
408
- parse: function(resp, options) {
498
+ /**
499
+ * **parse** converts a response into the hash of attributes to be `set` on
500
+ * the model. The default implementation is just to pass the response along.
501
+ * @param {Options} resp
502
+ * @param {Options} [options]
503
+ */
504
+ parse(resp, options) {
409
505
  return resp;
410
- },
411
-
412
- // Create a new model with identical attributes to this one.
413
- clone: function() {
414
- return new this.constructor(this.attributes);
415
- },
506
+ }
416
507
 
417
- // A model is new if it has never been saved to the server, and lacks an id.
418
- isNew: function() {
508
+ /**
509
+ * A model is new if it has never been saved to the server, and lacks an id.
510
+ */
511
+ isNew() {
419
512
  return !this.has(this.idAttribute);
420
- },
513
+ }
421
514
 
422
- // Check if the model is currently in a valid state.
423
- isValid: function(options) {
424
- return this._validate({}, extend({}, options, {validate: true}));
425
- },
515
+ /**
516
+ * Check if the model is currently in a valid state.
517
+ * @param {Options} [options]
518
+ */
519
+ isValid(options) {
520
+ return this._validate({}, Object.assign({}, options, { validate: true }));
521
+ }
426
522
 
427
- // Run validation against the next complete set of model attributes,
428
- // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
429
- _validate: function(attrs, options) {
523
+ /**
524
+ * Run validation against the next complete set of model attributes,
525
+ * returning `true` if all is well. Otherwise, fire an `"invalid"` event.
526
+ * @param {Attributes} attrs
527
+ * @param {Options} [options]
528
+ */
529
+ _validate(attrs, options) {
430
530
  if (!options.validate || !this.validate) return true;
431
- attrs = extend({}, this.attributes, attrs);
432
- const error = this.validationError = this.validate(attrs, options) || null;
531
+ attrs = Object.assign({}, this.attributes, attrs);
532
+ const error = (this.validationError = this.validate(attrs, options) || null);
433
533
  if (!error) return true;
434
- this.trigger('invalid', this, error, extend(options, {validationError: error}));
534
+ this.trigger('invalid', this, error, Object.assign(options, { validationError: error }));
435
535
  return false;
436
536
  }
437
- });
537
+ }
538
+
539
+ export { Model };