UNPKG

jupyterlab-emrys

Version:

A computational environment for Jupyter. Powered by Emrys

419 lines (418 loc) 14 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. /*----------------------------------------------------------------------------- | Copyright (c) 2014-2015, PhosphorJS Contributors | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ 'use strict'; var arrays = require('phosphor-arrays'); var phosphor_signaling_1 = require('phosphor-signaling'); /** * An enum of the change types which occur on an observable list. */ (function (ListChangeType) { /** * An item was added to the list. */ ListChangeType[ListChangeType["Add"] = 0] = "Add"; /** * An item was moved in the list. */ ListChangeType[ListChangeType["Move"] = 1] = "Move"; /** * An item was removed from the list. */ ListChangeType[ListChangeType["Remove"] = 2] = "Remove"; /** * Items were replaced in the list. */ ListChangeType[ListChangeType["Replace"] = 3] = "Replace"; /** * An item was set in the list. */ ListChangeType[ListChangeType["Set"] = 4] = "Set"; })(exports.ListChangeType || (exports.ListChangeType = {})); var ListChangeType = exports.ListChangeType; /** * A concrete implementation of [[IObservableList]]. */ var ObservableList = (function () { /** * Construct a new observable list. * * @param items - The initial items for the list. */ function ObservableList(items) { this.internal = items ? items.slice() : []; } Object.defineProperty(ObservableList.prototype, "changed", { /** * A signal emitted when the list has changed. * * #### Notes * This is a pure delegate to the [[changedSignal]]. */ get: function () { return ObservableList.changedSignal.bind(this); }, enumerable: true, configurable: true }); Object.defineProperty(ObservableList.prototype, "length", { /** * The number of items in the list. * * #### Notes * This is a read-only property. */ get: function () { return this.internal.length; }, enumerable: true, configurable: true }); /** * Get the item at a specific index in the list. * * @param index - The index of the item of interest. If this is * negative, it is offset from the end of the list. * * @returns The item at the specified index, or `undefined` if the * index is out of range. */ ObservableList.prototype.get = function (index) { return this.internal[this._norm(index)]; }; /** * Test whether the list contains a specific item. * * @param item - The item of interest. * * @returns `true` if the list contains the item, `false` otherwise. */ ObservableList.prototype.contains = function (item) { return this.internal.indexOf(item) !== -1; }; /** * Get the index of the first occurence of an item in the list. * * @param item - The item of interest. * * @returns The index of the specified item or `-1` if the item is * not contained in the list. */ ObservableList.prototype.indexOf = function (item) { return this.internal.indexOf(item); }; /** * Get a shallow copy of a portion of the list. * * @param start - The start index of the slice, inclusive. If this is * negative, it is offset from the end of the list. If this is not * provided, it defaults to `0`. In all cases, it is clamped to the * bounds of the list. * * @param end - The end index of the slice, exclusive. If this is * negative, it is offset from the end of the list. If this is not * provided, it defaults to `length`. In all cases, it is clamped * to the bounds of the list. * * @returns A new array containing the specified range of items. */ ObservableList.prototype.slice = function (start, end) { return this.internal.slice(start, end); }; /** * Set the item at a specific index. * * @param index - The index of interest. If this is negative, it is * offset from the end of the list. * * @param item - The item to set at the index. * * @returns The item which occupied the index, or `undefined` if the * index is out of range. */ ObservableList.prototype.set = function (index, item) { var i = this._norm(index); if (!this._check(i)) return void 0; return this.setItem(i, item); }; /** * Replace the contents of the list with the specified items. * * @param items - The items to assign to the list. * * @returns An array of the previous list items. * * #### Notes * This is equivalent to `list.replace(0, list.length, items)`. */ ObservableList.prototype.assign = function (items) { return this.replaceItems(0, this.internal.length, items); }; /** * Add an item to the end of the list. * * @param item - The item to add to the list. * * @returns The index at which the item was added. */ ObservableList.prototype.add = function (item) { return this.addItem(this.internal.length, item); }; /** * Insert an item into the list at a specific index. * * @param index - The index at which to insert the item. If this is * negative, it is offset from the end of the list. In all cases, * it is clamped to the bounds of the list. * * @param item - The item to insert into the list. * * @returns The index at which the item was inserted. */ ObservableList.prototype.insert = function (index, item) { return this.addItem(this._clamp(index), item); }; /** * Move an item from one index to another. * * @param fromIndex - The index of the item of interest. If this is * negative, it is offset from the end of the list. * * @param toIndex - The desired index for the item. If this is * negative, it is offset from the end of the list. * * @returns `true` if the item was moved, `false` otherwise. */ ObservableList.prototype.move = function (fromIndex, toIndex) { var i = this._norm(fromIndex); if (!this._check(i)) return false; var j = this._norm(toIndex); if (!this._check(j)) return false; return this.moveItem(i, j); }; /** * Remove the first occurrence of a specific item from the list. * * @param item - The item to remove from the list. * * @return The index occupied by the item, or `-1` if the item is * not contained in the list. */ ObservableList.prototype.remove = function (item) { var i = this.internal.indexOf(item); if (i !== -1) this.removeItem(i); return i; }; /** * Remove the item at a specific index. * * @param index - The index of the item of interest. If this is * negative, it is offset from the end of the list. * * @returns The item at the specified index, or `undefined` if the * index is out of range. */ ObservableList.prototype.removeAt = function (index) { var i = this._norm(index); if (!this._check(i)) return void 0; return this.removeItem(i); }; /** * Replace items at a specific location in the list. * * @param index - The index at which to modify the list. If this is * negative, it is offset from the end of the list. In all cases, * it is clamped to the bounds of the list. * * @param count - The number of items to remove at the given index. * This is clamped to the length of the list. * * @param items - The items to insert at the specified index. * * @returns An array of the items removed from the list. */ ObservableList.prototype.replace = function (index, count, items) { return this.replaceItems(this._norm(index), this._limit(count), items); }; /** * Remove all items from the list. * * @returns An array of the items removed from the list. * * #### Notes * This is equivalent to `list.replace(0, list.length, [])`. */ ObservableList.prototype.clear = function () { return this.replaceItems(0, this.internal.length, []); }; /** * Add an item to the list at the specified index. * * @param index - The index at which to add the item. This must be * an integer in the range `[0, internal.length]`. * * @param item - The item to add at the specified index. * * @returns The index at which the item was added. * * #### Notes * This may be reimplemented by subclasses to customize the behavior. */ ObservableList.prototype.addItem = function (index, item) { var i = arrays.insert(this.internal, index, item); this.changed.emit({ type: ListChangeType.Add, newIndex: i, newValue: item, oldIndex: -1, oldValue: void 0, }); return i; }; /** * Move an item in the list from one index to another. * * @param fromIndex - The initial index of the item. This must be * an integer in the range `[0, internal.length)`. * * @param toIndex - The desired index for the item. This must be * an integer in the range `[0, internal.length)`. * * @returns `true` if the item was moved, `false` otherwise. * * #### Notes * This may be reimplemented by subclasses to customize the behavior. */ ObservableList.prototype.moveItem = function (fromIndex, toIndex) { if (!arrays.move(this.internal, fromIndex, toIndex)) { return false; } var item = this.internal[toIndex]; this.changed.emit({ type: ListChangeType.Move, newIndex: toIndex, newValue: item, oldIndex: fromIndex, oldValue: item, }); return true; }; /** * Remove the item from the list at the specified index. * * @param index - The index of the item to remove. This must be * an integer in the range `[0, internal.length)`. * * @returns The item removed from the list. * * #### Notes * This may be reimplemented by subclasses to customize the behavior. */ ObservableList.prototype.removeItem = function (index) { var item = arrays.removeAt(this.internal, index); this.changed.emit({ type: ListChangeType.Remove, newIndex: -1, newValue: void 0, oldIndex: index, oldValue: item, }); return item; }; /** * Replace items at a specific location in the list. * * @param index - The index at which to modify the list. This must * be an integer in the range `[0, internal.length]`. * * @param count - The number of items to remove from the list. This * must be an integer in the range `[0, internal.length]`. * * @param items - The items to insert at the specified index. * * @returns An array of the items removed from the list. * * #### Notes * This may be reimplemented by subclasses to customize the behavior. */ ObservableList.prototype.replaceItems = function (index, count, items) { var old = (_a = this.internal).splice.apply(_a, [index, count].concat(items)); this.changed.emit({ type: ListChangeType.Replace, newIndex: index, newValue: items, oldIndex: index, oldValue: old, }); return old; var _a; }; /** * Set the item at a specific index in the list. * * @param index - The index of interest. This must be an integer in * the range `[0, internal.length)`. * * @param item - The item to set at the index. * * @returns The item which previously occupied the specified index. * * #### Notes * This may be reimplemented by subclasses to customize the behavior. */ ObservableList.prototype.setItem = function (index, item) { var old = this.internal[index]; this.internal[index] = item; this.changed.emit({ type: ListChangeType.Set, newIndex: index, newValue: item, oldIndex: index, oldValue: old, }); return old; }; /** * Normalize an index and offset negative values from the list end. */ ObservableList.prototype._norm = function (i) { return i < 0 ? Math.floor(i) + this.internal.length : Math.floor(i); }; /** * Check whether a normalized index is in range. */ ObservableList.prototype._check = function (i) { return i >= 0 && i < this.internal.length; }; /** * Normalize and clamp an index to the list bounds. */ ObservableList.prototype._clamp = function (i) { return Math.max(0, Math.min(this._norm(i), this.internal.length)); }; /** * Normalize and limit a count to the length of the list. */ ObservableList.prototype._limit = function (c) { return Math.max(0, Math.min(Math.floor(c), this.internal.length)); }; /** * A signal emitted when the list has changed. * * **See also:** [[changed]] */ ObservableList.changedSignal = new phosphor_signaling_1.Signal(); return ObservableList; }()); exports.ObservableList = ObservableList;