web-apps/vendor/touch/src/Sortable.js
Maxim Kadushkin 741b10515d webapps added
2016-03-10 21:48:53 -03:00

328 lines
8.9 KiB
JavaScript

/**
* A mixin which allows a data component to be sorted
* @ignore
*/
Ext.define('Ext.Sortable', {
mixins: {
observable: 'Ext.mixin.Observable'
},
requires: ['Ext.util.Draggable'],
config: {
/**
* @cfg
* @inheritdoc
*/
baseCls: Ext.baseCSSPrefix + 'sortable',
/**
* @cfg {Number} delay
* How many milliseconds a user must hold the draggable before starting a
* drag operation.
* @private
* @accessor
*/
delay: 0
},
/**
* @cfg {String} direction
* Possible values: 'vertical', 'horizontal'.
*/
direction: 'vertical',
/**
* @cfg {String} cancelSelector
* A simple CSS selector that represents elements within the draggable
* that should NOT initiate a drag.
*/
cancelSelector: null,
// not yet implemented
//indicator: true,
//proxy: true,
//tolerance: null,
/**
* @cfg {HTMLElement/Boolean} constrain
* An Element to constrain the Sortable dragging to.
* If `true` is specified, the dragging will be constrained to the element
* of the sortable.
*/
constrain: window,
/**
* @cfg {String} group
* Draggable and Droppable objects can participate in a group which are
* capable of interacting.
*/
group: 'base',
/**
* @cfg {Boolean} revert
* This should NOT be changed.
* @private
*/
revert: true,
/**
* @cfg {String} itemSelector
* A simple CSS selector that represents individual items within the Sortable.
*/
itemSelector: null,
/**
* @cfg {String} handleSelector
* A simple CSS selector to indicate what is the handle to drag the Sortable.
*/
handleSelector: null,
/**
* @cfg {Boolean} disabled
* Passing in `true` will disable this Sortable.
*/
disabled: false,
// Properties
/**
* Read-only property that indicates whether a Sortable is currently sorting.
* @type Boolean
* @private
* @readonly
*/
sorting: false,
/**
* Read-only value representing whether the Draggable can be moved vertically.
* This is automatically calculated by Draggable by the direction configuration.
* @type Boolean
* @private
* @readonly
*/
vertical: false,
/**
* Creates new Sortable.
* @param {Mixed} el
* @param {Object} config
*/
constructor : function(el, config) {
config = config || {};
Ext.apply(this, config);
this.addEvents(
/**
* @event sortstart
* @param {Ext.Sortable} this
* @param {Ext.event.Event} e
*/
'sortstart',
/**
* @event sortend
* @param {Ext.Sortable} this
* @param {Ext.event.Event} e
*/
'sortend',
/**
* @event sortchange
* @param {Ext.Sortable} this
* @param {Ext.Element} el The Element being dragged.
* @param {Number} index The index of the element after the sort change.
*/
'sortchange'
// not yet implemented.
// 'sortupdate',
// 'sortreceive',
// 'sortremove',
// 'sortenter',
// 'sortleave',
// 'sortactivate',
// 'sortdeactivate'
);
this.el = Ext.get(el);
this.callParent();
this.mixins.observable.constructor.call(this);
if (this.direction == 'horizontal') {
this.horizontal = true;
}
else if (this.direction == 'vertical') {
this.vertical = true;
}
else {
this.horizontal = this.vertical = true;
}
this.el.addCls(this.baseCls);
this.startEventName = (this.getDelay() > 0) ? 'taphold' : 'tapstart';
if (!this.disabled) {
this.enable();
}
},
// @private
onStart : function(e, t) {
if (this.cancelSelector && e.getTarget(this.cancelSelector)) {
return;
}
if (this.handleSelector && !e.getTarget(this.handleSelector)) {
return;
}
if (!this.sorting) {
this.onSortStart(e, t);
}
},
// @private
onSortStart : function(e, t) {
this.sorting = true;
var draggable = Ext.create('Ext.util.Draggable', t, {
threshold: 0,
revert: this.revert,
direction: this.direction,
constrain: this.constrain === true ? this.el : this.constrain,
animationDuration: 100
});
draggable.on({
drag: this.onDrag,
dragend: this.onDragEnd,
scope: this
});
this.dragEl = t;
this.calculateBoxes();
if (!draggable.dragging) {
draggable.onStart(e);
}
this.fireEvent('sortstart', this, e);
},
// @private
calculateBoxes : function() {
this.items = [];
var els = this.el.select(this.itemSelector, false),
ln = els.length, i, item, el, box;
for (i = 0; i < ln; i++) {
el = els[i];
if (el != this.dragEl) {
item = Ext.fly(el).getPageBox(true);
item.el = el;
this.items.push(item);
}
}
},
// @private
onDrag : function(draggable, e) {
var items = this.items,
ln = items.length,
region = draggable.region,
sortChange = false,
i, intersect, overlap, item;
for (i = 0; i < ln; i++) {
item = items[i];
intersect = region.intersect(item);
if (intersect) {
if (this.vertical && Math.abs(intersect.top - intersect.bottom) > (region.bottom - region.top) / 2) {
if (region.bottom > item.top && item.top > region.top) {
draggable.el.insertAfter(item.el);
}
else {
draggable.el.insertBefore(item.el);
}
sortChange = true;
}
else if (this.horizontal && Math.abs(intersect.left - intersect.right) > (region.right - region.left) / 2) {
if (region.right > item.left && item.left > region.left) {
draggable.el.insertAfter(item.el);
}
else {
draggable.el.insertBefore(item.el);
}
sortChange = true;
}
if (sortChange) {
// We reset the draggable (initializes all the new start values)
draggable.reset();
// Move the draggable to its current location (since the transform is now
// different)
draggable.moveTo(region.left, region.top);
// Finally lets recalculate all the items boxes
this.calculateBoxes();
this.fireEvent('sortchange', this, draggable.el, this.el.select(this.itemSelector, false).indexOf(draggable.el.dom));
return;
}
}
}
},
// @private
onDragEnd : function(draggable, e) {
draggable.destroy();
this.sorting = false;
this.fireEvent('sortend', this, draggable, e);
},
/**
* Enables sorting for this Sortable.
* This method is invoked immediately after construction of a Sortable unless
* the disabled configuration is set to `true`.
*/
enable : function() {
this.el.on(this.startEventName, this.onStart, this, {delegate: this.itemSelector, holdThreshold: this.getDelay()});
this.disabled = false;
},
/**
* Disables sorting for this Sortable.
*/
disable : function() {
this.el.un(this.startEventName, this.onStart, this);
this.disabled = true;
},
/**
* Method to determine whether this Sortable is currently disabled.
* @return {Boolean} The disabled state of this Sortable.
*/
isDisabled: function() {
return this.disabled;
},
/**
* Method to determine whether this Sortable is currently sorting.
* @return {Boolean} The sorting state of this Sortable.
*/
isSorting : function() {
return this.sorting;
},
/**
* Method to determine whether this Sortable is currently disabled.
* @return {Boolean} The disabled state of this Sortable.
*/
isVertical : function() {
return this.vertical;
},
/**
* Method to determine whether this Sortable is currently sorting.
* @return {Boolean} The sorting state of this Sortable.
*/
isHorizontal : function() {
return this.horizontal;
}
});