Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7261)

Unified Diff: chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js

Issue 8396001: Add sample extension that allows setting plugin-specific content settings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update docs Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js
new file mode 100644
index 0000000000000000000000000000000000000000..f12bd1d8e1828db434cd1575d3ea81bc3cddfaa0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js
@@ -0,0 +1,363 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview This is a data model representin
+ */
+
+cr.define('cr.ui', function() {
+ const EventTarget = cr.EventTarget;
+ const Event = cr.Event;
+
+ /**
+ * A data model that wraps a simple array and supports sorting by storing
+ * initial indexes of elements for each position in sorted array.
+ * @param {!Array} array The underlying array.
+ * @constructor
+ * @extends {EventTarget}
+ */
+ function ArrayDataModel(array) {
+ this.array_ = array;
+ this.indexes_ = [];
+ this.compareFunctions_ = {};
+
+ for (var i = 0; i < array.length; i++) {
+ this.indexes_.push(i);
+ }
+ }
+
+ ArrayDataModel.prototype = {
+ __proto__: EventTarget.prototype,
+
+ /**
+ * The length of the data model.
+ * @type {number}
+ */
+ get length() {
+ return this.array_.length;
+ },
+
+ /**
+ * Returns the item at the given index.
+ * This implementation returns the item at the given index in the sorted
+ * array.
+ * @param {number} index The index of the element to get.
+ * @return {*} The element at the given index.
+ */
+ item: function(index) {
+ if (index >= 0 && index < this.length)
+ return this.array_[this.indexes_[index]];
+ return undefined;
+ },
+
+ /**
+ * Returns compare function set for given field.
+ * @param {string} field The field to get compare function for.
+ * @return {function(*, *): number} Compare function set for given field.
+ */
+ compareFunction: function(field) {
+ return this.compareFunctions_[field];
+ },
+
+ /**
+ * Sets compare function for given field.
+ * @param {string} field The field to set compare function.
+ * @param {function(*, *): number} Compare function to set for given field.
+ */
+ setCompareFunction: function(field, compareFunction) {
+ if (!this.compareFunctions_) {
+ this.compareFunctions_ = {};
+ }
+ this.compareFunctions_[field] = compareFunction;
+ },
+
+ /**
+ * Returns current sort status.
+ * @return {!Object} Current sort status.
+ */
+ get sortStatus() {
+ if (this.sortStatus_) {
+ return this.createSortStatus(
+ this.sortStatus_.field, this.sortStatus_.direction);
+ } else {
+ return this.createSortStatus(null, null);
+ }
+ },
+
+ /**
+ * Returns the first matching item.
+ * @param {*} item The item to find.
+ * @param {number=} opt_fromIndex If provided, then the searching start at
+ * the {@code opt_fromIndex}.
+ * @return {number} The index of the first found element or -1 if not found.
+ */
+ indexOf: function(item, opt_fromIndex) {
+ return this.array_.indexOf(item, opt_fromIndex);
+ },
+
+ /**
+ * Returns an array of elements in a selected range.
+ * @param {number=} opt_from The starting index of the selected range.
+ * @param {number=} opt_to The ending index of selected range.
+ * @return {Array} An array of elements in the selected range.
+ */
+ slice: function(opt_from, opt_to) {
+ return this.array_.slice.apply(this.array_, arguments);
+ },
+
+ /**
+ * This removes and adds items to the model.
+ * This dispatches a splice event.
+ * This implementation runs sort after splice and creates permutation for
+ * the whole change.
+ * @param {number} index The index of the item to update.
+ * @param {number} deleteCount The number of items to remove.
+ * @param {...*} The items to add.
+ * @return {!Array} An array with the removed items.
+ */
+ splice: function(index, deleteCount, var_args) {
+ var addCount = arguments.length - 2;
+ var newIndexes = [];
+ var deletePermutation = [];
+ var deleted = 0;
+ for (var i = 0; i < this.indexes_.length; i++) {
+ var oldIndex = this.indexes_[i];
+ if (oldIndex < index) {
+ newIndexes.push(oldIndex);
+ deletePermutation.push(i - deleted);
+ } else if (oldIndex >= index + deleteCount) {
+ newIndexes.push(oldIndex - deleteCount + addCount);
+ deletePermutation.push(i - deleted);
+ } else {
+ deletePermutation.push(-1);
+ deleted++;
+ }
+ }
+ for (var i = 0; i < addCount; i++) {
+ newIndexes.push(index + i);
+ }
+ this.indexes_ = newIndexes;
+
+ var arr = this.array_;
+
+ // TODO(arv): Maybe unify splice and change events?
+ var spliceEvent = new Event('splice');
+ spliceEvent.index = index;
+ spliceEvent.removed = arr.slice(index, index + deleteCount);
+ spliceEvent.added = Array.prototype.slice.call(arguments, 2);
+
+ var rv = arr.splice.apply(arr, arguments);
+
+ var status = this.sortStatus;
+ // if sortStatus.field is null, this restores original order.
+ var sortPermutation = this.doSort_(this.sortStatus.field,
+ this.sortStatus.direction);
+ if (sortPermutation) {
+ var splicePermutation = deletePermutation.map(function(element) {
+ return element != -1 ? sortPermutation[element] : -1;
+ });
+ this.dispatchPermutedEvent_(splicePermutation);
+ } else {
+ this.dispatchPermutedEvent_(deletePermutation);
+ }
+
+ this.dispatchEvent(spliceEvent);
+
+ // If real sorting is needed, we should first call prepareSort (data may
+ // change), and then sort again.
+ // Still need to finish the sorting above (including events), so
+ // list will not go to inconsistent state.
+ if (status.field) {
+ setTimeout(this.sort.bind(this, status.field, status.direction), 0);
+ }
+ return rv;
+ },
+
+ /**
+ * Appends items to the end of the model.
+ *
+ * This dispatches a splice event.
+ *
+ * @param {...*} The items to append.
+ * @return {number} The new length of the model.
+ */
+ push: function(var_args) {
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift(this.length, 0);
+ this.splice.apply(this, args);
+ return this.length;
+ },
+
+ /**
+ * Use this to update a given item in the array. This does not remove and
+ * reinsert a new item.
+ * This dispatches a change event.
+ * This runs sort after updating.
+ * @param {number} index The index of the item to update.
+ */
+ updateIndex: function(index) {
+ if (index < 0 || index >= this.length)
+ throw Error('Invalid index, ' + index);
+
+ // TODO(arv): Maybe unify splice and change events?
+ var e = new Event('change');
+ e.index = index;
+ this.dispatchEvent(e);
+
+ if (this.sortStatus.field) {
+ var status = this.sortStatus;
+ var sortPermutation = this.doSort_(this.sortStatus.field,
+ this.sortStatus.direction);
+ if (sortPermutation)
+ this.dispatchPermutedEvent_(sortPermutation);
+ // We should first call prepareSort (data may change), and then sort.
+ // Still need to finish the sorting above (including events), so
+ // list will not go to inconsistent state.
+ setTimeout(this.sort.bind(this, status.field, status.direction), 0);
+ }
+ },
+
+ /**
+ * Creates sort status with given field and direction.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ * @return {!Object} Created sort status.
+ */
+ createSortStatus: function(field, direction) {
+ return {
+ field: field,
+ direction: direction
+ };
+ },
+
+ /**
+ * Called before a sort happens so that you may fetch additional data
+ * required for the sort.
+ *
+ * @param {string} field Sort field.
+ * @param {function()} callback The function to invoke when preparation
+ * is complete.
+ */
+ prepareSort: function(field, callback) {
+ callback();
+ },
+
+ /**
+ * Sorts data model according to given field and direction and dispathes
+ * sorted event.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ */
+ sort: function(field, direction) {
+ var self = this;
+
+ this.prepareSort(field, function() {
+ var sortPermutation = self.doSort_(field, direction);
+ if (sortPermutation)
+ self.dispatchPermutedEvent_(sortPermutation);
+ self.dispatchSortEvent_();
+ });
+ },
+
+ /**
+ * Sorts data model according to given field and direction.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ */
+ doSort_: function(field, direction) {
+ var compareFunction = this.sortFunction_(field, direction);
+ var positions = [];
+ for (var i = 0; i < this.length; i++) {
+ positions[this.indexes_[i]] = i;
+ }
+ this.indexes_.sort(compareFunction);
+ this.sortStatus_ = this.createSortStatus(field, direction);
+ var sortPermutation = [];
+ var changed = false;
+ for (var i = 0; i < this.length; i++) {
+ if (positions[this.indexes_[i]] != i)
+ changed = true;
+ sortPermutation[positions[this.indexes_[i]]] = i;
+ }
+ if (changed)
+ return sortPermutation;
+ return null;
+ },
+
+ dispatchSortEvent_: function() {
+ var e = new Event('sorted');
+ this.dispatchEvent(e);
+ },
+
+ dispatchPermutedEvent_: function(permutation) {
+ var e = new Event('permuted');
+ e.permutation = permutation;
+ e.newLength = this.length;
+ this.dispatchEvent(e);
+ },
+
+ /**
+ * Creates compare function for the field.
+ * Returns the function set as sortFunction for given field
+ * or default compare function
+ * @param {string} field Sort field.
+ * @param {function(*, *): number} Compare function.
+ */
+ createCompareFunction_: function(field) {
+ var compareFunction =
+ this.compareFunctions_ ? this.compareFunctions_[field] : null;
+ var defaultValuesCompareFunction = this.defaultValuesCompareFunction;
+ if (compareFunction) {
+ return compareFunction;
+ } else {
+ return function(a, b) {
+ return defaultValuesCompareFunction.call(null, a[field], b[field]);
+ }
+ }
+ return compareFunction;
+ },
+
+ /**
+ * Creates compare function for given field and direction.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ * @param {function(*, *): number} Compare function.
+ */
+ sortFunction_: function(field, direction) {
+ var compareFunction = null;
+ if (field !== null)
+ compareFunction = this.createCompareFunction_(field);
+ var dirMultiplier = direction == 'desc' ? -1 : 1;
+
+ return function(index1, index2) {
+ var item1 = this.array_[index1];
+ var item2 = this.array_[index2];
+
+ var compareResult = 0;
+ if (typeof(compareFunction) === 'function')
+ compareResult = compareFunction.call(null, item1, item2);
+ if (compareResult != 0)
+ return dirMultiplier * compareResult;
+ return dirMultiplier * this.defaultValuesCompareFunction(index1,
+ index2);
+ }.bind(this);
+ },
+
+ /**
+ * Default compare function.
+ */
+ defaultValuesCompareFunction: function(a, b) {
+ // We could insert i18n comparisons here.
+ if (a < b)
+ return -1;
+ if (a > b)
+ return 1;
+ return 0;
+ }
+ };
+
+ return {
+ ArrayDataModel: ArrayDataModel
+ };
+});

Powered by Google App Engine
This is Rietveld 408576698