3.0 source code
This commit is contained in:
739
OfficeWeb/vendor/touch/src/util/AbstractMixedCollection.js
vendored
Normal file
739
OfficeWeb/vendor/touch/src/util/AbstractMixedCollection.js
vendored
Normal file
@@ -0,0 +1,739 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.AbstractMixedCollection', {
|
||||
requires: ['Ext.util.Filter'],
|
||||
|
||||
mixins: {
|
||||
observable: 'Ext.mixin.Observable'
|
||||
},
|
||||
|
||||
/**
|
||||
* @event clear
|
||||
* Fires when the collection is cleared.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event add
|
||||
* Fires when an item is added to the collection.
|
||||
* @param {Number} index The index at which the item was added.
|
||||
* @param {Object} o The item added.
|
||||
* @param {String} key The key associated with the added item.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event replace
|
||||
* Fires when an item is replaced in the collection.
|
||||
* @param {String} key he key associated with the new added.
|
||||
* @param {Object} old The item being replaced.
|
||||
* @param {Object} new The new item.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event remove
|
||||
* Fires when an item is removed from the collection.
|
||||
* @param {Object} o The item being removed.
|
||||
* @param {String} key (optional) The key associated with the removed item.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates new MixedCollection.
|
||||
* @param {Boolean} [allowFunctions=false] Specify `true` if the {@link #addAll}
|
||||
* function should add function references to the collection.
|
||||
* @param {Function} [keyFn] A function that can accept an item of the type(s) stored in this MixedCollection
|
||||
* and return the key value for that item. This is used when available to look up the key on items that
|
||||
* were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
|
||||
* equivalent to providing an implementation for the {@link #getKey} method.
|
||||
*/
|
||||
constructor: function(allowFunctions, keyFn) {
|
||||
var me = this;
|
||||
|
||||
me.items = [];
|
||||
me.map = {};
|
||||
me.keys = [];
|
||||
me.length = 0;
|
||||
|
||||
me.allowFunctions = allowFunctions === true;
|
||||
|
||||
if (keyFn) {
|
||||
me.getKey = keyFn;
|
||||
}
|
||||
|
||||
me.mixins.observable.constructor.call(me);
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} allowFunctions Specify `true` if the {@link #addAll}
|
||||
* function should add function references to the collection.
|
||||
*/
|
||||
allowFunctions : false,
|
||||
|
||||
/**
|
||||
* Adds an item to the collection. Fires the {@link #event-add} event when complete.
|
||||
* @param {String} key The key to associate with the item, or the new item.
|
||||
*
|
||||
* If a {@link #getKey} implementation was specified for this MixedCollection,
|
||||
* or if the key of the stored items is in a property called `id`,
|
||||
* the MixedCollection will be able to _derive_ the key for the new item.
|
||||
* In this case just pass the new item in this parameter.
|
||||
* @param {Object} o The item to add.
|
||||
* @return {Object} The item added.
|
||||
*/
|
||||
add: function(key, obj){
|
||||
var me = this,
|
||||
myObj = obj,
|
||||
myKey = key,
|
||||
old;
|
||||
|
||||
if (arguments.length == 1) {
|
||||
myObj = myKey;
|
||||
myKey = me.getKey(myObj);
|
||||
}
|
||||
if (typeof myKey != 'undefined' && myKey !== null) {
|
||||
old = me.map[myKey];
|
||||
if (typeof old != 'undefined') {
|
||||
return me.replace(myKey, myObj);
|
||||
}
|
||||
me.map[myKey] = myObj;
|
||||
}
|
||||
me.length++;
|
||||
me.items.push(myObj);
|
||||
me.keys.push(myKey);
|
||||
me.fireEvent('add', me.length - 1, myObj, myKey);
|
||||
return myObj;
|
||||
},
|
||||
|
||||
/**
|
||||
* MixedCollection has a generic way to fetch keys if you implement `getKey`. The default implementation
|
||||
* simply returns `item.id` but you can provide your own implementation
|
||||
* to return a different value as in the following examples:
|
||||
*
|
||||
* // normal way
|
||||
* var mc = new Ext.util.MixedCollection();
|
||||
* mc.add(someEl.dom.id, someEl);
|
||||
* mc.add(otherEl.dom.id, otherEl);
|
||||
* //and so on
|
||||
*
|
||||
* // using getKey
|
||||
* var mc = new Ext.util.MixedCollection();
|
||||
* mc.getKey = function(el) {
|
||||
* return el.dom.id;
|
||||
* };
|
||||
* mc.add(someEl);
|
||||
* mc.add(otherEl);
|
||||
*
|
||||
* // or via the constructor
|
||||
* var mc = new Ext.util.MixedCollection(false, function(el) {
|
||||
* return el.dom.id;
|
||||
* });
|
||||
* mc.add(someEl);
|
||||
* mc.add(otherEl);
|
||||
*
|
||||
* @param {Object} item The item for which to find the key.
|
||||
* @return {Object} The key for the passed item.
|
||||
*/
|
||||
getKey: function(o){
|
||||
return o.id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces an item in the collection. Fires the {@link #event-replace} event when complete.
|
||||
* @param {String} key The key associated with the item to replace, or the replacement item.
|
||||
*
|
||||
* If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key
|
||||
* of your stored items is in a property called `id`, then the MixedCollection
|
||||
* will be able to _derive_ the key of the replacement item. If you want to replace an item
|
||||
* with one having the same key value, then just pass the replacement item in this parameter.
|
||||
* @param {Object} o (optional) If the first parameter passed was a key, the item to associate
|
||||
* with that key.
|
||||
* @return {Object} The new item.
|
||||
*/
|
||||
replace: function(key, o){
|
||||
var me = this,
|
||||
old,
|
||||
index;
|
||||
|
||||
if (arguments.length == 1) {
|
||||
o = arguments[0];
|
||||
key = me.getKey(o);
|
||||
}
|
||||
old = me.map[key];
|
||||
if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
|
||||
return me.add(key, o);
|
||||
}
|
||||
index = me.indexOfKey(key);
|
||||
me.items[index] = o;
|
||||
me.map[key] = o;
|
||||
me.fireEvent('replace', key, old, o);
|
||||
return o;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds all elements of an Array or an Object to the collection.
|
||||
* @param {Object/Array} objs An Object containing properties which will be added
|
||||
* to the collection, or an Array of values, each of which are added to the collection.
|
||||
* Functions references will be added to the collection if `{@link #allowFunctions}`
|
||||
* has been set to `true`.
|
||||
*/
|
||||
addAll: function(objs){
|
||||
var me = this,
|
||||
i = 0,
|
||||
args,
|
||||
len,
|
||||
key;
|
||||
|
||||
if (arguments.length > 1 || Ext.isArray(objs)) {
|
||||
args = arguments.length > 1 ? arguments : objs;
|
||||
for (len = args.length; i < len; i++) {
|
||||
me.add(args[i]);
|
||||
}
|
||||
} else {
|
||||
for (key in objs) {
|
||||
if (objs.hasOwnProperty(key)) {
|
||||
if (me.allowFunctions || typeof objs[key] != 'function') {
|
||||
me.add(key, objs[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes the specified function once for every item in the collection.
|
||||
*
|
||||
* @param {Function} fn The function to execute for each item.
|
||||
* @param {Mixed} fn.item The collection item.
|
||||
* @param {Number} fn.index The item's index.
|
||||
* @param {Number} fn.length The total number of items in the collection.
|
||||
* @param {Boolean} fn.return Returning `false` will stop the iteration.
|
||||
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
|
||||
* Defaults to the current item in the iteration.
|
||||
*/
|
||||
each: function(fn, scope){
|
||||
var items = [].concat(this.items), // each safe for removal
|
||||
i = 0,
|
||||
len = items.length,
|
||||
item;
|
||||
|
||||
for (; i < len; i++) {
|
||||
item = items[i];
|
||||
if (fn.call(scope || item, item, i, len) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes the specified function once for every key in the collection, passing each
|
||||
* key, and its associated item as the first two parameters.
|
||||
* @param {Function} fn The function to execute for each item.
|
||||
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed. Defaults to the browser window.
|
||||
*/
|
||||
eachKey: function(fn, scope){
|
||||
var keys = this.keys,
|
||||
items = this.items,
|
||||
i = 0,
|
||||
len = keys.length;
|
||||
|
||||
for (; i < len; i++) {
|
||||
fn.call(scope || window, keys[i], items[i], i, len);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the first item in the collection which elicits a `true` return value from the
|
||||
* passed selection function.
|
||||
* @param {Function} fn The selection function to execute for each item.
|
||||
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed. Defaults to the browser window.
|
||||
* @return {Object} The first item in the collection which returned `true` from the selection function.
|
||||
*/
|
||||
findBy: function(fn, scope) {
|
||||
var keys = this.keys,
|
||||
items = this.items,
|
||||
i = 0,
|
||||
len = items.length;
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (fn.call(scope || window, items[i], keys[i])) {
|
||||
return items[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts an item at the specified index in the collection. Fires the `{@link #event-add}` event when complete.
|
||||
* @param {Number} index The index to insert the item at.
|
||||
* @param {String} key The key to associate with the new item, or the item itself.
|
||||
* @param {Object} o (optional) If the second parameter was a key, the new item.
|
||||
* @return {Object} The item inserted.
|
||||
*/
|
||||
insert: function(index, key, obj){
|
||||
var me = this,
|
||||
myKey = key,
|
||||
myObj = obj;
|
||||
|
||||
if (arguments.length == 2) {
|
||||
myObj = myKey;
|
||||
myKey = me.getKey(myObj);
|
||||
}
|
||||
if (me.containsKey(myKey)) {
|
||||
me.suspendEvents();
|
||||
me.removeAtKey(myKey);
|
||||
me.resumeEvents();
|
||||
}
|
||||
if (index >= me.length) {
|
||||
return me.add(myKey, myObj);
|
||||
}
|
||||
me.length++;
|
||||
Ext.Array.splice(me.items, index, 0, myObj);
|
||||
if (typeof myKey != 'undefined' && myKey !== null) {
|
||||
me.map[myKey] = myObj;
|
||||
}
|
||||
Ext.Array.splice(me.keys, index, 0, myKey);
|
||||
me.fireEvent('add', index, myObj, myKey);
|
||||
return myObj;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an item from the collection.
|
||||
* @param {Object} o The item to remove.
|
||||
* @return {Object} The item removed or `false` if no item was removed.
|
||||
*/
|
||||
remove: function(o){
|
||||
return this.removeAt(this.indexOf(o));
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove all items in the passed array from the collection.
|
||||
* @param {Array} items An array of items to be removed.
|
||||
* @return {Ext.util.MixedCollection} this object
|
||||
*/
|
||||
removeAll: function(items){
|
||||
Ext.each(items || [], function(item) {
|
||||
this.remove(item);
|
||||
}, this);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an item from a specified index in the collection. Fires the `{@link #event-remove}` event when complete.
|
||||
* @param {Number} index The index within the collection of the item to remove.
|
||||
* @return {Object/Boolean} The item removed or `false` if no item was removed.
|
||||
*/
|
||||
removeAt: function(index){
|
||||
var me = this,
|
||||
o,
|
||||
key;
|
||||
|
||||
if (index < me.length && index >= 0) {
|
||||
me.length--;
|
||||
o = me.items[index];
|
||||
Ext.Array.erase(me.items, index, 1);
|
||||
key = me.keys[index];
|
||||
if (typeof key != 'undefined') {
|
||||
delete me.map[key];
|
||||
}
|
||||
Ext.Array.erase(me.keys, index, 1);
|
||||
me.fireEvent('remove', o, key);
|
||||
return o;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removed an item associated with the passed key from the collection.
|
||||
* @param {String} key The key of the item to remove.
|
||||
* @return {Object/Boolean} The item removed or `false` if no item was removed.
|
||||
*/
|
||||
removeAtKey: function(key){
|
||||
return this.removeAt(this.indexOfKey(key));
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the number of items in the collection.
|
||||
* @return {Number} the number of items in the collection.
|
||||
*/
|
||||
getCount: function(){
|
||||
return this.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns index within the collection of the passed Object.
|
||||
* @param {Object} o The item to find the index of.
|
||||
* @return {Number} index of the item. Returns -1 if not found.
|
||||
*/
|
||||
indexOf: function(o){
|
||||
return Ext.Array.indexOf(this.items, o);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns index within the collection of the passed key.
|
||||
* @param {String} key The key to find the index of.
|
||||
* @return {Number} The index of the key.
|
||||
*/
|
||||
indexOfKey: function(key){
|
||||
return Ext.Array.indexOf(this.keys, key);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the item associated with the passed key OR index.
|
||||
* Key has priority over index. This is the equivalent
|
||||
* of calling {@link #getByKey} first, then if nothing matched calling {@link #getAt}.
|
||||
* @param {String/Number} key The key or index of the item.
|
||||
* @return {Object} If the item is found, returns the item. If the item was not found, returns `undefined`.
|
||||
* If an item was found, but is a Class, returns `null`.
|
||||
*/
|
||||
get: function(key) {
|
||||
var me = this,
|
||||
mk = me.map[key],
|
||||
item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined;
|
||||
return typeof item != 'function' || me.allowFunctions ? item : null; // for prototype!
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the item at the specified index.
|
||||
* @param {Number} index The index of the item.
|
||||
* @return {Object} The item at the specified index.
|
||||
*/
|
||||
getAt: function(index) {
|
||||
return this.items[index];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the item associated with the passed key.
|
||||
* @param {String/Number} key The key of the item.
|
||||
* @return {Object} The item associated with the passed key.
|
||||
*/
|
||||
getByKey: function(key) {
|
||||
return this.map[key];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns `true` if the collection contains the passed Object as an item.
|
||||
* @param {Object} o The Object to look for in the collection.
|
||||
* @return {Boolean} `true` if the collection contains the Object as an item.
|
||||
*/
|
||||
contains: function(o){
|
||||
return Ext.Array.contains(this.items, o);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns `true` if the collection contains the passed Object as a key.
|
||||
* @param {String} key The key to look for in the collection.
|
||||
* @return {Boolean} `true` if the collection contains the Object as a key.
|
||||
*/
|
||||
containsKey: function(key){
|
||||
return typeof this.map[key] != 'undefined';
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all items from the collection. Fires the `{@link #event-clear}` event when complete.
|
||||
*/
|
||||
clear: function(){
|
||||
var me = this;
|
||||
|
||||
me.length = 0;
|
||||
me.items = [];
|
||||
me.keys = [];
|
||||
me.map = {};
|
||||
me.fireEvent('clear');
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the first item in the collection.
|
||||
* @return {Object} the first item in the collection..
|
||||
*/
|
||||
first: function() {
|
||||
return this.items[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the last item in the collection.
|
||||
* @return {Object} the last item in the collection..
|
||||
*/
|
||||
last: function() {
|
||||
return this.items[this.length - 1];
|
||||
},
|
||||
|
||||
/**
|
||||
* Collects all of the values of the given property and returns their sum.
|
||||
* @param {String} property The property to sum by.
|
||||
* @param {String} [root] Optional 'root' property to extract the first argument from. This is used mainly when
|
||||
* summing fields in records, where the fields are all stored inside the `data` object
|
||||
* @param {Number} [start=0] (optional) The record index to start at.
|
||||
* @param {Number} [end=-1] (optional) The record index to end at.
|
||||
* @return {Number} The total
|
||||
*/
|
||||
sum: function(property, root, start, end) {
|
||||
var values = this.extractValues(property, root),
|
||||
length = values.length,
|
||||
sum = 0,
|
||||
i;
|
||||
|
||||
start = start || 0;
|
||||
end = (end || end === 0) ? end : length - 1;
|
||||
|
||||
for (i = start; i <= end; i++) {
|
||||
sum += values[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
},
|
||||
|
||||
/**
|
||||
* Collects unique values of a particular property in this MixedCollection.
|
||||
* @param {String} property The property to collect on.
|
||||
* @param {String} [root] Optional 'root' property to extract the first argument from. This is used mainly when
|
||||
* summing fields in records, where the fields are all stored inside the `data` object.
|
||||
* @param {Boolean} allowBlank (optional) Pass `true` to allow `null`, `undefined`, or empty string values.
|
||||
* @return {Array} The unique values.
|
||||
*/
|
||||
collect: function(property, root, allowNull) {
|
||||
var values = this.extractValues(property, root),
|
||||
length = values.length,
|
||||
hits = {},
|
||||
unique = [],
|
||||
value, strValue, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
value = values[i];
|
||||
strValue = String(value);
|
||||
|
||||
if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
|
||||
hits[strValue] = true;
|
||||
unique.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
return unique;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Extracts all of the given property values from the items in the MixedCollection. Mainly used as a supporting method for
|
||||
* functions like `sum()` and `collect()`.
|
||||
* @param {String} property The property to extract.
|
||||
* @param {String} [root] Optional 'root' property to extract the first argument from. This is used mainly when
|
||||
* extracting field data from Model instances, where the fields are stored inside the `data` object.
|
||||
* @return {Array} The extracted values.
|
||||
*/
|
||||
extractValues: function(property, root) {
|
||||
var values = this.items;
|
||||
|
||||
if (root) {
|
||||
values = Ext.Array.pluck(values, root);
|
||||
}
|
||||
|
||||
return Ext.Array.pluck(values, property);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a range of items in this collection.
|
||||
* @param {Number} [startIndex=0] (optional) The starting index.
|
||||
* @param {Number} [endIndex=-1] (optional) The ending index.
|
||||
* @return {Array} An array of items
|
||||
*/
|
||||
getRange: function(start, end){
|
||||
var me = this,
|
||||
items = me.items,
|
||||
range = [],
|
||||
i;
|
||||
|
||||
if (items.length < 1) {
|
||||
return range;
|
||||
}
|
||||
|
||||
start = start || 0;
|
||||
end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
|
||||
if (start <= end) {
|
||||
for (i = start; i <= end; i++) {
|
||||
range[range.length] = items[i];
|
||||
}
|
||||
} else {
|
||||
for (i = start; i >= end; i--) {
|
||||
range[range.length] = items[i];
|
||||
}
|
||||
}
|
||||
return range;
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters the objects in this collection by a set of {@link Ext.util.Filter Filter}s, or by a single
|
||||
* property/value pair with optional parameters for substring matching and case sensitivity. See
|
||||
* {@link Ext.util.Filter Filter} for an example of using Filter objects (preferred). Alternatively,
|
||||
* MixedCollection can be easily filtered by property like this:
|
||||
*
|
||||
* // create a simple store with a few people defined
|
||||
* var people = new Ext.util.MixedCollection();
|
||||
* people.addAll([
|
||||
* {id: 1, age: 25, name: 'Ed'},
|
||||
* {id: 2, age: 24, name: 'Tommy'},
|
||||
* {id: 3, age: 24, name: 'Arne'},
|
||||
* {id: 4, age: 26, name: 'Aaron'}
|
||||
* ]);
|
||||
*
|
||||
* // a new MixedCollection containing only the items where age == 24
|
||||
* var middleAged = people.filter('age', 24);
|
||||
*
|
||||
* @param {Ext.util.Filter[]/String} property A property on your objects, or an array of {@link Ext.util.Filter Filter} objects
|
||||
* @param {String/RegExp} value Either string that the property values
|
||||
* should start with or a RegExp to test against the property.
|
||||
* @param {Boolean} anyMatch (optional) `true` to match any part of the string, not just the beginning
|
||||
* @param {Boolean} [caseSensitive=false] (optional) `true` for case sensitive comparison.
|
||||
* @return {Ext.util.MixedCollection} The new filtered collection
|
||||
*/
|
||||
filter: function(property, value, anyMatch, caseSensitive) {
|
||||
var filters = [],
|
||||
filterFn;
|
||||
|
||||
//support for the simple case of filtering by property/value
|
||||
if (Ext.isString(property)) {
|
||||
filters.push(Ext.create('Ext.util.Filter', {
|
||||
property : property,
|
||||
value : value,
|
||||
anyMatch : anyMatch,
|
||||
caseSensitive: caseSensitive
|
||||
}));
|
||||
} else if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
|
||||
filters = filters.concat(property);
|
||||
}
|
||||
|
||||
//at this point we have an array of zero or more Ext.util.Filter objects to filter with,
|
||||
//so here we construct a function that combines these filters by ANDing them together
|
||||
filterFn = function(record) {
|
||||
var isMatch = true,
|
||||
length = filters.length,
|
||||
i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
var filter = filters[i],
|
||||
fn = filter.getFilterFn(),
|
||||
scope = filter.getScope();
|
||||
|
||||
isMatch = isMatch && fn.call(scope, record);
|
||||
}
|
||||
|
||||
return isMatch;
|
||||
};
|
||||
|
||||
return this.filterBy(filterFn);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter by a function. Returns a _new_ collection that has been filtered.
|
||||
* The passed function will be called with each object in the collection.
|
||||
* If the function returns `true`, the value is included otherwise it is filtered.
|
||||
* @param {Function} fn The function to be called, it will receive the args `o` (the object), `k` (the key)
|
||||
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed. Defaults to this MixedCollection.
|
||||
* @return {Ext.util.MixedCollection} The new filtered collection.
|
||||
*/
|
||||
filterBy: function(fn, scope) {
|
||||
var me = this,
|
||||
newMC = new this.self(),
|
||||
keys = me.keys,
|
||||
items = me.items,
|
||||
length = items.length,
|
||||
i;
|
||||
|
||||
newMC.getKey = me.getKey;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (fn.call(scope || me, items[i], keys[i])) {
|
||||
newMC.add(keys[i], items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return newMC;
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the index of the first matching object in this collection by a specific property/value.
|
||||
* @param {String} property The name of a property on your objects.
|
||||
* @param {String/RegExp} value A string that the property values.
|
||||
* should start with or a RegExp to test against the property.
|
||||
* @param {Number} [start=0] (optional) The index to start searching at.
|
||||
* @param {Boolean} anyMatch (optional) `true` to match any part of the string, not just the beginning.
|
||||
* @param {Boolean} caseSensitive (optional) `true` for case sensitive comparison.
|
||||
* @return {Number} The matched index or -1.
|
||||
*/
|
||||
findIndex: function(property, value, start, anyMatch, caseSensitive){
|
||||
if(Ext.isEmpty(value, false)){
|
||||
return -1;
|
||||
}
|
||||
value = this.createValueMatcher(value, anyMatch, caseSensitive);
|
||||
return this.findIndexBy(function(o){
|
||||
return o && value.test(o[property]);
|
||||
}, null, start);
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the index of the first matching object in this collection by a function.
|
||||
* If the function returns `true` it is considered a match.
|
||||
* @param {Function} fn The function to be called, it will receive the args `o` (the object), `k` (the key).
|
||||
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed. Defaults to this MixedCollection.
|
||||
* @param {Number} [start=0] (optional) The index to start searching at.
|
||||
* @return {Number} The matched index or -1.
|
||||
*/
|
||||
findIndexBy: function(fn, scope, start){
|
||||
var me = this,
|
||||
keys = me.keys,
|
||||
items = me.items,
|
||||
i = start || 0,
|
||||
len = items.length;
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (fn.call(scope || me, items[i], keys[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a regular expression based on the given value and matching options. This is used internally for finding and filtering,
|
||||
* and by Ext.data.Store#filter
|
||||
* @private
|
||||
* @param {String} value The value to create the regex for. This is escaped using Ext.escapeRe
|
||||
* @param {Boolean} [anyMatch=false] `true` to allow any match - no regex start/end line anchors will be added.
|
||||
* @param {Boolean} [caseSensitive=false] `true` to make the regex case sensitive (adds 'i' switch to regex).
|
||||
* @param {Boolean} [exactMatch=false] `true` to force exact match (^ and $ characters added to the regex). Ignored if `anyMatch` is `true`.
|
||||
*/
|
||||
createValueMatcher: function(value, anyMatch, caseSensitive, exactMatch) {
|
||||
if (!value.exec) { // not a regex
|
||||
var er = Ext.String.escapeRegex;
|
||||
value = String(value);
|
||||
|
||||
if (anyMatch === true) {
|
||||
value = er(value);
|
||||
} else {
|
||||
value = '^' + er(value);
|
||||
if (exactMatch === true) {
|
||||
value += '$';
|
||||
}
|
||||
}
|
||||
value = new RegExp(value, caseSensitive ? '' : 'i');
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a shallow copy of this collection.
|
||||
* @return {Ext.util.MixedCollection}
|
||||
*/
|
||||
clone: function() {
|
||||
var me = this,
|
||||
copy = new this.self(),
|
||||
keys = me.keys,
|
||||
items = me.items,
|
||||
i = 0,
|
||||
len = items.length;
|
||||
|
||||
for(; i < len; i++){
|
||||
copy.add(keys[i], items[i]);
|
||||
}
|
||||
copy.getKey = me.getKey;
|
||||
return copy;
|
||||
}
|
||||
});
|
||||
1035
OfficeWeb/vendor/touch/src/util/Collection.js
vendored
Normal file
1035
OfficeWeb/vendor/touch/src/util/Collection.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
139
OfficeWeb/vendor/touch/src/util/DelayedTask.js
vendored
Normal file
139
OfficeWeb/vendor/touch/src/util/DelayedTask.js
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* The DelayedTask class provides a convenient way to "buffer" the execution of a method,
|
||||
* performing `setTimeout` where a new timeout cancels the old timeout. When called, the
|
||||
* task will wait the specified time period before executing. If during that time period,
|
||||
* the task is called again, the original call will be canceled. This continues so that
|
||||
* the function is only called a single time for each iteration.
|
||||
*
|
||||
* This method is especially useful for things like detecting whether a user has finished
|
||||
* typing in a text field. An example would be performing validation on a keypress. You can
|
||||
* use this class to buffer the keypress events for a certain number of milliseconds, and
|
||||
* perform only if they stop for that amount of time.
|
||||
*
|
||||
* Using {@link Ext.util.DelayedTask} is very simple:
|
||||
*
|
||||
* //create the delayed task instance with our callback
|
||||
* var task = Ext.create('Ext.util.DelayedTask', function() {
|
||||
* console.log('callback!');
|
||||
* });
|
||||
*
|
||||
* task.delay(1500); //the callback function will now be called after 1500ms
|
||||
*
|
||||
* task.cancel(); //the callback function will never be called now, unless we call delay() again
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* @example
|
||||
* //create a textfield where we can listen to text
|
||||
* var field = Ext.create('Ext.field.Text', {
|
||||
* xtype: 'textfield',
|
||||
* label: 'Length: 0'
|
||||
* });
|
||||
*
|
||||
* //add the textfield into a fieldset
|
||||
* Ext.Viewport.add({
|
||||
* xtype: 'formpanel',
|
||||
* items: [{
|
||||
* xtype: 'fieldset',
|
||||
* items: [field],
|
||||
* instructions: 'Type into the field and watch the count go up after 500ms.'
|
||||
* }]
|
||||
* });
|
||||
*
|
||||
* //create our delayed task with a function that returns the fields length as the fields label
|
||||
* var task = Ext.create('Ext.util.DelayedTask', function() {
|
||||
* field.setLabel('Length: ' + field.getValue().length);
|
||||
* });
|
||||
*
|
||||
* // Wait 500ms before calling our function. If the user presses another key
|
||||
* // during that 500ms, it will be canceled and we'll wait another 500ms.
|
||||
* field.on('keyup', function() {
|
||||
* task.delay(500);
|
||||
* });
|
||||
*
|
||||
* @constructor
|
||||
* The parameters to this constructor serve as defaults and are not required.
|
||||
* @param {Function} fn The default function to call.
|
||||
* @param {Object} scope The default scope (The `this` reference) in which the function is called. If
|
||||
* not specified, `this` will refer to the browser window.
|
||||
* @param {Array} args The default Array of arguments.
|
||||
*/
|
||||
Ext.define('Ext.util.DelayedTask', {
|
||||
config: {
|
||||
interval: null,
|
||||
delay: null,
|
||||
fn: null,
|
||||
scope: null,
|
||||
args: null
|
||||
},
|
||||
|
||||
constructor: function(fn, scope, args) {
|
||||
var config = {
|
||||
fn: fn,
|
||||
scope: scope,
|
||||
args: args
|
||||
};
|
||||
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels any pending timeout and queues a new one.
|
||||
* @param {Number} delay The milliseconds to delay
|
||||
* @param {Function} newFn Overrides the original function passed when instantiated.
|
||||
* @param {Object} newScope Overrides the original `scope` passed when instantiated. Remember that if no scope
|
||||
* is specified, `this` will refer to the browser window.
|
||||
* @param {Array} newArgs Overrides the original `args` passed when instantiated.
|
||||
*/
|
||||
delay: function(delay, newFn, newScope, newArgs) {
|
||||
var me = this;
|
||||
|
||||
//cancel any existing queued functions
|
||||
me.cancel();
|
||||
|
||||
//set all the new configurations
|
||||
me.setConfig({
|
||||
delay: delay,
|
||||
fn: newFn,
|
||||
scope: newScope,
|
||||
args: newArgs
|
||||
});
|
||||
|
||||
//create the callback method for this delayed task
|
||||
var call = function() {
|
||||
me.getFn().apply(me.getScope(), me.getArgs() || []);
|
||||
me.cancel();
|
||||
};
|
||||
|
||||
me.setInterval(setInterval(call, me.getDelay()));
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancel the last queued timeout
|
||||
*/
|
||||
cancel: function() {
|
||||
this.setInterval(null);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Clears the old interval
|
||||
*/
|
||||
updateInterval: function(newInterval, oldInterval) {
|
||||
if (oldInterval) {
|
||||
clearInterval(oldInterval);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Changes the value into an array if it isn't one.
|
||||
*/
|
||||
applyArgs: function(config) {
|
||||
if (!Ext.isArray(config)) {
|
||||
config = [config];
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
});
|
||||
415
OfficeWeb/vendor/touch/src/util/Draggable.js
vendored
Normal file
415
OfficeWeb/vendor/touch/src/util/Draggable.js
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
/**
|
||||
* A core util class to bring Draggable behavior to any DOM element
|
||||
*/
|
||||
Ext.define('Ext.util.Draggable', {
|
||||
isDraggable: true,
|
||||
|
||||
mixins: [
|
||||
'Ext.mixin.Observable'
|
||||
],
|
||||
|
||||
requires: [
|
||||
'Ext.util.Translatable'
|
||||
],
|
||||
|
||||
/**
|
||||
* @event dragstart
|
||||
* @preventable initDragStart
|
||||
* Fires whenever the component starts to be dragged
|
||||
* @param {Ext.util.Draggable} this
|
||||
* @param {Ext.event.Event} e the event object
|
||||
* @param {Number} offsetX The current offset value on the x axis
|
||||
* @param {Number} offsetY The current offset value on the y axis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event drag
|
||||
* Fires whenever the component is dragged
|
||||
* @param {Ext.util.Draggable} this
|
||||
* @param {Ext.event.Event} e the event object
|
||||
* @param {Number} offsetX The new offset value on the x axis
|
||||
* @param {Number} offsetY The new offset value on the y axis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event dragend
|
||||
* Fires whenever the component is dragged
|
||||
* @param {Ext.util.Draggable} this
|
||||
* @param {Ext.event.Event} e the event object
|
||||
* @param {Number} offsetX The current offset value on the x axis
|
||||
* @param {Number} offsetY The current offset value on the y axis
|
||||
*/
|
||||
|
||||
config: {
|
||||
cls: Ext.baseCSSPrefix + 'draggable',
|
||||
|
||||
draggingCls: Ext.baseCSSPrefix + 'dragging',
|
||||
|
||||
element: null,
|
||||
|
||||
constraint: 'container',
|
||||
|
||||
disabled: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} direction
|
||||
* Possible values: 'vertical', 'horizontal', or 'both'
|
||||
* @accessor
|
||||
*/
|
||||
direction: 'both',
|
||||
|
||||
/**
|
||||
* @cfg {Object/Number} initialOffset
|
||||
* The initial draggable offset. When specified as Number,
|
||||
* both x and y will be set to that value.
|
||||
*/
|
||||
initialOffset: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
|
||||
translatable: {}
|
||||
},
|
||||
|
||||
DIRECTION_BOTH: 'both',
|
||||
|
||||
DIRECTION_VERTICAL: 'vertical',
|
||||
|
||||
DIRECTION_HORIZONTAL: 'horizontal',
|
||||
|
||||
defaultConstraint: {
|
||||
min: { x: -Infinity, y: -Infinity },
|
||||
max: { x: Infinity, y: Infinity }
|
||||
},
|
||||
|
||||
containerWidth: 0,
|
||||
|
||||
containerHeight: 0,
|
||||
|
||||
width: 0,
|
||||
|
||||
height: 0,
|
||||
|
||||
/**
|
||||
* Creates new Draggable.
|
||||
* @param {Object} config The configuration object for this Draggable.
|
||||
*/
|
||||
constructor: function(config) {
|
||||
var element;
|
||||
|
||||
this.extraConstraint = {};
|
||||
|
||||
this.initialConfig = config;
|
||||
|
||||
this.offset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
this.listeners = {
|
||||
dragstart: 'onDragStart',
|
||||
drag : 'onDrag',
|
||||
dragend : 'onDragEnd',
|
||||
resize : 'onElementResize',
|
||||
scope: this
|
||||
};
|
||||
|
||||
if (config && config.element) {
|
||||
element = config.element;
|
||||
delete config.element;
|
||||
|
||||
this.setElement(element);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
applyElement: function(element) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Ext.get(element);
|
||||
},
|
||||
|
||||
updateElement: function(element) {
|
||||
element.on(this.listeners);
|
||||
|
||||
this.initConfig(this.initialConfig);
|
||||
},
|
||||
|
||||
updateInitialOffset: function(initialOffset) {
|
||||
if (typeof initialOffset == 'number') {
|
||||
initialOffset = {
|
||||
x: initialOffset,
|
||||
y: initialOffset
|
||||
};
|
||||
}
|
||||
|
||||
var offset = this.offset,
|
||||
x, y;
|
||||
|
||||
offset.x = x = initialOffset.x;
|
||||
offset.y = y = initialOffset.y;
|
||||
|
||||
this.getTranslatable().translate(x, y);
|
||||
},
|
||||
|
||||
updateCls: function(cls) {
|
||||
this.getElement().addCls(cls);
|
||||
},
|
||||
|
||||
applyTranslatable: function(translatable, currentInstance) {
|
||||
translatable = Ext.factory(translatable, Ext.util.Translatable, currentInstance);
|
||||
translatable.setElement(this.getElement());
|
||||
|
||||
return translatable;
|
||||
},
|
||||
|
||||
setExtraConstraint: function(constraint) {
|
||||
this.extraConstraint = constraint || {};
|
||||
|
||||
this.refreshConstraint();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addExtraConstraint: function(constraint) {
|
||||
Ext.merge(this.extraConstraint, constraint);
|
||||
|
||||
this.refreshConstraint();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
applyConstraint: function(newConstraint) {
|
||||
this.currentConstraint = newConstraint;
|
||||
|
||||
if (!newConstraint) {
|
||||
newConstraint = this.defaultConstraint;
|
||||
}
|
||||
|
||||
if (newConstraint === 'container') {
|
||||
return Ext.merge(this.getContainerConstraint(), this.extraConstraint);
|
||||
}
|
||||
|
||||
return Ext.merge({}, this.extraConstraint, newConstraint);
|
||||
},
|
||||
|
||||
updateConstraint: function() {
|
||||
this.refreshOffset();
|
||||
},
|
||||
|
||||
getContainerConstraint: function() {
|
||||
var container = this.getContainer(),
|
||||
element = this.getElement();
|
||||
|
||||
if (!container || !element.dom) {
|
||||
return this.defaultConstraint;
|
||||
}
|
||||
|
||||
return {
|
||||
min: { x: 0, y: 0 },
|
||||
max: { x: this.containerWidth - this.width, y: this.containerHeight - this.height }
|
||||
};
|
||||
},
|
||||
|
||||
getContainer: function() {
|
||||
var container = this.container;
|
||||
|
||||
if (!container) {
|
||||
container = this.getElement().getParent();
|
||||
|
||||
if (container) {
|
||||
this.container = container;
|
||||
|
||||
container.on({
|
||||
resize: 'onContainerResize',
|
||||
destroy: 'onContainerDestroy',
|
||||
scope: this
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
onElementResize: function(element, info) {
|
||||
this.width = info.width;
|
||||
this.height = info.height;
|
||||
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
onContainerResize: function(container, info) {
|
||||
this.containerWidth = info.width;
|
||||
this.containerHeight = info.height;
|
||||
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
onContainerDestroy: function() {
|
||||
delete this.container;
|
||||
delete this.containerSizeMonitor;
|
||||
},
|
||||
|
||||
detachListeners: function() {
|
||||
this.getElement().un(this.listeners);
|
||||
},
|
||||
|
||||
isAxisEnabled: function(axis) {
|
||||
var direction = this.getDirection();
|
||||
|
||||
if (axis === 'x') {
|
||||
return (direction === this.DIRECTION_BOTH || direction === this.DIRECTION_HORIZONTAL);
|
||||
}
|
||||
|
||||
return (direction === this.DIRECTION_BOTH || direction === this.DIRECTION_VERTICAL);
|
||||
},
|
||||
|
||||
onDragStart: function(e) {
|
||||
if (this.getDisabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var offset = this.offset;
|
||||
|
||||
this.fireAction('dragstart', [this, e, offset.x, offset.y], this.initDragStart);
|
||||
},
|
||||
|
||||
initDragStart: function(me, e, offsetX, offsetY) {
|
||||
this.dragStartOffset = {
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
};
|
||||
|
||||
this.isDragging = true;
|
||||
|
||||
this.getElement().addCls(this.getDraggingCls());
|
||||
},
|
||||
|
||||
onDrag: function(e) {
|
||||
if (!this.isDragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
var startOffset = this.dragStartOffset;
|
||||
|
||||
this.fireAction('drag', [this, e, startOffset.x + e.deltaX, startOffset.y + e.deltaY], this.doDrag);
|
||||
},
|
||||
|
||||
doDrag: function(me, e, offsetX, offsetY) {
|
||||
me.setOffset(offsetX, offsetY);
|
||||
},
|
||||
|
||||
onDragEnd: function(e) {
|
||||
if (!this.isDragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onDrag(e);
|
||||
|
||||
this.isDragging = false;
|
||||
|
||||
this.getElement().removeCls(this.getDraggingCls());
|
||||
|
||||
this.fireEvent('dragend', this, e, this.offset.x, this.offset.y);
|
||||
},
|
||||
|
||||
setOffset: function(x, y, animation) {
|
||||
var currentOffset = this.offset,
|
||||
constraint = this.getConstraint(),
|
||||
minOffset = constraint.min,
|
||||
maxOffset = constraint.max,
|
||||
min = Math.min,
|
||||
max = Math.max;
|
||||
|
||||
if (this.isAxisEnabled('x') && typeof x == 'number') {
|
||||
x = min(max(x, minOffset.x), maxOffset.x);
|
||||
}
|
||||
else {
|
||||
x = currentOffset.x;
|
||||
}
|
||||
|
||||
if (this.isAxisEnabled('y') && typeof y == 'number') {
|
||||
y = min(max(y, minOffset.y), maxOffset.y);
|
||||
}
|
||||
else {
|
||||
y = currentOffset.y;
|
||||
}
|
||||
|
||||
currentOffset.x = x;
|
||||
currentOffset.y = y;
|
||||
|
||||
this.getTranslatable().translate(x, y, animation);
|
||||
},
|
||||
|
||||
getOffset: function() {
|
||||
return this.offset;
|
||||
},
|
||||
|
||||
refreshConstraint: function() {
|
||||
this.setConstraint(this.currentConstraint);
|
||||
},
|
||||
|
||||
refreshOffset: function() {
|
||||
var offset = this.offset;
|
||||
|
||||
this.setOffset(offset.x, offset.y);
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
this.refreshConstraint();
|
||||
this.getTranslatable().refresh();
|
||||
this.refreshOffset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable the Draggable.
|
||||
* @return {Ext.util.Draggable} This Draggable instance
|
||||
*/
|
||||
enable: function() {
|
||||
return this.setDisabled(false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable the Draggable.
|
||||
* @return {Ext.util.Draggable} This Draggable instance
|
||||
*/
|
||||
disable: function() {
|
||||
return this.setDisabled(true);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var translatable = this.getTranslatable();
|
||||
|
||||
var element = this.getElement();
|
||||
if (element && !element.isDestroyed) {
|
||||
element.removeCls(this.getCls());
|
||||
}
|
||||
|
||||
this.detachListeners();
|
||||
|
||||
if (translatable) {
|
||||
translatable.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
}, function() {
|
||||
//<deprecated product=touch since=2.0>
|
||||
this.override({
|
||||
constructor: function(config) {
|
||||
if (config && config.constrain) {
|
||||
//<debug warn>
|
||||
Ext.Logger.deprecate("'constrain' config is deprecated, please use 'contraint' instead");
|
||||
//</debug>
|
||||
config.contraint = config.constrain;
|
||||
delete config.constrain;
|
||||
}
|
||||
|
||||
return this.callOverridden(arguments);
|
||||
}
|
||||
});
|
||||
//</deprecated>
|
||||
});
|
||||
|
||||
247
OfficeWeb/vendor/touch/src/util/Droppable.js
vendored
Normal file
247
OfficeWeb/vendor/touch/src/util/Droppable.js
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.util.Droppable', {
|
||||
mixins: {
|
||||
observable: 'Ext.mixin.Observable'
|
||||
},
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg
|
||||
* @inheritdoc
|
||||
*/
|
||||
baseCls: Ext.baseCSSPrefix + 'droppable'
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {String} activeCls
|
||||
* The CSS added to a Droppable when a Draggable in the same group is being
|
||||
* dragged.
|
||||
*/
|
||||
activeCls: Ext.baseCSSPrefix + 'drop-active',
|
||||
|
||||
/**
|
||||
* @cfg {String} invalidCls
|
||||
* The CSS class to add to the droppable when dragging a draggable that is
|
||||
* not in the same group.
|
||||
*/
|
||||
invalidCls: Ext.baseCSSPrefix + 'drop-invalid',
|
||||
|
||||
/**
|
||||
* @cfg {String} hoverCls
|
||||
* The CSS class to add to the droppable when hovering over a valid drop.
|
||||
*/
|
||||
hoverCls: Ext.baseCSSPrefix + 'drop-hover',
|
||||
|
||||
/**
|
||||
* @cfg {String} validDropMode
|
||||
* Determines when a drop is considered 'valid' whether it simply need to
|
||||
* intersect the region or if it needs to be contained within the region.
|
||||
* Valid values are: 'intersects' or 'contains'
|
||||
*/
|
||||
validDropMode: 'intersect',
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} disabled
|
||||
*/
|
||||
disabled: false,
|
||||
|
||||
/**
|
||||
* @cfg {String} group
|
||||
* Draggable and Droppable objects can participate in a group which are
|
||||
* capable of interacting.
|
||||
*/
|
||||
group: 'base',
|
||||
|
||||
// not yet implemented
|
||||
tolerance: null,
|
||||
|
||||
// @private
|
||||
monitoring: false,
|
||||
|
||||
/**
|
||||
* Creates new Droppable.
|
||||
* @param {Mixed} el String, HtmlElement or Ext.Element representing an
|
||||
* element on the page.
|
||||
* @param {Object} config Configuration options for this class.
|
||||
*/
|
||||
constructor: function(el, config) {
|
||||
var me = this;
|
||||
|
||||
config = config || {};
|
||||
Ext.apply(me, config);
|
||||
|
||||
/**
|
||||
* @event dropactivate
|
||||
* @param {Ext.util.Droppable} this
|
||||
* @param {Ext.util.Draggable} draggable
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event dropdeactivate
|
||||
* @param {Ext.util.Droppable} this
|
||||
* @param {Ext.util.Draggable} draggable
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event dropenter
|
||||
* @param {Ext.util.Droppable} this
|
||||
* @param {Ext.util.Draggable} draggable
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event dropleave
|
||||
* @param {Ext.util.Droppable} this
|
||||
* @param {Ext.util.Draggable} draggable
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event drop
|
||||
* @param {Ext.util.Droppable} this
|
||||
* @param {Ext.util.Draggable} draggable
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
me.el = Ext.get(el);
|
||||
me.callParent();
|
||||
|
||||
me.mixins.observable.constructor.call(me);
|
||||
|
||||
if (!me.disabled) {
|
||||
me.enable();
|
||||
}
|
||||
|
||||
me.el.addCls(me.baseCls);
|
||||
},
|
||||
|
||||
// @private
|
||||
onDragStart: function(draggable, e) {
|
||||
if (draggable.group === this.group) {
|
||||
this.monitoring = true;
|
||||
this.el.addCls(this.activeCls);
|
||||
this.region = this.el.getPageBox(true);
|
||||
|
||||
draggable.on({
|
||||
drag: this.onDrag,
|
||||
beforedragend: this.onBeforeDragEnd,
|
||||
dragend: this.onDragEnd,
|
||||
scope: this
|
||||
});
|
||||
|
||||
if (this.isDragOver(draggable)) {
|
||||
this.setCanDrop(true, draggable, e);
|
||||
}
|
||||
|
||||
this.fireEvent('dropactivate', this, draggable, e);
|
||||
}
|
||||
else {
|
||||
draggable.on({
|
||||
dragend: function() {
|
||||
this.el.removeCls(this.invalidCls);
|
||||
},
|
||||
scope: this,
|
||||
single: true
|
||||
});
|
||||
this.el.addCls(this.invalidCls);
|
||||
}
|
||||
},
|
||||
|
||||
// @private
|
||||
isDragOver: function(draggable, region) {
|
||||
return this.region[this.validDropMode](draggable.region);
|
||||
},
|
||||
|
||||
// @private
|
||||
onDrag: function(draggable, e) {
|
||||
this.setCanDrop(this.isDragOver(draggable), draggable, e);
|
||||
},
|
||||
|
||||
// @private
|
||||
setCanDrop: function(canDrop, draggable, e) {
|
||||
if (canDrop && !this.canDrop) {
|
||||
this.canDrop = true;
|
||||
this.el.addCls(this.hoverCls);
|
||||
this.fireEvent('dropenter', this, draggable, e);
|
||||
}
|
||||
else if (!canDrop && this.canDrop) {
|
||||
this.canDrop = false;
|
||||
this.el.removeCls(this.hoverCls);
|
||||
this.fireEvent('dropleave', this, draggable, e);
|
||||
}
|
||||
},
|
||||
|
||||
// @private
|
||||
onBeforeDragEnd: function(draggable, e) {
|
||||
draggable.cancelRevert = this.canDrop;
|
||||
},
|
||||
|
||||
// @private
|
||||
onDragEnd: function(draggable, e) {
|
||||
this.monitoring = false;
|
||||
this.el.removeCls(this.activeCls);
|
||||
|
||||
draggable.un({
|
||||
drag: this.onDrag,
|
||||
beforedragend: this.onBeforeDragEnd,
|
||||
dragend: this.onDragEnd,
|
||||
scope: this
|
||||
});
|
||||
|
||||
|
||||
if (this.canDrop) {
|
||||
this.canDrop = false;
|
||||
this.el.removeCls(this.hoverCls);
|
||||
this.fireEvent('drop', this, draggable, e);
|
||||
}
|
||||
|
||||
this.fireEvent('dropdeactivate', this, draggable, e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable the Droppable target.
|
||||
* This is invoked immediately after constructing a Droppable if the
|
||||
* disabled parameter is NOT set to true.
|
||||
*/
|
||||
enable: function() {
|
||||
if (!this.mgr) {
|
||||
this.mgr = Ext.util.Observable.observe(Ext.util.Draggable);
|
||||
}
|
||||
this.mgr.on({
|
||||
dragstart: this.onDragStart,
|
||||
scope: this
|
||||
});
|
||||
this.disabled = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable the Droppable target.
|
||||
*/
|
||||
disable: function() {
|
||||
this.mgr.un({
|
||||
dragstart: this.onDragStart,
|
||||
scope: this
|
||||
});
|
||||
this.disabled = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method to determine whether this Component is currently disabled.
|
||||
* @return {Boolean} the disabled state of this Component.
|
||||
*/
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method to determine whether this Droppable is currently monitoring drag operations of Draggables.
|
||||
* @return {Boolean} the monitoring state of this Droppable
|
||||
*/
|
||||
isMonitoring: function() {
|
||||
return this.monitoring;
|
||||
}
|
||||
});
|
||||
188
OfficeWeb/vendor/touch/src/util/Filter.js
vendored
Normal file
188
OfficeWeb/vendor/touch/src/util/Filter.js
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Represents a filter that can be applied to a {@link Ext.util.MixedCollection MixedCollection}. Can either simply
|
||||
* filter on a property/value pair or pass in a filter function with custom logic. Filters are always used in the
|
||||
* context of MixedCollections, though {@link Ext.data.Store Store}s frequently create them when filtering and searching
|
||||
* on their records. Example usage:
|
||||
*
|
||||
* // Set up a fictional MixedCollection containing a few people to filter on
|
||||
* var allNames = new Ext.util.MixedCollection();
|
||||
* allNames.addAll([
|
||||
* { id: 1, name: 'Ed', age: 25 },
|
||||
* { id: 2, name: 'Jamie', age: 37 },
|
||||
* { id: 3, name: 'Abe', age: 32 },
|
||||
* { id: 4, name: 'Aaron', age: 26 },
|
||||
* { id: 5, name: 'David', age: 32 }
|
||||
* ]);
|
||||
*
|
||||
* var ageFilter = new Ext.util.Filter({
|
||||
* property: 'age',
|
||||
* value : 32
|
||||
* });
|
||||
*
|
||||
* var longNameFilter = new Ext.util.Filter({
|
||||
* filterFn: function(item) {
|
||||
* return item.name.length > 4;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // a new MixedCollection with the 3 names longer than 4 characters
|
||||
* var longNames = allNames.filter(longNameFilter);
|
||||
*
|
||||
* // a new MixedCollection with the 2 people of age 32:
|
||||
* var youngFolk = allNames.filter(ageFilter);
|
||||
*/
|
||||
Ext.define('Ext.util.Filter', {
|
||||
isFilter: true,
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {String} [property=null]
|
||||
* The property to filter on. Required unless a `filter` is passed
|
||||
*/
|
||||
property: null,
|
||||
|
||||
/**
|
||||
* @cfg {RegExp/Mixed} [value=null]
|
||||
* The value you want to match against. Can be a regular expression which will be used as matcher or any other
|
||||
* value.
|
||||
*/
|
||||
value: null,
|
||||
|
||||
/**
|
||||
* @cfg {Function} filterFn
|
||||
* A custom filter function which is passed each item in the {@link Ext.util.MixedCollection} in turn. Should
|
||||
* return true to accept each item or false to reject it
|
||||
*/
|
||||
filterFn: Ext.emptyFn,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} [anyMatch=false]
|
||||
* True to allow any match - no regex start/end line anchors will be added.
|
||||
*/
|
||||
anyMatch: false,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} [exactMatch=false]
|
||||
* True to force exact match (^ and $ characters added to the regex). Ignored if anyMatch is true.
|
||||
*/
|
||||
exactMatch: false,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} [caseSensitive=false]
|
||||
* True to make the regex case sensitive (adds 'i' switch to regex).
|
||||
*/
|
||||
caseSensitive: false,
|
||||
|
||||
/**
|
||||
* @cfg {String} [root=null]
|
||||
* Optional root property. This is mostly useful when filtering a Store, in which case we set the root to 'data'
|
||||
* to make the filter pull the {@link #property} out of the data object of each item
|
||||
*/
|
||||
root: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} id
|
||||
* An optional id this filter can be keyed by in Collections. If no id is specified it will generate an id by
|
||||
* first trying a combination of property-value, and if none if these were specified (like when having a
|
||||
* filterFn) it will generate a random id.
|
||||
*/
|
||||
id: undefined,
|
||||
|
||||
/**
|
||||
* @cfg {Object} [scope=null]
|
||||
* The scope in which to run the filterFn
|
||||
*/
|
||||
scope: null
|
||||
},
|
||||
|
||||
applyId: function(id) {
|
||||
if (!id) {
|
||||
if (this.getProperty()) {
|
||||
id = this.getProperty() + '-' + String(this.getValue());
|
||||
}
|
||||
if (!id) {
|
||||
id = Ext.id(null, 'ext-filter-');
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates new Filter.
|
||||
* @param {Object} config Config object
|
||||
*/
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
applyFilterFn: function(filterFn) {
|
||||
if (filterFn === Ext.emptyFn) {
|
||||
filterFn = this.getInitialConfig('filter');
|
||||
if (filterFn) {
|
||||
return filterFn;
|
||||
}
|
||||
|
||||
var value = this.getValue();
|
||||
if (!this.getProperty() && !value && value !== 0) {
|
||||
// <debug>
|
||||
Ext.Logger.error('A Filter requires either a property and value, or a filterFn to be set');
|
||||
// </debug>
|
||||
return Ext.emptyFn;
|
||||
}
|
||||
else {
|
||||
return this.createFilterFn();
|
||||
}
|
||||
}
|
||||
return filterFn;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Creates a filter function for the configured property/value/anyMatch/caseSensitive options for this Filter
|
||||
*/
|
||||
createFilterFn: function() {
|
||||
var me = this,
|
||||
matcher = me.createValueMatcher();
|
||||
|
||||
return function(item) {
|
||||
var root = me.getRoot(),
|
||||
property = me.getProperty();
|
||||
|
||||
if (root) {
|
||||
item = item[root];
|
||||
}
|
||||
|
||||
return matcher.test(item[property]);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns a regular expression based on the given value and matching options
|
||||
*/
|
||||
createValueMatcher: function() {
|
||||
var me = this,
|
||||
value = me.getValue(),
|
||||
anyMatch = me.getAnyMatch(),
|
||||
exactMatch = me.getExactMatch(),
|
||||
caseSensitive = me.getCaseSensitive(),
|
||||
escapeRe = Ext.String.escapeRegex;
|
||||
|
||||
if (value === null || value === undefined || !value.exec) { // not a regex
|
||||
value = String(value);
|
||||
|
||||
if (anyMatch === true) {
|
||||
value = escapeRe(value);
|
||||
} else {
|
||||
value = '^' + escapeRe(value);
|
||||
if (exactMatch === true) {
|
||||
value += '$';
|
||||
}
|
||||
}
|
||||
value = new RegExp(value, caseSensitive ? '' : 'i');
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
});
|
||||
192
OfficeWeb/vendor/touch/src/util/Format.js
vendored
Normal file
192
OfficeWeb/vendor/touch/src/util/Format.js
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* Reusable data formatting functions
|
||||
*/
|
||||
Ext.define('Ext.util.Format', {
|
||||
requires: [
|
||||
'Ext.DateExtras'
|
||||
],
|
||||
|
||||
singleton: true,
|
||||
|
||||
/**
|
||||
* The global default date format.
|
||||
*/
|
||||
defaultDateFormat: 'm/d/Y',
|
||||
|
||||
escapeRe: /('|\\)/g,
|
||||
trimRe: /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
|
||||
formatRe: /\{(\d+)\}/g,
|
||||
escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
|
||||
dashesRe: /-/g,
|
||||
iso8601TestRe: /\d\dT\d\d/,
|
||||
iso8601SplitRe: /[- :T\.Z\+]/,
|
||||
|
||||
/**
|
||||
* Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length.
|
||||
* @param {String} value The string to truncate.
|
||||
* @param {Number} length The maximum length to allow before truncating.
|
||||
* @param {Boolean} word True to try to find a common word break.
|
||||
* @return {String} The converted text.
|
||||
*/
|
||||
ellipsis: function(value, len, word) {
|
||||
if (value && value.length > len) {
|
||||
if (word) {
|
||||
var vs = value.substr(0, len - 2),
|
||||
index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
|
||||
if (index != -1 && index >= (len - 15)) {
|
||||
return vs.substr(0, index) + "...";
|
||||
}
|
||||
}
|
||||
return value.substr(0, len - 3) + "...";
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Escapes the passed string for use in a regular expression.
|
||||
* @param {String} str
|
||||
* @return {String}
|
||||
*/
|
||||
escapeRegex: function(s) {
|
||||
return s.replace(Ext.util.Format.escapeRegexRe, "\\$1");
|
||||
},
|
||||
|
||||
/**
|
||||
* Escapes the passed string for ' and \.
|
||||
* @param {String} string The string to escape.
|
||||
* @return {String} The escaped string.
|
||||
*/
|
||||
escape: function(string) {
|
||||
return string.replace(Ext.util.Format.escapeRe, "\\$1");
|
||||
},
|
||||
|
||||
/**
|
||||
* Utility function that allows you to easily switch a string between two alternating values. The passed value
|
||||
* is compared to the current string, and if they are equal, the other value that was passed in is returned. If
|
||||
* they are already different, the first value passed in is returned.
|
||||
*
|
||||
* __Note:__ This method returns the new value but does not change the current string.
|
||||
*
|
||||
* // alternate sort directions
|
||||
* sort = Ext.util.Format.toggle(sort, 'ASC', 'DESC');
|
||||
*
|
||||
* // instead of conditional logic:
|
||||
* sort = (sort === 'ASC' ? 'DESC' : 'ASC');
|
||||
*
|
||||
* @param {String} string The current string
|
||||
* @param {String} value The value to compare to the current string
|
||||
* @param {String} other The new value to use if the string already equals the first value passed in
|
||||
* @return {String} The new value
|
||||
*/
|
||||
toggle: function(string, value, other) {
|
||||
return string == value ? other : value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Trims whitespace from either end of a string, leaving spaces within the string intact. Example:
|
||||
*
|
||||
* var s = ' foo bar ';
|
||||
* alert('-' + s + '-'); // alerts "- foo bar -"
|
||||
* alert('-' + Ext.util.Format.trim(s) + '-'); // alerts "-foo bar-"
|
||||
*
|
||||
* @param {String} string The string to escape
|
||||
* @return {String} The trimmed string
|
||||
*/
|
||||
trim: function(string) {
|
||||
return string.replace(Ext.util.Format.trimRe, "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Pads the left side of a string with a specified character. This is especially useful
|
||||
* for normalizing number and date strings. Example usage:
|
||||
*
|
||||
* var s = Ext.util.Format.leftPad('123', 5, '0');
|
||||
* // s now contains the string: '00123'
|
||||
*
|
||||
* @param {String} string The original string.
|
||||
* @param {Number} size The total length of the output string.
|
||||
* @param {String} [char=' '] (optional) The character with which to pad the original string.
|
||||
* @return {String} The padded string.
|
||||
*/
|
||||
leftPad: function (val, size, ch) {
|
||||
var result = String(val);
|
||||
ch = ch || " ";
|
||||
while (result.length < size) {
|
||||
result = ch + result;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
|
||||
* token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
|
||||
*
|
||||
* var cls = 'my-class', text = 'Some text';
|
||||
* var s = Ext.util.Format.format('<div class="{0}">{1}</div>', cls, text);
|
||||
* // s now contains the string: '<div class="my-class">Some text</div>'
|
||||
*
|
||||
* @param {String} string The tokenized string to be formatted.
|
||||
* @param {String...} values The values to replace token {0}, {1}, etc.
|
||||
* @return {String} The formatted string.
|
||||
*/
|
||||
format: function (format) {
|
||||
var args = Ext.toArray(arguments, 1);
|
||||
return format.replace(Ext.util.Format.formatRe, function(m, i) {
|
||||
return args[i];
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
|
||||
* @param {String} value The string to encode.
|
||||
* @return {String} The encoded text.
|
||||
*/
|
||||
htmlEncode: function(value) {
|
||||
return ! value ? value: String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert certain characters (&, <, >, and ') from their HTML character equivalents.
|
||||
* @param {String} value The string to decode.
|
||||
* @return {String} The decoded text.
|
||||
*/
|
||||
htmlDecode: function(value) {
|
||||
return ! value ? value: String(value).replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"').replace(/&/g, "&");
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse a value into a formatted date using the specified format pattern.
|
||||
* @param {String/Date} value The value to format. Strings must conform to the format expected by the JavaScript
|
||||
* Date object's [parse() method](http://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/parse).
|
||||
* @param {String} [format='m/d/Y'] (optional) Any valid date format string.
|
||||
* @return {String} The formatted date string.
|
||||
*/
|
||||
date: function(value, format) {
|
||||
var date = value;
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
if (!Ext.isDate(value)) {
|
||||
date = new Date(Date.parse(value));
|
||||
if (isNaN(date)) {
|
||||
// Dates with ISO 8601 format are not well supported by mobile devices, this can work around the issue.
|
||||
if (this.iso8601TestRe.test(value)) {
|
||||
date = value.split(this.iso8601SplitRe);
|
||||
date = new Date(date[0], date[1]-1, date[2], date[3], date[4], date[5]);
|
||||
}
|
||||
if (isNaN(date)) {
|
||||
// Dates with the format "2012-01-20" fail, but "2012/01/20" work in some browsers. We'll try and
|
||||
// get around that.
|
||||
date = new Date(Date.parse(value.replace(this.dashesRe, "/")));
|
||||
//<debug>
|
||||
if (isNaN(date)) {
|
||||
Ext.Logger.error("Cannot parse the passed value " + value + " into a valid date");
|
||||
}
|
||||
//</debug>
|
||||
}
|
||||
}
|
||||
value = date;
|
||||
}
|
||||
return Ext.Date.format(value, format || Ext.util.Format.defaultDateFormat);
|
||||
}
|
||||
});
|
||||
414
OfficeWeb/vendor/touch/src/util/Geolocation.js
vendored
Normal file
414
OfficeWeb/vendor/touch/src/util/Geolocation.js
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* Provides a cross browser class for retrieving location information.
|
||||
*
|
||||
* Based on the [Geolocation API Specification](http://dev.w3.org/geo/api/spec-source.html)
|
||||
*
|
||||
* When instantiated, by default this class immediately begins tracking location information,
|
||||
* firing a {@link #locationupdate} event when new location information is available. To disable this
|
||||
* location tracking (which may be battery intensive on mobile devices), set {@link #autoUpdate} to `false`.
|
||||
*
|
||||
* When this is done, only calls to {@link #updateLocation} will trigger a location retrieval.
|
||||
*
|
||||
* A {@link #locationerror} event is raised when an error occurs retrieving the location, either due to a user
|
||||
* denying the application access to it, or the browser not supporting it.
|
||||
*
|
||||
* The below code shows a GeoLocation making a single retrieval of location information.
|
||||
*
|
||||
* var geo = Ext.create('Ext.util.Geolocation', {
|
||||
* autoUpdate: false,
|
||||
* listeners: {
|
||||
* locationupdate: function(geo) {
|
||||
* alert('New latitude: ' + geo.getLatitude());
|
||||
* },
|
||||
* locationerror: function(geo, bTimeout, bPermissionDenied, bLocationUnavailable, message) {
|
||||
* if(bTimeout){
|
||||
* alert('Timeout occurred.');
|
||||
* } else {
|
||||
* alert('Error occurred.');
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
* geo.updateLocation();
|
||||
*/
|
||||
Ext.define('Ext.util.Geolocation', {
|
||||
extend: 'Ext.Evented',
|
||||
alternateClassName: ['Ext.util.GeoLocation'],
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @event locationerror
|
||||
* Raised when a location retrieval operation failed.
|
||||
*
|
||||
* In the case of calling updateLocation, this event will be raised only once.
|
||||
*
|
||||
* If {@link #autoUpdate} is set to `true`, this event could be raised repeatedly.
|
||||
* The first error is relative to the moment {@link #autoUpdate} was set to `true`
|
||||
* (or this {@link Ext.util.Geolocation} was initialized with the {@link #autoUpdate} config option set to `true`).
|
||||
* Subsequent errors are relative to the moment when the device determines that it's position has changed.
|
||||
* @param {Ext.util.Geolocation} this
|
||||
* @param {Boolean} timeout
|
||||
* Boolean indicating a timeout occurred
|
||||
* @param {Boolean} permissionDenied
|
||||
* Boolean indicating the user denied the location request
|
||||
* @param {Boolean} locationUnavailable
|
||||
* Boolean indicating that the location of the device could not be determined.
|
||||
* For instance, one or more of the location providers used in the location acquisition
|
||||
* process reported an internal error that caused the process to fail entirely.
|
||||
* @param {String} message An error message describing the details of the error encountered.
|
||||
*
|
||||
* This attribute is primarily intended for debugging and should not be used
|
||||
* directly in an application user interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event locationupdate
|
||||
* Raised when a location retrieval operation has been completed successfully.
|
||||
* @param {Ext.util.Geolocation} this
|
||||
* Retrieve the current location information from the GeoLocation object by using the read-only
|
||||
* properties: {@link #latitude}, {@link #longitude}, {@link #accuracy}, {@link #altitude}, {@link #altitudeAccuracy}, {@link #heading}, and {@link #speed}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} autoUpdate
|
||||
* When set to `true`, continually monitor the location of the device (beginning immediately)
|
||||
* and fire {@link #locationupdate} and {@link #locationerror} events.
|
||||
*/
|
||||
autoUpdate: true,
|
||||
|
||||
/**
|
||||
* @cfg {Number} frequency
|
||||
* The frequency of each update if {@link #autoUpdate} is set to `true`.
|
||||
*/
|
||||
frequency: 10000,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* geographical coordinate specified in degrees.
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
latitude: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* geographical coordinate specified in degrees.
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
longitude: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* accuracy level of the latitude and longitude coordinates,
|
||||
* specified in meters.
|
||||
*
|
||||
* This will always be a non-negative number.
|
||||
*
|
||||
* This corresponds to a 95% confidence level.
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
accuracy: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* height of the position, specified in meters above the ellipsoid
|
||||
* [WGS84](http://dev.w3.org/geo/api/spec-source.html#ref-wgs).
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
altitude: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* accuracy level of the altitude coordinate, specified in meters.
|
||||
*
|
||||
* If altitude is not null then this will be a non-negative number.
|
||||
* Otherwise this returns `null`.
|
||||
*
|
||||
* This corresponds to a 95% confidence level.
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
altitudeAccuracy: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* direction of travel of the hosting device,
|
||||
* specified in non-negative degrees between 0 and 359,
|
||||
* counting clockwise relative to the true north.
|
||||
*
|
||||
* If speed is 0 (device is stationary), then this returns `NaN`.
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
heading: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing the last retrieved
|
||||
* current ground speed of the device, specified in meters per second.
|
||||
*
|
||||
* If this feature is unsupported by the device, this returns `null`.
|
||||
*
|
||||
* If the device is stationary, this returns 0,
|
||||
* otherwise it returns a non-negative number.
|
||||
* @type Number
|
||||
* @readonly
|
||||
*/
|
||||
speed: null,
|
||||
|
||||
/**
|
||||
* Read-only property representing when the last retrieved
|
||||
* positioning information was acquired by the device.
|
||||
* @type Date
|
||||
* @readonly
|
||||
*/
|
||||
timestamp: null,
|
||||
|
||||
//PositionOptions interface
|
||||
/**
|
||||
* @cfg {Boolean} allowHighAccuracy
|
||||
* When set to `true`, provide a hint that the application would like to receive
|
||||
* the best possible results. This may result in slower response times or increased power consumption.
|
||||
* The user might also deny this capability, or the device might not be able to provide more accurate
|
||||
* results than if this option was set to `false`.
|
||||
*/
|
||||
allowHighAccuracy: false,
|
||||
|
||||
/**
|
||||
* @cfg {Number} timeout
|
||||
* The maximum number of milliseconds allowed to elapse between a location update operation
|
||||
* and the corresponding {@link #locationupdate} event being raised. If a location was not successfully
|
||||
* acquired before the given timeout elapses (and no other internal errors have occurred in this interval),
|
||||
* then a {@link #locationerror} event will be raised indicating a timeout as the cause.
|
||||
*
|
||||
* Note that the time that is spent obtaining the user permission is **not** included in the period
|
||||
* covered by the timeout. The `timeout` attribute only applies to the location acquisition operation.
|
||||
*
|
||||
* In the case of calling `updateLocation`, the {@link #locationerror} event will be raised only once.
|
||||
*
|
||||
* If {@link #autoUpdate} is set to `true`, the {@link #locationerror} event could be raised repeatedly.
|
||||
* The first timeout is relative to the moment {@link #autoUpdate} was set to `true`
|
||||
* (or this {@link Ext.util.Geolocation} was initialized with the {@link #autoUpdate} config option set to `true`).
|
||||
* Subsequent timeouts are relative to the moment when the device determines that it's position has changed.
|
||||
*/
|
||||
|
||||
timeout: Infinity,
|
||||
|
||||
/**
|
||||
* @cfg {Number} maximumAge
|
||||
* This option indicates that the application is willing to accept cached location information whose age
|
||||
* is no greater than the specified time in milliseconds. If `maximumAge` is set to 0, an attempt to retrieve
|
||||
* new location information is made immediately.
|
||||
*
|
||||
* Setting the `maximumAge` to Infinity returns a cached position regardless of its age.
|
||||
*
|
||||
* If the device does not have cached location information available whose age is no
|
||||
* greater than the specified `maximumAge`, then it must acquire new location information.
|
||||
*
|
||||
* For example, if location information no older than 10 minutes is required, set this property to 600000.
|
||||
*/
|
||||
maximumAge: 0,
|
||||
|
||||
// @private
|
||||
provider : undefined
|
||||
},
|
||||
|
||||
updateMaximumAge: function() {
|
||||
if (this.watchOperation) {
|
||||
this.updateWatchOperation();
|
||||
}
|
||||
},
|
||||
|
||||
updateTimeout: function() {
|
||||
if (this.watchOperation) {
|
||||
this.updateWatchOperation();
|
||||
}
|
||||
},
|
||||
|
||||
updateAllowHighAccuracy: function() {
|
||||
if (this.watchOperation) {
|
||||
this.updateWatchOperation();
|
||||
}
|
||||
},
|
||||
|
||||
applyProvider: function(config) {
|
||||
if (Ext.feature.has.Geolocation) {
|
||||
if (!config) {
|
||||
if (navigator && navigator.geolocation) {
|
||||
config = navigator.geolocation;
|
||||
}
|
||||
else if (window.google) {
|
||||
config = google.gears.factory.create('beta.geolocation');
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.fireEvent('locationerror', this, false, false, true, 'This device does not support Geolocation.');
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
||||
updateAutoUpdate: function(newAutoUpdate, oldAutoUpdate) {
|
||||
var me = this,
|
||||
provider = me.getProvider();
|
||||
|
||||
if (oldAutoUpdate && provider) {
|
||||
clearInterval(me.watchOperationId);
|
||||
me.watchOperationId = null;
|
||||
}
|
||||
|
||||
if (newAutoUpdate) {
|
||||
if (!provider) {
|
||||
me.fireEvent('locationerror', me, false, false, true, null);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
me.updateWatchOperation();
|
||||
}
|
||||
catch(e) {
|
||||
me.fireEvent('locationerror', me, false, false, true, e.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// @private
|
||||
updateWatchOperation: function() {
|
||||
var me = this,
|
||||
provider = me.getProvider();
|
||||
|
||||
// The native watchPosition method is currently broken in iOS5...
|
||||
|
||||
if (me.watchOperationId) {
|
||||
clearInterval(me.watchOperationId);
|
||||
}
|
||||
|
||||
function pollPosition() {
|
||||
provider.getCurrentPosition(
|
||||
Ext.bind(me.fireUpdate, me),
|
||||
Ext.bind(me.fireError, me),
|
||||
me.parseOptions()
|
||||
);
|
||||
}
|
||||
|
||||
pollPosition();
|
||||
me.watchOperationId = setInterval(pollPosition, this.getFrequency());
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes a onetime location update operation,
|
||||
* raising either a {@link #locationupdate} or {@link #locationerror} event.
|
||||
*
|
||||
* Does not interfere with or restart ongoing location monitoring.
|
||||
* @param {Function} callback
|
||||
* A callback method to be called when the location retrieval has been completed.
|
||||
*
|
||||
* Will be called on both success and failure.
|
||||
*
|
||||
* The method will be passed one parameter, {@link Ext.util.Geolocation} (**this** reference),
|
||||
* set to `null` on failure.
|
||||
*
|
||||
* geo.updateLocation(function (geo) {
|
||||
* alert('Latitude: ' + (geo !== null ? geo.latitude : 'failed'));
|
||||
* });
|
||||
*
|
||||
* @param {Object} scope (optional) The scope (**this** reference) in which the handler function is executed.
|
||||
*
|
||||
* **If omitted, defaults to the object which fired the event.**
|
||||
* <!--positonOptions undocumented param, see W3C spec-->
|
||||
*/
|
||||
updateLocation: function(callback, scope, positionOptions) {
|
||||
var me = this,
|
||||
provider = me.getProvider();
|
||||
|
||||
var failFunction = function(message, error) {
|
||||
if (error) {
|
||||
me.fireError(error);
|
||||
}
|
||||
else {
|
||||
me.fireEvent('locationerror', me, false, false, true, message);
|
||||
}
|
||||
if (callback) {
|
||||
callback.call(scope || me, null, me); //last parameter for legacy purposes
|
||||
}
|
||||
};
|
||||
|
||||
if (!provider) {
|
||||
failFunction(null);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
provider.getCurrentPosition(
|
||||
//success callback
|
||||
function(position) {
|
||||
me.fireUpdate(position);
|
||||
if (callback) {
|
||||
callback.call(scope || me, me, me); //last parameter for legacy purposes
|
||||
}
|
||||
},
|
||||
//error callback
|
||||
function(error) {
|
||||
failFunction(null, error);
|
||||
},
|
||||
positionOptions || me.parseOptions()
|
||||
);
|
||||
}
|
||||
catch(e) {
|
||||
failFunction(e.message);
|
||||
}
|
||||
},
|
||||
|
||||
// @private
|
||||
fireUpdate: function(position) {
|
||||
var me = this,
|
||||
coords = position.coords;
|
||||
|
||||
this.position = position;
|
||||
|
||||
me.setConfig({
|
||||
timestamp: position.timestamp,
|
||||
latitude: coords.latitude,
|
||||
longitude: coords.longitude,
|
||||
accuracy: coords.accuracy,
|
||||
altitude: coords.altitude,
|
||||
altitudeAccuracy: coords.altitudeAccuracy,
|
||||
heading: coords.heading,
|
||||
speed: coords.speed
|
||||
});
|
||||
|
||||
me.fireEvent('locationupdate', me);
|
||||
},
|
||||
|
||||
// @private
|
||||
fireError: function(error) {
|
||||
var errorCode = error.code;
|
||||
this.fireEvent('locationerror', this,
|
||||
errorCode == error.TIMEOUT,
|
||||
errorCode == error.PERMISSION_DENIED,
|
||||
errorCode == error.POSITION_UNAVAILABLE,
|
||||
error.message == undefined ? null : error.message
|
||||
);
|
||||
},
|
||||
|
||||
// @private
|
||||
parseOptions: function() {
|
||||
var timeout = this.getTimeout(),
|
||||
ret = {
|
||||
maximumAge: this.getMaximumAge(),
|
||||
enableHighAccuracy: this.getAllowHighAccuracy()
|
||||
};
|
||||
|
||||
//Google doesn't like Infinity
|
||||
if (timeout !== Infinity) {
|
||||
ret.timeout = timeout;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this.setAutoUpdate(false);
|
||||
}
|
||||
});
|
||||
98
OfficeWeb/vendor/touch/src/util/Grouper.js
vendored
Normal file
98
OfficeWeb/vendor/touch/src/util/Grouper.js
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.Grouper', {
|
||||
|
||||
/* Begin Definitions */
|
||||
|
||||
extend: 'Ext.util.Sorter',
|
||||
|
||||
isGrouper: true,
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Function} groupFn This function will be called for each item in the collection to
|
||||
* determine the group to which it belongs.
|
||||
* @cfg {Object} groupFn.item The current item from the collection
|
||||
* @cfg {String} groupFn.return The group identifier for the item
|
||||
*/
|
||||
groupFn: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} sortProperty You can define this configuration if you want the groups to be sorted
|
||||
* on something other then the group string returned by the `groupFn`.
|
||||
*/
|
||||
sortProperty: null,
|
||||
|
||||
/**
|
||||
* @cfg {Function} sorterFn
|
||||
* Grouper has a custom sorterFn that cannot be overridden by the user. If a property has been defined
|
||||
* on this grouper, we use the default `sorterFn`, else we sort based on the returned group string.
|
||||
*/
|
||||
sorterFn: function(item1, item2) {
|
||||
var property = this.getSortProperty(),
|
||||
groupFn, group1, group2, modifier;
|
||||
|
||||
groupFn = this.getGroupFn();
|
||||
group1 = groupFn.call(this, item1);
|
||||
group2 = groupFn.call(this, item2);
|
||||
|
||||
if (property) {
|
||||
if (group1 !== group2) {
|
||||
return this.defaultSortFn.call(this, item1, item2);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return (group1 > group2) ? 1 : ((group1 < group2) ? -1 : 0);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Basic default sorter function that just compares the defined property of each object.
|
||||
*/
|
||||
defaultSortFn: function(item1, item2) {
|
||||
var me = this,
|
||||
transform = me._transform,
|
||||
root = me._root,
|
||||
value1, value2,
|
||||
property = me._sortProperty;
|
||||
|
||||
if (root !== null) {
|
||||
item1 = item1[root];
|
||||
item2 = item2[root];
|
||||
}
|
||||
|
||||
value1 = item1[property];
|
||||
value2 = item2[property];
|
||||
|
||||
if (transform) {
|
||||
value1 = transform(value1);
|
||||
value2 = transform(value2);
|
||||
}
|
||||
|
||||
return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0);
|
||||
},
|
||||
|
||||
updateProperty: function(property) {
|
||||
this.setGroupFn(this.standardGroupFn);
|
||||
},
|
||||
|
||||
standardGroupFn: function(item) {
|
||||
var root = this.getRoot(),
|
||||
property = this.getProperty(),
|
||||
data = item;
|
||||
|
||||
if (root) {
|
||||
data = item[root];
|
||||
}
|
||||
|
||||
return data[property];
|
||||
},
|
||||
|
||||
getGroupString: function(item) {
|
||||
var group = this.getGroupFn().call(this, item);
|
||||
return typeof group != 'undefined' ? group.toString() : '';
|
||||
}
|
||||
});
|
||||
320
OfficeWeb/vendor/touch/src/util/HashMap.js
vendored
Normal file
320
OfficeWeb/vendor/touch/src/util/HashMap.js
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
* Represents a collection of a set of key and value pairs. Each key in the HashMap must be unique, the same
|
||||
* key cannot exist twice. Access to items is provided via the key only. Sample usage:
|
||||
*
|
||||
* var map = Ext.create('Ext.util.HashMap');
|
||||
* map.add('key1', 1);
|
||||
* map.add('key2', 2);
|
||||
* map.add('key3', 3);
|
||||
*
|
||||
* map.each(function(key, value, length){
|
||||
* console.log(key, value, length);
|
||||
* });
|
||||
*
|
||||
* The HashMap is an unordered class, there is no guarantee when iterating over the items that they will be in
|
||||
* any particular order. If this is required, then use a {@link Ext.util.MixedCollection}.
|
||||
*/
|
||||
Ext.define('Ext.util.HashMap', {
|
||||
mixins: {
|
||||
observable: 'Ext.mixin.Observable'
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {Function} keyFn
|
||||
* A function that is used to retrieve a default key for a passed object.
|
||||
* A default is provided that returns the **id** property on the object.
|
||||
* This function is only used if the add method is called with a single argument.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates new HashMap.
|
||||
* @param {Object} config The configuration options
|
||||
*/
|
||||
constructor: function(config) {
|
||||
/**
|
||||
* @event add
|
||||
* Fires when a new item is added to the hash.
|
||||
* @param {Ext.util.HashMap} this
|
||||
* @param {String} key The key of the added item.
|
||||
* @param {Object} value The value of the added item.
|
||||
*/
|
||||
/**
|
||||
* @event clear
|
||||
* Fires when the hash is cleared.
|
||||
* @param {Ext.util.HashMap} this
|
||||
*/
|
||||
/**
|
||||
* @event remove
|
||||
* Fires when an item is removed from the hash.
|
||||
* @param {Ext.util.HashMap} this
|
||||
* @param {String} key The key of the removed item.
|
||||
* @param {Object} value The value of the removed item.
|
||||
*/
|
||||
/**
|
||||
* @event replace
|
||||
* Fires when an item is replaced in the hash.
|
||||
* @param {Ext.util.HashMap} this
|
||||
* @param {String} key The key of the replaced item.
|
||||
* @param {Object} value The new value for the item.
|
||||
* @param {Object} old The old value for the item.
|
||||
*/
|
||||
|
||||
this.callParent();
|
||||
|
||||
this.mixins.observable.constructor.call(this);
|
||||
|
||||
this.clear(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the number of items in the hash.
|
||||
* @return {Number} The number of items in the hash.
|
||||
*/
|
||||
getCount: function() {
|
||||
return this.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Implementation for being able to extract the key from an object if only
|
||||
* a single argument is passed.
|
||||
* @private
|
||||
* @param {String} key The key
|
||||
* @param {Object} value The value
|
||||
* @return {Array} [key, value]
|
||||
*/
|
||||
getData: function(key, value) {
|
||||
// if we have no value, it means we need to get the key from the object
|
||||
if (value === undefined) {
|
||||
value = key;
|
||||
key = this.getKey(value);
|
||||
}
|
||||
|
||||
return [key, value];
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the key from an object. This is a default implementation, it may be overridden.
|
||||
* @private
|
||||
* @param {Object} o The object to get the key from.
|
||||
* @return {String} The key to use.
|
||||
*/
|
||||
getKey: function(o) {
|
||||
return o.id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a new item to the hash. An exception will be thrown if the key already exists.
|
||||
* @param {String} key The key of the new item.
|
||||
* @param {Object} value The value of the new item.
|
||||
* @return {Object} The value of the new item added.
|
||||
*/
|
||||
add: function(key, value) {
|
||||
var me = this,
|
||||
data;
|
||||
|
||||
if (me.containsKey(key)) {
|
||||
throw new Error('This key already exists in the HashMap');
|
||||
}
|
||||
|
||||
data = this.getData(key, value);
|
||||
key = data[0];
|
||||
value = data[1];
|
||||
me.map[key] = value;
|
||||
++me.length;
|
||||
me.fireEvent('add', me, key, value);
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces an item in the hash. If the key doesn't exist, the
|
||||
* `{@link #method-add}` method will be used.
|
||||
* @param {String} key The key of the item.
|
||||
* @param {Object} value The new value for the item.
|
||||
* @return {Object} The new value of the item.
|
||||
*/
|
||||
replace: function(key, value) {
|
||||
var me = this,
|
||||
map = me.map,
|
||||
old;
|
||||
|
||||
if (!me.containsKey(key)) {
|
||||
me.add(key, value);
|
||||
}
|
||||
old = map[key];
|
||||
map[key] = value;
|
||||
me.fireEvent('replace', me, key, value, old);
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an item from the hash.
|
||||
* @param {Object} o The value of the item to remove.
|
||||
* @return {Boolean} `true` if the item was successfully removed.
|
||||
*/
|
||||
remove: function(o) {
|
||||
var key = this.findKey(o);
|
||||
if (key !== undefined) {
|
||||
return this.removeByKey(key);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an item from the hash.
|
||||
* @param {String} key The key to remove.
|
||||
* @return {Boolean} `true` if the item was successfully removed.
|
||||
*/
|
||||
removeByKey: function(key) {
|
||||
var me = this,
|
||||
value;
|
||||
|
||||
if (me.containsKey(key)) {
|
||||
value = me.map[key];
|
||||
delete me.map[key];
|
||||
--me.length;
|
||||
me.fireEvent('remove', me, key, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves an item with a particular key.
|
||||
* @param {String} key The key to lookup.
|
||||
* @return {Object} The value at that key. If it doesn't exist, `undefined` is returned.
|
||||
*/
|
||||
get: function(key) {
|
||||
return this.map[key];
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all items from the hash.
|
||||
* @return {Ext.util.HashMap} this
|
||||
*/
|
||||
clear: function(/* private */ initial) {
|
||||
var me = this;
|
||||
me.map = {};
|
||||
me.length = 0;
|
||||
if (initial !== true) {
|
||||
me.fireEvent('clear', me);
|
||||
}
|
||||
return me;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether a key exists in the hash.
|
||||
* @param {String} key The key to check for.
|
||||
* @return {Boolean} `true` if they key exists in the hash.
|
||||
*/
|
||||
containsKey: function(key) {
|
||||
return this.map[key] !== undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether a value exists in the hash.
|
||||
* @param {Object} value The value to check for.
|
||||
* @return {Boolean} `true` if the value exists in the dictionary.
|
||||
*/
|
||||
contains: function(value) {
|
||||
return this.containsKey(this.findKey(value));
|
||||
},
|
||||
|
||||
/**
|
||||
* Return all of the keys in the hash.
|
||||
* @return {Array} An array of keys.
|
||||
*/
|
||||
getKeys: function() {
|
||||
return this.getArray(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return all of the values in the hash.
|
||||
* @return {Array} An array of values.
|
||||
*/
|
||||
getValues: function() {
|
||||
return this.getArray(false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets either the keys/values in an array from the hash.
|
||||
* @private
|
||||
* @param {Boolean} isKey `true` to extract the keys, otherwise, the value.
|
||||
* @return {Array} An array of either keys/values from the hash.
|
||||
*/
|
||||
getArray: function(isKey) {
|
||||
var arr = [],
|
||||
key,
|
||||
map = this.map;
|
||||
for (key in map) {
|
||||
if (map.hasOwnProperty(key)) {
|
||||
arr.push(isKey ? key : map[key]);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes the specified function once for each item in the hash.
|
||||
*
|
||||
* @param {Function} fn The function to execute.
|
||||
* @param {String} fn.key The key of the item.
|
||||
* @param {Number} fn.value The value of the item.
|
||||
* @param {Number} fn.length The total number of items in the hash.
|
||||
* @param {Boolean} fn.return Returning `false` from the function will cease the iteration.
|
||||
* @param {Object} [scope=this] The scope to execute in.
|
||||
* @return {Ext.util.HashMap} this
|
||||
*/
|
||||
each: function(fn, scope) {
|
||||
// copy items so they may be removed during iteration.
|
||||
var items = Ext.apply({}, this.map),
|
||||
key,
|
||||
length = this.length;
|
||||
|
||||
scope = scope || this;
|
||||
for (key in items) {
|
||||
if (items.hasOwnProperty(key)) {
|
||||
if (fn.call(scope, key, items[key], length) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs a shallow copy on this hash.
|
||||
* @return {Ext.util.HashMap} The new hash object.
|
||||
*/
|
||||
clone: function() {
|
||||
var hash = new Ext.util.HashMap(),
|
||||
map = this.map,
|
||||
key;
|
||||
|
||||
hash.suspendEvents();
|
||||
for (key in map) {
|
||||
if (map.hasOwnProperty(key)) {
|
||||
hash.add(key, map[key]);
|
||||
}
|
||||
}
|
||||
hash.resumeEvents();
|
||||
return hash;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Find the key for a value.
|
||||
* @param {Object} value The value to find.
|
||||
* @return {Object} The value of the item. Returns `undefined` if not found.
|
||||
*/
|
||||
findKey: function(value) {
|
||||
var key,
|
||||
map = this.map;
|
||||
|
||||
for (key in map) {
|
||||
if (map.hasOwnProperty(key) && map[key] === value) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
300
OfficeWeb/vendor/touch/src/util/Inflector.js
vendored
Normal file
300
OfficeWeb/vendor/touch/src/util/Inflector.js
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
/**
|
||||
* General purpose inflector class that {@link #pluralize pluralizes}, {@link #singularize singularizes} and
|
||||
* {@link #ordinalize ordinalizes} words. Sample usage:
|
||||
*
|
||||
* // turning singular words into plurals
|
||||
* Ext.util.Inflector.pluralize('word'); // 'words'
|
||||
* Ext.util.Inflector.pluralize('person'); // 'people'
|
||||
* Ext.util.Inflector.pluralize('sheep'); // 'sheep'
|
||||
*
|
||||
* // turning plurals into singulars
|
||||
* Ext.util.Inflector.singularize('words'); // 'word'
|
||||
* Ext.util.Inflector.singularize('people'); // 'person'
|
||||
* Ext.util.Inflector.singularize('sheep'); // 'sheep'
|
||||
*
|
||||
* // ordinalizing numbers
|
||||
* Ext.util.Inflector.ordinalize(11); // "11th"
|
||||
* Ext.util.Inflector.ordinalize(21); // "21st"
|
||||
* Ext.util.Inflector.ordinalize(1043); // "1043rd"
|
||||
*
|
||||
* ## Customization
|
||||
*
|
||||
* The Inflector comes with a default set of US English pluralization rules. These can be augmented with additional
|
||||
* rules if the default rules do not meet your application's requirements, or swapped out entirely for other languages.
|
||||
* Here is how we might add a rule that pluralizes "ox" to "oxen":
|
||||
*
|
||||
* Ext.util.Inflector.plural(/^(ox)$/i, "$1en");
|
||||
*
|
||||
* Each rule consists of two items - a regular expression that matches one or more rules, and a replacement string.
|
||||
* In this case, the regular expression will only match the string "ox", and will replace that match with "oxen".
|
||||
* Here's how we could add the inverse rule:
|
||||
*
|
||||
* Ext.util.Inflector.singular(/^(ox)en$/i, "$1");
|
||||
*
|
||||
* __Note:__ The ox/oxen rules are present by default.
|
||||
*/
|
||||
Ext.define('Ext.util.Inflector', {
|
||||
|
||||
/* Begin Definitions */
|
||||
|
||||
singleton: true,
|
||||
|
||||
/* End Definitions */
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The registered plural tuples. Each item in the array should contain two items - the first must be a regular
|
||||
* expression that matchers the singular form of a word, the second must be a String that replaces the matched
|
||||
* part of the regular expression. This is managed by the {@link #plural} method.
|
||||
* @property plurals
|
||||
* @type Array
|
||||
*/
|
||||
plurals: [
|
||||
[(/(quiz)$/i), "$1zes" ],
|
||||
[(/^(ox)$/i), "$1en" ],
|
||||
[(/([m|l])ouse$/i), "$1ice" ],
|
||||
[(/(matr|vert|ind)ix|ex$/i), "$1ices" ],
|
||||
[(/(x|ch|ss|sh)$/i), "$1es" ],
|
||||
[(/([^aeiouy]|qu)y$/i), "$1ies" ],
|
||||
[(/(hive)$/i), "$1s" ],
|
||||
[(/(?:([^f])fe|([lr])f)$/i), "$1$2ves"],
|
||||
[(/sis$/i), "ses" ],
|
||||
[(/([ti])um$/i), "$1a" ],
|
||||
[(/(buffal|tomat|potat)o$/i), "$1oes" ],
|
||||
[(/(bu)s$/i), "$1ses" ],
|
||||
[(/(alias|status|sex)$/i), "$1es" ],
|
||||
[(/(octop|vir)us$/i), "$1i" ],
|
||||
[(/(ax|test)is$/i), "$1es" ],
|
||||
[(/^person$/), "people" ],
|
||||
[(/^man$/), "men" ],
|
||||
[(/^(child)$/), "$1ren" ],
|
||||
[(/s$/i), "s" ],
|
||||
[(/$/), "s" ]
|
||||
],
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The set of registered singular matchers. Each item in the array should contain two items - the first must be a
|
||||
* regular expression that matches the plural form of a word, the second must be a String that replaces the
|
||||
* matched part of the regular expression. This is managed by the {@link #singular} method.
|
||||
* @property singulars
|
||||
* @type Array
|
||||
*/
|
||||
singulars: [
|
||||
[(/(quiz)zes$/i), "$1" ],
|
||||
[(/(matr)ices$/i), "$1ix" ],
|
||||
[(/(vert|ind)ices$/i), "$1ex" ],
|
||||
[(/^(ox)en/i), "$1" ],
|
||||
[(/(alias|status)es$/i), "$1" ],
|
||||
[(/(octop|vir)i$/i), "$1us" ],
|
||||
[(/(cris|ax|test)es$/i), "$1is" ],
|
||||
[(/(shoe)s$/i), "$1" ],
|
||||
[(/(o)es$/i), "$1" ],
|
||||
[(/(bus)es$/i), "$1" ],
|
||||
[(/([m|l])ice$/i), "$1ouse" ],
|
||||
[(/(x|ch|ss|sh)es$/i), "$1" ],
|
||||
[(/(m)ovies$/i), "$1ovie" ],
|
||||
[(/(s)eries$/i), "$1eries"],
|
||||
[(/([^aeiouy]|qu)ies$/i), "$1y" ],
|
||||
[(/([lr])ves$/i), "$1f" ],
|
||||
[(/(tive)s$/i), "$1" ],
|
||||
[(/(hive)s$/i), "$1" ],
|
||||
[(/([^f])ves$/i), "$1fe" ],
|
||||
[(/(^analy)ses$/i), "$1sis" ],
|
||||
[(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
|
||||
[(/([ti])a$/i), "$1um" ],
|
||||
[(/(n)ews$/i), "$1ews" ],
|
||||
[(/people$/i), "person" ],
|
||||
[(/s$/i), "" ]
|
||||
],
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The registered uncountable words
|
||||
* @property uncountable
|
||||
* @type Array
|
||||
*/
|
||||
uncountable: [
|
||||
"sheep",
|
||||
"fish",
|
||||
"series",
|
||||
"species",
|
||||
"money",
|
||||
"rice",
|
||||
"information",
|
||||
"equipment",
|
||||
"grass",
|
||||
"mud",
|
||||
"offspring",
|
||||
"deer",
|
||||
"means"
|
||||
],
|
||||
|
||||
/**
|
||||
* Adds a new singularization rule to the Inflector. See the intro docs for more information
|
||||
* @param {RegExp} matcher The matcher regex
|
||||
* @param {String} replacer The replacement string, which can reference matches from the matcher argument
|
||||
*/
|
||||
singular: function(matcher, replacer) {
|
||||
this.singulars.unshift([matcher, replacer]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new pluralization rule to the Inflector. See the intro docs for more information
|
||||
* @param {RegExp} matcher The matcher regex
|
||||
* @param {String} replacer The replacement string, which can reference matches from the matcher argument
|
||||
*/
|
||||
plural: function(matcher, replacer) {
|
||||
this.plurals.unshift([matcher, replacer]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all registered singularization rules
|
||||
*/
|
||||
clearSingulars: function() {
|
||||
this.singulars = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all registered pluralization rules
|
||||
*/
|
||||
clearPlurals: function() {
|
||||
this.plurals = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the given word is transnumeral (the word is its own singular and plural form - e.g. sheep, fish)
|
||||
* @param {String} word The word to test
|
||||
* @return {Boolean} True if the word is transnumeral
|
||||
*/
|
||||
isTransnumeral: function(word) {
|
||||
return Ext.Array.indexOf(this.uncountable, word) != -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the pluralized form of a word (e.g. Ext.util.Inflector.pluralize('word') returns 'words')
|
||||
* @param {String} word The word to pluralize
|
||||
* @return {String} The pluralized form of the word
|
||||
*/
|
||||
pluralize: function(word) {
|
||||
if (this.isTransnumeral(word)) {
|
||||
return word;
|
||||
}
|
||||
|
||||
var plurals = this.plurals,
|
||||
length = plurals.length,
|
||||
tuple, regex, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
tuple = plurals[i];
|
||||
regex = tuple[0];
|
||||
|
||||
if (regex == word || (regex.test && regex.test(word))) {
|
||||
return word.replace(regex, tuple[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return word;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the singularized form of a word (e.g. Ext.util.Inflector.singularize('words') returns 'word')
|
||||
* @param {String} word The word to singularize
|
||||
* @return {String} The singularized form of the word
|
||||
*/
|
||||
singularize: function(word) {
|
||||
if (this.isTransnumeral(word)) {
|
||||
return word;
|
||||
}
|
||||
|
||||
var singulars = this.singulars,
|
||||
length = singulars.length,
|
||||
tuple, regex, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
tuple = singulars[i];
|
||||
regex = tuple[0];
|
||||
|
||||
if (regex == word || (regex.test && regex.test(word))) {
|
||||
return word.replace(regex, tuple[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return word;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the correct {@link Ext.data.Model Model} name for a given string. Mostly used internally by the data
|
||||
* package
|
||||
* @param {String} word The word to classify
|
||||
* @return {String} The classified version of the word
|
||||
*/
|
||||
classify: function(word) {
|
||||
return Ext.String.capitalize(this.singularize(word));
|
||||
},
|
||||
|
||||
/**
|
||||
* Ordinalizes a given number by adding a prefix such as 'st', 'nd', 'rd' or 'th' based on the last digit of the
|
||||
* number. 21 -> 21st, 22 -> 22nd, 23 -> 23rd, 24 -> 24th etc
|
||||
* @param {Number} number The number to ordinalize
|
||||
* @return {String} The ordinalized number
|
||||
*/
|
||||
ordinalize: function(number) {
|
||||
var parsed = parseInt(number, 10),
|
||||
mod10 = parsed % 10,
|
||||
mod100 = parsed % 100;
|
||||
|
||||
//11 through 13 are a special case
|
||||
if (11 <= mod100 && mod100 <= 13) {
|
||||
return number + "th";
|
||||
} else {
|
||||
switch(mod10) {
|
||||
case 1 : return number + "st";
|
||||
case 2 : return number + "nd";
|
||||
case 3 : return number + "rd";
|
||||
default: return number + "th";
|
||||
}
|
||||
}
|
||||
}
|
||||
}, function() {
|
||||
//aside from the rules above, there are a number of words that have irregular pluralization so we add them here
|
||||
var irregulars = {
|
||||
alumnus: 'alumni',
|
||||
cactus : 'cacti',
|
||||
focus : 'foci',
|
||||
nucleus: 'nuclei',
|
||||
radius: 'radii',
|
||||
stimulus: 'stimuli',
|
||||
ellipsis: 'ellipses',
|
||||
paralysis: 'paralyses',
|
||||
oasis: 'oases',
|
||||
appendix: 'appendices',
|
||||
index: 'indexes',
|
||||
beau: 'beaux',
|
||||
bureau: 'bureaux',
|
||||
tableau: 'tableaux',
|
||||
woman: 'women',
|
||||
child: 'children',
|
||||
man: 'men',
|
||||
corpus: 'corpora',
|
||||
criterion: 'criteria',
|
||||
curriculum: 'curricula',
|
||||
genus: 'genera',
|
||||
memorandum: 'memoranda',
|
||||
phenomenon: 'phenomena',
|
||||
foot: 'feet',
|
||||
goose: 'geese',
|
||||
tooth: 'teeth',
|
||||
antenna: 'antennae',
|
||||
formula: 'formulae',
|
||||
nebula: 'nebulae',
|
||||
vertebra: 'vertebrae',
|
||||
vita: 'vitae'
|
||||
},
|
||||
singular;
|
||||
|
||||
for (singular in irregulars) {
|
||||
this.plural(singular, irregulars[singular]);
|
||||
this.singular(irregulars[singular], singular);
|
||||
}
|
||||
});
|
||||
521
OfficeWeb/vendor/touch/src/util/JSON.js
vendored
Normal file
521
OfficeWeb/vendor/touch/src/util/JSON.js
vendored
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
http://www.JSON.org/json2.js
|
||||
2010-03-20
|
||||
|
||||
Public Domain.
|
||||
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
See http://www.JSON.org/js.html
|
||||
|
||||
|
||||
This code should be minified before deployment.
|
||||
See http://javascript.crockford.com/jsmin.html
|
||||
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||
NOT CONTROL.
|
||||
|
||||
|
||||
This file creates a global JSON object containing two methods: stringify
|
||||
and parse.
|
||||
|
||||
JSON.stringify(value, replacer, space)
|
||||
value any JavaScript value, usually an object or array.
|
||||
|
||||
replacer an optional parameter that determines how object
|
||||
values are stringified for objects. It can be a
|
||||
function or an array of strings.
|
||||
|
||||
space an optional parameter that specifies the indentation
|
||||
of nested structures. If it is omitted, the text will
|
||||
be packed without extra whitespace. If it is a number,
|
||||
it will specify the number of spaces to indent at each
|
||||
level. If it is a string (such as '\t' or ' '),
|
||||
it contains the characters used to indent at each level.
|
||||
|
||||
This method produces a JSON text from a JavaScript value.
|
||||
|
||||
When an object value is found, if the object contains a toJSON
|
||||
method, its toJSON method will be called and the result will be
|
||||
stringified. A toJSON method does not serialize: it returns the
|
||||
value represented by the name/value pair that should be serialized,
|
||||
or undefined if nothing should be serialized. The toJSON method
|
||||
will be passed the key associated with the value, and this will be
|
||||
bound to the value
|
||||
|
||||
For example, this would serialize Dates as ISO strings.
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
return this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z';
|
||||
};
|
||||
|
||||
You can provide an optional replacer method. It will be passed the
|
||||
key and value of each member, with this bound to the containing
|
||||
object. The value that is returned from your method will be
|
||||
serialized. If your method returns undefined, then the member will
|
||||
be excluded from the serialization.
|
||||
|
||||
If the replacer parameter is an array of strings, then it will be
|
||||
used to select the members to be serialized. It filters the results
|
||||
such that only members with keys listed in the replacer array are
|
||||
stringified.
|
||||
|
||||
Values that do not have JSON representations, such as undefined or
|
||||
functions, will not be serialized. Such values in objects will be
|
||||
dropped; in arrays they will be replaced with null. You can use
|
||||
a replacer function to replace those with JSON values.
|
||||
JSON.stringify(undefined) returns undefined.
|
||||
|
||||
The optional space parameter produces a stringification of the
|
||||
value that is filled with line breaks and indentation to make it
|
||||
easier to read.
|
||||
|
||||
If the space parameter is a non-empty string, then that string will
|
||||
be used for indentation. If the space parameter is a number, then
|
||||
the indentation will be that many spaces.
|
||||
|
||||
Example:
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||
// text is '["e",{"pluribus":"unum"}]'
|
||||
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||
|
||||
text = JSON.stringify([new Date()], function (key, value) {
|
||||
return this[key] instanceof Date ?
|
||||
'Date(' + this[key] + ')' : value;
|
||||
});
|
||||
// text is '["Date(---current time---)"]'
|
||||
|
||||
|
||||
JSON.parse(text, reviver)
|
||||
This method parses a JSON text to produce an object or array.
|
||||
It can throw a SyntaxError exception.
|
||||
|
||||
The optional reviver parameter is a function that can filter and
|
||||
transform the results. It receives each of the keys and values,
|
||||
and its return value is used instead of the original value.
|
||||
If it returns what it received, then the structure is not modified.
|
||||
If it returns undefined then the member is deleted.
|
||||
|
||||
Example:
|
||||
|
||||
// Parse the text. Values that look like ISO date strings will
|
||||
// be converted to Date objects.
|
||||
|
||||
myData = JSON.parse(text, function (key, value) {
|
||||
var a;
|
||||
if (typeof value === 'string') {
|
||||
a =
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||
if (a) {
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||
+a[5], +a[6]));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||
var d;
|
||||
if (typeof value === 'string' &&
|
||||
value.slice(0, 5) === 'Date(' &&
|
||||
value.slice(-1) === ')') {
|
||||
d = new Date(value.slice(5, -1));
|
||||
if (d) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
|
||||
This is a reference implementation. You are free to copy, modify, or
|
||||
redistribute.
|
||||
*/
|
||||
|
||||
/*jslint evil: true, strict: false */
|
||||
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||
test, toJSON, toString, valueOf
|
||||
*/
|
||||
|
||||
|
||||
// Create a JSON object only if one does not already exist. We create the
|
||||
// methods in a closure to avoid creating global variables.
|
||||
|
||||
if (!this.JSON) {
|
||||
this.JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
|
||||
return isFinite(this.valueOf()) ?
|
||||
this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z' : null;
|
||||
};
|
||||
|
||||
String.prototype.toJSON =
|
||||
Number.prototype.toJSON =
|
||||
Boolean.prototype.toJSON = function (key) {
|
||||
return this.valueOf();
|
||||
};
|
||||
}
|
||||
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap,
|
||||
indent,
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
rep;
|
||||
|
||||
|
||||
function quote(string) {
|
||||
|
||||
// If the string contains no control characters, no quote characters, and no
|
||||
// backslash characters, then we can safely slap some quotes around it.
|
||||
// Otherwise we must also replace the offending characters with safe escape
|
||||
// sequences.
|
||||
|
||||
escapable.lastIndex = 0;
|
||||
return escapable.test(string) ?
|
||||
'"' + string.replace(escapable, function (a) {
|
||||
var c = meta[a];
|
||||
return typeof c === 'string' ? c :
|
||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
}) + '"' :
|
||||
'"' + string + '"';
|
||||
}
|
||||
|
||||
|
||||
function str(key, holder) {
|
||||
|
||||
// Produce a string from holder[key].
|
||||
|
||||
var i, // The loop counter.
|
||||
k, // The member key.
|
||||
v, // The member value.
|
||||
length,
|
||||
mind = gap,
|
||||
partial,
|
||||
value = holder[key];
|
||||
|
||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||
|
||||
if (value && typeof value === 'object' &&
|
||||
typeof value.toJSON === 'function') {
|
||||
value = value.toJSON(key);
|
||||
}
|
||||
|
||||
// If we were called with a replacer function, then call the replacer to
|
||||
// obtain a replacement value.
|
||||
|
||||
if (typeof rep === 'function') {
|
||||
value = rep.call(holder, key, value);
|
||||
}
|
||||
|
||||
// What happens next depends on the value's type.
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return quote(value);
|
||||
|
||||
case 'number':
|
||||
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||
|
||||
return isFinite(value) ? String(value) : 'null';
|
||||
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
|
||||
// If the value is a boolean or null, convert it to a string. Note:
|
||||
// typeof null does not produce 'null'. The case is included here in
|
||||
// the remote chance that this gets fixed someday.
|
||||
|
||||
return String(value);
|
||||
|
||||
// If the type is 'object', we might be dealing with an object or an array or
|
||||
// null.
|
||||
|
||||
case 'object':
|
||||
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||
// so watch out for that case.
|
||||
|
||||
if (!value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
// Make an array to hold the partial results of stringifying this object value.
|
||||
|
||||
gap += indent;
|
||||
partial = [];
|
||||
|
||||
// Is the value an array?
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
|
||||
// The value is an array. Stringify every element. Use null as a placeholder
|
||||
// for non-JSON values.
|
||||
|
||||
length = value.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
partial[i] = str(i, value) || 'null';
|
||||
}
|
||||
|
||||
// Join all of the elements together, separated with commas, and wrap them in
|
||||
// brackets.
|
||||
|
||||
v = partial.length === 0 ? '[]' :
|
||||
gap ? '[\n' + gap +
|
||||
partial.join(',\n' + gap) + '\n' +
|
||||
mind + ']' :
|
||||
'[' + partial.join(',') + ']';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the replacer is an array, use it to select the members to be stringified.
|
||||
|
||||
if (rep && typeof rep === 'object') {
|
||||
length = rep.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
k = rep[i];
|
||||
if (typeof k === 'string') {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Otherwise, iterate through all of the keys in the object.
|
||||
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Join all of the member texts together, separated with commas,
|
||||
// and wrap them in braces.
|
||||
|
||||
v = partial.length === 0 ? '{}' :
|
||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
||||
mind + '}' : '{' + partial.join(',') + '}';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the JSON object does not yet have a stringify method, give it one.
|
||||
|
||||
if (typeof JSON.stringify !== 'function') {
|
||||
JSON.stringify = function (value, replacer, space) {
|
||||
|
||||
// The stringify method takes a value and an optional replacer, and an optional
|
||||
// space parameter, and returns a JSON text. The replacer can be a function
|
||||
// that can replace values, or an array of strings that will select the keys.
|
||||
// A default replacer method can be provided. Use of the space parameter can
|
||||
// produce text that is more easily readable.
|
||||
|
||||
var i;
|
||||
gap = '';
|
||||
indent = '';
|
||||
|
||||
// If the space parameter is a number, make an indent string containing that
|
||||
// many spaces.
|
||||
|
||||
if (typeof space === 'number') {
|
||||
for (i = 0; i < space; i += 1) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// If the space parameter is a string, it will be used as the indent string.
|
||||
|
||||
} else if (typeof space === 'string') {
|
||||
indent = space;
|
||||
}
|
||||
|
||||
// If there is a replacer, it must be a function or an array.
|
||||
// Otherwise, throw an error.
|
||||
|
||||
rep = replacer;
|
||||
if (replacer && typeof replacer !== 'function' &&
|
||||
(typeof replacer !== 'object' ||
|
||||
typeof replacer.length !== 'number')) {
|
||||
throw new Error('JSON.stringify');
|
||||
}
|
||||
|
||||
// Make a fake root object containing our value under the key of ''.
|
||||
// Return the result of stringifying the value.
|
||||
|
||||
return str('', {'': value});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// If the JSON object does not yet have a parse method, give it one.
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
|
||||
// The parse method takes a text and an optional reviver function, and returns
|
||||
// a JavaScript value if the text is a valid JSON text.
|
||||
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
|
||||
// The walk method is used to recursively walk the resulting structure so
|
||||
// that modifications can be made.
|
||||
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
|
||||
|
||||
// Parsing happens in four stages. In the first stage, we replace certain
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||
|
||||
text = String(text);
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
// In the second stage, we run the text against regular expressions that look
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||
// because they can cause invocation, and '=' because it can cause mutation.
|
||||
// But just to be safe, we want to reject all unexpected forms.
|
||||
|
||||
// We split the second stage into 4 regexp operations in order to work around
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||
// we look to see that the remaining characters are only whitespace or ']' or
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||
|
||||
if (/^[\],:{}\s]*$/.
|
||||
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
// In the third stage we use the eval function to compile the text into a
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||
// in parens to eliminate the ambiguity.
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||
// each name/value pair to a reviver function for possible transformation.
|
||||
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
||||
|
||||
/**
|
||||
* @class Ext.util.JSON
|
||||
* Modified version of Douglas Crockford"s json.js that doesn"t
|
||||
* mess with the Object prototype
|
||||
* http://www.json.org/js.html
|
||||
* @singleton
|
||||
* @ignore
|
||||
*/
|
||||
Ext.util.JSON = {
|
||||
encode: function(o) {
|
||||
return JSON.stringify(o);
|
||||
},
|
||||
|
||||
decode: function(s) {
|
||||
return JSON.parse(s);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shorthand for {@link Ext.util.JSON#encode}
|
||||
* @param {Mixed} o The variable to encode
|
||||
* @return {String} The JSON string
|
||||
* @member Ext
|
||||
* @method encode
|
||||
* @ignore
|
||||
*/
|
||||
Ext.encode = Ext.util.JSON.encode;
|
||||
/**
|
||||
* Shorthand for {@link Ext.util.JSON#decode}
|
||||
* @param {String} json The JSON string
|
||||
* @param {Boolean} safe (optional) Whether to return null or throw an exception if the JSON is invalid.
|
||||
* @return {Object} The resulting object
|
||||
* @member Ext
|
||||
* @method decode
|
||||
* @ignore
|
||||
*/
|
||||
Ext.decode = Ext.util.JSON.decode;
|
||||
66
OfficeWeb/vendor/touch/src/util/LineSegment.js
vendored
Normal file
66
OfficeWeb/vendor/touch/src/util/LineSegment.js
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @class Ext.util.LineSegment
|
||||
*
|
||||
* Utility class that represents a line segment, constructed by two {@link Ext.util.Point}
|
||||
*/
|
||||
Ext.define('Ext.util.LineSegment', {
|
||||
requires: ['Ext.util.Point'],
|
||||
|
||||
/**
|
||||
* Creates new LineSegment out of two points.
|
||||
* @param {Ext.util.Point} point1
|
||||
* @param {Ext.util.Point} point2
|
||||
*/
|
||||
constructor: function(point1, point2) {
|
||||
var Point = Ext.util.Point;
|
||||
|
||||
this.point1 = Point.from(point1);
|
||||
this.point2 = Point.from(point2);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the point where two lines intersect.
|
||||
* @param {Ext.util.LineSegment} lineSegment The line to intersect with.
|
||||
* @return {Ext.util.Point}
|
||||
*/
|
||||
intersects: function(lineSegment) {
|
||||
var point1 = this.point1,
|
||||
point2 = this.point2,
|
||||
point3 = lineSegment.point1,
|
||||
point4 = lineSegment.point2,
|
||||
x1 = point1.x,
|
||||
x2 = point2.x,
|
||||
x3 = point3.x,
|
||||
x4 = point4.x,
|
||||
y1 = point1.y,
|
||||
y2 = point2.y,
|
||||
y3 = point3.y,
|
||||
y4 = point4.y,
|
||||
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4),
|
||||
xi, yi;
|
||||
|
||||
if (d == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
|
||||
yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
|
||||
|
||||
if (xi < Math.min(x1, x2) || xi > Math.max(x1, x2)
|
||||
|| xi < Math.min(x3, x4) || xi > Math.max(x3, x4)
|
||||
|| yi < Math.min(y1, y2) || yi > Math.max(y1, y2)
|
||||
|| yi < Math.min(y3, y4) || yi > Math.max(y3, y4)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Ext.util.Point(xi, yi);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns string representation of the line. Useful for debugging.
|
||||
* @return {String} For example `Point[12,8] Point[0,0]`
|
||||
*/
|
||||
toString: function() {
|
||||
return this.point1.toString() + " " + this.point2.toString();
|
||||
}
|
||||
});
|
||||
194
OfficeWeb/vendor/touch/src/util/MixedCollection.js
vendored
Normal file
194
OfficeWeb/vendor/touch/src/util/MixedCollection.js
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Represents a collection of a set of key and value pairs. Each key in the MixedCollection must be unique, the same key
|
||||
* cannot exist twice. This collection is ordered, items in the collection can be accessed by index or via the key.
|
||||
* Newly added items are added to the end of the collection. This class is similar to {@link Ext.util.HashMap} however
|
||||
* it is heavier and provides more functionality. Sample usage:
|
||||
*
|
||||
* @example
|
||||
* var coll = new Ext.util.MixedCollection();
|
||||
* coll.add('key1', 'val1');
|
||||
* coll.add('key2', 'val2');
|
||||
* coll.add('key3', 'val3');
|
||||
*
|
||||
* alert(coll.get('key1')); // 'val1'
|
||||
* alert(coll.indexOfKey('key3')); // 2
|
||||
*
|
||||
* The MixedCollection also has support for sorting and filtering of the values in the collection.
|
||||
*
|
||||
* @example
|
||||
* var coll = new Ext.util.MixedCollection();
|
||||
* coll.add('key1', 100);
|
||||
* coll.add('key2', -100);
|
||||
* coll.add('key3', 17);
|
||||
* coll.add('key4', 0);
|
||||
* var biggerThanZero = coll.filterBy(function(value){
|
||||
* return value > 0;
|
||||
* });
|
||||
* alert(biggerThanZero.getCount()); // 2
|
||||
*/
|
||||
Ext.define('Ext.util.MixedCollection', {
|
||||
extend: 'Ext.util.AbstractMixedCollection',
|
||||
mixins: {
|
||||
sortable: 'Ext.util.Sortable'
|
||||
},
|
||||
|
||||
/**
|
||||
* @event sort
|
||||
* Fires whenever MixedCollection is sorted.
|
||||
* @param {Ext.util.MixedCollection} this
|
||||
*/
|
||||
|
||||
constructor: function() {
|
||||
var me = this;
|
||||
me.callParent(arguments);
|
||||
me.mixins.sortable.initSortable.call(me);
|
||||
},
|
||||
|
||||
doSort: function(sorterFn) {
|
||||
this.sortBy(sorterFn);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Performs the actual sorting based on a direction and a sorting function. Internally,
|
||||
* this creates a temporary array of all items in the MixedCollection, sorts it and then writes
|
||||
* the sorted array data back into `this.items` and `this.keys`.
|
||||
* @param {String} property Property to sort by ('key', 'value', or 'index')
|
||||
* @param {String} [dir=ASC] (optional) Direction to sort 'ASC' or 'DESC'.
|
||||
* @param {Function} fn (optional) Comparison function that defines the sort order.
|
||||
* Defaults to sorting by numeric value.
|
||||
*/
|
||||
_sort: function(property, dir, fn){
|
||||
var me = this,
|
||||
i, len,
|
||||
dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
|
||||
|
||||
//this is a temporary array used to apply the sorting function
|
||||
c = [],
|
||||
keys = me.keys,
|
||||
items = me.items;
|
||||
|
||||
//default to a simple sorter function if one is not provided
|
||||
fn = fn || function(a, b) {
|
||||
return a - b;
|
||||
};
|
||||
|
||||
//copy all the items into a temporary array, which we will sort
|
||||
for(i = 0, len = items.length; i < len; i++){
|
||||
c[c.length] = {
|
||||
key : keys[i],
|
||||
value: items[i],
|
||||
index: i
|
||||
};
|
||||
}
|
||||
|
||||
//sort the temporary array
|
||||
Ext.Array.sort(c, function(a, b){
|
||||
var v = fn(a[property], b[property]) * dsc;
|
||||
if(v === 0){
|
||||
v = (a.index < b.index ? -1 : 1);
|
||||
}
|
||||
return v;
|
||||
});
|
||||
|
||||
//copy the temporary array back into the main this.items and this.keys objects
|
||||
for(i = 0, len = c.length; i < len; i++){
|
||||
items[i] = c[i].value;
|
||||
keys[i] = c[i].key;
|
||||
}
|
||||
|
||||
me.fireEvent('sort', me);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sorts the collection by a single sorter function.
|
||||
* @param {Function} sorterFn The function to sort by.
|
||||
*/
|
||||
sortBy: function(sorterFn) {
|
||||
var me = this,
|
||||
items = me.items,
|
||||
keys = me.keys,
|
||||
length = items.length,
|
||||
temp = [],
|
||||
i;
|
||||
|
||||
//first we create a copy of the items array so that we can sort it
|
||||
for (i = 0; i < length; i++) {
|
||||
temp[i] = {
|
||||
key : keys[i],
|
||||
value: items[i],
|
||||
index: i
|
||||
};
|
||||
}
|
||||
|
||||
Ext.Array.sort(temp, function(a, b) {
|
||||
var v = sorterFn(a.value, b.value);
|
||||
if (v === 0) {
|
||||
v = (a.index < b.index ? -1 : 1);
|
||||
}
|
||||
|
||||
return v;
|
||||
});
|
||||
|
||||
//copy the temporary array back into the main this.items and this.keys objects
|
||||
for (i = 0; i < length; i++) {
|
||||
items[i] = temp[i].value;
|
||||
keys[i] = temp[i].key;
|
||||
}
|
||||
|
||||
me.fireEvent('sort', me, items, keys);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reorders each of the items based on a mapping from old index to new index. Internally this just translates into a
|
||||
* sort. The `sort` event is fired whenever reordering has occured.
|
||||
* @param {Object} mapping Mapping from old item index to new item index.
|
||||
*/
|
||||
reorder: function(mapping) {
|
||||
var me = this,
|
||||
items = me.items,
|
||||
index = 0,
|
||||
length = items.length,
|
||||
order = [],
|
||||
remaining = [],
|
||||
oldIndex;
|
||||
|
||||
me.suspendEvents();
|
||||
|
||||
//object of {oldPosition: newPosition} reversed to {newPosition: oldPosition}
|
||||
for (oldIndex in mapping) {
|
||||
order[mapping[oldIndex]] = items[oldIndex];
|
||||
}
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
if (mapping[index] == undefined) {
|
||||
remaining.push(items[index]);
|
||||
}
|
||||
}
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
if (order[index] == undefined) {
|
||||
order[index] = remaining.shift();
|
||||
}
|
||||
}
|
||||
|
||||
me.clear();
|
||||
me.addAll(order);
|
||||
|
||||
me.resumeEvents();
|
||||
me.fireEvent('sort', me);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sorts this collection by **key**s.
|
||||
* @param {String} [direction=ASC] 'ASC' or 'DESC'.
|
||||
* @param {Function} [fn] Comparison function that defines the sort order. Defaults to sorting by case insensitive
|
||||
* string.
|
||||
*/
|
||||
sortByKey: function(dir, fn){
|
||||
this._sort('key', dir, fn || function(a, b){
|
||||
var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
|
||||
return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
|
||||
});
|
||||
}
|
||||
});
|
||||
60
OfficeWeb/vendor/touch/src/util/Offset.js
vendored
Normal file
60
OfficeWeb/vendor/touch/src/util/Offset.js
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.Offset', {
|
||||
|
||||
/* Begin Definitions */
|
||||
|
||||
statics: {
|
||||
fromObject: function(obj) {
|
||||
return new this(obj.x, obj.y);
|
||||
}
|
||||
},
|
||||
|
||||
/* End Definitions */
|
||||
|
||||
constructor: function(x, y) {
|
||||
this.x = (x != null && !isNaN(x)) ? x : 0;
|
||||
this.y = (y != null && !isNaN(y)) ? y : 0;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
copy: function() {
|
||||
return new Ext.util.Offset(this.x, this.y);
|
||||
},
|
||||
|
||||
copyFrom: function(p) {
|
||||
this.x = p.x;
|
||||
this.y = p.y;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return "Offset[" + this.x + "," + this.y + "]";
|
||||
},
|
||||
|
||||
equals: function(offset) {
|
||||
//<debug>
|
||||
if(!(offset instanceof this.statics())) {
|
||||
Ext.Error.raise('Offset must be an instance of Ext.util.Offset');
|
||||
}
|
||||
//</debug>
|
||||
|
||||
return (this.x == offset.x && this.y == offset.y);
|
||||
},
|
||||
|
||||
round: function(to) {
|
||||
if (!isNaN(to)) {
|
||||
var factor = Math.pow(10, to);
|
||||
this.x = Math.round(this.x * factor) / factor;
|
||||
this.y = Math.round(this.y * factor) / factor;
|
||||
} else {
|
||||
this.x = Math.round(this.x);
|
||||
this.y = Math.round(this.y);
|
||||
}
|
||||
},
|
||||
|
||||
isZero: function() {
|
||||
return this.x == 0 && this.y == 0;
|
||||
}
|
||||
});
|
||||
18
OfficeWeb/vendor/touch/src/util/PaintMonitor.js
vendored
Normal file
18
OfficeWeb/vendor/touch/src/util/PaintMonitor.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.util.PaintMonitor', {
|
||||
requires: [
|
||||
'Ext.util.paintmonitor.CssAnimation',
|
||||
'Ext.util.paintmonitor.OverflowChange'
|
||||
],
|
||||
|
||||
constructor: function(config) {
|
||||
if (Ext.browser.engineVersion.gtEq('536')) {
|
||||
return new Ext.util.paintmonitor.OverflowChange(config);
|
||||
}
|
||||
else {
|
||||
return new Ext.util.paintmonitor.CssAnimation(config);
|
||||
}
|
||||
}
|
||||
});
|
||||
191
OfficeWeb/vendor/touch/src/util/Point.js
vendored
Normal file
191
OfficeWeb/vendor/touch/src/util/Point.js
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* Represents a 2D point with x and y properties, useful for comparison and instantiation
|
||||
* from an event:
|
||||
*
|
||||
* var point = Ext.util.Point.fromEvent(e);
|
||||
*/
|
||||
Ext.define('Ext.util.Point', {
|
||||
|
||||
radianToDegreeConstant: 180 / Math.PI,
|
||||
|
||||
statics: {
|
||||
/**
|
||||
* Returns a new instance of {@link Ext.util.Point} based on the `pageX` / `pageY` values of the given event.
|
||||
* @static
|
||||
* @param {Event} e The event.
|
||||
* @return {Ext.util.Point}
|
||||
*/
|
||||
fromEvent: function(e) {
|
||||
var changedTouches = e.changedTouches,
|
||||
touch = (changedTouches && changedTouches.length > 0) ? changedTouches[0] : e;
|
||||
|
||||
return this.fromTouch(touch);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a new instance of {@link Ext.util.Point} based on the `pageX` / `pageY` values of the given touch.
|
||||
* @static
|
||||
* @param {Event} touch
|
||||
* @return {Ext.util.Point}
|
||||
*/
|
||||
fromTouch: function(touch) {
|
||||
return new this(touch.pageX, touch.pageY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a new point from an object that has `x` and `y` properties, if that object is not an instance
|
||||
* of {@link Ext.util.Point}. Otherwise, returns the given point itself.
|
||||
* @param object
|
||||
* @return {Ext.util.Point}
|
||||
*/
|
||||
from: function(object) {
|
||||
if (!object) {
|
||||
return new this(0, 0);
|
||||
}
|
||||
|
||||
if (!(object instanceof this)) {
|
||||
return new this(object.x, object.y);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates point on 2D plane.
|
||||
* @param {Number} [x=0] X coordinate.
|
||||
* @param {Number} [y=0] Y coordinate.
|
||||
*/
|
||||
constructor: function(x, y) {
|
||||
if (typeof x == 'undefined') {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (typeof y == 'undefined') {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a new instance of this point.
|
||||
* @return {Ext.util.Point} The new point.
|
||||
*/
|
||||
clone: function() {
|
||||
return new this.self(this.x, this.y);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clones this Point.
|
||||
* @deprecated 2.0.0 Please use {@link #clone} instead.
|
||||
* @return {Ext.util.Point} The new point.
|
||||
*/
|
||||
copy: function() {
|
||||
return this.clone.apply(this, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the `x` and `y` values of another point / object to this point itself.
|
||||
* @param {Ext.util.Point/Object} point.
|
||||
* @return {Ext.util.Point} This point.
|
||||
*/
|
||||
copyFrom: function(point) {
|
||||
this.x = point.x;
|
||||
this.y = point.y;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a human-eye-friendly string that represents this point,
|
||||
* useful for debugging.
|
||||
* @return {String} For example `Point[12,8]`.
|
||||
*/
|
||||
toString: function() {
|
||||
return "Point[" + this.x + "," + this.y + "]";
|
||||
},
|
||||
|
||||
/**
|
||||
* Compare this point and another point.
|
||||
* @param {Ext.util.Point/Object} The point to compare with, either an instance
|
||||
* of {@link Ext.util.Point} or an object with `x` and `y` properties.
|
||||
* @return {Boolean} Returns whether they are equivalent.
|
||||
*/
|
||||
equals: function(point) {
|
||||
return (this.x === point.x && this.y === point.y);
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the given point is not away from this point within the given threshold amount.
|
||||
* @param {Ext.util.Point/Object} The point to check with, either an instance
|
||||
* of {@link Ext.util.Point} or an object with `x` and `y` properties.
|
||||
* @param {Object/Number} threshold Can be either an object with `x` and `y` properties or a number.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isCloseTo: function(point, threshold) {
|
||||
if (typeof threshold == 'number') {
|
||||
threshold = {x: threshold};
|
||||
threshold.y = threshold.x;
|
||||
}
|
||||
|
||||
var x = point.x,
|
||||
y = point.y,
|
||||
thresholdX = threshold.x,
|
||||
thresholdY = threshold.y;
|
||||
|
||||
return (this.x <= x + thresholdX && this.x >= x - thresholdX &&
|
||||
this.y <= y + thresholdY && this.y >= y - thresholdY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns `true` if this point is close to another one.
|
||||
* @deprecated 2.0.0 Please use {@link #isCloseTo} instead.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isWithin: function() {
|
||||
return this.isCloseTo.apply(this, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Translate this point by the given amounts.
|
||||
* @param {Number} x Amount to translate in the x-axis.
|
||||
* @param {Number} y Amount to translate in the y-axis.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
translate: function(x, y) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Compare this point with another point when the `x` and `y` values of both points are rounded. For example:
|
||||
* [100.3,199.8] will equals to [100, 200].
|
||||
* @param {Ext.util.Point/Object} point The point to compare with, either an instance
|
||||
* of Ext.util.Point or an object with `x` and `y` properties.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
roundedEquals: function(point) {
|
||||
return (Math.round(this.x) === Math.round(point.x) &&
|
||||
Math.round(this.y) === Math.round(point.y));
|
||||
},
|
||||
|
||||
getDistanceTo: function(point) {
|
||||
var deltaX = this.x - point.x,
|
||||
deltaY = this.y - point.y;
|
||||
|
||||
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
},
|
||||
|
||||
getAngleTo: function(point) {
|
||||
var deltaX = this.x - point.x,
|
||||
deltaY = this.y - point.y;
|
||||
|
||||
return Math.atan2(deltaY, deltaX) * this.radianToDegreeConstant;
|
||||
}
|
||||
});
|
||||
127
OfficeWeb/vendor/touch/src/util/PositionMap.js
vendored
Normal file
127
OfficeWeb/vendor/touch/src/util/PositionMap.js
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.PositionMap', {
|
||||
config: {
|
||||
minimumHeight: 50
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.map = [];
|
||||
this.adjustments = {};
|
||||
this.offset = 0;
|
||||
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
populate: function(count, offset) {
|
||||
var map = this.map = this.map || [],
|
||||
minimumHeight = this.getMinimumHeight(),
|
||||
i, previousIndex, ln;
|
||||
|
||||
// We add 1 item to the count so that we can get the height of the bottom item
|
||||
count++;
|
||||
map.length = count;
|
||||
|
||||
map[0] = 0;
|
||||
for (i = offset + 1, ln = count - 1; i <= ln; i++) {
|
||||
previousIndex = i - 1;
|
||||
map[i] = map[previousIndex] + minimumHeight;
|
||||
}
|
||||
|
||||
this.adjustments = {
|
||||
indices: [],
|
||||
heights: {}
|
||||
};
|
||||
this.offset = 0;
|
||||
for (i = 1, ln = count - 1; i <= ln; i++) {
|
||||
previousIndex = i - 1;
|
||||
this.offset += map[i] - map[previousIndex] - minimumHeight;
|
||||
}
|
||||
},
|
||||
|
||||
setItemHeight: function(index, height) {
|
||||
height = Math.max(height, this.getMinimumHeight());
|
||||
if (height !== this.getItemHeight(index)) {
|
||||
var adjustments = this.adjustments;
|
||||
adjustments.indices.push(parseInt(index, 10));
|
||||
adjustments.heights[index] = height;
|
||||
}
|
||||
},
|
||||
|
||||
update: function() {
|
||||
var adjustments = this.adjustments,
|
||||
indices = adjustments.indices,
|
||||
heights = adjustments.heights,
|
||||
map = this.map,
|
||||
ln = indices.length,
|
||||
minimumHeight = this.getMinimumHeight(),
|
||||
difference = 0,
|
||||
i, j, height, index, nextIndex, currentHeight;
|
||||
|
||||
if (!adjustments.indices.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Ext.Array.sort(indices, function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
|
||||
for (i = 0; i < ln; i++) {
|
||||
index = indices[i];
|
||||
nextIndex = indices[i + 1] || map.length - 1;
|
||||
|
||||
currentHeight = (map[index + 1] !== undefined) ? (map[index + 1] - map[index] + difference) : minimumHeight;
|
||||
height = heights[index];
|
||||
|
||||
difference += height - currentHeight;
|
||||
|
||||
for (j = index + 1; j <= nextIndex; j++) {
|
||||
map[j] += difference;
|
||||
}
|
||||
}
|
||||
|
||||
this.offset += difference;
|
||||
this.adjustments = {
|
||||
indices: [],
|
||||
heights: {}
|
||||
};
|
||||
return true;
|
||||
},
|
||||
|
||||
getItemHeight: function(index) {
|
||||
return this.map[index + 1] - this.map[index];
|
||||
},
|
||||
|
||||
getTotalHeight: function() {
|
||||
return ((this.map.length - 1) * this.getMinimumHeight()) + this.offset;
|
||||
},
|
||||
|
||||
findIndex: function(pos) {
|
||||
return this.map.length ? this.binarySearch(this.map, pos) : 0;
|
||||
},
|
||||
|
||||
binarySearch: function(sorted, value) {
|
||||
var start = 0,
|
||||
end = sorted.length;
|
||||
|
||||
if (value < sorted[0]) {
|
||||
return 0;
|
||||
}
|
||||
if (value > sorted[end - 1]) {
|
||||
return end - 1;
|
||||
}
|
||||
while (start + 1 < end) {
|
||||
var mid = (start + end) >> 1,
|
||||
val = sorted[mid];
|
||||
if (val == value) {
|
||||
return mid;
|
||||
} else if (val < value) {
|
||||
start = mid;
|
||||
} else {
|
||||
end = mid;
|
||||
}
|
||||
}
|
||||
return start;
|
||||
}
|
||||
});
|
||||
371
OfficeWeb/vendor/touch/src/util/Region.js
vendored
Normal file
371
OfficeWeb/vendor/touch/src/util/Region.js
vendored
Normal file
@@ -0,0 +1,371 @@
|
||||
/**
|
||||
* Represents a rectangular region and provides a number of utility methods
|
||||
* to compare regions.
|
||||
*/
|
||||
Ext.define('Ext.util.Region', {
|
||||
|
||||
requires: ['Ext.util.Offset'],
|
||||
|
||||
statics: {
|
||||
/**
|
||||
* @static
|
||||
* Retrieves an Ext.util.Region for a particular element.
|
||||
* @param {String/HTMLElement/Ext.Element} el The element or its ID.
|
||||
* @return {Ext.util.Region} region
|
||||
*/
|
||||
getRegion: function(el) {
|
||||
return Ext.fly(el).getPageBox(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* @static
|
||||
* Creates new Region from an object:
|
||||
*
|
||||
* Ext.util.Region.from({top: 0, right: 5, bottom: 3, left: -1});
|
||||
* // the above is equivalent to:
|
||||
* new Ext.util.Region(0, 5, 3, -1);
|
||||
*
|
||||
* @param {Object} o An object with `top`, `right`, `bottom`, and `left` properties.
|
||||
* @param {Number} o.top
|
||||
* @param {Number} o.right
|
||||
* @param {Number} o.bottom
|
||||
* @param {Number} o.left
|
||||
* @return {Ext.util.Region} The region constructed based on the passed object.
|
||||
*/
|
||||
from: function(o) {
|
||||
return new this(o.top, o.right, o.bottom, o.left);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates new Region.
|
||||
* @param {Number} top Top
|
||||
* @param {Number} right Right
|
||||
* @param {Number} bottom Bottom
|
||||
* @param {Number} left Left
|
||||
*/
|
||||
constructor: function(top, right, bottom, left) {
|
||||
var me = this;
|
||||
me.top = top;
|
||||
me[1] = top;
|
||||
me.right = right;
|
||||
me.bottom = bottom;
|
||||
me.left = left;
|
||||
me[0] = left;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if this region completely contains the region that is passed in.
|
||||
* @param {Ext.util.Region} region
|
||||
* @return {Boolean}
|
||||
*/
|
||||
contains: function(region) {
|
||||
var me = this;
|
||||
return (region.left >= me.left &&
|
||||
region.right <= me.right &&
|
||||
region.top >= me.top &&
|
||||
region.bottom <= me.bottom);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if this region intersects the region passed in.
|
||||
* @param {Ext.util.Region} region
|
||||
* @return {Ext.util.Region/Boolean} Returns the intersected region or `false` if there is no intersection.
|
||||
*/
|
||||
intersect: function(region) {
|
||||
var me = this,
|
||||
t = Math.max(me.top, region.top),
|
||||
r = Math.min(me.right, region.right),
|
||||
b = Math.min(me.bottom, region.bottom),
|
||||
l = Math.max(me.left, region.left);
|
||||
|
||||
if (b > t && r > l) {
|
||||
return new Ext.util.Region(t, r, b, l);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the smallest region that contains the current AND `targetRegion`.
|
||||
* @param {Ext.util.Region} region
|
||||
* @return {Ext.util.Region}
|
||||
*/
|
||||
union: function(region) {
|
||||
var me = this,
|
||||
t = Math.min(me.top, region.top),
|
||||
r = Math.max(me.right, region.right),
|
||||
b = Math.max(me.bottom, region.bottom),
|
||||
l = Math.min(me.left, region.left);
|
||||
|
||||
return new Ext.util.Region(t, r, b, l);
|
||||
},
|
||||
|
||||
/**
|
||||
* Modifies the current region to be constrained to the `targetRegion`.
|
||||
* @param {Ext.util.Region} targetRegion
|
||||
* @return {Ext.util.Region} this
|
||||
*/
|
||||
constrainTo: function(targetRegion) {
|
||||
var me = this,
|
||||
constrain = Ext.util.Numbers.constrain;
|
||||
me.top = constrain(me.top, targetRegion.top, targetRegion.bottom);
|
||||
me.bottom = constrain(me.bottom, targetRegion.top, targetRegion.bottom);
|
||||
me.left = constrain(me.left, targetRegion.left, targetRegion.right);
|
||||
me.right = constrain(me.right, targetRegion.left, targetRegion.right);
|
||||
return me;
|
||||
},
|
||||
|
||||
/**
|
||||
* Modifies the current region to be adjusted by offsets.
|
||||
* @param {Number} top Top offset
|
||||
* @param {Number} right Right offset
|
||||
* @param {Number} bottom Bottom offset
|
||||
* @param {Number} left Left offset
|
||||
* @return {Ext.util.Region} this
|
||||
* @chainable
|
||||
*/
|
||||
adjust: function(top, right, bottom, left) {
|
||||
var me = this;
|
||||
me.top += top;
|
||||
me.left += left;
|
||||
me.right += right;
|
||||
me.bottom += bottom;
|
||||
return me;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the offset amount of a point outside the region.
|
||||
* @param {String/Object} axis optional.
|
||||
* @param {Ext.util.Point} p The point.
|
||||
* @return {Ext.util.Region}
|
||||
*/
|
||||
getOutOfBoundOffset: function(axis, p) {
|
||||
if (!Ext.isObject(axis)) {
|
||||
if (axis == 'x') {
|
||||
return this.getOutOfBoundOffsetX(p);
|
||||
} else {
|
||||
return this.getOutOfBoundOffsetY(p);
|
||||
}
|
||||
} else {
|
||||
var d = new Ext.util.Offset();
|
||||
d.x = this.getOutOfBoundOffsetX(axis.x);
|
||||
d.y = this.getOutOfBoundOffsetY(axis.y);
|
||||
return d;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the offset amount on the x-axis.
|
||||
* @param {Number} p The offset.
|
||||
* @return {Number}
|
||||
*/
|
||||
getOutOfBoundOffsetX: function(p) {
|
||||
if (p <= this.left) {
|
||||
return this.left - p;
|
||||
} else if (p >= this.right) {
|
||||
return this.right - p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the offset amount on the y-axis.
|
||||
* @param {Number} p The offset.
|
||||
* @return {Number}
|
||||
*/
|
||||
getOutOfBoundOffsetY: function(p) {
|
||||
if (p <= this.top) {
|
||||
return this.top - p;
|
||||
} else if (p >= this.bottom) {
|
||||
return this.bottom - p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the point / offset is out of bounds.
|
||||
* @param {String} axis optional
|
||||
* @param {Ext.util.Point/Number} p The point / offset.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isOutOfBound: function(axis, p) {
|
||||
if (!Ext.isObject(axis)) {
|
||||
if (axis == 'x') {
|
||||
return this.isOutOfBoundX(p);
|
||||
} else {
|
||||
return this.isOutOfBoundY(p);
|
||||
}
|
||||
} else {
|
||||
p = axis;
|
||||
return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the offset is out of bound in the x-axis.
|
||||
* @param {Number} p The offset.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isOutOfBoundX: function(p) {
|
||||
return (p < this.left || p > this.right);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the offset is out of bound in the y-axis.
|
||||
* @param {Number} p The offset.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isOutOfBoundY: function(p) {
|
||||
return (p < this.top || p > this.bottom);
|
||||
},
|
||||
|
||||
/*
|
||||
* Restrict a point within the region by a certain factor.
|
||||
* @param {String} axis Optional
|
||||
* @param {Ext.util.Point/Ext.util.Offset/Object} p
|
||||
* @param {Number} factor
|
||||
* @return {Ext.util.Point/Ext.util.Offset/Object/Number}
|
||||
*/
|
||||
restrict: function(axis, p, factor) {
|
||||
if (Ext.isObject(axis)) {
|
||||
var newP;
|
||||
|
||||
factor = p;
|
||||
p = axis;
|
||||
|
||||
if (p.copy) {
|
||||
newP = p.copy();
|
||||
}
|
||||
else {
|
||||
newP = {
|
||||
x: p.x,
|
||||
y: p.y
|
||||
};
|
||||
}
|
||||
|
||||
newP.x = this.restrictX(p.x, factor);
|
||||
newP.y = this.restrictY(p.y, factor);
|
||||
return newP;
|
||||
} else {
|
||||
if (axis == 'x') {
|
||||
return this.restrictX(p, factor);
|
||||
} else {
|
||||
return this.restrictY(p, factor);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Restrict an offset within the region by a certain factor, on the x-axis.
|
||||
* @param {Number} p
|
||||
* @param {Number} [factor=1] (optional) The factor.
|
||||
* @return {Number}
|
||||
*/
|
||||
restrictX: function(p, factor) {
|
||||
if (!factor) {
|
||||
factor = 1;
|
||||
}
|
||||
|
||||
if (p <= this.left) {
|
||||
p -= (p - this.left) * factor;
|
||||
}
|
||||
else if (p >= this.right) {
|
||||
p -= (p - this.right) * factor;
|
||||
}
|
||||
return p;
|
||||
},
|
||||
|
||||
/*
|
||||
* Restrict an offset within the region by a certain factor, on the y-axis.
|
||||
* @param {Number} p
|
||||
* @param {Number} [factor=1] (optional) The factor.
|
||||
* @return {Number}
|
||||
*/
|
||||
restrictY: function(p, factor) {
|
||||
if (!factor) {
|
||||
factor = 1;
|
||||
}
|
||||
|
||||
if (p <= this.top) {
|
||||
p -= (p - this.top) * factor;
|
||||
}
|
||||
else if (p >= this.bottom) {
|
||||
p -= (p - this.bottom) * factor;
|
||||
}
|
||||
return p;
|
||||
},
|
||||
|
||||
/*
|
||||
* Get the width / height of this region.
|
||||
* @return {Object} An object with `width` and `height` properties.
|
||||
* @return {Number} return.width
|
||||
* @return {Number} return.height
|
||||
*/
|
||||
getSize: function() {
|
||||
return {
|
||||
width: this.right - this.left,
|
||||
height: this.bottom - this.top
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a new instance.
|
||||
* @return {Ext.util.Region}
|
||||
*/
|
||||
copy: function() {
|
||||
return new Ext.util.Region(this.top, this.right, this.bottom, this.left);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dump this to an eye-friendly string, great for debugging.
|
||||
* @return {String} For example `Region[0,1,3,2]`.
|
||||
*/
|
||||
toString: function() {
|
||||
return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Translate this region by the given offset amount.
|
||||
* @param {Object} offset
|
||||
* @return {Ext.util.Region} This Region.
|
||||
* @chainable
|
||||
*/
|
||||
translateBy: function(offset) {
|
||||
this.left += offset.x;
|
||||
this.right += offset.x;
|
||||
this.top += offset.y;
|
||||
this.bottom += offset.y;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Round all the properties of this region.
|
||||
* @return {Ext.util.Region} This Region.
|
||||
* @chainable
|
||||
*/
|
||||
round: function() {
|
||||
this.top = Math.round(this.top);
|
||||
this.right = Math.round(this.right);
|
||||
this.bottom = Math.round(this.bottom);
|
||||
this.left = Math.round(this.left);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether this region is equivalent to the given region.
|
||||
* @param {Ext.util.Region} region The region to compare with.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
equals: function(region) {
|
||||
return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left)
|
||||
}
|
||||
});
|
||||
18
OfficeWeb/vendor/touch/src/util/SizeMonitor.js
vendored
Normal file
18
OfficeWeb/vendor/touch/src/util/SizeMonitor.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.util.SizeMonitor', {
|
||||
requires: [
|
||||
'Ext.util.sizemonitor.Scroll',
|
||||
'Ext.util.sizemonitor.OverflowChange'
|
||||
],
|
||||
|
||||
constructor: function(config) {
|
||||
if (Ext.browser.engineVersion.gtEq('535')) {
|
||||
return new Ext.util.sizemonitor.OverflowChange(config);
|
||||
}
|
||||
else {
|
||||
return new Ext.util.sizemonitor.Scroll(config);
|
||||
}
|
||||
}
|
||||
});
|
||||
249
OfficeWeb/vendor/touch/src/util/Sortable.js
vendored
Normal file
249
OfficeWeb/vendor/touch/src/util/Sortable.js
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* @docauthor Tommy Maintz <tommy@sencha.com>
|
||||
*
|
||||
* A mixin which allows a data component to be sorted. This is used by e.g. {@link Ext.data.Store} and {@link Ext.data.TreeStore}.
|
||||
*
|
||||
* __Note:__ This mixin is mainly for internal library use and most users should not need to use it directly. It
|
||||
* is more likely you will want to use one of the component classes that import this mixin, such as
|
||||
* {@link Ext.data.Store} or {@link Ext.data.TreeStore}.
|
||||
*/
|
||||
Ext.define("Ext.util.Sortable", {
|
||||
extend: 'Ext.mixin.Mixin',
|
||||
/**
|
||||
* @property {Boolean} isSortable
|
||||
* Flag denoting that this object is sortable. Always `true`.
|
||||
* @readonly
|
||||
*/
|
||||
isSortable: true,
|
||||
|
||||
mixinConfig: {
|
||||
hooks: {
|
||||
destroy: 'destroy'
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @property {String} defaultSortDirection
|
||||
* The default sort direction to use if one is not specified.
|
||||
*/
|
||||
defaultSortDirection: "ASC",
|
||||
|
||||
requires: [
|
||||
'Ext.util.Sorter'
|
||||
],
|
||||
|
||||
/**
|
||||
* @property {String} sortRoot
|
||||
* The property in each item that contains the data to sort.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Performs initialization of this mixin. Component classes using this mixin should call this method during their
|
||||
* own initialization.
|
||||
*/
|
||||
initSortable: function() {
|
||||
var me = this,
|
||||
sorters = me.sorters;
|
||||
|
||||
/**
|
||||
* @property {Ext.util.MixedCollection} sorters
|
||||
* The collection of {@link Ext.util.Sorter Sorters} currently applied to this Store
|
||||
*/
|
||||
me.sorters = Ext.create('Ext.util.AbstractMixedCollection', false, function(item) {
|
||||
return item.id || item.property;
|
||||
});
|
||||
|
||||
if (sorters) {
|
||||
me.sorters.addAll(me.decodeSorters(sorters));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sorts the data in the Store by one or more of its properties. Example usage:
|
||||
*
|
||||
* //sort by a single field
|
||||
* myStore.sort('myField', 'DESC');
|
||||
*
|
||||
* //sorting by multiple fields
|
||||
* myStore.sort([
|
||||
* {
|
||||
* property : 'age',
|
||||
* direction: 'ASC'
|
||||
* },
|
||||
* {
|
||||
* property : 'name',
|
||||
* direction: 'DESC'
|
||||
* }
|
||||
* ]);
|
||||
*
|
||||
* Internally, Store converts the passed arguments into an array of {@link Ext.util.Sorter} instances, and delegates
|
||||
* the actual sorting to its internal {@link Ext.util.MixedCollection}.
|
||||
*
|
||||
* When passing a single string argument to sort, Store maintains a ASC/DESC toggler per field, so this code:
|
||||
*
|
||||
* store.sort('myField');
|
||||
* store.sort('myField');
|
||||
*
|
||||
* Is equivalent to this code, because Store handles the toggling automatically:
|
||||
*
|
||||
* store.sort('myField', 'ASC');
|
||||
* store.sort('myField', 'DESC');
|
||||
*
|
||||
* @param {String/Ext.util.Sorter[]} sorters Either a string name of one of the fields in this Store's configured
|
||||
* {@link Ext.data.Model Model}, or an array of sorter configurations.
|
||||
* @param {String} [direction="ASC"] The overall direction to sort the data by.
|
||||
* @param {String} [where]
|
||||
* @param {Boolean} [doSort]
|
||||
* @return {Ext.util.Sorter[]}
|
||||
*/
|
||||
sort: function(sorters, direction, where, doSort) {
|
||||
var me = this,
|
||||
sorter, sorterFn,
|
||||
newSorters;
|
||||
|
||||
if (Ext.isArray(sorters)) {
|
||||
doSort = where;
|
||||
where = direction;
|
||||
newSorters = sorters;
|
||||
}
|
||||
else if (Ext.isObject(sorters)) {
|
||||
doSort = where;
|
||||
where = direction;
|
||||
newSorters = [sorters];
|
||||
}
|
||||
else if (Ext.isString(sorters)) {
|
||||
sorter = me.sorters.get(sorters);
|
||||
|
||||
if (!sorter) {
|
||||
sorter = {
|
||||
property : sorters,
|
||||
direction: direction
|
||||
};
|
||||
newSorters = [sorter];
|
||||
}
|
||||
else if (direction === undefined) {
|
||||
sorter.toggle();
|
||||
}
|
||||
else {
|
||||
sorter.setDirection(direction);
|
||||
}
|
||||
}
|
||||
|
||||
if (newSorters && newSorters.length) {
|
||||
newSorters = me.decodeSorters(newSorters);
|
||||
if (Ext.isString(where)) {
|
||||
if (where === 'prepend') {
|
||||
sorters = me.sorters.clone().items;
|
||||
|
||||
me.sorters.clear();
|
||||
me.sorters.addAll(newSorters);
|
||||
me.sorters.addAll(sorters);
|
||||
}
|
||||
else {
|
||||
me.sorters.addAll(newSorters);
|
||||
}
|
||||
}
|
||||
else {
|
||||
me.sorters.clear();
|
||||
me.sorters.addAll(newSorters);
|
||||
}
|
||||
|
||||
if (doSort !== false) {
|
||||
me.onBeforeSort(newSorters);
|
||||
}
|
||||
}
|
||||
|
||||
if (doSort !== false) {
|
||||
sorters = me.sorters.items;
|
||||
if (sorters.length) {
|
||||
//construct an amalgamated sorter function which combines all of the Sorters passed
|
||||
sorterFn = function(r1, r2) {
|
||||
var result = sorters[0].sort(r1, r2),
|
||||
length = sorters.length,
|
||||
i;
|
||||
|
||||
//if we have more than one sorter, OR any additional sorter functions together
|
||||
for (i = 1; i < length; i++) {
|
||||
result = result || sorters[i].sort.call(this, r1, r2);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
me.doSort(sorterFn);
|
||||
}
|
||||
}
|
||||
|
||||
return sorters;
|
||||
},
|
||||
|
||||
onBeforeSort: Ext.emptyFn,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Normalizes an array of sorter objects, ensuring that they are all {@link Ext.util.Sorter} instances.
|
||||
* @param {Array} sorters The sorters array.
|
||||
* @return {Array} Array of {@link Ext.util.Sorter} objects.
|
||||
*/
|
||||
decodeSorters: function(sorters) {
|
||||
if (!Ext.isArray(sorters)) {
|
||||
if (sorters === undefined) {
|
||||
sorters = [];
|
||||
} else {
|
||||
sorters = [sorters];
|
||||
}
|
||||
}
|
||||
|
||||
var length = sorters.length,
|
||||
Sorter = Ext.util.Sorter,
|
||||
fields = this.model ? this.model.prototype.fields : null,
|
||||
field,
|
||||
config, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
config = sorters[i];
|
||||
|
||||
if (!(config instanceof Sorter)) {
|
||||
if (Ext.isString(config)) {
|
||||
config = {
|
||||
property: config
|
||||
};
|
||||
}
|
||||
|
||||
Ext.applyIf(config, {
|
||||
root : this.sortRoot,
|
||||
direction: "ASC"
|
||||
});
|
||||
|
||||
if (config.fn) {
|
||||
config.sorterFn = config.fn;
|
||||
}
|
||||
|
||||
//support a function to be passed as a sorter definition
|
||||
if (typeof config == 'function') {
|
||||
config = {
|
||||
sorterFn: config
|
||||
};
|
||||
}
|
||||
|
||||
// ensure sortType gets pushed on if necessary
|
||||
if (fields && !config.transform) {
|
||||
field = fields.get(config.property);
|
||||
config.transform = field ? field.sortType : undefined;
|
||||
}
|
||||
sorters[i] = Ext.create('Ext.util.Sorter', config);
|
||||
}
|
||||
}
|
||||
|
||||
return sorters;
|
||||
},
|
||||
|
||||
getSorters: function() {
|
||||
return this.sorters.items;
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.callSuper();
|
||||
Ext.destroy(this.sorters);
|
||||
}
|
||||
});
|
||||
194
OfficeWeb/vendor/touch/src/util/Sorter.js
vendored
Normal file
194
OfficeWeb/vendor/touch/src/util/Sorter.js
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Represents a single sorter that can be used as part of the sorters configuration in Ext.mixin.Sortable.
|
||||
*
|
||||
* A common place for Sorters to be used are {@link Ext.data.Store Stores}. For example:
|
||||
*
|
||||
* @example miniphone
|
||||
* var store = Ext.create('Ext.data.Store', {
|
||||
* fields: ['firstName', 'lastName'],
|
||||
* sorters: 'lastName',
|
||||
*
|
||||
* data: [
|
||||
* { firstName: 'Tommy', lastName: 'Maintz' },
|
||||
* { firstName: 'Rob', lastName: 'Dougan' },
|
||||
* { firstName: 'Ed', lastName: 'Spencer'},
|
||||
* { firstName: 'Jamie', lastName: 'Avins' },
|
||||
* { firstName: 'Nick', lastName: 'Poulden'}
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* Ext.create('Ext.List', {
|
||||
* fullscreen: true,
|
||||
* itemTpl: '<div class="contact">{firstName} <strong>{lastName}</strong></div>',
|
||||
* store: store
|
||||
* });
|
||||
*
|
||||
* In the next example, we specify a custom sorter function:
|
||||
*
|
||||
* @example miniphone
|
||||
* var store = Ext.create('Ext.data.Store', {
|
||||
* fields: ['person'],
|
||||
* sorters: [
|
||||
* {
|
||||
* // Sort by first letter of last name, in descending order
|
||||
* sorterFn: function(record1, record2) {
|
||||
* var name1 = record1.data.person.name.split('-')[1].substr(0, 1),
|
||||
* name2 = record2.data.person.name.split('-')[1].substr(0, 1);
|
||||
*
|
||||
* return name1 > name2 ? 1 : (name1 === name2 ? 0 : -1);
|
||||
* },
|
||||
* direction: 'DESC'
|
||||
* }
|
||||
* ],
|
||||
* data: [
|
||||
* { person: { name: 'Tommy-Maintz' } },
|
||||
* { person: { name: 'Rob-Dougan' } },
|
||||
* { person: { name: 'Ed-Spencer' } },
|
||||
* { person: { name: 'Nick-Poulden' } },
|
||||
* { person: { name: 'Jamie-Avins' } }
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* Ext.create('Ext.List', {
|
||||
* fullscreen: true,
|
||||
* itemTpl: '{person.name}',
|
||||
* store: store
|
||||
* });
|
||||
*/
|
||||
Ext.define('Ext.util.Sorter', {
|
||||
isSorter: true,
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {String} property The property to sort by. Required unless `sorterFn` is provided
|
||||
*/
|
||||
property: null,
|
||||
|
||||
/**
|
||||
* @cfg {Function} sorterFn A specific sorter function to execute. Can be passed instead of {@link #property}.
|
||||
* This function should compare the two passed arguments, returning -1, 0 or 1 depending on if item 1 should be
|
||||
* sorted before, at the same level, or after item 2.
|
||||
*
|
||||
* sorterFn: function(person1, person2) {
|
||||
* return (person1.age > person2.age) ? 1 : (person1.age === person2.age ? 0 : -1);
|
||||
* }
|
||||
*/
|
||||
sorterFn: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} root Optional root property. This is mostly useful when sorting a Store, in which case we set the
|
||||
* root to 'data' to make the filter pull the {@link #property} out of the data object of each item
|
||||
*/
|
||||
root: null,
|
||||
|
||||
/**
|
||||
* @cfg {Function} transform A function that will be run on each value before
|
||||
* it is compared in the sorter. The function will receive a single argument,
|
||||
* the value.
|
||||
*/
|
||||
transform: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} direction The direction to sort by. Valid values are "ASC", and "DESC".
|
||||
*/
|
||||
direction: "ASC",
|
||||
|
||||
/**
|
||||
* @cfg {Mixed} id An optional id this sorter can be keyed by in Collections. If
|
||||
* no id is specified it will use the property name used in this Sorter. If no
|
||||
* property is specified, e.g. when adding a custom sorter function we will generate
|
||||
* a random id.
|
||||
*/
|
||||
id: undefined
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
// <debug>
|
||||
applySorterFn: function(sorterFn) {
|
||||
if (!sorterFn && !this.getProperty()) {
|
||||
Ext.Logger.error("A Sorter requires either a property or a sorterFn.");
|
||||
}
|
||||
return sorterFn;
|
||||
},
|
||||
|
||||
applyProperty: function(property) {
|
||||
if (!property && !this.getSorterFn()) {
|
||||
Ext.Logger.error("A Sorter requires either a property or a sorterFn.");
|
||||
}
|
||||
return property;
|
||||
},
|
||||
// </debug>
|
||||
|
||||
applyId: function(id) {
|
||||
if (!id) {
|
||||
id = this.getProperty();
|
||||
if (!id) {
|
||||
id = Ext.id(null, 'ext-sorter-');
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Creates and returns a function which sorts an array by the given property and direction
|
||||
* @return {Function} A function which sorts by the property/direction combination provided
|
||||
*/
|
||||
createSortFunction: function(sorterFn) {
|
||||
var me = this,
|
||||
modifier = me.getDirection().toUpperCase() == "DESC" ? -1 : 1;
|
||||
|
||||
//create a comparison function. Takes 2 objects, returns 1 if object 1 is greater,
|
||||
//-1 if object 2 is greater or 0 if they are equal
|
||||
return function(o1, o2) {
|
||||
return modifier * sorterFn.call(me, o1, o2);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Basic default sorter function that just compares the defined property of each object
|
||||
*/
|
||||
defaultSortFn: function(item1, item2) {
|
||||
var me = this,
|
||||
transform = me._transform,
|
||||
root = me._root,
|
||||
value1, value2,
|
||||
property = me._property;
|
||||
|
||||
if (root !== null) {
|
||||
item1 = item1[root];
|
||||
item2 = item2[root];
|
||||
}
|
||||
|
||||
value1 = item1[property];
|
||||
value2 = item2[property];
|
||||
|
||||
if (transform) {
|
||||
value1 = transform(value1);
|
||||
value2 = transform(value2);
|
||||
}
|
||||
|
||||
return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0);
|
||||
},
|
||||
|
||||
updateDirection: function() {
|
||||
this.updateSortFn();
|
||||
},
|
||||
|
||||
updateSortFn: function() {
|
||||
this.sort = this.createSortFunction(this.getSorterFn() || this.defaultSortFn);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the direction of this Sorter. Note that when you call this function,
|
||||
* the Collection this Sorter is part of does not get refreshed automatically.
|
||||
*/
|
||||
toggle: function() {
|
||||
this.setDirection(Ext.String.toggle(this.getDirection(), "ASC", "DESC"));
|
||||
}
|
||||
});
|
||||
135
OfficeWeb/vendor/touch/src/util/TapRepeater.js
vendored
Normal file
135
OfficeWeb/vendor/touch/src/util/TapRepeater.js
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* A wrapper class which can be applied to any element. Fires a "tap" event while
|
||||
* touching the device. The interval between firings may be specified in the config but
|
||||
* defaults to 20 milliseconds.
|
||||
*/
|
||||
Ext.define('Ext.util.TapRepeater', {
|
||||
requires: ['Ext.DateExtras'],
|
||||
|
||||
mixins: {
|
||||
observable: 'Ext.mixin.Observable'
|
||||
},
|
||||
|
||||
/**
|
||||
* @event touchstart
|
||||
* Fires when the touch is started.
|
||||
* @param {Ext.util.TapRepeater} this
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event tap
|
||||
* Fires on a specified interval during the time the element is pressed.
|
||||
* @param {Ext.util.TapRepeater} this
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event touchend
|
||||
* Fires when the touch is ended.
|
||||
* @param {Ext.util.TapRepeater} this
|
||||
* @param {Ext.event.Event} e
|
||||
*/
|
||||
|
||||
config: {
|
||||
el: null,
|
||||
accelerate: true,
|
||||
interval: 10,
|
||||
delay: 250,
|
||||
preventDefault: true,
|
||||
stopDefault: false,
|
||||
timer: 0,
|
||||
pressCls: null
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates new TapRepeater.
|
||||
* @param {Mixed} el The element to listen on
|
||||
* @param {Object} config
|
||||
*/
|
||||
constructor: function(config) {
|
||||
var me = this;
|
||||
//<debug warn>
|
||||
for (var configName in config) {
|
||||
if (me.self.prototype.config && !(configName in me.self.prototype.config)) {
|
||||
me[configName] = config[configName];
|
||||
Ext.Logger.warn('Applied config as instance property: "' + configName + '"', me);
|
||||
}
|
||||
}
|
||||
//</debug>
|
||||
me.initConfig(config);
|
||||
},
|
||||
|
||||
updateEl: function(newEl, oldEl) {
|
||||
var eventCfg = {
|
||||
touchstart: 'onTouchStart',
|
||||
touchend: 'onTouchEnd',
|
||||
tap: 'eventOptions',
|
||||
scope: this
|
||||
};
|
||||
if (oldEl) {
|
||||
oldEl.un(eventCfg)
|
||||
}
|
||||
newEl.on(eventCfg);
|
||||
},
|
||||
|
||||
// @private
|
||||
eventOptions: function(e) {
|
||||
if (this.getPreventDefault()) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (this.getStopDefault()) {
|
||||
e.stopEvent();
|
||||
}
|
||||
},
|
||||
|
||||
// @private
|
||||
destroy: function() {
|
||||
this.clearListeners();
|
||||
Ext.destroy(this.el);
|
||||
},
|
||||
|
||||
// @private
|
||||
onTouchStart: function(e) {
|
||||
var me = this,
|
||||
pressCls = me.getPressCls();
|
||||
clearTimeout(me.getTimer());
|
||||
if (pressCls) {
|
||||
me.getEl().addCls(pressCls);
|
||||
}
|
||||
me.tapStartTime = new Date();
|
||||
|
||||
me.fireEvent('touchstart', me, e);
|
||||
me.fireEvent('tap', me, e);
|
||||
|
||||
// Do not honor delay or interval if acceleration wanted.
|
||||
if (me.getAccelerate()) {
|
||||
me.delay = 400;
|
||||
}
|
||||
me.setTimer(Ext.defer(me.tap, me.getDelay() || me.getInterval(), me, [e]));
|
||||
},
|
||||
|
||||
// @private
|
||||
tap: function(e) {
|
||||
var me = this;
|
||||
me.fireEvent('tap', me, e);
|
||||
me.setTimer(Ext.defer(me.tap, me.getAccelerate() ? me.easeOutExpo(Ext.Date.getElapsed(me.tapStartTime),
|
||||
400,
|
||||
-390,
|
||||
12000) : me.getInterval(), me, [e]));
|
||||
},
|
||||
|
||||
// Easing calculation
|
||||
// @private
|
||||
easeOutExpo: function(t, b, c, d) {
|
||||
return (t == d) ? b + c : c * ( - Math.pow(2, -10 * t / d) + 1) + b;
|
||||
},
|
||||
|
||||
// @private
|
||||
onTouchEnd: function(e) {
|
||||
var me = this;
|
||||
clearTimeout(me.getTimer());
|
||||
me.getEl().removeCls(me.getPressCls());
|
||||
me.fireEvent('touchend', me, e);
|
||||
}
|
||||
});
|
||||
39
OfficeWeb/vendor/touch/src/util/Translatable.js
vendored
Normal file
39
OfficeWeb/vendor/touch/src/util/Translatable.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The utility class to abstract different implementations to have the best performance when applying 2D translation
|
||||
* on any DOM element.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.Translatable', {
|
||||
requires: [
|
||||
'Ext.util.translatable.CssTransform',
|
||||
'Ext.util.translatable.ScrollPosition'
|
||||
],
|
||||
|
||||
constructor: function(config) {
|
||||
var namespace = Ext.util.translatable,
|
||||
CssTransform = namespace.CssTransform,
|
||||
ScrollPosition = namespace.ScrollPosition,
|
||||
classReference;
|
||||
|
||||
if (typeof config == 'object' && 'translationMethod' in config) {
|
||||
if (config.translationMethod === 'scrollposition') {
|
||||
classReference = ScrollPosition;
|
||||
}
|
||||
else if (config.translationMethod === 'csstransform') {
|
||||
classReference = CssTransform;
|
||||
}
|
||||
}
|
||||
|
||||
if (!classReference) {
|
||||
if (Ext.os.is.Android2 || Ext.browser.is.ChromeMobile) {
|
||||
classReference = ScrollPosition;
|
||||
}
|
||||
else {
|
||||
classReference = CssTransform;
|
||||
}
|
||||
}
|
||||
|
||||
return new classReference(config);
|
||||
}
|
||||
});
|
||||
50
OfficeWeb/vendor/touch/src/util/TranslatableGroup.js
vendored
Normal file
50
OfficeWeb/vendor/touch/src/util/TranslatableGroup.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.TranslatableGroup', {
|
||||
extend: 'Ext.util.translatable.Abstract',
|
||||
|
||||
config: {
|
||||
items: [],
|
||||
|
||||
activeIndex: 0,
|
||||
|
||||
itemLength: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
|
||||
applyItems: function(items) {
|
||||
return Ext.Array.from(items);
|
||||
},
|
||||
|
||||
doTranslate: function(x, y) {
|
||||
var items = this.getItems(),
|
||||
activeIndex = this.getActiveIndex(),
|
||||
itemLength = this.getItemLength(),
|
||||
itemLengthX = itemLength.x,
|
||||
itemLengthY = itemLength.y,
|
||||
useX = typeof x == 'number',
|
||||
useY = typeof y == 'number',
|
||||
offset, i, ln, item, translateX, translateY;
|
||||
|
||||
for (i = 0, ln = items.length; i < ln; i++) {
|
||||
item = items[i];
|
||||
|
||||
if (item) {
|
||||
offset = (i - activeIndex);
|
||||
|
||||
if (useX) {
|
||||
translateX = x + offset * itemLengthX;
|
||||
}
|
||||
|
||||
if (useY) {
|
||||
translateY = y + offset * itemLengthY;
|
||||
}
|
||||
|
||||
item.translate(translateX, translateY);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
30
OfficeWeb/vendor/touch/src/util/TranslatableList.js
vendored
Normal file
30
OfficeWeb/vendor/touch/src/util/TranslatableList.js
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.TranslatableList', {
|
||||
extend: 'Ext.util.translatable.Abstract',
|
||||
|
||||
config: {
|
||||
items: []
|
||||
},
|
||||
|
||||
applyItems: function(items) {
|
||||
return Ext.Array.from(items);
|
||||
},
|
||||
|
||||
doTranslate: function(x, y) {
|
||||
var items = this.getItems(),
|
||||
offset = 0,
|
||||
i, ln, item, translateY;
|
||||
|
||||
for (i = 0, ln = items.length; i < ln; i++) {
|
||||
item = items[i];
|
||||
|
||||
if (item && !item._list_hidden) {
|
||||
translateY = y + offset;
|
||||
offset += item.$height;
|
||||
item.translate(0, translateY);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
81
OfficeWeb/vendor/touch/src/util/Wrapper.js
vendored
Normal file
81
OfficeWeb/vendor/touch/src/util/Wrapper.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.util.Wrapper', {
|
||||
mixins: ['Ext.mixin.Bindable'],
|
||||
|
||||
constructor: function(elementConfig, wrappedElement) {
|
||||
var element = this.link('element', Ext.Element.create(elementConfig));
|
||||
|
||||
if (wrappedElement) {
|
||||
element.insertBefore(wrappedElement);
|
||||
this.wrap(wrappedElement);
|
||||
}
|
||||
},
|
||||
|
||||
bindSize: function(sizeName) {
|
||||
var wrappedElement = this.wrappedElement,
|
||||
boundMethodName;
|
||||
|
||||
this.boundSizeName = sizeName;
|
||||
this.boundMethodName = boundMethodName = sizeName === 'width' ? 'setWidth' : 'setHeight';
|
||||
|
||||
this.bind(wrappedElement, boundMethodName, 'onBoundSizeChange');
|
||||
wrappedElement[boundMethodName].call(wrappedElement, wrappedElement.getStyleValue(sizeName));
|
||||
},
|
||||
|
||||
onBoundSizeChange: function(size, args) {
|
||||
var element = this.element;
|
||||
|
||||
if (typeof size === 'string' && size.substr(-1) === '%') {
|
||||
args[0] = '100%';
|
||||
}
|
||||
else {
|
||||
size = '';
|
||||
}
|
||||
|
||||
element[this.boundMethodName].call(element, size);
|
||||
},
|
||||
|
||||
wrap: function(wrappedElement) {
|
||||
var element = this.element,
|
||||
innerDom;
|
||||
|
||||
this.wrappedElement = wrappedElement;
|
||||
|
||||
innerDom = element.dom;
|
||||
|
||||
while (innerDom.firstElementChild !== null) {
|
||||
innerDom = innerDom.firstElementChild;
|
||||
}
|
||||
|
||||
innerDom.appendChild(wrappedElement.dom);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var element = this.element,
|
||||
dom = element.dom,
|
||||
wrappedElement = this.wrappedElement,
|
||||
boundMethodName = this.boundMethodName,
|
||||
parentNode = dom.parentNode,
|
||||
size;
|
||||
|
||||
if (boundMethodName) {
|
||||
this.unbind(wrappedElement, boundMethodName, 'onBoundSizeChange');
|
||||
size = element.getStyle(this.boundSizeName);
|
||||
|
||||
if (size) {
|
||||
wrappedElement[boundMethodName].call(wrappedElement, size);
|
||||
}
|
||||
}
|
||||
|
||||
if (parentNode) {
|
||||
if (!wrappedElement.isDestroyed) {
|
||||
parentNode.replaceChild(dom.firstElementChild, dom);
|
||||
}
|
||||
delete this.wrappedElement;
|
||||
}
|
||||
|
||||
this.callSuper();
|
||||
}
|
||||
});
|
||||
66
OfficeWeb/vendor/touch/src/util/paintmonitor/Abstract.js
vendored
Normal file
66
OfficeWeb/vendor/touch/src/util/paintmonitor/Abstract.js
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.paintmonitor.Abstract', {
|
||||
|
||||
config: {
|
||||
element: null,
|
||||
|
||||
callback: Ext.emptyFn,
|
||||
|
||||
scope: null,
|
||||
|
||||
args: []
|
||||
},
|
||||
|
||||
eventName: '',
|
||||
|
||||
monitorClass: '',
|
||||
|
||||
constructor: function(config) {
|
||||
this.onElementPainted = Ext.Function.bind(this.onElementPainted, this);
|
||||
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
bindListeners: function(bind) {
|
||||
this.monitorElement[bind ? 'addEventListener' : 'removeEventListener'](this.eventName, this.onElementPainted, true);
|
||||
},
|
||||
|
||||
applyElement: function(element) {
|
||||
if (element) {
|
||||
return Ext.get(element);
|
||||
}
|
||||
},
|
||||
|
||||
updateElement: function(element) {
|
||||
this.monitorElement = Ext.Element.create({
|
||||
classList: ['x-paint-monitor', this.monitorClass]
|
||||
}, true);
|
||||
element.appendChild(this.monitorElement);
|
||||
element.addCls('x-paint-monitored');
|
||||
this.bindListeners(true);
|
||||
},
|
||||
|
||||
onElementPainted: function() {},
|
||||
|
||||
destroy: function() {
|
||||
var monitorElement = this.monitorElement,
|
||||
parentNode = monitorElement.parentNode,
|
||||
element = this.getElement();
|
||||
|
||||
this.bindListeners(false);
|
||||
delete this.monitorElement;
|
||||
|
||||
if (element && !element.isDestroyed) {
|
||||
element.removeCls('x-paint-monitored');
|
||||
delete this._element;
|
||||
}
|
||||
|
||||
if (parentNode) {
|
||||
parentNode.removeChild(monitorElement);
|
||||
}
|
||||
|
||||
this.callSuper();
|
||||
}
|
||||
});
|
||||
17
OfficeWeb/vendor/touch/src/util/paintmonitor/CssAnimation.js
vendored
Normal file
17
OfficeWeb/vendor/touch/src/util/paintmonitor/CssAnimation.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.paintmonitor.CssAnimation', {
|
||||
|
||||
extend: 'Ext.util.paintmonitor.Abstract',
|
||||
|
||||
eventName: 'webkitAnimationEnd',
|
||||
|
||||
monitorClass: 'cssanimation',
|
||||
|
||||
onElementPainted: function(e) {
|
||||
if (e.animationName === 'x-paint-monitor-helper') {
|
||||
this.getCallback().apply(this.getScope(), this.getArgs());
|
||||
}
|
||||
}
|
||||
});
|
||||
15
OfficeWeb/vendor/touch/src/util/paintmonitor/OverflowChange.js
vendored
Normal file
15
OfficeWeb/vendor/touch/src/util/paintmonitor/OverflowChange.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.paintmonitor.OverflowChange', {
|
||||
|
||||
extend: 'Ext.util.paintmonitor.Abstract',
|
||||
|
||||
eventName: 'overflowchanged',
|
||||
|
||||
monitorClass: 'overflowchange',
|
||||
|
||||
onElementPainted: function(e) {
|
||||
this.getCallback().apply(this.getScope(), this.getArgs());
|
||||
}
|
||||
});
|
||||
129
OfficeWeb/vendor/touch/src/util/sizemonitor/Abstract.js
vendored
Normal file
129
OfficeWeb/vendor/touch/src/util/sizemonitor/Abstract.js
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.sizemonitor.Abstract', {
|
||||
|
||||
mixins: ['Ext.mixin.Templatable'],
|
||||
|
||||
requires: [
|
||||
'Ext.TaskQueue'
|
||||
],
|
||||
|
||||
config: {
|
||||
element: null,
|
||||
|
||||
callback: Ext.emptyFn,
|
||||
|
||||
scope: null,
|
||||
|
||||
args: []
|
||||
},
|
||||
|
||||
width: 0,
|
||||
|
||||
height: 0,
|
||||
|
||||
contentWidth: 0,
|
||||
|
||||
contentHeight: 0,
|
||||
|
||||
constructor: function(config) {
|
||||
this.refresh = Ext.Function.bind(this.refresh, this);
|
||||
|
||||
this.info = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
contentWidth: 0,
|
||||
contentHeight: 0,
|
||||
flag: 0
|
||||
};
|
||||
|
||||
this.initElement();
|
||||
|
||||
this.initConfig(config);
|
||||
|
||||
this.bindListeners(true);
|
||||
},
|
||||
|
||||
bindListeners: Ext.emptyFn,
|
||||
|
||||
applyElement: function(element) {
|
||||
if (element) {
|
||||
return Ext.get(element);
|
||||
}
|
||||
},
|
||||
|
||||
updateElement: function(element) {
|
||||
element.append(this.detectorsContainer);
|
||||
element.addCls('x-size-monitored');
|
||||
},
|
||||
|
||||
applyArgs: function(args) {
|
||||
return args.concat([this.info]);
|
||||
},
|
||||
|
||||
refreshMonitors: Ext.emptyFn,
|
||||
|
||||
forceRefresh: function() {
|
||||
Ext.TaskQueue.requestRead('refresh', this);
|
||||
},
|
||||
|
||||
refreshSize: function() {
|
||||
var element = this.getElement();
|
||||
|
||||
if (!element || element.isDestroyed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var width = element.getWidth(),
|
||||
height = element.getHeight(),
|
||||
contentElement = this.detectorsContainer,
|
||||
contentWidth = contentElement.offsetWidth,
|
||||
contentHeight = contentElement.offsetHeight,
|
||||
currentContentWidth = this.contentWidth,
|
||||
currentContentHeight = this.contentHeight,
|
||||
info = this.info,
|
||||
resized = false,
|
||||
flag;
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.contentWidth = contentWidth;
|
||||
this.contentHeight = contentHeight;
|
||||
|
||||
flag = ((currentContentWidth !== contentWidth ? 1 : 0) + (currentContentHeight !== contentHeight ? 2 : 0));
|
||||
|
||||
if (flag > 0) {
|
||||
info.width = width;
|
||||
info.height = height;
|
||||
info.contentWidth = contentWidth;
|
||||
info.contentHeight = contentHeight;
|
||||
info.flag = flag;
|
||||
|
||||
resized = true;
|
||||
this.getCallback().apply(this.getScope(), this.getArgs());
|
||||
}
|
||||
|
||||
return resized;
|
||||
},
|
||||
|
||||
refresh: function(force) {
|
||||
if (this.refreshSize() || force) {
|
||||
Ext.TaskQueue.requestWrite('refreshMonitors', this);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var element = this.getElement();
|
||||
|
||||
this.bindListeners(false);
|
||||
|
||||
if (element && !element.isDestroyed) {
|
||||
element.removeCls('x-size-monitored');
|
||||
}
|
||||
|
||||
delete this._element;
|
||||
|
||||
this.callSuper();
|
||||
}
|
||||
});
|
||||
78
OfficeWeb/vendor/touch/src/util/sizemonitor/OverflowChange.js
vendored
Normal file
78
OfficeWeb/vendor/touch/src/util/sizemonitor/OverflowChange.js
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.sizemonitor.OverflowChange', {
|
||||
|
||||
extend: 'Ext.util.sizemonitor.Abstract',
|
||||
|
||||
constructor: function(config) {
|
||||
this.onExpand = Ext.Function.bind(this.onExpand, this);
|
||||
this.onShrink = Ext.Function.bind(this.onShrink, this);
|
||||
|
||||
this.callSuper(arguments);
|
||||
},
|
||||
|
||||
getElementConfig: function() {
|
||||
return {
|
||||
reference: 'detectorsContainer',
|
||||
classList: ['x-size-monitors', 'overflowchanged'],
|
||||
children: [
|
||||
{
|
||||
reference: 'expandMonitor',
|
||||
className: 'expand',
|
||||
children: [{
|
||||
reference: 'expandHelper'
|
||||
}]
|
||||
},
|
||||
{
|
||||
reference: 'shrinkMonitor',
|
||||
className: 'shrink',
|
||||
children: [{
|
||||
reference: 'shrinkHelper'
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
bindListeners: function(bind) {
|
||||
var method = bind ? 'addEventListener' : 'removeEventListener';
|
||||
|
||||
this.expandMonitor[method]('overflowchanged', this.onExpand, true);
|
||||
this.shrinkMonitor[method]('overflowchanged', this.onShrink, true);
|
||||
},
|
||||
|
||||
onExpand: function(e) {
|
||||
if (e.horizontalOverflow && e.verticalOverflow) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ext.TaskQueue.requestRead('refresh', this);
|
||||
},
|
||||
|
||||
onShrink: function(e) {
|
||||
if (!e.horizontalOverflow && !e.verticalOverflow) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ext.TaskQueue.requestRead('refresh', this);
|
||||
},
|
||||
|
||||
refreshMonitors: function() {
|
||||
var expandHelper = this.expandHelper,
|
||||
shrinkHelper = this.shrinkHelper,
|
||||
width = this.contentWidth,
|
||||
height = this.contentHeight;
|
||||
|
||||
if (expandHelper && !expandHelper.isDestroyed) {
|
||||
expandHelper.style.width = (width + 1) + 'px';
|
||||
expandHelper.style.height = (height + 1) + 'px';
|
||||
}
|
||||
if (shrinkHelper && !shrinkHelper.isDestroyed) {
|
||||
shrinkHelper.style.width = width + 'px';
|
||||
shrinkHelper.style.height = height + 'px';
|
||||
}
|
||||
|
||||
Ext.TaskQueue.requestRead('refresh', this);
|
||||
}
|
||||
});
|
||||
61
OfficeWeb/vendor/touch/src/util/sizemonitor/Scroll.js
vendored
Normal file
61
OfficeWeb/vendor/touch/src/util/sizemonitor/Scroll.js
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.sizemonitor.Scroll', {
|
||||
|
||||
extend: 'Ext.util.sizemonitor.Abstract',
|
||||
|
||||
getElementConfig: function() {
|
||||
return {
|
||||
reference: 'detectorsContainer',
|
||||
classList: ['x-size-monitors', 'scroll'],
|
||||
children: [
|
||||
{
|
||||
reference: 'expandMonitor',
|
||||
className: 'expand'
|
||||
},
|
||||
{
|
||||
reference: 'shrinkMonitor',
|
||||
className: 'shrink'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.onScroll = Ext.Function.bind(this.onScroll, this);
|
||||
|
||||
this.callSuper(arguments);
|
||||
},
|
||||
|
||||
bindListeners: function(bind) {
|
||||
var method = bind ? 'addEventListener' : 'removeEventListener';
|
||||
|
||||
this.expandMonitor[method]('scroll', this.onScroll, true);
|
||||
this.shrinkMonitor[method]('scroll', this.onScroll, true);
|
||||
},
|
||||
|
||||
forceRefresh: function() {
|
||||
Ext.TaskQueue.requestRead('refresh', this, [true]);
|
||||
},
|
||||
|
||||
onScroll: function() {
|
||||
Ext.TaskQueue.requestRead('refresh', this);
|
||||
},
|
||||
|
||||
refreshMonitors: function() {
|
||||
var expandMonitor = this.expandMonitor,
|
||||
shrinkMonitor = this.shrinkMonitor,
|
||||
end = 1000000;
|
||||
|
||||
if (expandMonitor && !expandMonitor.isDestroyed) {
|
||||
expandMonitor.scrollLeft = end;
|
||||
expandMonitor.scrollTop = end;
|
||||
}
|
||||
|
||||
if (shrinkMonitor && !shrinkMonitor.isDestroyed) {
|
||||
shrinkMonitor.scrollLeft = end;
|
||||
shrinkMonitor.scrollTop = end;
|
||||
}
|
||||
}
|
||||
});
|
||||
257
OfficeWeb/vendor/touch/src/util/translatable/Abstract.js
vendored
Normal file
257
OfficeWeb/vendor/touch/src/util/translatable/Abstract.js
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* The abstract class. Sub-classes are expected, at the very least, to implement translation logics inside
|
||||
* the 'translate' method
|
||||
*/
|
||||
Ext.define('Ext.util.translatable.Abstract', {
|
||||
extend: 'Ext.Evented',
|
||||
|
||||
requires: ['Ext.fx.easing.Linear'],
|
||||
|
||||
config: {
|
||||
easing: null,
|
||||
|
||||
easingX: null,
|
||||
|
||||
easingY: null,
|
||||
|
||||
fps: Ext.os.is.Android4 ? 50 : 60
|
||||
},
|
||||
|
||||
/**
|
||||
* @event animationstart
|
||||
* Fires whenever the animation is started
|
||||
* @param {Ext.util.translatable.Abstract} this
|
||||
* @param {Number} x The current translation on the x axis
|
||||
* @param {Number} y The current translation on the y axis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event animationframe
|
||||
* Fires for each animation frame
|
||||
* @param {Ext.util.translatable.Abstract} this
|
||||
* @param {Number} x The new translation on the x axis
|
||||
* @param {Number} y The new translation on the y axis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event animationend
|
||||
* Fires whenever the animation is ended
|
||||
* @param {Ext.util.translatable.Abstract} this
|
||||
* @param {Number} x The current translation on the x axis
|
||||
* @param {Number} y The current translation on the y axis
|
||||
*/
|
||||
|
||||
x: 0,
|
||||
|
||||
y: 0,
|
||||
|
||||
activeEasingX: null,
|
||||
|
||||
activeEasingY: null,
|
||||
|
||||
isAnimating: false,
|
||||
|
||||
isTranslatable: true,
|
||||
|
||||
constructor: function(config) {
|
||||
this.doAnimationFrame = Ext.Function.bind(this.doAnimationFrame, this);
|
||||
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
factoryEasing: function(easing) {
|
||||
return Ext.factory(easing, Ext.fx.easing.Linear, null, 'easing');
|
||||
},
|
||||
|
||||
applyEasing: function(easing) {
|
||||
if (!this.getEasingX()) {
|
||||
this.setEasingX(this.factoryEasing(easing));
|
||||
}
|
||||
|
||||
if (!this.getEasingY()) {
|
||||
this.setEasingY(this.factoryEasing(easing));
|
||||
}
|
||||
},
|
||||
|
||||
applyEasingX: function(easing) {
|
||||
return this.factoryEasing(easing);
|
||||
},
|
||||
|
||||
applyEasingY: function(easing) {
|
||||
return this.factoryEasing(easing);
|
||||
},
|
||||
|
||||
updateFps: function(fps) {
|
||||
this.animationInterval = 1000 / fps;
|
||||
},
|
||||
|
||||
doTranslate: Ext.emptyFn,
|
||||
|
||||
translate: function(x, y, animation) {
|
||||
if (animation) {
|
||||
return this.translateAnimated(x, y, animation);
|
||||
}
|
||||
|
||||
if (this.isAnimating) {
|
||||
this.stopAnimation();
|
||||
}
|
||||
|
||||
if (!isNaN(x) && typeof x == 'number') {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
if (!isNaN(y) && typeof y == 'number') {
|
||||
this.y = y;
|
||||
}
|
||||
this.doTranslate(x, y);
|
||||
},
|
||||
|
||||
translateAxis: function(axis, value, animation) {
|
||||
var x, y;
|
||||
|
||||
if (axis == 'x') {
|
||||
x = value;
|
||||
}
|
||||
else {
|
||||
y = value;
|
||||
}
|
||||
|
||||
return this.translate(x, y, animation);
|
||||
},
|
||||
|
||||
animate: function(easingX, easingY) {
|
||||
this.activeEasingX = easingX;
|
||||
this.activeEasingY = easingY;
|
||||
|
||||
this.isAnimating = true;
|
||||
this.lastX = null;
|
||||
this.lastY = null;
|
||||
|
||||
this.animationFrameId = requestAnimationFrame(this.doAnimationFrame);
|
||||
|
||||
this.fireEvent('animationstart', this, this.x, this.y);
|
||||
return this;
|
||||
},
|
||||
|
||||
translateAnimated: function(x, y, animation) {
|
||||
if (!Ext.isObject(animation)) {
|
||||
animation = {};
|
||||
}
|
||||
|
||||
if (this.isAnimating) {
|
||||
this.stopAnimation();
|
||||
}
|
||||
|
||||
var now = Ext.Date.now(),
|
||||
easing = animation.easing,
|
||||
easingX = (typeof x == 'number') ? (animation.easingX || easing || this.getEasingX() || true) : null,
|
||||
easingY = (typeof y == 'number') ? (animation.easingY || easing || this.getEasingY() || true) : null;
|
||||
|
||||
if (easingX) {
|
||||
easingX = this.factoryEasing(easingX);
|
||||
easingX.setStartTime(now);
|
||||
easingX.setStartValue(this.x);
|
||||
easingX.setEndValue(x);
|
||||
|
||||
if ('duration' in animation) {
|
||||
easingX.setDuration(animation.duration);
|
||||
}
|
||||
}
|
||||
|
||||
if (easingY) {
|
||||
easingY = this.factoryEasing(easingY);
|
||||
easingY.setStartTime(now);
|
||||
easingY.setStartValue(this.y);
|
||||
easingY.setEndValue(y);
|
||||
|
||||
if ('duration' in animation) {
|
||||
easingY.setDuration(animation.duration);
|
||||
}
|
||||
}
|
||||
|
||||
return this.animate(easingX, easingY);
|
||||
},
|
||||
|
||||
doAnimationFrame: function() {
|
||||
var me = this,
|
||||
easingX = me.activeEasingX,
|
||||
easingY = me.activeEasingY,
|
||||
now = Date.now(),
|
||||
x, y;
|
||||
|
||||
this.animationFrameId = requestAnimationFrame(this.doAnimationFrame);
|
||||
|
||||
if (!me.isAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
me.lastRun = now;
|
||||
|
||||
if (easingX === null && easingY === null) {
|
||||
me.stopAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (easingX !== null) {
|
||||
me.x = x = Math.round(easingX.getValue());
|
||||
|
||||
if (easingX.isEnded) {
|
||||
me.activeEasingX = null;
|
||||
me.fireEvent('axisanimationend', me, 'x', x);
|
||||
}
|
||||
}
|
||||
else {
|
||||
x = me.x;
|
||||
}
|
||||
|
||||
if (easingY !== null) {
|
||||
me.y = y = Math.round(easingY.getValue());
|
||||
|
||||
if (easingY.isEnded) {
|
||||
me.activeEasingY = null;
|
||||
me.fireEvent('axisanimationend', me, 'y', y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
y = me.y;
|
||||
}
|
||||
|
||||
if (me.lastX !== x || me.lastY !== y) {
|
||||
me.doTranslate(x, y);
|
||||
|
||||
me.lastX = x;
|
||||
me.lastY = y;
|
||||
}
|
||||
|
||||
me.fireEvent('animationframe', me, x, y);
|
||||
},
|
||||
|
||||
|
||||
stopAnimation: function() {
|
||||
if (!this.isAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeEasingX = null;
|
||||
this.activeEasingY = null;
|
||||
|
||||
this.isAnimating = false;
|
||||
|
||||
cancelAnimationFrame(this.animationFrameId);
|
||||
this.fireEvent('animationend', this, this.x, this.y);
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
this.translate(this.x, this.y);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this.isAnimating) {
|
||||
this.stopAnimation();
|
||||
}
|
||||
|
||||
this.callParent(arguments);
|
||||
}
|
||||
});
|
||||
29
OfficeWeb/vendor/touch/src/util/translatable/CssPosition.js
vendored
Normal file
29
OfficeWeb/vendor/touch/src/util/translatable/CssPosition.js
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @class Ext.util.translatable.CssPosition
|
||||
* @private
|
||||
*/
|
||||
|
||||
Ext.define('Ext.util.translatable.CssPosition', {
|
||||
extend: 'Ext.util.translatable.Dom',
|
||||
|
||||
doTranslate: function(x, y) {
|
||||
var domStyle = this.getElement().dom.style;
|
||||
|
||||
if (typeof x == 'number') {
|
||||
domStyle.left = x + 'px';
|
||||
}
|
||||
|
||||
if (typeof y == 'number') {
|
||||
domStyle.top = y + 'px';
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var domStyle = this.getElement().dom.style;
|
||||
|
||||
domStyle.left = null;
|
||||
domStyle.top = null;
|
||||
|
||||
this.callParent(arguments);
|
||||
}
|
||||
});
|
||||
22
OfficeWeb/vendor/touch/src/util/translatable/CssTransform.js
vendored
Normal file
22
OfficeWeb/vendor/touch/src/util/translatable/CssTransform.js
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* CSS Transform implementation
|
||||
*/
|
||||
Ext.define('Ext.util.translatable.CssTransform', {
|
||||
extend: 'Ext.util.translatable.Dom',
|
||||
|
||||
doTranslate: function() {
|
||||
this.getElement().dom.style.webkitTransform = 'translate3d(' + this.x + 'px, ' + this.y + 'px, 0px)';
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var element = this.getElement();
|
||||
|
||||
if (element && !element.isDestroyed) {
|
||||
element.dom.style.webkitTransform = null;
|
||||
}
|
||||
|
||||
this.callSuper();
|
||||
}
|
||||
});
|
||||
22
OfficeWeb/vendor/touch/src/util/translatable/Dom.js
vendored
Normal file
22
OfficeWeb/vendor/touch/src/util/translatable/Dom.js
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Ext.define('Ext.util.translatable.Dom', {
|
||||
extend: 'Ext.util.translatable.Abstract',
|
||||
|
||||
config: {
|
||||
element: null
|
||||
},
|
||||
|
||||
applyElement: function(element) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Ext.get(element);
|
||||
},
|
||||
|
||||
updateElement: function() {
|
||||
this.refresh();
|
||||
}
|
||||
});
|
||||
97
OfficeWeb/vendor/touch/src/util/translatable/ScrollPosition.js
vendored
Normal file
97
OfficeWeb/vendor/touch/src/util/translatable/ScrollPosition.js
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Scroll position implementation
|
||||
*/
|
||||
Ext.define('Ext.util.translatable.ScrollPosition', {
|
||||
extend: 'Ext.util.translatable.Dom',
|
||||
|
||||
wrapperWidth: 0,
|
||||
|
||||
wrapperHeight: 0,
|
||||
|
||||
config: {
|
||||
useWrapper: true
|
||||
},
|
||||
|
||||
getWrapper: function() {
|
||||
var wrapper = this.wrapper,
|
||||
element = this.getElement(),
|
||||
container;
|
||||
|
||||
if (!wrapper) {
|
||||
container = element.getParent();
|
||||
|
||||
if (!container) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.getUseWrapper()) {
|
||||
wrapper = element.wrap();
|
||||
}
|
||||
else {
|
||||
wrapper = container;
|
||||
}
|
||||
|
||||
element.addCls('x-translatable');
|
||||
wrapper.addCls('x-translatable-container');
|
||||
|
||||
this.wrapper = wrapper;
|
||||
|
||||
wrapper.on('resize', 'onWrapperResize', this);
|
||||
wrapper.on('painted', 'refresh', this);
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
},
|
||||
|
||||
doTranslate: function(x, y) {
|
||||
var wrapper = this.getWrapper(),
|
||||
dom;
|
||||
|
||||
if (wrapper) {
|
||||
dom = wrapper.dom;
|
||||
|
||||
if (typeof x == 'number') {
|
||||
dom.scrollLeft = this.wrapperWidth - x;
|
||||
}
|
||||
|
||||
if (typeof y == 'number') {
|
||||
dom.scrollTop = this.wrapperHeight - y;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onWrapperResize: function(wrapper, info) {
|
||||
this.wrapperWidth = info.width;
|
||||
this.wrapperHeight = info.height;
|
||||
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var element = this.getElement(),
|
||||
wrapper = this.wrapper;
|
||||
|
||||
if (wrapper) {
|
||||
if (!element.isDestroyed) {
|
||||
if (this.getUseWrapper()) {
|
||||
wrapper.doReplaceWith(element);
|
||||
}
|
||||
element.removeCls('x-translatable');
|
||||
}
|
||||
|
||||
wrapper.removeCls('x-translatable-container');
|
||||
wrapper.un('resize', 'onWrapperResize', this);
|
||||
wrapper.un('painted', 'refresh', this);
|
||||
|
||||
delete this.wrapper;
|
||||
delete this._element;
|
||||
}
|
||||
|
||||
this.callSuper();
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user