8
0

model.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. /**
  7. * The base MVC model class.
  8. *
  9. * @class Model
  10. * @mixins EventEmitter
  11. */
  12. CKEDITOR.define( [ 'emittermixin', 'ckeditorerror', 'utils' ], ( EmitterMixin, CKEditorError, utils ) => {
  13. class Model {
  14. /**
  15. * Creates a new Model instance.
  16. *
  17. * @param {Object} [attributes] The model state attributes to be set during the instance creation.
  18. * @param {Object} [properties] The properties to be appended to the instance during creation.
  19. * @method constructor
  20. */
  21. constructor( attributes, properties ) {
  22. /**
  23. * The internal hash containing the model's state.
  24. *
  25. * @property _attributes
  26. * @private
  27. */
  28. this._attributes = {};
  29. // Extend this instance with the additional (out of state) properties.
  30. if ( properties ) {
  31. utils.extend( this, properties );
  32. }
  33. // Initialize the attributes.
  34. if ( attributes ) {
  35. this.set( attributes );
  36. }
  37. }
  38. /**
  39. * Creates and sets the value of a model attribute of this object. This attribute will be part of the model
  40. * state and will be observable.
  41. *
  42. * It accepts also a single object literal containing key/value pairs with attributes to be set.
  43. *
  44. * This method throws the {@link model-set-cannot-override} error if the model instance already
  45. * have a property with a given attribute name. This prevents from mistakenly overriding existing
  46. * properties and methods, but means that `foo.set( 'bar', 1 )` may be slightly slower than `foo.bar = 1`.
  47. *
  48. * @param {String} name The attributes name.
  49. * @param {*} value The attributes value.
  50. */
  51. set( name, value ) {
  52. // If the first parameter is an Object, we gonna interact through its properties.
  53. if ( utils.isObject( name ) ) {
  54. Object.keys( name ).forEach( ( attr ) => {
  55. this.set( attr, name[ attr ] );
  56. }, this );
  57. return;
  58. }
  59. if ( ( name in this ) && !( name in this._attributes ) ) {
  60. /**
  61. * Cannot override an existing property.
  62. *
  63. * This error is thrown when trying to {@link Model#set set} an attribute with
  64. * a name of an already existing property. For example:
  65. *
  66. * let model = new Model();
  67. * model.property = 1;
  68. * model.set( 'property', 2 ); // throws
  69. *
  70. * model.set( 'attr', 1 );
  71. * model.set( 'attr', 2 ); // ok, because this is an existing attribute.
  72. *
  73. * @error model-set-cannot-override
  74. */
  75. throw new CKEditorError( 'model-set-cannot-override: Cannot override an existing property.' );
  76. }
  77. Object.defineProperty( this, name, {
  78. enumerable: true,
  79. configurable: true,
  80. get: () => {
  81. return this._attributes[ name ];
  82. },
  83. set: ( value ) => {
  84. const oldValue = this._attributes[ name ];
  85. if ( oldValue !== value ) {
  86. this._attributes[ name ] = value;
  87. this.fire( 'change', name, value, oldValue );
  88. this.fire( 'change:' + name, value, oldValue );
  89. }
  90. }
  91. } );
  92. this[ name ] = value;
  93. }
  94. }
  95. utils.extend( Model.prototype, EmitterMixin );
  96. return Model;
  97. } );
  98. /**
  99. * Fired when an attribute changed value.
  100. *
  101. * @event change
  102. * @param {String} name The attribute name.
  103. * @param {*} value The new attribute value.
  104. * @param {*} oldValue The previous attribute value.
  105. */
  106. /**
  107. * Fired when an specific attribute changed value.
  108. *
  109. * @event change:{attribute}
  110. * @param {*} value The new attribute value.
  111. * @param {*} oldValue The previous attribute value.
  112. */