1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview This is a data model representin
7 */
8
9cr.define('cr.ui', function() {
10  const EventTarget = cr.EventTarget;
11  const Event = cr.Event;
12
13  /**
14   * A data model that wraps a simple array.
15   * @param {!Array} array The underlying array.
16   * @constructor
17   * @extends {EventTarget}
18   */
19  function ArrayDataModel(array) {
20    this.array_ = array;
21  }
22
23  ArrayDataModel.prototype = {
24    __proto__: EventTarget.prototype,
25
26    /**
27     * The length of the data model.
28     * @type {number}
29     */
30    get length() {
31      return this.array_.length;
32    },
33
34    /**
35     * Returns the item at the given index.
36     * @param {number} index The index of the element to get.
37     * @return {*} The element at the given index.
38     */
39    item: function(index) {
40      return this.array_[index];
41    },
42
43    /**
44     * Returns the first matching item.
45     * @param {*} item The item to find.
46     * @param {number=} opt_fromIndex If provided, then the searching start at
47     *     the {@code opt_fromIndex}.
48     * @return {number} The index of the first found element or -1 if not found.
49     */
50    indexOf: function(item, opt_fromIndex) {
51      return this.array_.indexOf(item, opt_fromIndex);
52    },
53
54    /**
55     * Returns an array of elements in a selected range.
56     * @param {number=} opt_from The starting index of the selected range.
57     * @param {number=} opt_to The ending index of selected range.
58     * @return {Array} An array of elements in the selected range.
59     */
60    slice: function(opt_from, opt_to) {
61      return this.array_.slice.apply(this.array_, arguments);
62    },
63
64    /**
65     * This removes and adds items to the model.
66     *
67     * This dispatches a splice event.
68     *
69     * @param {number} index The index of the item to update.
70     * @param {number} deleteCount The number of items to remove.
71     * @param {...*} The items to add.
72     * @return {!Array} An array with the removed items.
73     */
74    splice: function(index, deleteCount, var_args) {
75      var arr = this.array_;
76
77      // TODO(arv): Maybe unify splice and change events?
78      var e = new Event('splice');
79      e.index = index;
80      e.removed = arr.slice(index, index + deleteCount);
81      e.added = Array.prototype.slice.call(arguments, 2);
82
83      var rv = arr.splice.apply(arr, arguments);
84
85      this.dispatchEvent(e);
86
87      return rv;
88    },
89
90    /**
91     * Appends items to the end of the model.
92     *
93     * This dispatches a splice event.
94     *
95     * @param {...*} The items to append.
96     * @return {number} The new length of the model.
97     */
98    push: function(var_args) {
99      var args = Array.prototype.slice.call(arguments);
100      args.unshift(this.length, 0);
101      this.splice.apply(this, args);
102      return this.length;
103    },
104
105    /**
106     * Use this to update a given item in the array. This does not remove and
107     * reinsert a new item.
108     *
109     * This dispatches a change event.
110     *
111     * @param {number} index The index of the item to update.
112     */
113    updateIndex: function(index) {
114      if (index < 0 || index >= this.length)
115        throw Error('Invalid index, ' + index);
116
117      // TODO(arv): Maybe unify splice and change events?
118      var e = new Event('change');
119      e.index = index;
120      this.dispatchEvent(e);
121    }
122  };
123
124  return {
125    ArrayDataModel: ArrayDataModel
126  };
127});
128