帶刪除功能:javascript
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>拖拽插件jquery.dad.js</title> <style type="text/css"> .dad-noSelect,.dad-noSelect *{ -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; cursor: -webkit-grabbing !important; cursor: -moz-grabbing !important; } .dad-container{ position: relative; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .dad-container::after{ content: ''; clear: both !important; display: block; } .dad-active .dad-draggable-area{ cursor: -webkit-grab; cursor: -moz-grab; } .dad-draggable-area>*,.dad-draggable-area img{ pointer-events: none; } .dads-children.active{ pointer-events: none; } .dads-children-clone{ opacity: 1; z-index: 9999; pointer-events: none; } .dads-children-placeholder{ pointer-events: none; overflow: hidden; position: absolute !important; box-sizing: border-box; border:4px dashed #639BF6; margin:5px; text-align: center; color: #639BF6; font-weight: bold; } .daddy>div { box-sizing: border-box; width: 20%; padding: 5px; float: left; display: block; position: relative; } .daddy>div>div { display: block; height: 120px; line-height: 120px; text-align: center; font-size: 30px; font-weight: bold; background: #639BF6; color: white; font-family: "Arial", sans-serif; } .m-delete{pointer-events: auto;} </style> </head> <body> ccs文件和js文件能夠去GitHub上下載,下載地址是:https://github.com/williammustaffa/jquery.dad.js 本實例是直接把源代碼都複製過來了 <div id="daddy" class="dad daddy"> <div> <div>1</div> <input type="button" value="刪除" class="m-delete js-delete"> </div> <div> <div>2</div> <input type="button" value="刪除" class="m-delete js-delete"> </div> <div> <div>3</div> <input type="button" value="刪除" class="m-delete js-delete"> </div> <div> <div>4</div> <input type="button" value="刪除" class="m-delete js-delete"> </div> <div> <div>5</div> <input type="button" value="刪除" class="m-delete js-delete"> </div> </div> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script> <!-- <script src='jquery.dad.js'></script> --> <script type="text/javascript"> /*! * jquery.dad.js v1 (http://konsolestudio.com/dad) * Author William Lima */ (function ($) { 'use strict'; var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints; $.fn.dad = function (opts) { var _this = this; var defaults = { target: '>div', draggable: false, placeholder: '', callback: false, containerClass: 'dad-container', childrenClass: 'dads-children', cloneClass: 'dads-children-clone', active: true, }; var options = $.extend({}, defaults, opts); $(this).each(function () { var active = options.active; var $daddy = $(this); var childrenClass = options.childrenClass; var cloneClass = options.cloneClass; var jQclass = '.' + childrenClass; var $target = $daddy.find(options.target); var placeholder = options.placeholder; var callback = options.callback; var dragClass = 'dad-draggable-area'; var holderClass = 'dads-children-placeholder'; // HANDLE MOUSE var mouse = { x: 0, y: 0, target: false, clone: false, placeholder: false, cloneoffset: { x: 0, y: 0, }, updatePosition: function (e) { this.x = e.pageX; this.y = e.pageY; }, move: function (e) { this.updatePosition(e); if (this.clone !== false && _this.target !== false) { this.clone.css({ left: this.x - this.cloneoffset.x, top: this.y - this.cloneoffset.y, }); } }, }; $(window).on('mousemove touchmove', function (e) { var ev = e; if (mouse.clone !== false && mouse.target !== false) e.preventDefault(); if (supportsTouch && e.type == 'touchmove') { ev = e.originalEvent.touches[0]; var mouseTarget = document.elementFromPoint(ev.clientX, ev.clientY); $(mouseTarget).trigger('touchenter'); } mouse.move(ev); }); $daddy.addClass(options.containerClass); if (!$daddy.hasClass('dad-active') && active === true) { $daddy.addClass('dad-active'); }; _this.addDropzone = function (selector, func) { $(selector).on('mouseenter touchenter', function () { if (mouse.target !== false) { mouse.placeholder.css({ display: 'none' }); mouse.target.css({ display: 'none' }); $(this).addClass('active'); } }).on('mouseup touchend', function () { if (mouse.target != false) { mouse.placeholder.css({ display: 'block' }); mouse.target.css({ display: 'block' }); func(mouse.target); dadEnd(); }; $(this).removeClass('active'); }).on('mouseleave touchleave', function () { if (mouse.target !== false) { mouse.placeholder.css({ display: 'block' }); mouse.target.css({ display: 'block' }); } $(this).removeClass('active'); }); }; // GET POSITION FUNCTION _this.getPosition = function () { var positionArray = []; $(this).find(jQclass).each(function () { positionArray[$(this).attr('data-dad-id')] = parseInt($(this).attr('data-dad-position')); }); return positionArray; }; _this.activate = function () { active = true; if (!$daddy.hasClass('dad-active')) { $daddy.addClass('dad-active'); } return _this; }; // DEACTIVATE FUNCTION _this.deactivate = function () { active = false; $daddy.removeClass('dad-active'); return _this; }; // DEFAULT DROPPING $daddy.on('DOMNodeInserted', function (e) { var $thisTarget = $(e.target); if (!$thisTarget.hasClass(childrenClass) && !$thisTarget.hasClass(holderClass)) { $thisTarget.addClass(childrenClass); } }); $(document).on('mouseup touchend', function () { dadEnd(); }); // ORDER ELEMENTS var order = 1; $target.addClass(childrenClass).each(function () { if ($(this).data('dad-id') == undefined) { $(this).attr('data-dad-id', order); } $(this).attr('data-dad-position', order); order++; }); // CREATE REORDER FUNCTION function updatePosition(e) { var order = 1; e.find(jQclass).each(function () { $(this).attr('data-dad-position', order); order++; }); } // END EVENT function dadEnd() { if (mouse.target != false && mouse.clone != false) { if (callback != false) { callback(mouse.target); } var appear = mouse.target; var desappear = mouse.clone; var holder = mouse.placeholder; var bLeft = 0; var bTop = 0; // Maybe we will use this in the future //Math.floor(parseFloat($daddy.css('border-left-width'))); //Math.floor(parseFloat($daddy.css('border-top-width'))); if ($.contains($daddy[0], mouse.target[0])) { mouse.clone.animate({ top: mouse.target.offset().top - $daddy.offset().top - bTop, left: mouse.target.offset().left - $daddy.offset().left - bLeft, }, 300, function () { appear.css({ visibility: 'visible', }).removeClass('active'); desappear.remove(); }); } else { mouse.clone.fadeOut(300, function () { desappear.remove(); }); } holder.remove(); mouse.clone = false; mouse.placeholder = false; mouse.target = false; updatePosition($daddy); } $('html, body').removeClass('dad-noSelect'); } // UPDATE EVENT function dadUpdate(obj) { if (mouse.target !== false && mouse.clone !== false) { var $origin = $('<span style="display:none"></span>'); var $newplace = $('<span style="display:none"></span>'); if (obj.prevAll().hasClass('active')) { obj.after($newplace); } else { obj.before($newplace); } mouse.target.before($origin); $newplace.before(mouse.target); // UPDATE PLACEHOLDER mouse.placeholder.css({ top: mouse.target.offset().top - $daddy.offset().top, left: mouse.target.offset().left - $daddy.offset().left, width: mouse.target.outerWidth() - 10, height: mouse.target.outerHeight() - 10, }); $origin.remove(); $newplace.remove(); } } // GRABBING EVENT var jq = (options.draggable !== false) ? options.draggable : jQclass; $daddy.find(jq).addClass(dragClass); $daddy.on('mousedown touchstart', jq, function (e) { var isDelete = $(e.target).hasClass('js-delete'); if(isDelete) { return; } // For touchstart we must update "mouse" position if (e.type == 'touchstart') { mouse.updatePosition(e.originalEvent.touches[0]); } if (mouse.target == false && active == true && (e.which == 1 || e.type == 'touchstart')) { var $self = $(this); // GET TARGET if (options.draggable !== false) { mouse.target = $daddy.find(jQclass).has(this); } else { mouse.target = $self; } // ADD CLONE mouse.clone = mouse.target.clone(); mouse.target.css({ visibility: 'hidden' }).addClass('active'); mouse.clone.addClass(cloneClass); $daddy.append(mouse.clone); // ADD PLACEHOLDER var $placeholder = $('<div></div>'); mouse.placeholder = $placeholder; mouse.placeholder.addClass(holderClass); mouse.placeholder.css({ top: mouse.target.offset().top - $daddy.offset().top, left: mouse.target.offset().left - $daddy.offset().left, width: mouse.target.outerWidth() - 10, height: mouse.target.outerHeight() - 10, lineHeight: mouse.target.height() - 18 + 'px', textAlign: 'center', }).text(placeholder); $daddy.append(mouse.placeholder); // GET OFFSET FOR CLONE var bLeft = Math.floor(parseFloat($daddy.css('border-left-width'))); var bTop = Math.floor(parseFloat($daddy.css('border-top-width'))); var difx = mouse.x - mouse.target.offset().left + $daddy.offset().left + bLeft; var dify = mouse.y - mouse.target.offset().top + $daddy.offset().top + bTop; mouse.cloneoffset.x = difx; mouse.cloneoffset.y = dify; // REMOVE THE CHILDREN DAD CLASS AND SET THE POSITION ON SCREEN mouse.clone.removeClass(childrenClass).css({ position: 'absolute', top: mouse.y - mouse.cloneoffset.y, left: mouse.x - mouse.cloneoffset.x, }); // UNABLE THE TEXT SELECTION AND SET THE GRAB CURSOR $('html,body').addClass('dad-noSelect'); } }); $daddy.on('mouseenter touchenter', jQclass, function () { dadUpdate($(this)); }); }); return this; }; })(jQuery); </script> <script type="text/javascript"> $(function () { var myAction = {}; var dom = { dad: $('#daddy'), delete: $('.js-delete') } $.extend(myAction, { initDad: function () { dom.dad.dad(); }, initEvent: function () { dom.delete.on('click', function () { var that = $(this); that.parent().remove(); }); } }); var init = function () { myAction.initDad(); myAction.initEvent(); }(); }); </script> </body> </html>
不帶刪除功能:css
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>拖拽插件jquery.dad.js</title> <style type="text/css"> .dad-noSelect,.dad-noSelect *{ -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; cursor: -webkit-grabbing !important; cursor: -moz-grabbing !important; } .dad-container{ position: relative; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .dad-container::after{ content: ''; clear: both !important; display: block; } .dad-active .dad-draggable-area{ cursor: -webkit-grab; cursor: -moz-grab; } .dad-draggable-area>*,.dad-draggable-area img{ pointer-events: none; } .dads-children.active{ pointer-events: none; } .dads-children-clone{ opacity: 1; z-index: 9999; pointer-events: none; } .dads-children-placeholder{ pointer-events: none; overflow: hidden; position: absolute !important; box-sizing: border-box; border:4px dashed #639BF6; margin:5px; text-align: center; color: #639BF6; font-weight: bold; } .daddy>div { box-sizing: border-box; width: 20%; padding: 5px; float: left; display: block; position: relative; } .daddy>div>div { display: block; height: 120px; line-height: 120px; text-align: center; font-size: 30px; font-weight: bold; background: #639BF6; color: white; font-family: "Arial", sans-serif; } </style> </head> <body> ccs文件和js文件能夠去GitHub上下載,下載地址是:https://github.com/williammustaffa/jquery.dad.js 本實例是直接把源代碼都複製過來了 <div id="daddy" class="dad daddy"> <div> <div>1</div> </div> <div> <div>2</div> </div> <div> <div>3</div> </div> <div> <div>4</div> </div> <div> <div>5</div> </div> </div> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script> <!-- <script src='jquery.dad.js'></script> --> <script type="text/javascript"> /*! * jquery.dad.js v1 (http://konsolestudio.com/dad) * Author William Lima */ (function ($) { 'use strict'; var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints; $.fn.dad = function (opts) { var _this = this; var defaults = { target: '>div', draggable: false, placeholder: '', callback: false, containerClass: 'dad-container', childrenClass: 'dads-children', cloneClass: 'dads-children-clone', active: true, }; var options = $.extend({}, defaults, opts); $(this).each(function () { var active = options.active; var $daddy = $(this); var childrenClass = options.childrenClass; var cloneClass = options.cloneClass; var jQclass = '.' + childrenClass; var $target = $daddy.find(options.target); var placeholder = options.placeholder; var callback = options.callback; var dragClass = 'dad-draggable-area'; var holderClass = 'dads-children-placeholder'; // HANDLE MOUSE var mouse = { x: 0, y: 0, target: false, clone: false, placeholder: false, cloneoffset: { x: 0, y: 0, }, updatePosition: function (e) { this.x = e.pageX; this.y = e.pageY; }, move: function (e) { this.updatePosition(e); if (this.clone !== false && _this.target !== false) { this.clone.css({ left: this.x - this.cloneoffset.x, top: this.y - this.cloneoffset.y, }); } }, }; $(window).on('mousemove touchmove', function (e) { var ev = e; if (mouse.clone !== false && mouse.target !== false) e.preventDefault(); if (supportsTouch && e.type == 'touchmove') { ev = e.originalEvent.touches[0]; var mouseTarget = document.elementFromPoint(ev.clientX, ev.clientY); $(mouseTarget).trigger('touchenter'); } mouse.move(ev); }); $daddy.addClass(options.containerClass); if (!$daddy.hasClass('dad-active') && active === true) { $daddy.addClass('dad-active'); }; _this.addDropzone = function (selector, func) { $(selector).on('mouseenter touchenter', function () { if (mouse.target !== false) { mouse.placeholder.css({ display: 'none' }); mouse.target.css({ display: 'none' }); $(this).addClass('active'); } }).on('mouseup touchend', function () { if (mouse.target != false) { mouse.placeholder.css({ display: 'block' }); mouse.target.css({ display: 'block' }); func(mouse.target); dadEnd(); }; $(this).removeClass('active'); }).on('mouseleave touchleave', function () { if (mouse.target !== false) { mouse.placeholder.css({ display: 'block' }); mouse.target.css({ display: 'block' }); } $(this).removeClass('active'); }); }; // GET POSITION FUNCTION _this.getPosition = function () { var positionArray = []; $(this).find(jQclass).each(function () { positionArray[$(this).attr('data-dad-id')] = parseInt($(this).attr('data-dad-position')); }); return positionArray; }; _this.activate = function () { active = true; if (!$daddy.hasClass('dad-active')) { $daddy.addClass('dad-active'); } return _this; }; // DEACTIVATE FUNCTION _this.deactivate = function () { active = false; $daddy.removeClass('dad-active'); return _this; }; // DEFAULT DROPPING $daddy.on('DOMNodeInserted', function (e) { var $thisTarget = $(e.target); if (!$thisTarget.hasClass(childrenClass) && !$thisTarget.hasClass(holderClass)) { $thisTarget.addClass(childrenClass); } }); $(document).on('mouseup touchend', function () { dadEnd(); }); // ORDER ELEMENTS var order = 1; $target.addClass(childrenClass).each(function () { if ($(this).data('dad-id') == undefined) { $(this).attr('data-dad-id', order); } $(this).attr('data-dad-position', order); order++; }); // CREATE REORDER FUNCTION function updatePosition(e) { var order = 1; e.find(jQclass).each(function () { $(this).attr('data-dad-position', order); order++; }); } // END EVENT function dadEnd() { if (mouse.target != false && mouse.clone != false) { if (callback != false) { callback(mouse.target); } var appear = mouse.target; var desappear = mouse.clone; var holder = mouse.placeholder; var bLeft = 0; var bTop = 0; // Maybe we will use this in the future //Math.floor(parseFloat($daddy.css('border-left-width'))); //Math.floor(parseFloat($daddy.css('border-top-width'))); if ($.contains($daddy[0], mouse.target[0])) { mouse.clone.animate({ top: mouse.target.offset().top - $daddy.offset().top - bTop, left: mouse.target.offset().left - $daddy.offset().left - bLeft, }, 300, function () { appear.css({ visibility: 'visible', }).removeClass('active'); desappear.remove(); }); } else { mouse.clone.fadeOut(300, function () { desappear.remove(); }); } holder.remove(); mouse.clone = false; mouse.placeholder = false; mouse.target = false; updatePosition($daddy); } $('html, body').removeClass('dad-noSelect'); } // UPDATE EVENT function dadUpdate(obj) { if (mouse.target !== false && mouse.clone !== false) { var $origin = $('<span style="display:none"></span>'); var $newplace = $('<span style="display:none"></span>'); if (obj.prevAll().hasClass('active')) { obj.after($newplace); } else { obj.before($newplace); } mouse.target.before($origin); $newplace.before(mouse.target); // UPDATE PLACEHOLDER mouse.placeholder.css({ top: mouse.target.offset().top - $daddy.offset().top, left: mouse.target.offset().left - $daddy.offset().left, width: mouse.target.outerWidth() - 10, height: mouse.target.outerHeight() - 10, }); $origin.remove(); $newplace.remove(); } } // GRABBING EVENT var jq = (options.draggable !== false) ? options.draggable : jQclass; $daddy.find(jq).addClass(dragClass); $daddy.on('mousedown touchstart', jq, function (e) { // For touchstart we must update "mouse" position if (e.type == 'touchstart') { mouse.updatePosition(e.originalEvent.touches[0]); } if (mouse.target == false && active == true && (e.which == 1 || e.type == 'touchstart')) { var $self = $(this); // GET TARGET if (options.draggable !== false) { mouse.target = $daddy.find(jQclass).has(this); } else { mouse.target = $self; } // ADD CLONE mouse.clone = mouse.target.clone(); mouse.target.css({ visibility: 'hidden' }).addClass('active'); mouse.clone.addClass(cloneClass); $daddy.append(mouse.clone); // ADD PLACEHOLDER var $placeholder = $('<div></div>'); mouse.placeholder = $placeholder; mouse.placeholder.addClass(holderClass); mouse.placeholder.css({ top: mouse.target.offset().top - $daddy.offset().top, left: mouse.target.offset().left - $daddy.offset().left, width: mouse.target.outerWidth() - 10, height: mouse.target.outerHeight() - 10, lineHeight: mouse.target.height() - 18 + 'px', textAlign: 'center', }).text(placeholder); $daddy.append(mouse.placeholder); // GET OFFSET FOR CLONE var bLeft = Math.floor(parseFloat($daddy.css('border-left-width'))); var bTop = Math.floor(parseFloat($daddy.css('border-top-width'))); var difx = mouse.x - mouse.target.offset().left + $daddy.offset().left + bLeft; var dify = mouse.y - mouse.target.offset().top + $daddy.offset().top + bTop; mouse.cloneoffset.x = difx; mouse.cloneoffset.y = dify; // REMOVE THE CHILDREN DAD CLASS AND SET THE POSITION ON SCREEN mouse.clone.removeClass(childrenClass).css({ position: 'absolute', top: mouse.y - mouse.cloneoffset.y, left: mouse.x - mouse.cloneoffset.x, }); // UNABLE THE TEXT SELECTION AND SET THE GRAB CURSOR $('html,body').addClass('dad-noSelect'); } }); $daddy.on('mouseenter touchenter', jQclass, function () { dadUpdate($(this)); }); }); return this; }; })(jQuery); </script> <script type="text/javascript"> $(function () { //dad simple demo $('.dad').dad(); }); </script> </body> </html>