123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 |
- /*!
- * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
- * Dual-licensed under the BSD or MIT licenses
- */
- ;(function($, window, document, undefined)
- {
- var hasTouch = 'ontouchstart' in document;
- /**
- * Detect CSS pointer-events property
- * events are normally disabled on the dragging element to avoid conflicts
- * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
- */
- var hasPointerEvents = (function()
- {
- var el = document.createElement('div'),
- docEl = document.documentElement;
- if (!('pointerEvents' in el.style)) {
- return false;
- }
- el.style.pointerEvents = 'auto';
- el.style.pointerEvents = 'x';
- docEl.appendChild(el);
- var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
- docEl.removeChild(el);
- return !!supports;
- })();
- var defaults = {
- listNodeName : 'ol',
- itemNodeName : 'li',
- rootClass : 'dd',
- listClass : 'dd-list',
- itemClass : 'dd-item',
- dragClass : 'dd-dragel',
- handleClass : 'dd-handle',
- collapsedClass : 'dd-collapsed',
- placeClass : 'dd-placeholder',
- noDragClass : 'dd-nodrag',
- emptyClass : 'dd-empty',
- deleteClass : 'dd-del',
- itemKey :'',
- itemName :'',
- aliasName :'',
- expandBtnHTML : '<button data-action="expand" type="button">Expand</button>',
- collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>',
- group : 0,
- maxDepth : 5,
- threshold : 20,
- rmSourceItem :true ,
- addItemCloseBtn :false,
- dragFlag :true,
- addItemQuickBtn:false,
- quickKey:'quickKey',
- quickDesc:'quickDesc',
- quickTitle:'快捷',
- quickEnum:[{'key':'是','value':'是'},{'key':'否','value':'否'}],
- data:null,
- dataJsonKey:'json'
- };
- function Plugin(element, options)
- {
- this.w = $(document);
- this.el = $(element);
- this.options = $.extend({}, defaults, options);
-
- this.init();
- }
- Plugin.prototype = {
- init: function()
- {
- var list = this;
-
- list.buildOl();
- list.reset();
- list.el.data('nestable-group', this.options.group);
- list.placeEl = $('<div class="' + list.options.placeClass + '"/>');
- $.each(this.el.find(list.options.itemNodeName), function(k, el) {
- list.setParent($(el));
- });
- list.el.on('click', 'button', function(e) {
- if (list.dragEl) {
- return;
- }
- var target = $(e.currentTarget),
- action = target.data('action'),
- item = target.parent(list.options.itemNodeName);
- if (action === 'collapse') {
- list.collapseItem(item);
- }
- if (action === 'expand') {
- list.expandItem(item);
- }
- });
- var onStartEvent = function(e)
- {
- var handle = $(e.target);
- if (!handle.hasClass(list.options.handleClass)) {
- if (handle.closest('.' + list.options.noDragClass).length) {
- return;
- }
- handle = handle.closest('.' + list.options.handleClass);
- }
- if (!handle.length || list.dragEl) {
- return;
- }
- list.isTouch = /^touch/.test(e.type);
- if (list.isTouch && e.touches.length !== 1) {
- return;
- }
- e.preventDefault();
- list.dragStart(e.touches ? e.touches[0] : e);
- };
- var onMoveEvent = function(e)
- {
- if (list.dragEl) {
- e.preventDefault();
- list.dragMove(e.touches ? e.touches[0] : e);
- }
- };
- var onEndEvent = function(e)
- {
-
- if (list.dragEl) {
- e.preventDefault();
- list.dragStop(e.touches ? e.touches[0] : e);
- }
- };
- if (hasTouch) {
- list.el[0].addEventListener('touchstart', onStartEvent, false);
- window.addEventListener('touchmove', onMoveEvent, false);
- window.addEventListener('touchend', onEndEvent, false);
- window.addEventListener('touchcancel', onEndEvent, false);
- }
- if(this.options.dragFlag){
-
- list.el.on('mousedown', onStartEvent);
- list.w.on('mousemove', onMoveEvent);
- list.w.on('mouseup', onEndEvent);
- }
-
- if(this.options.addItemCloseBtn){
-
- list.el.delegate("."+this.options.deleteClass,'click',function(e){
-
- var itemList = $(this).parent().parent();
-
- var length = itemList.children().length;
-
- $(this).parent('.'+list.options.itemClass).remove();
-
- if(length == 1){
-
- itemList.remove();
-
- list.el.append("<div class='"+list.options.emptyClass+"'></div>");
- }
-
- });
- }
-
- //2020年2月19日19:59:49 增加没有数据时插入空图片
- list.el.children().length == 0 && list.el.append("<div class='"+list.options.emptyClass+"'></div>");
-
- $.each(list.el.find("." + list.options.itemClass),function(i,item){
-
- var id = $(item).attr("data-id");
-
- if(id == null || id == undefined || id == ""){
-
- if(util.isNull(list.options.itemKey)){
-
- var num = list.randomNum();
-
- $(item).attr("data-id",num) ;
-
- return true;
- }
-
-
-
- $(item).attr("data-id",$(item).data(list.options.itemKey.toLowerCase())) ;
- }
-
- });
-
- },
- randomNum:function(){
-
- return new Date().getTime()+ parseInt(Math.random()*100000,10);
-
- },
- serialize: function()
- {
- var data,
- depth = 0,
- list = this;
- step = function(level, depth)
- {
- var array = [ ],
- items = level.children(list.options.itemNodeName);
- items.each(function()
- {
- var li = $(this),
- item = $.extend({}, li.data()),
- sub = li.children(list.options.listNodeName);
- if (sub.length) {
- item.children = step(sub, depth + 1);
- }
- array.push(item);
- });
- return array;
- };
- data = step(list.el.find(list.options.listNodeName).first(), depth);
- return data;
- },
- serialise: function()
- {
- return this.serialize();
- },
- reset: function()
- {
- this.mouse = {
- offsetX : 0,
- offsetY : 0,
- startX : 0,
- startY : 0,
- lastX : 0,
- lastY : 0,
- nowX : 0,
- nowY : 0,
- distX : 0,
- distY : 0,
- dirAx : 0,
- dirX : 0,
- dirY : 0,
- lastDirX : 0,
- lastDirY : 0,
- distAxX : 0,
- distAxY : 0
- };
- this.isTouch = false;
- this.moving = false;
- this.dragEl = null;
- this.dragRootEl = null;
- this.dragDepth = 0;
- this.hasNewRoot = false;
- this.pointEl = null;
- this.sourceIndex = null;
- this.sourceParent = null;
- },
- expandItem: function(li)
- {
- li.removeClass(this.options.collapsedClass);
- li.children('[data-action="expand"]').hide();
- li.children('[data-action="collapse"]').show();
- li.children(this.options.listNodeName).show();
- },
- collapseItem: function(li)
- {
- var lists = li.children(this.options.listNodeName);
- if (lists.length) {
- li.addClass(this.options.collapsedClass);
- li.children('[data-action="collapse"]').hide();
- li.children('[data-action="expand"]').show();
- li.children(this.options.listNodeName).hide();
- }
- },
- expandAll: function()
- {
- var list = this;
- list.el.find(list.options.itemNodeName).each(function() {
- list.expandItem($(this));
- });
- },
- collapseAll: function()
- {
- var list = this;
- list.el.find(list.options.itemNodeName).each(function() {
- list.collapseItem($(this));
- });
- },
- setParent: function(li)
- {
- if (li.children(this.options.listNodeName).length) {
- li.prepend($(this.options.expandBtnHTML));
- li.prepend($(this.options.collapseBtnHTML));
- }
- li.children('[data-action="expand"]').hide();
- },
- unsetParent: function(li)
- {
- li.removeClass(this.options.collapsedClass);
- li.children('[data-action]').remove();
- li.children(this.options.listNodeName).remove();
- },
- dragStart: function(e)
- {
- var mouse = this.mouse,
- target = $(e.target),
- dragItem = target.closest(this.options.itemNodeName);
-
- this.sourceIndex = dragItem.index();
-
- this.sourceParent = dragItem.parent();
-
- this.placeEl.css('height', dragItem.height());
-
-
-
- mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
- mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
- mouse.startX = mouse.lastX = e.pageX;
- mouse.startY = mouse.lastY = e.pageY;
- this.dragRootEl = this.el;
- this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
- this.dragEl.css('width', dragItem.width());
- dragItem.after(this.placeEl);
- dragItem[0].parentNode.removeChild(dragItem[0]);
- dragItem.appendTo(this.dragEl);
- $(document.body).append(this.dragEl);
- this.dragEl.css({
- 'left' : e.pageX - mouse.offsetX,
- 'top' : e.pageY - mouse.offsetY
- });
- // total depth of dragging item
- var i, depth,
- items = this.dragEl.find(this.options.itemNodeName);
- for (i = 0; i < items.length; i++) {
- depth = $(items[i]).parents(this.options.listNodeName).length;
- if (depth > this.dragDepth) {
- this.dragDepth = depth;
- }
- }
- },
-
- getCloseBtnFlag:function(){
-
- return this.options.addItemCloseBtn;
- },
- getQuickBtn:function(){
-
- return this.options.addItemQuickBtn;
- },
- getItems:function(){
-
- return this.el.find("."+this.options.itemClass);
- },
-
- getItemData: function(){
-
- var arr = new Array();
-
- var that =this;
-
- $.each(that.getItems(),function(i,item){
-
- var d = $(item).data("json");
-
- var quickFlag = that.options.quickEnum[1].key;
-
- var checkbox = $(item).find("input[type=checkbox][name="+that.options.quickKey+"]:checked");
-
- if(checkbox.length > 0 ){
-
- quickFlag = that.options.quickEnum[0].key;
- }
-
- d[that.options.quickKey] = checkbox.length > 0 ? that.options.quickEnum[0].key : that.options.quickEnum[1].key;
-
- d[that.options.quickDesc] = checkbox.length > 0 ? that.options.quickEnum[0].value : that.options.quickEnum[1].value;
-
- arr.push(d);
-
- });
-
- return arr;
-
- },
-
- getQuickHtml:function(flag){
-
- return '<div style="float:right;margin-top:-35px;"><input type="checkbox" name="'+this.options.quickKey+'" '+(flag ? 'checked="checked"': '')+' />'+this.options.quickTitle+'</div> ';
- },
- getCloseBtnHtml:function(flag){
-
- var f = flag ? flag :this.options.addItemQuickBtn;
-
- return '<i class="layui-icon layui-icon-delete '+this.options.deleteClass+'" style="font-size: 30px; color:red ;float:right;margin-top:-35px;'+(f?'margin-right:50px;':'')+'"></i> ';
-
- },
-
- dragStop: function(e)
- {
-
-
- var el = this.dragEl.children(this.options.itemNodeName).first();
-
-
- el[0].parentNode.removeChild(el[0]);
-
- var plceRoot = this.placeEl.parents("."+this.options.rootClass);
-
- var item = plceRoot.find("[data-id="+el.attr("data-id")+"]");
-
- if(item.length == 0){
-
- var clone = el.clone();
-
- if(plceRoot.nestable('getQuickBtn') && this.el.attr("id")!= plceRoot.attr("id")){
- clone.append(plceRoot.nestable('getQuickHtml'));
- }
-
- if(plceRoot.nestable('getCloseBtnFlag') && this.el.attr("id")!= plceRoot.attr("id")){
-
- clone.append(this.getCloseBtnHtml(plceRoot.nestable('getQuickBtn')));
- }
-
- this.placeEl.replaceWith(clone);
-
- }else{
- this.placeEl.remove();
- }
- this.dragEl.remove();
-
- this.el.trigger('change');
- if (this.hasNewRoot) {
- this.dragRootEl.trigger('change');
- }
-
-
-
- if( !this.options.rmSourceItem){
-
- var sourceItem = this.el.find("[data-id="+el.attr("data-id")+"]");
-
- sourceItem.length == 0 && this.addItem(el);
-
- }
- this.reset();
- },
- addItem :function (el){
-
- if(this.sourceParent.children().length == 0){
-
- this.sourceParent.append(el.clone());
-
- return ;
- }
-
- if(this.sourceIndex == this.sourceParent.children().length){
-
- this.sourceParent.append(el.clone());
-
- return ;
- }
-
- this.sourceParent.children().eq(this.sourceIndex).before(el.clone());
-
-
- },
- buildOl :function (){
-
- var that = this;
-
- if(!util.isNull(that.options.data) && that.options.data.length > 0){
-
- var ol = $('<ol class="dd-list"></ol>');
-
- $.each(that.options.data,function(i,item){
-
- var li = $('<li class="dd-item" ></div>');
-
- li.attr("data-"+that.options.dataJsonKey,JSON.stringify(item));
- li.attr("data-"+that.options.itemKey.toLowerCase(),item[that.options.itemKey]);
-
- var div = $('<div class="dd-handle">'+(util.isNull(item[that.options.aliasName]) ? item[that.options.itemName] : item[that.options.aliasName])+'</div>');
-
- li.append(div);
-
- if(that.options.addItemQuickBtn){
-
- li.append(that.getQuickHtml(item[that.options.quickKey] == that.options.quickEnum[0].key ? true :false));
-
- }
-
- if(that.options.addItemCloseBtn){
-
- li.append(that.getCloseBtnHtml(true));
- }
-
- ol.append(li);
-
- });
-
- that.el.append(ol);
-
- }
- },
- dragMove: function(e)
- {
- var list, parent, prev, next, depth,
- opt = this.options,
- mouse = this.mouse;
- this.dragEl.css({
- 'left' : e.pageX - mouse.offsetX,
- 'top' : e.pageY - mouse.offsetY
- });
- // mouse position last events
- mouse.lastX = mouse.nowX;
- mouse.lastY = mouse.nowY;
- // mouse position this events
- mouse.nowX = e.pageX;
- mouse.nowY = e.pageY;
- // distance mouse moved between events
- mouse.distX = mouse.nowX - mouse.lastX;
- mouse.distY = mouse.nowY - mouse.lastY;
- // direction mouse was moving
- mouse.lastDirX = mouse.dirX;
- mouse.lastDirY = mouse.dirY;
- // direction mouse is now moving (on both axis)
- mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
- mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
- // axis mouse is now moving on
- var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
- // do nothing on first move
- if (!mouse.moving) {
- mouse.dirAx = newAx;
- mouse.moving = true;
- return;
- }
- // calc distance moved on this axis (and direction)
- if (mouse.dirAx !== newAx) {
- mouse.distAxX = 0;
- mouse.distAxY = 0;
- } else {
- mouse.distAxX += Math.abs(mouse.distX);
- if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
- mouse.distAxX = 0;
- }
- mouse.distAxY += Math.abs(mouse.distY);
- if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {
- mouse.distAxY = 0;
- }
- }
- mouse.dirAx = newAx;
- /**
- * move horizontal
- */
- if (mouse.dirAx && mouse.distAxX >= opt.threshold) {
- // reset move distance on x-axis for new phase
- mouse.distAxX = 0;
- prev = this.placeEl.prev(opt.itemNodeName);
- // increase horizontal level if previous sibling exists and is not collapsed
- if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
- // cannot increase level when item above is collapsed
- list = prev.find(opt.listNodeName).last();
- // check if depth limit has reached
- depth = this.placeEl.parents(opt.listNodeName).length;
- if (depth + this.dragDepth <= opt.maxDepth) {
- // create new sub-level if one doesn't exist
- if (!list.length) {
- list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);
- list.append(this.placeEl);
- prev.append(list);
- this.setParent(prev);
- } else {
- // else append to next level up
- list = prev.children(opt.listNodeName).last();
- list.append(this.placeEl);
- }
- }
- }
- // decrease horizontal level
- if (mouse.distX < 0) {
- // we can't decrease a level if an item preceeds the current one
- next = this.placeEl.next(opt.itemNodeName);
- if (!next.length) {
- parent = this.placeEl.parent();
- this.placeEl.closest(opt.itemNodeName).after(this.placeEl);
- if (!parent.children().length) {
- this.unsetParent(parent.parent());
- }
- }
- }
- }
- var isEmpty = false;
- // find list item under cursor
- if (!hasPointerEvents) {
- this.dragEl[0].style.visibility = 'hidden';
- }
- this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));
- if (!hasPointerEvents) {
- this.dragEl[0].style.visibility = 'visible';
- }
- if (this.pointEl.hasClass(opt.handleClass)) {
- this.pointEl = this.pointEl.parent(opt.itemNodeName);
- }
- if (this.pointEl.hasClass(opt.emptyClass)) {
- isEmpty = true;
- }
- else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {
- return;
- }
- // find parent list of item under cursor
- var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
- isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
- /**
- * move vertical
- */
- if (!mouse.dirAx || isNewRoot || isEmpty) {
- // check if groups match if dragging over new root
- if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
- return;
- }
- // check depth limit
- depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
- if (depth > opt.maxDepth) {
- return;
- }
- var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
- parent = this.placeEl.parent();
- // if empty create new list to replace empty placeholder
- if (isEmpty) {
- list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
- list.append(this.placeEl);
- this.pointEl.replaceWith(list);
- }
- else if (before) {
- this.pointEl.before(this.placeEl);
- }
- else {
- this.pointEl.after(this.placeEl);
- }
- if (!parent.children().length) {
- this.unsetParent(parent.parent());
- }
- if (!this.dragRootEl.find(opt.itemNodeName).length) {
- this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>');
- }
- // parent root list has changed
- if (isNewRoot) {
- this.dragRootEl = pointElRoot;
- this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
- }
- }
- }
- };
- $.fn.nestable = function(params)
- {
- var lists = this,
- retval = this;
- lists.each(function()
- {
- var plugin = $(this).data("nestable");
- if (!plugin) {
- $(this).data("nestable", new Plugin(this, params));
- $(this).data("nestable-id", new Date().getTime());
- } else {
- if (typeof params === 'string' && typeof plugin[params] === 'function') {
- retval = plugin[params]();
- }
- }
- });
- return retval || lists;
- };
- })(window.jQuery || window.Zepto, window, document);
|