sortable.js
86 lines
| 1 | /* |
| 2 | * HTML5 Sortable jQuery Plugin |
| 3 | * http://farhadi.ir/projects/html5sortable |
| 4 | * |
| 5 | * Copyright 2012, Ali Farhadi |
| 6 | * Released under the MIT license. |
| 7 | */ |
| 8 | (function($) { |
| 9 | var dragging, placeholders = $(); |
| 10 | $.fn.sortable = function(options) { |
| 11 | var method = String(options); |
| 12 | options = $.extend({ |
| 13 | connectWith: false |
| 14 | }, options); |
| 15 | return this.each(function() { |
| 16 | if (/^(enable|disable|destroy)$/.test(method)) { |
| 17 | var items = $(this).children($(this).data('items')).attr('draggable', method == 'enable'); |
| 18 | if (method == 'destroy') { |
| 19 | items.add(this).removeData('connectWith items') |
| 20 | .off('dragstart.h5s dragend.h5s selectstart.h5s dragover.h5s dragenter.h5s drop.h5s'); |
| 21 | } |
| 22 | return; |
| 23 | } |
| 24 | var isHandle, index, items = $(this).children(options.items); |
| 25 | var placeholder = $('<' + (/^(ul|ol)$/i.test(this.tagName) ? 'li' : 'div') + ' class="sortable-placeholder">'); |
| 26 | items.find(options.handle).mousedown(function() { |
| 27 | isHandle = true; |
| 28 | }).mouseup(function() { |
| 29 | isHandle = false; |
| 30 | }); |
| 31 | $(this).data('items', options.items) |
| 32 | placeholders = placeholders.add(placeholder); |
| 33 | if (options.connectWith) { |
| 34 | $(options.connectWith).add(this).data('connectWith', options.connectWith); |
| 35 | } |
| 36 | items.attr('draggable', 'true').on('dragstart.h5s', function(e) { |
| 37 | if (options.handle && !isHandle) { |
| 38 | return false; |
| 39 | } |
| 40 | isHandle = false; |
| 41 | var dt = e.originalEvent.dataTransfer; |
| 42 | dt.effectAllowed = 'move'; |
| 43 | dt.setData('Text', 'dummy'); |
| 44 | index = (dragging = $(this)).addClass('sortable-dragging').index(); |
| 45 | }).on('dragend.h5s', function() { |
| 46 | if (!dragging) { |
| 47 | return; |
| 48 | } |
| 49 | dragging.removeClass('sortable-dragging').show(); |
| 50 | placeholders.detach(); |
| 51 | if (index != dragging.index()) { |
| 52 | dragging.parent().trigger('sortupdate', {item: dragging}); |
| 53 | } |
| 54 | dragging = null; |
| 55 | }).not('a[href], img').on('selectstart.h5s', function() { |
| 56 | this.dragDrop && this.dragDrop(); |
| 57 | return false; |
| 58 | }).end().add([this, placeholder]).on('dragover.h5s dragenter.h5s drop.h5s', function(e) { |
| 59 | if (!items.is(dragging) && options.connectWith !== $(dragging).parent().data('connectWith')) { |
| 60 | return true; |
| 61 | } |
| 62 | if (e.type == 'drop') { |
| 63 | e.stopPropagation(); |
| 64 | placeholders.filter(':visible').after(dragging); |
| 65 | dragging.trigger('dragend.h5s'); |
| 66 | return false; |
| 67 | } |
| 68 | e.preventDefault(); |
| 69 | e.originalEvent.dataTransfer.dropEffect = 'move'; |
| 70 | if (items.is(this)) { |
| 71 | if (options.forcePlaceholderSize) { |
| 72 | placeholder.height(dragging.outerHeight()); |
| 73 | } |
| 74 | dragging.hide(); |
| 75 | $(this)[placeholder.index() < $(this).index() ? 'after' : 'before'](placeholder); |
| 76 | placeholders.not(placeholder).detach(); |
| 77 | } else if (!placeholders.is(this) && !$(this).children(options.items).length) { |
| 78 | placeholders.detach(); |
| 79 | $(this).append(placeholder); |
| 80 | } |
| 81 | return false; |
| 82 | }); |
| 83 | }); |
| 84 | }; |
| 85 | })(jQuery); |
| 86 |