3.0 source code
This commit is contained in:
69
OfficeWeb/vendor/touch/src/mixin/Bindable.js
vendored
Normal file
69
OfficeWeb/vendor/touch/src/mixin/Bindable.js
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.mixin.Bindable', {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
mixinConfig: {
|
||||
id: 'bindable'
|
||||
},
|
||||
|
||||
bind: function(instance, boundMethod, bindingMethod, preventDefault) {
|
||||
if (!bindingMethod) {
|
||||
bindingMethod = boundMethod;
|
||||
}
|
||||
|
||||
var boundFn = instance[boundMethod],
|
||||
fn;
|
||||
|
||||
instance[boundMethod] = fn = function() {
|
||||
var binding = fn.$binding,
|
||||
scope = binding.bindingScope,
|
||||
args = Array.prototype.slice.call(arguments);
|
||||
|
||||
args.push(arguments);
|
||||
|
||||
if (!binding.preventDefault && scope[binding.bindingMethod].apply(scope, args) !== false) {
|
||||
return binding.boundFn.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
fn.$binding = {
|
||||
preventDefault: !!preventDefault,
|
||||
boundFn: boundFn,
|
||||
bindingMethod: bindingMethod,
|
||||
bindingScope: this
|
||||
};
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind: function(instance, boundMethod, bindingMethod) {
|
||||
if (!bindingMethod) {
|
||||
bindingMethod = boundMethod;
|
||||
}
|
||||
|
||||
var fn = instance[boundMethod],
|
||||
binding = fn.$binding,
|
||||
boundFn, currentBinding;
|
||||
|
||||
while (binding) {
|
||||
boundFn = binding.boundFn;
|
||||
|
||||
if (binding.bindingMethod === bindingMethod && binding.bindingScope === this) {
|
||||
if (currentBinding) {
|
||||
currentBinding.boundFn = boundFn;
|
||||
}
|
||||
else {
|
||||
instance[boundMethod] = boundFn;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
currentBinding = binding;
|
||||
binding = binding.boundFn;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
289
OfficeWeb/vendor/touch/src/mixin/Filterable.js
vendored
Normal file
289
OfficeWeb/vendor/touch/src/mixin/Filterable.js
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.mixin.Filterable', {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
requires: [
|
||||
'Ext.util.Filter'
|
||||
],
|
||||
|
||||
mixinConfig: {
|
||||
id: 'filterable'
|
||||
},
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Array} filters
|
||||
* An array with filters. A filter can be an instance of Ext.util.Filter,
|
||||
* an object representing an Ext.util.Filter configuration, or a filter function.
|
||||
*/
|
||||
filters: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} filterRoot
|
||||
* The root inside each item in which the properties exist that we want to filter on.
|
||||
* This is useful for filtering records in which the data exists inside a 'data' property.
|
||||
*/
|
||||
filterRoot: null
|
||||
},
|
||||
|
||||
/**
|
||||
* @property {Boolean} dirtyFilterFn
|
||||
* A flag indicating whether the currently cashed filter function is still valid.
|
||||
* @readonly
|
||||
*/
|
||||
dirtyFilterFn: false,
|
||||
|
||||
/**
|
||||
* @property currentSortFn
|
||||
* This is the cached sorting function which is a generated function that calls all the
|
||||
* configured sorters in the correct order.
|
||||
* @readonly
|
||||
*/
|
||||
filterFn: null,
|
||||
|
||||
/**
|
||||
* @property {Boolean} filtered
|
||||
* A read-only flag indicating if this object is filtered.
|
||||
* @readonly
|
||||
*/
|
||||
filtered: false,
|
||||
|
||||
applyFilters: function(filters, collection) {
|
||||
if (!collection) {
|
||||
collection = this.createFiltersCollection();
|
||||
}
|
||||
|
||||
collection.clear();
|
||||
|
||||
this.filtered = false;
|
||||
this.dirtyFilterFn = true;
|
||||
|
||||
if (filters) {
|
||||
this.addFilters(filters);
|
||||
}
|
||||
|
||||
return collection;
|
||||
},
|
||||
|
||||
createFiltersCollection: function() {
|
||||
this._filters = Ext.create('Ext.util.Collection', function(filter) {
|
||||
return filter.getId();
|
||||
});
|
||||
return this._filters;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method adds a filter.
|
||||
* @param {Ext.util.Sorter/Function/Object} filter Can be an instance of Ext.util.Filter,
|
||||
* an object representing an Ext.util.Filter configuration, or a filter function.
|
||||
*/
|
||||
addFilter: function(filter) {
|
||||
this.addFilters([filter]);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method adds all the filters in a passed array.
|
||||
* @param {Array} filters An array with filters. A filter can be an instance of {@link Ext.util.Filter},
|
||||
* an object representing an Ext.util.Filter configuration, or a filter function.
|
||||
* @return {Object}
|
||||
*/
|
||||
addFilters: function(filters) {
|
||||
var currentFilters = this.getFilters();
|
||||
return this.insertFilters(currentFilters ? currentFilters.length : 0, filters);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method adds a filter at a given index.
|
||||
* @param {Number} index The index at which to insert the filter.
|
||||
* @param {Ext.util.Sorter/Function/Object} filter Can be an instance of {@link Ext.util.Filter},
|
||||
* an object representing an Ext.util.Filter configuration, or a filter function.
|
||||
* @return {Object}
|
||||
*/
|
||||
insertFilter: function(index, filter) {
|
||||
return this.insertFilters(index, [filter]);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method inserts all the filters in the passed array at the given index.
|
||||
* @param {Number} index The index at which to insert the filters.
|
||||
* @param {Array} filters Each filter can be an instance of {@link Ext.util.Filter},
|
||||
* an object representing an Ext.util.Filter configuration, or a filter function.
|
||||
* @return {Array}
|
||||
*/
|
||||
insertFilters: function(index, filters) {
|
||||
// We begin by making sure we are dealing with an array of sorters
|
||||
if (!Ext.isArray(filters)) {
|
||||
filters = [filters];
|
||||
}
|
||||
|
||||
var ln = filters.length,
|
||||
filterRoot = this.getFilterRoot(),
|
||||
currentFilters = this.getFilters(),
|
||||
newFilters = [],
|
||||
filterConfig, i, filter;
|
||||
|
||||
if (!currentFilters) {
|
||||
currentFilters = this.createFiltersCollection();
|
||||
}
|
||||
|
||||
// We first have to convert every sorter into a proper Sorter instance
|
||||
for (i = 0; i < ln; i++) {
|
||||
filter = filters[i];
|
||||
filterConfig = {
|
||||
root: filterRoot
|
||||
};
|
||||
|
||||
if (Ext.isFunction(filter)) {
|
||||
filterConfig.filterFn = filter;
|
||||
}
|
||||
// If we are dealing with an object, we assume its a Sorter configuration. In this case
|
||||
// we create an instance of Sorter passing this configuration.
|
||||
else if (Ext.isObject(filter)) {
|
||||
if (!filter.isFilter) {
|
||||
if (filter.fn) {
|
||||
filter.filterFn = filter.fn;
|
||||
delete filter.fn;
|
||||
}
|
||||
|
||||
filterConfig = Ext.apply(filterConfig, filter);
|
||||
}
|
||||
else {
|
||||
newFilters.push(filter);
|
||||
if (!filter.getRoot()) {
|
||||
filter.setRoot(filterRoot);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Finally we get to the point where it has to be invalid
|
||||
// <debug>
|
||||
else {
|
||||
Ext.Logger.warn('Invalid filter specified:', filter);
|
||||
}
|
||||
// </debug>
|
||||
|
||||
// If a sorter config was created, make it an instance
|
||||
filter = Ext.create('Ext.util.Filter', filterConfig);
|
||||
newFilters.push(filter);
|
||||
}
|
||||
|
||||
// Now lets add the newly created sorters.
|
||||
for (i = 0, ln = newFilters.length; i < ln; i++) {
|
||||
currentFilters.insert(index + i, newFilters[i]);
|
||||
}
|
||||
|
||||
this.dirtyFilterFn = true;
|
||||
|
||||
if (currentFilters.length) {
|
||||
this.filtered = true;
|
||||
}
|
||||
|
||||
return currentFilters;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method removes all the filters in a passed array.
|
||||
* @param {Array} filters Each value in the array can be a string (property name),
|
||||
* function (sorterFn), an object containing a property and value keys or
|
||||
* {@link Ext.util.Sorter Sorter} instance.
|
||||
*/
|
||||
removeFilters: function(filters) {
|
||||
// We begin by making sure we are dealing with an array of sorters
|
||||
if (!Ext.isArray(filters)) {
|
||||
filters = [filters];
|
||||
}
|
||||
|
||||
var ln = filters.length,
|
||||
currentFilters = this.getFilters(),
|
||||
i, filter;
|
||||
|
||||
for (i = 0; i < ln; i++) {
|
||||
filter = filters[i];
|
||||
|
||||
if (typeof filter === 'string') {
|
||||
currentFilters.each(function(item) {
|
||||
if (item.getProperty() === filter) {
|
||||
currentFilters.remove(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (typeof filter === 'function') {
|
||||
currentFilters.each(function(item) {
|
||||
if (item.getFilterFn() === filter) {
|
||||
currentFilters.remove(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (filter.isFilter) {
|
||||
currentFilters.remove(filter);
|
||||
}
|
||||
else if (filter.property !== undefined && filter.value !== undefined) {
|
||||
currentFilters.each(function(item) {
|
||||
if (item.getProperty() === filter.property && item.getValue() === filter.value) {
|
||||
currentFilters.remove(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentFilters.length) {
|
||||
this.filtered = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This updates the cached sortFn based on the current sorters.
|
||||
* @return {Function} sortFn The generated sort function.
|
||||
* @private
|
||||
*/
|
||||
updateFilterFn: function() {
|
||||
var filters = this.getFilters().items;
|
||||
|
||||
this.filterFn = function(item) {
|
||||
var isMatch = true,
|
||||
length = filters.length,
|
||||
i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
var filter = filters[i],
|
||||
fn = filter.getFilterFn(),
|
||||
scope = filter.getScope() || this;
|
||||
|
||||
isMatch = isMatch && fn.call(scope, item);
|
||||
}
|
||||
|
||||
return isMatch;
|
||||
};
|
||||
|
||||
this.dirtyFilterFn = false;
|
||||
return this.filterFn;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method will sort an array based on the currently configured {@link Ext.data.Store#sorters sorters}.
|
||||
* @param {Array} data The array you want to have sorted.
|
||||
* @return {Array} The array you passed after it is sorted.
|
||||
*/
|
||||
filter: function(data) {
|
||||
return this.getFilters().length ? Ext.Array.filter(data, this.getFilterFn()) : data;
|
||||
},
|
||||
|
||||
isFiltered: function(item) {
|
||||
return this.getFilters().length ? !this.getFilterFn()(item) : false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an up to date sort function.
|
||||
* @return {Function} sortFn The sort function.
|
||||
*/
|
||||
getFilterFn: function() {
|
||||
if (this.dirtyFilterFn) {
|
||||
return this.updateFilterFn();
|
||||
}
|
||||
return this.filterFn;
|
||||
}
|
||||
});
|
||||
83
OfficeWeb/vendor/touch/src/mixin/Identifiable.js
vendored
Normal file
83
OfficeWeb/vendor/touch/src/mixin/Identifiable.js
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
//@tag dom,core
|
||||
//@require Ext.dom.Helper
|
||||
|
||||
/**
|
||||
* An Identifiable mixin.
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.mixin.Identifiable', {
|
||||
statics: {
|
||||
uniqueIds: {}
|
||||
},
|
||||
|
||||
isIdentifiable: true,
|
||||
|
||||
mixinId: 'identifiable',
|
||||
|
||||
idCleanRegex: /\.|[^\w\-]/g,
|
||||
|
||||
defaultIdPrefix: 'ext-',
|
||||
|
||||
defaultIdSeparator: '-',
|
||||
|
||||
getOptimizedId: function() {
|
||||
return this.id;
|
||||
},
|
||||
|
||||
getUniqueId: function() {
|
||||
var id = this.id,
|
||||
prototype, separator, xtype, uniqueIds, prefix;
|
||||
|
||||
if (!id) {
|
||||
prototype = this.self.prototype;
|
||||
separator = this.defaultIdSeparator;
|
||||
|
||||
uniqueIds = Ext.mixin.Identifiable.uniqueIds;
|
||||
|
||||
if (!prototype.hasOwnProperty('identifiablePrefix')) {
|
||||
xtype = this.xtype;
|
||||
|
||||
if (xtype) {
|
||||
prefix = this.defaultIdPrefix + xtype + separator;
|
||||
}
|
||||
else {
|
||||
prefix = prototype.$className.replace(this.idCleanRegex, separator).toLowerCase() + separator;
|
||||
}
|
||||
|
||||
prototype.identifiablePrefix = prefix;
|
||||
}
|
||||
|
||||
prefix = this.identifiablePrefix;
|
||||
|
||||
if (!uniqueIds.hasOwnProperty(prefix)) {
|
||||
uniqueIds[prefix] = 0;
|
||||
}
|
||||
|
||||
id = this.id = prefix + (++uniqueIds[prefix]);
|
||||
}
|
||||
|
||||
this.getUniqueId = this.getOptimizedId;
|
||||
|
||||
return id;
|
||||
},
|
||||
|
||||
setId: function(id) {
|
||||
this.id = id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the id of this component. Will autogenerate an id if one has not already been set.
|
||||
* @return {String} id
|
||||
*/
|
||||
getId: function() {
|
||||
var id = this.id;
|
||||
|
||||
if (!id) {
|
||||
id = this.getUniqueId();
|
||||
}
|
||||
|
||||
this.getId = this.getOptimizedId;
|
||||
|
||||
return id;
|
||||
}
|
||||
});
|
||||
56
OfficeWeb/vendor/touch/src/mixin/Mixin.js
vendored
Normal file
56
OfficeWeb/vendor/touch/src/mixin/Mixin.js
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
//@require Ext.Class
|
||||
//@require Ext.ClassManager
|
||||
//@require Ext.Loader
|
||||
|
||||
/**
|
||||
* Base class for all mixins.
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.mixin.Mixin', {
|
||||
onClassExtended: function(cls, data) {
|
||||
var mixinConfig = data.mixinConfig,
|
||||
parentClassMixinConfig,
|
||||
beforeHooks, afterHooks;
|
||||
|
||||
if (mixinConfig) {
|
||||
parentClassMixinConfig = cls.superclass.mixinConfig;
|
||||
|
||||
if (parentClassMixinConfig) {
|
||||
mixinConfig = data.mixinConfig = Ext.merge({}, parentClassMixinConfig, mixinConfig);
|
||||
}
|
||||
|
||||
data.mixinId = mixinConfig.id;
|
||||
|
||||
beforeHooks = mixinConfig.beforeHooks;
|
||||
afterHooks = mixinConfig.hooks || mixinConfig.afterHooks;
|
||||
|
||||
if (beforeHooks || afterHooks) {
|
||||
Ext.Function.interceptBefore(data, 'onClassMixedIn', function(targetClass) {
|
||||
var mixin = this.prototype;
|
||||
|
||||
if (beforeHooks) {
|
||||
Ext.Object.each(beforeHooks, function(from, to) {
|
||||
targetClass.override(to, function() {
|
||||
if (mixin[from].apply(this, arguments) !== false) {
|
||||
return this.callOverridden(arguments);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (afterHooks) {
|
||||
Ext.Object.each(afterHooks, function(from, to) {
|
||||
targetClass.override(to, function() {
|
||||
var ret = this.callOverridden(arguments);
|
||||
|
||||
mixin[from].apply(this, arguments);
|
||||
|
||||
return ret;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
939
OfficeWeb/vendor/touch/src/mixin/Observable.js
vendored
Normal file
939
OfficeWeb/vendor/touch/src/mixin/Observable.js
vendored
Normal file
@@ -0,0 +1,939 @@
|
||||
/**
|
||||
* Mixin that provides a common interface for publishing events. Classes using this mixin can use the {@link #fireEvent}
|
||||
* and {@link #fireAction} methods to notify listeners of events on the class.
|
||||
*
|
||||
* Classes can also define a {@link #listeners} config to add an event handler to the current object. See
|
||||
* {@link #addListener} for more details.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Ext.define('Employee', {
|
||||
* mixins: ['Ext.mixin.Observable'],
|
||||
*
|
||||
* config: {
|
||||
* fullName: ''
|
||||
* },
|
||||
*
|
||||
* constructor: function(config) {
|
||||
* this.initConfig(config); // We need to initialize the config options when the class is instantiated
|
||||
* },
|
||||
*
|
||||
* quitJob: function() {
|
||||
* this.fireEvent('quit');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* var newEmployee = Ext.create('Employee', {
|
||||
*
|
||||
* fullName: 'Ed Spencer',
|
||||
*
|
||||
* listeners: {
|
||||
* quit: function() { // This function will be called when the 'quit' event is fired
|
||||
* // By default, "this" will be the object that fired the event.
|
||||
* console.log(this.getFullName() + " has quit!");
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* newEmployee.quitJob(); // Will log 'Ed Spencer has quit!'
|
||||
*
|
||||
* @aside guide events
|
||||
*/
|
||||
Ext.define('Ext.mixin.Observable', {
|
||||
|
||||
requires: ['Ext.event.Dispatcher'],
|
||||
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
mixins: ['Ext.mixin.Identifiable'],
|
||||
|
||||
mixinConfig: {
|
||||
id: 'observable',
|
||||
hooks: {
|
||||
destroy: 'destroy'
|
||||
}
|
||||
},
|
||||
|
||||
alternateClassName: 'Ext.util.Observable',
|
||||
|
||||
// @private
|
||||
isObservable: true,
|
||||
|
||||
observableType: 'observable',
|
||||
|
||||
validIdRegex: /^([\w\-]+)$/,
|
||||
|
||||
observableIdPrefix: '#',
|
||||
|
||||
listenerOptionsRegex: /^(?:delegate|single|delay|buffer|args|prepend)$/,
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Object} listeners
|
||||
*
|
||||
* A config object containing one or more event handlers to be added to this object during initialization. This
|
||||
* should be a valid listeners `config` object as specified in the {@link #addListener} example for attaching
|
||||
* multiple handlers at once.
|
||||
*
|
||||
* See the [Event guide](#!/guide/events) for more
|
||||
*
|
||||
* __Note:__ It is bad practice to specify a listener's `config` when you are defining a class using `Ext.define()`.
|
||||
* Instead, only specify listeners when you are instantiating your class with `Ext.create()`.
|
||||
* @accessor
|
||||
*/
|
||||
listeners: null,
|
||||
|
||||
/**
|
||||
* @cfg {String/String[]} bubbleEvents The event name to bubble, or an Array of event names.
|
||||
* @accessor
|
||||
*/
|
||||
bubbleEvents: null
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
applyListeners: function(listeners) {
|
||||
if (listeners) {
|
||||
this.addListener(listeners);
|
||||
}
|
||||
},
|
||||
|
||||
applyBubbleEvents: function(bubbleEvents) {
|
||||
if (bubbleEvents) {
|
||||
this.enableBubble(bubbleEvents);
|
||||
}
|
||||
},
|
||||
|
||||
getOptimizedObservableId: function() {
|
||||
return this.observableId;
|
||||
},
|
||||
|
||||
getObservableId: function() {
|
||||
if (!this.observableId) {
|
||||
var id = this.getUniqueId();
|
||||
|
||||
//<debug error>
|
||||
if (!id.match(this.validIdRegex)) {
|
||||
Ext.Logger.error("Invalid unique id of '" + id + "' for this object", this);
|
||||
}
|
||||
//</debug>
|
||||
|
||||
this.observableId = this.observableIdPrefix + id;
|
||||
|
||||
this.getObservableId = this.getOptimizedObservableId;
|
||||
}
|
||||
|
||||
return this.observableId;
|
||||
},
|
||||
|
||||
getOptimizedEventDispatcher: function() {
|
||||
return this.eventDispatcher;
|
||||
},
|
||||
|
||||
getEventDispatcher: function() {
|
||||
if (!this.eventDispatcher) {
|
||||
this.eventDispatcher = Ext.event.Dispatcher.getInstance();
|
||||
this.getEventDispatcher = this.getOptimizedEventDispatcher;
|
||||
|
||||
this.getListeners();
|
||||
this.getBubbleEvents();
|
||||
}
|
||||
|
||||
return this.eventDispatcher;
|
||||
},
|
||||
|
||||
getManagedListeners: function(object, eventName) {
|
||||
var id = object.getUniqueId(),
|
||||
managedListeners = this.managedListeners;
|
||||
|
||||
if (!managedListeners) {
|
||||
this.managedListeners = managedListeners = {};
|
||||
}
|
||||
|
||||
if (!managedListeners[id]) {
|
||||
managedListeners[id] = {};
|
||||
object.doAddListener('destroy', 'clearManagedListeners', this, {
|
||||
single: true,
|
||||
args: [object]
|
||||
});
|
||||
}
|
||||
|
||||
if (!managedListeners[id][eventName]) {
|
||||
managedListeners[id][eventName] = [];
|
||||
}
|
||||
|
||||
return managedListeners[id][eventName];
|
||||
},
|
||||
|
||||
getUsedSelectors: function() {
|
||||
var selectors = this.usedSelectors;
|
||||
|
||||
if (!selectors) {
|
||||
selectors = this.usedSelectors = [];
|
||||
selectors.$map = {};
|
||||
}
|
||||
|
||||
return selectors;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fires the specified event with the passed parameters (minus the event name, plus the `options` object passed
|
||||
* to {@link #addListener}).
|
||||
*
|
||||
* The first argument is the name of the event. Every other argument passed will be available when you listen for
|
||||
* the event.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Firstly, we set up a listener for our new event.
|
||||
*
|
||||
* this.on('myevent', function(arg1, arg2, arg3, arg4, options, e) {
|
||||
* console.log(arg1); // true
|
||||
* console.log(arg2); // 2
|
||||
* console.log(arg3); // { test: 'foo' }
|
||||
* console.log(arg4); // 14
|
||||
* console.log(options); // the options added when adding the listener
|
||||
* console.log(e); // the event object with information about the event
|
||||
* });
|
||||
*
|
||||
* And then we can fire off the event.
|
||||
*
|
||||
* this.fireEvent('myevent', true, 2, { test: 'foo' }, 14);
|
||||
*
|
||||
* An event may be set to bubble up an Observable parent hierarchy by calling {@link #enableBubble}.
|
||||
*
|
||||
* @param {String} eventName The name of the event to fire.
|
||||
* @param {Object...} args Variable number of parameters are passed to handlers.
|
||||
* @return {Boolean} Returns `false` if any of the handlers return `false`, otherwise it returns `true`.
|
||||
*/
|
||||
fireEvent: function(eventName) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
return this.doFireEvent(eventName, args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fires the specified event with the passed parameters and execute a function (action)
|
||||
* at the end if there are no listeners that return `false`.
|
||||
*
|
||||
* @param {String} eventName The name of the event to fire.
|
||||
* @param {Array} args Arguments to pass to handers.
|
||||
* @param {Function} fn Action.
|
||||
* @param {Object} scope Scope of fn.
|
||||
* @return {Object}
|
||||
*/
|
||||
fireAction: function(eventName, args, fn, scope, options, order) {
|
||||
var fnType = typeof fn,
|
||||
action;
|
||||
|
||||
if (args === undefined) {
|
||||
args = [];
|
||||
}
|
||||
|
||||
if (fnType != 'undefined') {
|
||||
action = {
|
||||
fn: fn,
|
||||
isLateBinding: fnType == 'string',
|
||||
scope: scope || this,
|
||||
options: options || {},
|
||||
order: order
|
||||
};
|
||||
}
|
||||
|
||||
return this.doFireEvent(eventName, args, action);
|
||||
},
|
||||
|
||||
doFireEvent: function(eventName, args, action, connectedController) {
|
||||
if (this.eventFiringSuspended) {
|
||||
return;
|
||||
}
|
||||
|
||||
var id = this.getObservableId(),
|
||||
dispatcher = this.getEventDispatcher();
|
||||
|
||||
return dispatcher.dispatchEvent(this.observableType, id, eventName, args, action, connectedController);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param name
|
||||
* @param fn
|
||||
* @param scope
|
||||
* @param options
|
||||
* @return {Boolean}
|
||||
*/
|
||||
doAddListener: function(name, fn, scope, options, order) {
|
||||
var isManaged = (scope && scope !== this && scope.isIdentifiable),
|
||||
usedSelectors = this.getUsedSelectors(),
|
||||
usedSelectorsMap = usedSelectors.$map,
|
||||
selector = this.getObservableId(),
|
||||
isAdded, managedListeners, delegate;
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!scope) {
|
||||
scope = this;
|
||||
}
|
||||
|
||||
if (options.delegate) {
|
||||
delegate = options.delegate;
|
||||
// See https://sencha.jira.com/browse/TOUCH-1579
|
||||
selector += ' ' + delegate;
|
||||
}
|
||||
|
||||
if (!(selector in usedSelectorsMap)) {
|
||||
usedSelectorsMap[selector] = true;
|
||||
usedSelectors.push(selector);
|
||||
}
|
||||
|
||||
isAdded = this.addDispatcherListener(selector, name, fn, scope, options, order);
|
||||
|
||||
if (isAdded && isManaged) {
|
||||
managedListeners = this.getManagedListeners(scope, name);
|
||||
managedListeners.push({
|
||||
delegate: delegate,
|
||||
scope: scope,
|
||||
fn: fn,
|
||||
order: order
|
||||
});
|
||||
}
|
||||
|
||||
return isAdded;
|
||||
},
|
||||
|
||||
addDispatcherListener: function(selector, name, fn, scope, options, order) {
|
||||
return this.getEventDispatcher().addListener(this.observableType, selector, name, fn, scope, options, order);
|
||||
},
|
||||
|
||||
doRemoveListener: function(name, fn, scope, options, order) {
|
||||
var isManaged = (scope && scope !== this && scope.isIdentifiable),
|
||||
selector = this.getObservableId(),
|
||||
isRemoved,
|
||||
managedListeners, i, ln, listener, delegate;
|
||||
|
||||
if (options && options.delegate) {
|
||||
delegate = options.delegate;
|
||||
// See https://sencha.jira.com/browse/TOUCH-1579
|
||||
selector += ' ' + delegate;
|
||||
}
|
||||
|
||||
if (!scope) {
|
||||
scope = this;
|
||||
}
|
||||
|
||||
isRemoved = this.removeDispatcherListener(selector, name, fn, scope, order);
|
||||
|
||||
if (isRemoved && isManaged) {
|
||||
managedListeners = this.getManagedListeners(scope, name);
|
||||
|
||||
for (i = 0,ln = managedListeners.length; i < ln; i++) {
|
||||
listener = managedListeners[i];
|
||||
|
||||
if (listener.fn === fn && listener.scope === scope && listener.delegate === delegate && listener.order === order) {
|
||||
managedListeners.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isRemoved;
|
||||
},
|
||||
|
||||
removeDispatcherListener: function(selector, name, fn, scope, order) {
|
||||
return this.getEventDispatcher().removeListener(this.observableType, selector, name, fn, scope, order);
|
||||
},
|
||||
|
||||
clearManagedListeners: function(object) {
|
||||
var managedListeners = this.managedListeners,
|
||||
id, namedListeners, listeners, eventName, i, ln, listener, options;
|
||||
|
||||
if (!managedListeners) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (object) {
|
||||
if (typeof object != 'string') {
|
||||
id = object.getUniqueId();
|
||||
}
|
||||
else {
|
||||
id = object;
|
||||
}
|
||||
|
||||
namedListeners = managedListeners[id];
|
||||
|
||||
for (eventName in namedListeners) {
|
||||
if (namedListeners.hasOwnProperty(eventName)) {
|
||||
listeners = namedListeners[eventName];
|
||||
|
||||
for (i = 0,ln = listeners.length; i < ln; i++) {
|
||||
listener = listeners[i];
|
||||
|
||||
options = {};
|
||||
|
||||
if (listener.delegate) {
|
||||
options.delegate = listener.delegate;
|
||||
}
|
||||
|
||||
if (this.doRemoveListener(eventName, listener.fn, listener.scope, options, listener.order)) {
|
||||
i--;
|
||||
ln--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete managedListeners[id];
|
||||
return this;
|
||||
}
|
||||
|
||||
for (id in managedListeners) {
|
||||
if (managedListeners.hasOwnProperty(id)) {
|
||||
this.clearManagedListeners(id);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param operation
|
||||
* @param eventName
|
||||
* @param fn
|
||||
* @param scope
|
||||
* @param options
|
||||
* @param order
|
||||
* @return {Object}
|
||||
*/
|
||||
changeListener: function(actionFn, eventName, fn, scope, options, order) {
|
||||
var eventNames,
|
||||
listeners,
|
||||
listenerOptionsRegex,
|
||||
actualOptions,
|
||||
name, value, i, ln, listener, valueType;
|
||||
|
||||
if (typeof fn != 'undefined') {
|
||||
// Support for array format to add multiple listeners
|
||||
if (typeof eventName != 'string') {
|
||||
for (i = 0,ln = eventName.length; i < ln; i++) {
|
||||
name = eventName[i];
|
||||
|
||||
actionFn.call(this, name, fn, scope, options, order);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
actionFn.call(this, eventName, fn, scope, options, order);
|
||||
}
|
||||
else if (Ext.isArray(eventName)) {
|
||||
listeners = eventName;
|
||||
|
||||
for (i = 0,ln = listeners.length; i < ln; i++) {
|
||||
listener = listeners[i];
|
||||
|
||||
actionFn.call(this, listener.event, listener.fn, listener.scope, listener, listener.order);
|
||||
}
|
||||
}
|
||||
else {
|
||||
listenerOptionsRegex = this.listenerOptionsRegex;
|
||||
options = eventName;
|
||||
eventNames = [];
|
||||
listeners = [];
|
||||
actualOptions = {};
|
||||
|
||||
for (name in options) {
|
||||
value = options[name];
|
||||
|
||||
if (name === 'scope') {
|
||||
scope = value;
|
||||
continue;
|
||||
}
|
||||
else if (name === 'order') {
|
||||
order = value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!listenerOptionsRegex.test(name)) {
|
||||
valueType = typeof value;
|
||||
|
||||
if (valueType != 'string' && valueType != 'function') {
|
||||
actionFn.call(this, name, value.fn, value.scope || scope, value, value.order || order);
|
||||
continue;
|
||||
}
|
||||
|
||||
eventNames.push(name);
|
||||
listeners.push(value);
|
||||
}
|
||||
else {
|
||||
actualOptions[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0,ln = eventNames.length; i < ln; i++) {
|
||||
actionFn.call(this, eventNames[i], listeners[i], scope, actualOptions, order);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Appends an event handler to this object. You can review the available handlers by looking at the 'events'
|
||||
* section of the documentation for the component you are working with.
|
||||
*
|
||||
* ## Combining Options
|
||||
*
|
||||
* Using the options argument, it is possible to combine different types of listeners:
|
||||
*
|
||||
* A delayed, one-time listener:
|
||||
*
|
||||
* container.on('tap', this.handleTap, this, {
|
||||
* single: true,
|
||||
* delay: 100
|
||||
* });
|
||||
*
|
||||
* ## Attaching multiple handlers in 1 call
|
||||
*
|
||||
* The method also allows for a single argument to be passed which is a config object containing properties which
|
||||
* specify multiple events. For example:
|
||||
*
|
||||
* container.on({
|
||||
* tap : this.onTap,
|
||||
* swipe: this.onSwipe,
|
||||
*
|
||||
* scope: this // Important. Ensure "this" is correct during handler execution
|
||||
* });
|
||||
*
|
||||
* One can also specify options for each event handler separately:
|
||||
*
|
||||
* container.on({
|
||||
* tap : { fn: this.onTap, scope: this, single: true },
|
||||
* swipe: { fn: button.onSwipe, scope: button }
|
||||
* });
|
||||
*
|
||||
* See the [Events Guide](#!/guide/events) for more.
|
||||
*
|
||||
* @param {String/String[]/Object} eventName The name of the event to listen for. May also be an object who's property names are
|
||||
* event names.
|
||||
* @param {Function} fn The method the event invokes. Will be called with arguments given to
|
||||
* {@link #fireEvent} plus the `options` parameter described below.
|
||||
* @param {Object} [scope] The scope (`this` reference) in which the handler function is executed. **If
|
||||
* omitted, defaults to the object which fired the event.**
|
||||
* @param {Object} [options] An object containing handler configuration.
|
||||
*
|
||||
* This object may contain any of the following properties:
|
||||
|
||||
* @param {Object} [options.scope] The scope (`this` reference) in which the handler function is executed. If omitted, defaults to the object
|
||||
* which fired the event.
|
||||
* @param {Number} [options.delay] The number of milliseconds to delay the invocation of the handler after the event fires.
|
||||
* @param {Boolean} [options.single] `true` to add a handler to handle just the next firing of the event, and then remove itself.
|
||||
* @param {String} [options.order=current] The order of when the listener should be added into the listener queue.
|
||||
*
|
||||
* If you set an order of `before` and the event you are listening to is preventable, you can return `false` and it will stop the event.
|
||||
*
|
||||
* Available options are `before`, `current` and `after`.
|
||||
*
|
||||
* @param {Number} [options.buffer] Causes the handler to be delayed by the specified number of milliseconds. If the event fires again within that
|
||||
* time, the original handler is _not_ invoked, but the new handler is scheduled in its place.
|
||||
* @param {String} [options.element] Allows you to add a listener onto a element of this component using the elements reference.
|
||||
*
|
||||
* Ext.create('Ext.Component', {
|
||||
* listeners: {
|
||||
* element: 'element',
|
||||
* tap: function() {
|
||||
* alert('element tap!');
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* All components have the `element` reference, which is the outer most element of the component. {@link Ext.Container} also has the
|
||||
* `innerElement` element which contains all children. In most cases `element` is adequate.
|
||||
*
|
||||
* @param {String} [options.delegate] Uses {@link Ext.ComponentQuery} to delegate events to a specified query selector within this item.
|
||||
*
|
||||
* // Create a container with a two children; a button and a toolbar
|
||||
* var container = Ext.create('Ext.Container', {
|
||||
* items: [
|
||||
* {
|
||||
* xtype: 'toolbar',
|
||||
* docked: 'top',
|
||||
* title: 'My Toolbar'
|
||||
* },
|
||||
* {
|
||||
* xtype: 'button',
|
||||
* text: 'My Button'
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* container.on({
|
||||
* // Ext.Buttons have an xtype of 'button', so we use that are a selector for our delegate
|
||||
* delegate: 'button',
|
||||
*
|
||||
* tap: function() {
|
||||
* alert('Button tapped!');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @param {String} [order='current'] The order of when the listener should be added into the listener queue.
|
||||
* Possible values are `before`, `current` and `after`.
|
||||
*/
|
||||
addListener: function(eventName, fn, scope, options, order) {
|
||||
return this.changeListener(this.doAddListener, eventName, fn, scope, options, order);
|
||||
},
|
||||
|
||||
toggleListener: function(toggle, eventName, fn, scope, options, order) {
|
||||
return this.changeListener(toggle ? this.doAddListener : this.doRemoveListener, eventName, fn, scope, options, order);
|
||||
},
|
||||
|
||||
/**
|
||||
* Appends a before-event handler. Returning `false` from the handler will stop the event.
|
||||
*
|
||||
* Same as {@link #addListener} with `order` set to `'before'`.
|
||||
*
|
||||
* @param {String/String[]/Object} eventName The name of the event to listen for.
|
||||
* @param {Function} fn The method the event invokes.
|
||||
* @param {Object} [scope] The scope for `fn`.
|
||||
* @param {Object} [options] An object containing handler configuration.
|
||||
*/
|
||||
addBeforeListener: function(eventName, fn, scope, options) {
|
||||
return this.addListener(eventName, fn, scope, options, 'before');
|
||||
},
|
||||
|
||||
/**
|
||||
* Appends an after-event handler.
|
||||
*
|
||||
* Same as {@link #addListener} with `order` set to `'after'`.
|
||||
*
|
||||
* @param {String/String[]/Object} eventName The name of the event to listen for.
|
||||
* @param {Function} fn The method the event invokes.
|
||||
* @param {Object} [scope] The scope for `fn`.
|
||||
* @param {Object} [options] An object containing handler configuration.
|
||||
*/
|
||||
addAfterListener: function(eventName, fn, scope, options) {
|
||||
return this.addListener(eventName, fn, scope, options, 'after');
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes an event handler.
|
||||
*
|
||||
* @param {String/String[]/Object} eventName The type of event the handler was associated with.
|
||||
* @param {Function} fn The handler to remove. **This must be a reference to the function passed into the
|
||||
* {@link #addListener} call.**
|
||||
* @param {Object} [scope] The scope originally specified for the handler. It must be the same as the
|
||||
* scope argument specified in the original call to {@link #addListener} or the listener will not be removed.
|
||||
* @param {Object} [options] Extra options object. See {@link #addListener} for details.
|
||||
* @param {String} [order='current'] The order of the listener to remove.
|
||||
* Possible values are `before`, `current` and `after`.
|
||||
*/
|
||||
removeListener: function(eventName, fn, scope, options, order) {
|
||||
return this.changeListener(this.doRemoveListener, eventName, fn, scope, options, order);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a before-event handler.
|
||||
*
|
||||
* Same as {@link #removeListener} with `order` set to `'before'`.
|
||||
*
|
||||
* @param {String/String[]/Object} eventName The name of the event the handler was associated with.
|
||||
* @param {Function} fn The handler to remove.
|
||||
* @param {Object} [scope] The scope originally specified for `fn`.
|
||||
* @param {Object} [options] Extra options object.
|
||||
*/
|
||||
removeBeforeListener: function(eventName, fn, scope, options) {
|
||||
return this.removeListener(eventName, fn, scope, options, 'before');
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a before-event handler.
|
||||
*
|
||||
* Same as {@link #removeListener} with `order` set to `'after'`.
|
||||
*
|
||||
* @param {String/String[]/Object} eventName The name of the event the handler was associated with.
|
||||
* @param {Function} fn The handler to remove.
|
||||
* @param {Object} [scope] The scope originally specified for `fn`.
|
||||
* @param {Object} [options] Extra options object.
|
||||
*/
|
||||
removeAfterListener: function(eventName, fn, scope, options) {
|
||||
return this.removeListener(eventName, fn, scope, options, 'after');
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all listeners for this object.
|
||||
*/
|
||||
clearListeners: function() {
|
||||
var usedSelectors = this.getUsedSelectors(),
|
||||
dispatcher = this.getEventDispatcher(),
|
||||
i, ln, selector;
|
||||
|
||||
for (i = 0,ln = usedSelectors.length; i < ln; i++) {
|
||||
selector = usedSelectors[i];
|
||||
|
||||
dispatcher.clearListeners(this.observableType, selector);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks to see if this object has any listeners for a specified event
|
||||
*
|
||||
* @param {String} eventName The name of the event to check for
|
||||
* @return {Boolean} True if the event is being listened for, else false
|
||||
*/
|
||||
hasListener: function(eventName) {
|
||||
return this.getEventDispatcher().hasListener(this.observableType, this.getObservableId(), eventName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Suspends the firing of all events. (see {@link #resumeEvents})
|
||||
*
|
||||
* @param {Boolean} queueSuspended Pass as true to queue up suspended events to be fired
|
||||
* after the {@link #resumeEvents} call instead of discarding all suspended events.
|
||||
*/
|
||||
suspendEvents: function(queueSuspended) {
|
||||
this.eventFiringSuspended = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resumes firing events (see {@link #suspendEvents}).
|
||||
*
|
||||
* If events were suspended using the `queueSuspended` parameter, then all events fired
|
||||
* during event suspension will be sent to any listeners now.
|
||||
*/
|
||||
resumeEvents: function() {
|
||||
this.eventFiringSuspended = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Relays selected events from the specified Observable as if the events were fired by `this`.
|
||||
* @param {Object} object The Observable whose events this object is to relay.
|
||||
* @param {String/Array/Object} events Array of event names to relay.
|
||||
*/
|
||||
relayEvents: function(object, events, prefix) {
|
||||
var i, ln, oldName, newName;
|
||||
|
||||
if (typeof prefix == 'undefined') {
|
||||
prefix = '';
|
||||
}
|
||||
|
||||
if (typeof events == 'string') {
|
||||
events = [events];
|
||||
}
|
||||
|
||||
if (Ext.isArray(events)) {
|
||||
for (i = 0,ln = events.length; i < ln; i++) {
|
||||
oldName = events[i];
|
||||
newName = prefix + oldName;
|
||||
|
||||
object.addListener(oldName, this.createEventRelayer(newName), this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (oldName in events) {
|
||||
if (events.hasOwnProperty(oldName)) {
|
||||
newName = prefix + events[oldName];
|
||||
|
||||
object.addListener(oldName, this.createEventRelayer(newName), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param args
|
||||
* @param fn
|
||||
*/
|
||||
relayEvent: function(args, fn, scope, options, order) {
|
||||
var fnType = typeof fn,
|
||||
controller = args[args.length - 1],
|
||||
eventName = controller.getInfo().eventName,
|
||||
action;
|
||||
|
||||
args = Array.prototype.slice.call(args, 0, -2);
|
||||
args[0] = this;
|
||||
|
||||
if (fnType != 'undefined') {
|
||||
action = {
|
||||
fn: fn,
|
||||
scope: scope || this,
|
||||
options: options || {},
|
||||
order: order,
|
||||
isLateBinding: fnType == 'string'
|
||||
};
|
||||
}
|
||||
|
||||
return this.doFireEvent(eventName, args, action, controller);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Creates an event handling function which re-fires the event from this object as the passed event name.
|
||||
* @param newName
|
||||
* @return {Function}
|
||||
*/
|
||||
createEventRelayer: function(newName){
|
||||
return function() {
|
||||
return this.doFireEvent(newName, Array.prototype.slice.call(arguments, 0, -2));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables events fired by this Observable to bubble up an owner hierarchy by calling `this.getBubbleTarget()` if
|
||||
* present. There is no implementation in the Observable base class.
|
||||
*
|
||||
* @param {String/String[]} events The event name to bubble, or an Array of event names.
|
||||
*/
|
||||
enableBubble: function(events) {
|
||||
var isBubblingEnabled = this.isBubblingEnabled,
|
||||
i, ln, name;
|
||||
|
||||
if (!isBubblingEnabled) {
|
||||
isBubblingEnabled = this.isBubblingEnabled = {};
|
||||
}
|
||||
|
||||
if (typeof events == 'string') {
|
||||
events = Ext.Array.clone(arguments);
|
||||
}
|
||||
|
||||
for (i = 0,ln = events.length; i < ln; i++) {
|
||||
name = events[i];
|
||||
|
||||
if (!isBubblingEnabled[name]) {
|
||||
isBubblingEnabled[name] = true;
|
||||
this.addListener(name, this.createEventBubbler(name), this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
createEventBubbler: function(name) {
|
||||
return function doBubbleEvent() {
|
||||
var bubbleTarget = ('getBubbleTarget' in this) ? this.getBubbleTarget() : null;
|
||||
|
||||
if (bubbleTarget && bubbleTarget !== this && bubbleTarget.isObservable) {
|
||||
bubbleTarget.fireAction(name, Array.prototype.slice.call(arguments, 0, -2), doBubbleEvent, bubbleTarget, null, 'after');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getBubbleTarget: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this.observableId) {
|
||||
this.fireEvent('destroy', this);
|
||||
this.clearListeners();
|
||||
this.clearManagedListeners();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
addEvents: Ext.emptyFn
|
||||
|
||||
}, function() {
|
||||
this.createAlias({
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #addListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#addListener
|
||||
*/
|
||||
on: 'addListener',
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #removeListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#removeListener
|
||||
*/
|
||||
un: 'removeListener',
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #addBeforeListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#addBeforeListener
|
||||
*/
|
||||
onBefore: 'addBeforeListener',
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #addAfterListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#addAfterListener
|
||||
*/
|
||||
onAfter: 'addAfterListener',
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #removeBeforeListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#removeBeforeListener
|
||||
*/
|
||||
unBefore: 'removeBeforeListener',
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #removeAfterListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#removeAfterListener
|
||||
*/
|
||||
unAfter: 'removeAfterListener'
|
||||
});
|
||||
|
||||
//<deprecated product=touch since=2.0>
|
||||
/**
|
||||
* @method addEvents
|
||||
* Adds the specified events to the list of events which this Observable may fire.
|
||||
* @param {Object/String...} eventNames Either an object with event names as properties with a value of `true`
|
||||
* or the first event name string if multiple event names are being passed as separate parameters.
|
||||
* @deprecated 2.0 It's no longer needed to add events before firing.
|
||||
*/
|
||||
Ext.deprecateClassMethod(this, 'addEvents', function(){}, "addEvents() is deprecated. It's no longer needed to add events before firing");
|
||||
|
||||
/**
|
||||
* @method addManagedListener
|
||||
* Adds listeners to any Observable object (or Element) which are automatically removed when this Component
|
||||
* is destroyed.
|
||||
* @param {Ext.mixin.Observable/HTMLElement} object The item to which to add a listener/listeners.
|
||||
* @param {Object/String} eventName The event name, or an object containing event name properties.
|
||||
* @param {Function} [fn] If the `eventName` parameter was an event name, this is the handler function.
|
||||
* @param {Object} [scope] If the `eventName` parameter was an event name, this is the scope in which
|
||||
* the handler function is executed.
|
||||
* @param {Object} [options] If the `eventName` parameter was an event name, this is the
|
||||
* {@link #addListener} options.
|
||||
* @deprecated 2.0 All listeners are now automatically managed where necessary. Simply use {@link #addListener}.
|
||||
*/
|
||||
Ext.deprecateClassMethod(this, 'addManagedListener', function(object, eventName, fn, scope, options) {
|
||||
return object.addListener(eventName, fn, scope, options);
|
||||
}, "addManagedListener() / mon() is deprecated, simply use addListener() / on(). All listeners are now automatically managed where necessary.");
|
||||
|
||||
/**
|
||||
* @method removeManagedListener
|
||||
* Adds listeners to any Observable object (or Element) which are automatically removed when this Component
|
||||
* is destroyed.
|
||||
* @param {Ext.mixin.Observable/HTMLElement} object The item to which to add a listener/listeners.
|
||||
* @param {Object/String} eventName The event name, or an object containing event name properties.
|
||||
* @param {Function} [fn] If the `eventName` parameter was an event name, this is the handler function.
|
||||
* @param {Object} [scope] If the `eventName` parameter was an event name, this is the scope in which
|
||||
* the handler function is executed.
|
||||
* @deprecated 2.0 All listeners are now automatically managed where necessary. Simply use {@link #removeListener}.
|
||||
*/
|
||||
Ext.deprecateClassMethod(this, 'removeManagedListener', function(object, eventName, fn, scope) {
|
||||
return object.removeListener(eventName, fn, scope);
|
||||
}, "removeManagedListener() / mun() is deprecated, simply use removeListener() / un(). All listeners are now automatically managed where necessary.");
|
||||
|
||||
this.createAlias({
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #addManagedListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#addManagedListener
|
||||
* @deprecated 2.0.0 This is now done automatically
|
||||
*/
|
||||
mon: 'addManagedListener',
|
||||
/**
|
||||
* @method
|
||||
* Alias for {@link #removeManagedListener}.
|
||||
* @inheritdoc Ext.mixin.Observable#removeManagedListener
|
||||
* @deprecated 2.0.0 This is now done automatically
|
||||
*/
|
||||
mun: 'removeManagedListener'
|
||||
});
|
||||
//</deprecated>
|
||||
});
|
||||
538
OfficeWeb/vendor/touch/src/mixin/Selectable.js
vendored
Normal file
538
OfficeWeb/vendor/touch/src/mixin/Selectable.js
vendored
Normal file
@@ -0,0 +1,538 @@
|
||||
/**
|
||||
* Tracks what records are currently selected in a databound widget. This class is mixed in to {@link Ext.dataview.DataView} and
|
||||
* all subclasses.
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.mixin.Selectable', {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
mixinConfig: {
|
||||
id: 'selectable',
|
||||
hooks: {
|
||||
updateStore: 'updateStore'
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @event beforeselectionchange
|
||||
* Fires before an item is selected.
|
||||
* @param {Ext.mixin.Selectable} this
|
||||
* @preventable selectionchange
|
||||
* @deprecated 2.0.0 Please listen to the {@link #selectionchange} event with an order of `before` instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event selectionchange
|
||||
* Fires when a selection changes.
|
||||
* @param {Ext.mixin.Selectable} this
|
||||
* @param {Ext.data.Model[]} records The records whose selection has changed.
|
||||
*/
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Boolean} disableSelection `true` to disable selection.
|
||||
* This configuration will lock the selection model that the DataView uses.
|
||||
* @accessor
|
||||
*/
|
||||
disableSelection: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} mode
|
||||
* Modes of selection.
|
||||
* Valid values are `'SINGLE'`, `'SIMPLE'`, and `'MULTI'`.
|
||||
* @accessor
|
||||
*/
|
||||
mode: 'SINGLE',
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} allowDeselect
|
||||
* Allow users to deselect a record in a DataView, List or Grid. Only applicable when the Selectable's `mode` is
|
||||
* `'SINGLE'`.
|
||||
* @accessor
|
||||
*/
|
||||
allowDeselect: false,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.data.Model} lastSelected
|
||||
* @private
|
||||
* @accessor
|
||||
*/
|
||||
lastSelected: null,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.data.Model} lastFocused
|
||||
* @private
|
||||
* @accessor
|
||||
*/
|
||||
lastFocused: null,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} deselectOnContainerClick `true` to deselect current selection when the container body is
|
||||
* clicked.
|
||||
* @accessor
|
||||
*/
|
||||
deselectOnContainerClick: true
|
||||
},
|
||||
|
||||
modes: {
|
||||
SINGLE: true,
|
||||
SIMPLE: true,
|
||||
MULTI: true
|
||||
},
|
||||
|
||||
selectableEventHooks: {
|
||||
addrecords: 'onSelectionStoreAdd',
|
||||
removerecords: 'onSelectionStoreRemove',
|
||||
updaterecord: 'onSelectionStoreUpdate',
|
||||
load: 'refreshSelection',
|
||||
refresh: 'refreshSelection'
|
||||
},
|
||||
|
||||
constructor: function() {
|
||||
this.selected = new Ext.util.MixedCollection();
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyMode: function(mode) {
|
||||
mode = mode ? mode.toUpperCase() : 'SINGLE';
|
||||
// set to mode specified unless it doesnt exist, in that case
|
||||
// use single.
|
||||
return this.modes[mode] ? mode : 'SINGLE';
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateStore: function(newStore, oldStore) {
|
||||
var me = this,
|
||||
bindEvents = Ext.apply({}, me.selectableEventHooks, { scope: me });
|
||||
|
||||
if (oldStore && Ext.isObject(oldStore) && oldStore.isStore) {
|
||||
if (oldStore.autoDestroy) {
|
||||
oldStore.destroy();
|
||||
}
|
||||
else {
|
||||
oldStore.un(bindEvents);
|
||||
newStore.un('clear', 'onSelectionStoreClear', this);
|
||||
}
|
||||
}
|
||||
|
||||
if (newStore) {
|
||||
newStore.on(bindEvents);
|
||||
newStore.onBefore('clear', 'onSelectionStoreClear', this);
|
||||
me.refreshSelection();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects all records.
|
||||
* @param {Boolean} silent `true` to suppress all select events.
|
||||
*/
|
||||
selectAll: function(silent) {
|
||||
var me = this,
|
||||
selections = me.getStore().getRange(),
|
||||
ln = selections.length,
|
||||
i = 0;
|
||||
for (; i < ln; i++) {
|
||||
me.select(selections[i], true, silent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Deselects all records.
|
||||
*/
|
||||
deselectAll: function(supress) {
|
||||
var me = this,
|
||||
selections = me.getStore().getRange();
|
||||
|
||||
me.deselect(selections, supress);
|
||||
|
||||
me.selected.clear();
|
||||
me.setLastSelected(null);
|
||||
me.setLastFocused(null);
|
||||
},
|
||||
|
||||
// Provides differentiation of logic between MULTI, SIMPLE and SINGLE
|
||||
// selection modes.
|
||||
selectWithEvent: function(record) {
|
||||
var me = this,
|
||||
isSelected = me.isSelected(record);
|
||||
switch (me.getMode()) {
|
||||
case 'MULTI':
|
||||
case 'SIMPLE':
|
||||
if (isSelected) {
|
||||
me.deselect(record);
|
||||
}
|
||||
else {
|
||||
me.select(record, true);
|
||||
}
|
||||
break;
|
||||
case 'SINGLE':
|
||||
if (me.getAllowDeselect() && isSelected) {
|
||||
// if allowDeselect is on and this record isSelected, deselect it
|
||||
me.deselect(record);
|
||||
} else {
|
||||
// select the record and do NOT maintain existing selections
|
||||
me.select(record, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects a range of rows if the selection model {@link Ext.mixin.Selectable#getDisableSelection} is not locked.
|
||||
* All rows in between `startRow` and `endRow` are also selected.
|
||||
* @param {Number} startRow The index of the first row in the range.
|
||||
* @param {Number} endRow The index of the last row in the range.
|
||||
* @param {Boolean} keepExisting (optional) `true` to retain existing selections.
|
||||
*/
|
||||
selectRange: function(startRecord, endRecord, keepExisting) {
|
||||
var me = this,
|
||||
store = me.getStore(),
|
||||
records = [],
|
||||
tmp, i;
|
||||
|
||||
if (me.getDisableSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// swap values
|
||||
if (startRecord > endRecord) {
|
||||
tmp = endRecord;
|
||||
endRecord = startRecord;
|
||||
startRecord = tmp;
|
||||
}
|
||||
|
||||
for (i = startRecord; i <= endRecord; i++) {
|
||||
records.push(store.getAt(i));
|
||||
}
|
||||
this.doMultiSelect(records, keepExisting);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the given records to the currently selected set.
|
||||
* @param {Ext.data.Model/Array/Number} records The records to select.
|
||||
* @param {Boolean} keepExisting If `true`, the existing selection will be added to (if not, the old selection is replaced).
|
||||
* @param {Boolean} suppressEvent If `true`, the `select` event will not be fired.
|
||||
*/
|
||||
select: function(records, keepExisting, suppressEvent) {
|
||||
var me = this,
|
||||
record;
|
||||
|
||||
if (me.getDisableSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof records === "number") {
|
||||
records = [me.getStore().getAt(records)];
|
||||
}
|
||||
|
||||
if (!records) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.getMode() == "SINGLE" && records) {
|
||||
record = records.length ? records[0] : records;
|
||||
me.doSingleSelect(record, suppressEvent);
|
||||
} else {
|
||||
me.doMultiSelect(records, keepExisting, suppressEvent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects a single record.
|
||||
* @private
|
||||
*/
|
||||
doSingleSelect: function(record, suppressEvent) {
|
||||
var me = this,
|
||||
selected = me.selected;
|
||||
|
||||
if (me.getDisableSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// already selected.
|
||||
// should we also check beforeselect?
|
||||
if (me.isSelected(record)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected.getCount() > 0) {
|
||||
me.deselect(me.getLastSelected(), suppressEvent);
|
||||
}
|
||||
|
||||
selected.add(record);
|
||||
me.setLastSelected(record);
|
||||
me.onItemSelect(record, suppressEvent);
|
||||
me.setLastFocused(record);
|
||||
|
||||
if (!suppressEvent) {
|
||||
me.fireSelectionChange([record]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects a set of multiple records.
|
||||
* @private
|
||||
*/
|
||||
doMultiSelect: function(records, keepExisting, suppressEvent) {
|
||||
if (records === null || this.getDisableSelection()) {
|
||||
return;
|
||||
}
|
||||
records = !Ext.isArray(records) ? [records] : records;
|
||||
|
||||
var me = this,
|
||||
selected = me.selected,
|
||||
ln = records.length,
|
||||
change = false,
|
||||
i = 0,
|
||||
record;
|
||||
|
||||
if (!keepExisting && selected.getCount() > 0) {
|
||||
change = true;
|
||||
me.deselect(me.getSelection(), true);
|
||||
}
|
||||
for (; i < ln; i++) {
|
||||
record = records[i];
|
||||
if (keepExisting && me.isSelected(record)) {
|
||||
continue;
|
||||
}
|
||||
change = true;
|
||||
me.setLastSelected(record);
|
||||
selected.add(record);
|
||||
if (!suppressEvent) {
|
||||
me.setLastFocused(record);
|
||||
}
|
||||
|
||||
me.onItemSelect(record, suppressEvent);
|
||||
}
|
||||
if (change && !suppressEvent) {
|
||||
this.fireSelectionChange(records);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Deselects the given record(s). If many records are currently selected, it will only deselect those you pass in.
|
||||
* @param {Number/Array/Ext.data.Model} records The record(s) to deselect. Can also be a number to reference by index.
|
||||
* @param {Boolean} suppressEvent If `true` the `deselect` event will not be fired.
|
||||
*/
|
||||
deselect: function(records, suppressEvent) {
|
||||
var me = this;
|
||||
|
||||
if (me.getDisableSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
records = Ext.isArray(records) ? records : [records];
|
||||
|
||||
var selected = me.selected,
|
||||
change = false,
|
||||
i = 0,
|
||||
store = me.getStore(),
|
||||
ln = records.length,
|
||||
record;
|
||||
|
||||
for (; i < ln; i++) {
|
||||
record = records[i];
|
||||
|
||||
if (typeof record === 'number') {
|
||||
record = store.getAt(record);
|
||||
}
|
||||
|
||||
if (selected.remove(record)) {
|
||||
if (me.getLastSelected() == record) {
|
||||
me.setLastSelected(selected.last());
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
if (record) {
|
||||
me.onItemDeselect(record, suppressEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (change && !suppressEvent) {
|
||||
me.fireSelectionChange(records);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a record as the last focused record. This does NOT mean
|
||||
* that the record has been selected.
|
||||
* @param {Ext.data.Record} newRecord
|
||||
* @param {Ext.data.Record} oldRecord
|
||||
*/
|
||||
updateLastFocused: function(newRecord, oldRecord) {
|
||||
this.onLastFocusChanged(oldRecord, newRecord);
|
||||
},
|
||||
|
||||
fireSelectionChange: function(records) {
|
||||
var me = this;
|
||||
//<deprecated product=touch since=2.0>
|
||||
me.fireAction('beforeselectionchange', [me], function() {
|
||||
//</deprecated>
|
||||
me.fireAction('selectionchange', [me, records], 'getSelection');
|
||||
//<deprecated product=touch since=2.0>
|
||||
});
|
||||
//</deprecated>
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of the currently selected records.
|
||||
* @return {Array} An array of selected records.
|
||||
*/
|
||||
getSelection: function() {
|
||||
return this.selected.getRange();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns `true` if the specified row is selected.
|
||||
* @param {Ext.data.Model/Number} record The record or index of the record to check.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isSelected: function(record) {
|
||||
record = Ext.isNumber(record) ? this.getStore().getAt(record) : record;
|
||||
return this.selected.indexOf(record) !== -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns `true` if there is a selected record.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
hasSelection: function() {
|
||||
return this.selected.getCount() > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
refreshSelection: function() {
|
||||
var me = this,
|
||||
selections = me.getSelection();
|
||||
|
||||
me.deselectAll(true);
|
||||
if (selections.length) {
|
||||
me.select(selections, false, true);
|
||||
}
|
||||
},
|
||||
|
||||
// prune records from the SelectionModel if
|
||||
// they were selected at the time they were
|
||||
// removed.
|
||||
onSelectionStoreRemove: function(store, records) {
|
||||
var me = this,
|
||||
selected = me.selected,
|
||||
ln = records.length,
|
||||
record, i;
|
||||
|
||||
if (me.getDisableSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ln; i++) {
|
||||
record = records[i];
|
||||
if (selected.remove(record)) {
|
||||
if (me.getLastSelected() == record) {
|
||||
me.setLastSelected(null);
|
||||
}
|
||||
if (me.getLastFocused() == record) {
|
||||
me.setLastFocused(null);
|
||||
}
|
||||
me.fireSelectionChange([record]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onSelectionStoreClear: function(store) {
|
||||
var records = store.getData().items;
|
||||
this.onSelectionStoreRemove(store, records);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the number of selections.
|
||||
* @return {Number}
|
||||
*/
|
||||
getSelectionCount: function() {
|
||||
return this.selected.getCount();
|
||||
},
|
||||
|
||||
onSelectionStoreAdd: Ext.emptyFn,
|
||||
onSelectionStoreUpdate: Ext.emptyFn,
|
||||
onItemSelect: Ext.emptyFn,
|
||||
onItemDeselect: Ext.emptyFn,
|
||||
onLastFocusChanged: Ext.emptyFn,
|
||||
onEditorKey: Ext.emptyFn
|
||||
}, function() {
|
||||
/**
|
||||
* Selects a record instance by record instance or index.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method doSelect
|
||||
* @param {Ext.data.Model/Number} records An array of records or an index.
|
||||
* @param {Boolean} keepExisting
|
||||
* @param {Boolean} suppressEvent Set to `false` to not fire a select event.
|
||||
* @deprecated 2.0.0 Please use {@link #select} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deselects a record instance by record instance or index.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method doDeselect
|
||||
* @param {Ext.data.Model/Number} records An array of records or an index.
|
||||
* @param {Boolean} suppressEvent Set to `false` to not fire a deselect event.
|
||||
* @deprecated 2.0.0 Please use {@link #deselect} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the selection mode currently used by this Selectable.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method getSelectionMode
|
||||
* @return {String} The current mode.
|
||||
* @deprecated 2.0.0 Please use {@link #getMode} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the array of previously selected items.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method getLastSelected
|
||||
* @return {Array} The previous selection.
|
||||
* @deprecated 2.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns `true` if the Selectable is currently locked.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method isLocked
|
||||
* @return {Boolean} True if currently locked
|
||||
* @deprecated 2.0.0 Please use {@link #getDisableSelection} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This was an internal function accidentally exposed in 1.x and now deprecated. Calling it has no effect
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method setLastFocused
|
||||
* @deprecated 2.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deselects any currently selected records and clears all stored selections.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method clearSelections
|
||||
* @deprecated 2.0.0 Please use {@link #deselectAll} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the number of selections.
|
||||
* @member Ext.mixin.Selectable
|
||||
* @method getCount
|
||||
* @return {Number}
|
||||
* @deprecated 2.0.0 Please use {@link #getSelectionCount} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} locked
|
||||
* @inheritdoc Ext.mixin.Selectable#disableSelection
|
||||
* @deprecated 2.0.0 Please use {@link #disableSelection} instead.
|
||||
*/
|
||||
});
|
||||
344
OfficeWeb/vendor/touch/src/mixin/Sortable.js
vendored
Normal file
344
OfficeWeb/vendor/touch/src/mixin/Sortable.js
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.mixin.Sortable', {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
requires: [
|
||||
'Ext.util.Sorter'
|
||||
],
|
||||
|
||||
mixinConfig: {
|
||||
id: 'sortable'
|
||||
},
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Array} sorters
|
||||
* An array with sorters. A sorter can be an instance of {@link Ext.util.Sorter}, a string
|
||||
* indicating a property name, an object representing an Ext.util.Sorter configuration,
|
||||
* or a sort function.
|
||||
*/
|
||||
sorters: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} defaultSortDirection
|
||||
* The default sort direction to use if one is not specified.
|
||||
*/
|
||||
defaultSortDirection: "ASC",
|
||||
|
||||
/**
|
||||
* @cfg {String} sortRoot
|
||||
* The root inside each item in which the properties exist that we want to sort on.
|
||||
* This is useful for sorting records in which the data exists inside a `data` property.
|
||||
*/
|
||||
sortRoot: null
|
||||
},
|
||||
|
||||
/**
|
||||
* @property {Boolean} dirtySortFn
|
||||
* A flag indicating whether the currently cashed sort function is still valid.
|
||||
* @readonly
|
||||
*/
|
||||
dirtySortFn: false,
|
||||
|
||||
/**
|
||||
* @property currentSortFn
|
||||
* This is the cached sorting function which is a generated function that calls all the
|
||||
* configured sorters in the correct order.
|
||||
* @readonly
|
||||
*/
|
||||
sortFn: null,
|
||||
|
||||
/**
|
||||
* @property {Boolean} sorted
|
||||
* A read-only flag indicating if this object is sorted.
|
||||
* @readonly
|
||||
*/
|
||||
sorted: false,
|
||||
|
||||
applySorters: function(sorters, collection) {
|
||||
if (!collection) {
|
||||
collection = this.createSortersCollection();
|
||||
}
|
||||
|
||||
collection.clear();
|
||||
this.sorted = false;
|
||||
|
||||
if (sorters) {
|
||||
this.addSorters(sorters);
|
||||
}
|
||||
|
||||
return collection;
|
||||
},
|
||||
|
||||
createSortersCollection: function() {
|
||||
this._sorters = Ext.create('Ext.util.Collection', function(sorter) {
|
||||
return sorter.getId();
|
||||
});
|
||||
return this._sorters;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method adds a sorter.
|
||||
* @param {Ext.util.Sorter/String/Function/Object} sorter Can be an instance of
|
||||
* Ext.util.Sorter, a string indicating a property name, an object representing an Ext.util.Sorter
|
||||
* configuration, or a sort function.
|
||||
* @param {String} defaultDirection The default direction for each sorter in the array. Defaults
|
||||
* to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
|
||||
*/
|
||||
addSorter: function(sorter, defaultDirection) {
|
||||
this.addSorters([sorter], defaultDirection);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method adds all the sorters in a passed array.
|
||||
* @param {Array} sorters An array with sorters. A sorter can be an instance of Ext.util.Sorter, a string
|
||||
* indicating a property name, an object representing an Ext.util.Sorter configuration,
|
||||
* or a sort function.
|
||||
* @param {String} defaultDirection The default direction for each sorter in the array. Defaults
|
||||
* to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
|
||||
*/
|
||||
addSorters: function(sorters, defaultDirection) {
|
||||
var currentSorters = this.getSorters();
|
||||
return this.insertSorters(currentSorters ? currentSorters.length : 0, sorters, defaultDirection);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method adds a sorter at a given index.
|
||||
* @param {Number} index The index at which to insert the sorter.
|
||||
* @param {Ext.util.Sorter/String/Function/Object} sorter Can be an instance of Ext.util.Sorter,
|
||||
* a string indicating a property name, an object representing an Ext.util.Sorter configuration,
|
||||
* or a sort function.
|
||||
* @param {String} defaultDirection The default direction for each sorter in the array. Defaults
|
||||
* to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
|
||||
*/
|
||||
insertSorter: function(index, sorter, defaultDirection) {
|
||||
return this.insertSorters(index, [sorter], defaultDirection);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method inserts all the sorters in the passed array at the given index.
|
||||
* @param {Number} index The index at which to insert the sorters.
|
||||
* @param {Array} sorters Can be an instance of Ext.util.Sorter, a string indicating a property name,
|
||||
* an object representing an Ext.util.Sorter configuration, or a sort function.
|
||||
* @param {String} defaultDirection The default direction for each sorter in the array. Defaults
|
||||
* to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
|
||||
*/
|
||||
insertSorters: function(index, sorters, defaultDirection) {
|
||||
// We begin by making sure we are dealing with an array of sorters
|
||||
if (!Ext.isArray(sorters)) {
|
||||
sorters = [sorters];
|
||||
}
|
||||
|
||||
var ln = sorters.length,
|
||||
direction = defaultDirection || this.getDefaultSortDirection(),
|
||||
sortRoot = this.getSortRoot(),
|
||||
currentSorters = this.getSorters(),
|
||||
newSorters = [],
|
||||
sorterConfig, i, sorter, currentSorter;
|
||||
|
||||
if (!currentSorters) {
|
||||
// This will guarantee that we get the collection
|
||||
currentSorters = this.createSortersCollection();
|
||||
}
|
||||
|
||||
// We first have to convert every sorter into a proper Sorter instance
|
||||
for (i = 0; i < ln; i++) {
|
||||
sorter = sorters[i];
|
||||
sorterConfig = {
|
||||
direction: direction,
|
||||
root: sortRoot
|
||||
};
|
||||
|
||||
// If we are dealing with a string we assume it is a property they want to sort on.
|
||||
if (typeof sorter === 'string') {
|
||||
currentSorter = currentSorters.get(sorter);
|
||||
|
||||
if (!currentSorter) {
|
||||
sorterConfig.property = sorter;
|
||||
} else {
|
||||
if (defaultDirection) {
|
||||
currentSorter.setDirection(defaultDirection);
|
||||
} else {
|
||||
// If we already have a sorter for this property we just toggle its direction.
|
||||
currentSorter.toggle();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// If it is a function, we assume its a sorting function.
|
||||
else if (Ext.isFunction(sorter)) {
|
||||
sorterConfig.sorterFn = sorter;
|
||||
}
|
||||
// If we are dealing with an object, we assume its a Sorter configuration. In this case
|
||||
// we create an instance of Sorter passing this configuration.
|
||||
else if (Ext.isObject(sorter)) {
|
||||
if (!sorter.isSorter) {
|
||||
if (sorter.fn) {
|
||||
sorter.sorterFn = sorter.fn;
|
||||
delete sorter.fn;
|
||||
}
|
||||
|
||||
sorterConfig = Ext.apply(sorterConfig, sorter);
|
||||
}
|
||||
else {
|
||||
newSorters.push(sorter);
|
||||
if (!sorter.getRoot()) {
|
||||
sorter.setRoot(sortRoot);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Finally we get to the point where it has to be invalid
|
||||
// <debug>
|
||||
else {
|
||||
Ext.Logger.warn('Invalid sorter specified:', sorter);
|
||||
}
|
||||
// </debug>
|
||||
|
||||
// If a sorter config was created, make it an instance
|
||||
sorter = Ext.create('Ext.util.Sorter', sorterConfig);
|
||||
newSorters.push(sorter);
|
||||
}
|
||||
|
||||
// Now lets add the newly created sorters.
|
||||
for (i = 0, ln = newSorters.length; i < ln; i++) {
|
||||
currentSorters.insert(index + i, newSorters[i]);
|
||||
}
|
||||
|
||||
this.dirtySortFn = true;
|
||||
|
||||
if (currentSorters.length) {
|
||||
this.sorted = true;
|
||||
}
|
||||
return currentSorters;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method removes a sorter.
|
||||
* @param {Ext.util.Sorter/String/Function/Object} sorter Can be an instance of Ext.util.Sorter,
|
||||
* a string indicating a property name, an object representing an Ext.util.Sorter configuration,
|
||||
* or a sort function.
|
||||
*/
|
||||
removeSorter: function(sorter) {
|
||||
return this.removeSorters([sorter]);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method removes all the sorters in a passed array.
|
||||
* @param {Array} sorters Each value in the array can be a string (property name),
|
||||
* function (sorterFn) or {@link Ext.util.Sorter Sorter} instance.
|
||||
*/
|
||||
removeSorters: function(sorters) {
|
||||
// We begin by making sure we are dealing with an array of sorters
|
||||
if (!Ext.isArray(sorters)) {
|
||||
sorters = [sorters];
|
||||
}
|
||||
|
||||
var ln = sorters.length,
|
||||
currentSorters = this.getSorters(),
|
||||
i, sorter;
|
||||
|
||||
for (i = 0; i < ln; i++) {
|
||||
sorter = sorters[i];
|
||||
|
||||
if (typeof sorter === 'string') {
|
||||
currentSorters.removeAtKey(sorter);
|
||||
}
|
||||
else if (typeof sorter === 'function') {
|
||||
currentSorters.each(function(item) {
|
||||
if (item.getSorterFn() === sorter) {
|
||||
currentSorters.remove(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (sorter.isSorter) {
|
||||
currentSorters.remove(sorter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentSorters.length) {
|
||||
this.sorted = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This updates the cached sortFn based on the current sorters.
|
||||
* @return {Function} The generated sort function.
|
||||
* @private
|
||||
*/
|
||||
updateSortFn: function() {
|
||||
var sorters = this.getSorters().items;
|
||||
|
||||
this.sortFn = function(r1, r2) {
|
||||
var ln = sorters.length,
|
||||
result, i;
|
||||
|
||||
// We loop over each sorter and check if r1 should be before or after r2
|
||||
for (i = 0; i < ln; i++) {
|
||||
result = sorters[i].sort.call(this, r1, r2);
|
||||
|
||||
// If the result is -1 or 1 at this point it means that the sort is done.
|
||||
// Only if they are equal (0) we continue to see if a next sort function
|
||||
// actually might find a winner.
|
||||
if (result !== 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
this.dirtySortFn = false;
|
||||
return this.sortFn;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an up to date sort function.
|
||||
* @return {Function} The sort function.
|
||||
*/
|
||||
getSortFn: function() {
|
||||
if (this.dirtySortFn) {
|
||||
return this.updateSortFn();
|
||||
}
|
||||
return this.sortFn;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method will sort an array based on the currently configured {@link #sorters}.
|
||||
* @param {Array} data The array you want to have sorted.
|
||||
* @return {Array} The array you passed after it is sorted.
|
||||
*/
|
||||
sort: function(data) {
|
||||
Ext.Array.sort(data, this.getSortFn());
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method returns the index that a given item would be inserted into a given array based
|
||||
* on the current sorters.
|
||||
* @param {Array} items The array that you want to insert the item into.
|
||||
* @param {Mixed} item The item that you want to insert into the items array.
|
||||
* @return {Number} The index for the given item in the given array based on the current sorters.
|
||||
*/
|
||||
findInsertionIndex: function(items, item, sortFn) {
|
||||
var start = 0,
|
||||
end = items.length - 1,
|
||||
sorterFn = sortFn || this.getSortFn(),
|
||||
middle,
|
||||
comparison;
|
||||
|
||||
while (start <= end) {
|
||||
middle = (start + end) >> 1;
|
||||
comparison = sorterFn(item, items[middle]);
|
||||
if (comparison >= 0) {
|
||||
start = middle + 1;
|
||||
} else if (comparison < 0) {
|
||||
end = middle - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
});
|
||||
54
OfficeWeb/vendor/touch/src/mixin/Templatable.js
vendored
Normal file
54
OfficeWeb/vendor/touch/src/mixin/Templatable.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.mixin.Templatable', {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
mixinConfig: {
|
||||
id: 'templatable'
|
||||
},
|
||||
|
||||
referenceAttributeName: 'reference',
|
||||
|
||||
referenceSelector: '[reference]',
|
||||
|
||||
getElementConfig: function() {
|
||||
return {
|
||||
reference: 'element'
|
||||
};
|
||||
},
|
||||
|
||||
getElementTemplate: function() {
|
||||
var elementTemplate = document.createDocumentFragment();
|
||||
elementTemplate.appendChild(Ext.Element.create(this.getElementConfig(), true));
|
||||
return elementTemplate;
|
||||
},
|
||||
|
||||
initElement: function() {
|
||||
var prototype = this.self.prototype;
|
||||
|
||||
prototype.elementTemplate = this.getElementTemplate();
|
||||
prototype.initElement = prototype.doInitElement;
|
||||
|
||||
this.initElement.apply(this, arguments);
|
||||
},
|
||||
|
||||
linkElement: function(reference, node) {
|
||||
this.link(reference, node);
|
||||
},
|
||||
|
||||
doInitElement: function() {
|
||||
var referenceAttributeName = this.referenceAttributeName,
|
||||
renderElement, referenceNodes, i, ln, referenceNode, reference;
|
||||
|
||||
renderElement = this.elementTemplate.cloneNode(true);
|
||||
referenceNodes = renderElement.querySelectorAll(this.referenceSelector);
|
||||
|
||||
for (i = 0,ln = referenceNodes.length; i < ln; i++) {
|
||||
referenceNode = referenceNodes[i];
|
||||
reference = referenceNode.getAttribute(referenceAttributeName);
|
||||
referenceNode.removeAttribute(referenceAttributeName);
|
||||
this.linkElement(reference, referenceNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
59
OfficeWeb/vendor/touch/src/mixin/Traversable.js
vendored
Normal file
59
OfficeWeb/vendor/touch/src/mixin/Traversable.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* A Traversable mixin.
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.mixin.Traversable', {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
|
||||
mixinConfig: {
|
||||
id: 'traversable'
|
||||
},
|
||||
|
||||
setParent: function(parent) {
|
||||
this.parent = parent;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @member Ext.Component
|
||||
* Returns `true` if this component has a parent.
|
||||
* @return {Boolean} `true` if this component has a parent.
|
||||
*/
|
||||
hasParent: function() {
|
||||
return Boolean(this.parent);
|
||||
},
|
||||
|
||||
/**
|
||||
* @member Ext.Component
|
||||
* Returns the parent of this component, if it has one.
|
||||
* @return {Ext.Component} The parent of this component.
|
||||
*/
|
||||
getParent: function() {
|
||||
return this.parent;
|
||||
},
|
||||
|
||||
getAncestors: function() {
|
||||
var ancestors = [],
|
||||
parent = this.getParent();
|
||||
|
||||
while (parent) {
|
||||
ancestors.push(parent);
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
return ancestors;
|
||||
},
|
||||
|
||||
getAncestorIds: function() {
|
||||
var ancestorIds = [],
|
||||
parent = this.getParent();
|
||||
|
||||
while (parent) {
|
||||
ancestorIds.push(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
return ancestorIds;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user