zui
Version:
一个基于 Bootstrap 深度定制开源前端实践方案,帮助你快速构建现代跨屏应用。
172 lines (150 loc) • 6.05 kB
JavaScript
/* ========================================================================
* ZUI: sortable.js
* http://zui.sexy
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
+ function($, window, document) {
'use strict';
if(!$.fn.droppable) {
console.error('Sortable requires droppable.js');
return;
}
var NAME = 'zui.sortable',
DEFAULTS = {
selector : 'li,div',
dragCssClass : 'invisible',
sortingClass : 'sortable-sorting'
},
STR_ORDER = 'order';
var Sortable = function(element, options) {
var that = this;
that.$ = $(element);
that.options = $.extend({}, DEFAULTS, that.$.data(), options);
that.init();
};
Sortable.DEFAULTS = DEFAULTS;
Sortable.NAME = NAME;
Sortable.prototype.init = function() {
var that = this,
$root = that.$,
options = that.options,
selector = options.selector,
containerSelector = options.containerSelector,
sortingClass = options.sortingClass,
dragCssClass = options.dragCssClass,
targetSelector = options.targetSelector,
isReverse = options.reverse,
orderChanged;
var markOrders = function($items) {
$items = $items || that.getItems(1);
var itemsCount = $items.length;
if (itemsCount) {
$items.each(function(itemIndex) {
var itemOrder = isReverse ? itemsCount - itemIndex : itemIndex;
$(this).attr('data-' + STR_ORDER, itemOrder).data(STR_ORDER, itemOrder);
});
}
};
markOrders();
$root.droppable({
handle : options.trigger,
target : targetSelector ? targetSelector : (containerSelector ? (selector + ',' + containerSelector) : selector),
selector : selector,
container : $root,
always : options.always,
flex : true,
lazy : options.lazy,
canMoveHere : options.canMoveHere,
dropToClass : options.dropToClass,
before : options.before,
nested : !!containerSelector,
mouseButton : options.mouseButton,
stopPropagation : options.stopPropagation,
start: function(e) {
if(dragCssClass) e.element.addClass(dragCssClass);
orderChanged = false;
that.trigger('start', e);
},
drag: function(e) {
$root.addClass(sortingClass);
if(e.isIn) {
var $ele = e.element,
$target = e.target,
isContainer = containerSelector && $target.is(containerSelector);
if (isContainer) {
if (!$target.children(selector).filter('.dragging').length) {
$target.append($ele);
var $items = that.getItems(1);
markOrders($items);
that.trigger(STR_ORDER, {
list: $items,
element: $ele
});
}
return;
}
var eleOrder = $ele.data(STR_ORDER),
targetOrder = $target.data(STR_ORDER);
if(eleOrder === targetOrder) return markOrders($items);
else if(eleOrder > targetOrder) {
$target[isReverse ? 'after' : 'before']($ele);
} else {
$target[isReverse ? 'before' : 'after']($ele);
}
orderChanged = true;
var $items = that.getItems(1);
markOrders($items);
that.trigger(STR_ORDER, {
list: $items,
element: $ele
});
}
},
finish: function(e) {
if(dragCssClass && e.element) e.element.removeClass(dragCssClass);
$root.removeClass(sortingClass);
that.trigger('finish', {
list: that.getItems(),
element: e.element,
changed: orderChanged
});
}
});
};
Sortable.prototype.destroy = function() {
this.$.droppable('destroy');
this.$.data(NAME, null);
};
Sortable.prototype.reset = function() {
this.destroy();
this.init();
};
Sortable.prototype.getItems = function(onlyElements) {
var $items = this.$.find(this.options.selector).not('.drag-shadow');
if(!onlyElements) {
return $items.map(function() {
var $item = $(this);
return {
item: $item,
order: $item.data('order')
};
});
}
return $items;
};
Sortable.prototype.trigger = function(name, params) {
return $.zui.callEvent(this.options[name], params, this);
};
$.fn.sortable = function(option) {
return this.each(function() {
var $this = $(this);
var data = $this.data(NAME);
var options = typeof option == 'object' && option;
if(!data) $this.data(NAME, (data = new Sortable(this, options)));
else if(typeof option == 'object') data.reset();
if(typeof option == 'string') data[option]();
});
};
$.fn.sortable.Constructor = Sortable;
}(jQuery, window, document);