JQuery可sorting列表和固定/locking项目

是否有可能lockingJQuery可sorting列表中的列表项目,这些项目将保留在列表中的特定位置。

例如,

考虑这个伪项目与locking项目…

item A item B(locked) item C(locked) item D item E item F item G(locked) 

所以,我想要固定项目B,C和G,如果用户在项目开始时拖放项目D,项目A“跳过”固定/locking项目B和C以下结果…

 item D item B(locked) item C(locked) item A item E item F item G(locked) 

我一直在寻找这样的东西没有运气。 可能吗..?

我扩展了jQuery.Ui.sortable

概观

具有fixedfunction的jQuery.Ui.sortable小部件扩展。 该function允许用户修复列表中的元素。
使用.fixedsortable()构造函数,可以构造一个扩展了特性的.sortable()类。 您可以使用原始方法和扩展

https://gist.github.com/3758329#file_fixedsortable.js > fixedsortable.js

http://jsfiddle.net/omnosis/jQkdb/

用法

一般:

要使用,请将fixed属性添加到可sorting列表的系数:

 $("#list").fixedsortable({ fixed: (value) }) 

值可以是:

  • 整数例子: 3
  • 整数数组示例: [1,2,5]
  • 一个html元素或一个html元素列表
  • 一个CSSselect器
  • jquery对象

HTML:

 <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> //the jquery <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script> //the original jquery-ui <script type="text/javascript" src="https://raw.github.com/gist/3758329/91749ff63cbc5056264389588a8ab64238484d74/fixedsortable.js"></script> //the extended sortable ... <ul id="sortable1"> <li>oranges</li> <li class="static">apples</li> <li>bananas</li> <li>pineapples</li> <li>grapes</li> <li class="static">pears</li> <li>mango</li> </ul> <ul id="sortable2"> <li>bananas</li> <li foo="asd">oranges</li> <li foo="dsa">apples</li> <li>pineapples</li> <li>grapes</li> <li>pears</li> <li>mango</li> </ul> <ul id="sortable3"> <li>bananas</li> <li>oranges</li> <li>apples</li> <li>pineapples</li> <li>grapes</li> <li>pears</li> <li>mango</li> </ul> 

使用Javascript

 $(function() { $("#sortable1").fixedsortable({ fixed: "> .static" }); $("#sortable2").fixedsortable({ fixed: $("li[foo]").css("background","red") }); $("#sortable3").fixedsortable({ fixed: 2 }) }); 

笔记:

如果你坚持使用.sortable而不是.fixedsortable你可以使用这个https://gist.github.com/3758329#file_sortable.js而不是jquery.ui库。; 这是jQuery.ui的完整替代,但我不build议使用这个,因为以后的更新。

我一直在这个超过12小时:(我疯了..

这是一个有希望的无错版本,在您拖动时更新。 当开始sorting时,它会生成当前所需的项目位置,这意味着您应该能够随时更改类,刷新小部件的列表项并且您可以轻松完成。

它还使用可sorting的内置items属性来防止拖动固定项目,并排除列表顶部和底部的任何sorting问题。

我试图移动固定的项目,但是这导致了可怕的错误行为,尤其是当组中有多个固定项目时。 最后的解决scheme从列表中分离所有固定项目,向前端添加一个辅助元素,然后将固定元素重新插入到他们想要的位置,这似乎修复了所有的错误。

试试这里的演示: http : //jsfiddle.net/PQrqS/1/

HTML:

 <ul id="sortable"> <li>oranges</li> <li class="static">apples</li> <li>bananas</li> <li>pineapples</li> <li>grapes</li> <li class="static">pears</li> <li>mango</li> </ul> 

CSS:

 .static { color:red; } li { background-color:whitesmoke; border:1px solid silver; width:100px; padding:2px; margin:2px; } 

使用Javascript:

 $('#sortable').sortable({ items: ':not(.static)', start: function(){ $('.static', this).each(function(){ var $this = $(this); $this.data('pos', $this.index()); }); }, change: function(){ $sortable = $(this); $statics = $('.static', this).detach(); $helper = $('<li></li>').prependTo(this); $statics.each(function(){ var $this = $(this); var target = $this.data('pos'); $this.insertAfter($('li', $sortable).eq(target)); }); $helper.remove(); } }); 

检查一下: 强制一个项目保留在一个jQuery UI可sorting列表中

另外,我已经在这里使用了多个固定元素来实现上述解决scheme: http : //jsfiddle.net/enBnH/12/ (过时,请参阅下文)我认为这是相当自明的。

编辑:

我已经自动生成lockto值的过程,并将ID添加到类为“fixed”的类(请注意,我必须添加一个ID以便我们可以引用它)

请参阅完整的解决scheme这里: http : //jsfiddle.net/enBnH/44/

编辑

好吧,经过上面的一个巨大的错误,我刚刚重写了dang的东西: http : //jsfiddle.net/thomas4g/GPMZZ/15/

注意:上面的工作,但@ DarthJDG的答案似乎对我来说好多了。 我会把我的事情放在一边,有人可能更喜欢我的行为(我学会了不删除的东西,只是因为有一个更好的版本:P)

使用items参数可以达到你想要的效果:

 $("#mytable tbody").sortable({items: 'tr.sortable'}); 

现在只有具有.sortable CSS类的行才能被sorting。

如果你只想locking第一行,你可以这样做:

 $("#mytable tbody").sortable({items: 'tr:not(:first)'}); 

可能性是无止境的…

这是基于@DarthJDG代码。 然而,它没有检索所有的ID和sorting不工作与表。 所以我设法更新他的解决scheme与列表和表都工作,并保持ID在数组中。

使用Javascript:

 var fixed = '.static'; //class which will be locked var items = 'li'; //tags that will be sorted $('ul').sortable({ cancel: fixed, items: items, start: function () { $(fixed, this).each(function () { var $this = $(this); $this.data('pos', $this.index()); }); }, change: function () { var $sortable = $(this); var $statics = $(fixed, this).detach(); var tagName = $statics.prop('tagName'); var $helper = $('<'+tagName+'/>').prependTo(this); $statics.each(function () { var $this = $(this); var target = $this.data('pos'); $this.insertAfter($(items, $sortable).eq(target)); }); $helper.remove(); } }); 

演示: http : //plnkr.co/edit/hMeIiRFT97e9FGk7hmbs

不好了! 主要链接被破坏。 这里是来自https://gist.github.com/peterh-capella/4234752的代码转储;

代码访问2016年1月6日

 //this code is created to fix this problem: http://stackoverflow.com/questions/4299241/ (function( $, undefined ) { $.widget("ui.fixedsortable", $.ui.sortable, { options: $.extend({},$.ui.sortable.prototype.options,{fixed:[]}), _create: function() { var o = this.options; this.containerCache = {}; this.element.addClass("ui-sortable"); //Get the items $.ui.sortable.prototype.refresh.apply(this,arguments); if( typeof this.options.fixed == "number") { var num = this.options.fixed this.options.fixed = [num]; } else if( typeof this.options.fixed == "string" || typeof this.options.fixed == "object") { if(this.options.fixed.constructor != Array) { var selec = this.options.fixed; var temparr = []; var temp = $(this.element[0]).find(selec); var x = this; temp.each(function() { var i; for(i=0;i<x.items.length && x.items[i].item.get(0) != this;++i) {} if(i<x.items.length) temparr.push(i); }); this.options.fixed = temparr; } } //Let's determine if the items are being displayed horizontally this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; //Let's determine the parent's offset this.offset = this.element.offset(); //Initialize mouse events for interaction $.ui.sortable.prototype._mouseInit.apply(this,arguments); }, _mouseCapture: function( event ) { this._fixPrev = this._returnItems(); return $.ui.sortable.prototype._mouseCapture.apply(this,arguments); }, _mouseStart: function( event ) { for(var i=0;i<this.options.fixed.length;++i) { var num = this.options.fixed[i]; var elem = this.items[num]; if(event.target == elem.item.get(0)) return false; } return $.ui.sortable.prototype._mouseStart.apply(this,arguments); }, _rearrange: function(event, i, a, hardRefresh) { a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); this._refix(i); //Various things done here to improve the performance: // 1. we create a setTimeout, that calls refreshPositions // 2. on the instance, we have a counter variable, that get's higher after every append // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same // 4. this lets only the last addition to the timeout stack through this.counter = this.counter ? ++this.counter : 1; var self = this, counter = this.counter; window.setTimeout(function() { if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove },0); }, _refix: function(a) { var prev = this._fixPrev; var curr = this._returnItems(); var Fixcodes = this.options.fixed; var NoFixed = []; var Fixed = []; var Mixed = [] var post = []; for(var i=0;i<Fixcodes.length;++i) { var fix_index = Fixcodes[i]; var fix_item = prev[fix_index]; var j = 0; for(j=0;j<curr.length && curr[j].item.get(0) != fix_item.item.get(0);++j) {} curr.splice(j,1); Fixed.push(fix_item); } for(var i=0;i<curr.length;++i) { if(curr[i].item.get(0) != this.currentItem.get(0)) { NoFixed.push(curr[i]); } } var fix_count = 0; var nofix_count = 0; for(var i=0;i<Fixed.length + NoFixed.length;++i) { if(Fixcodes.indexOf(i) >= 0) { Mixed.push(Fixed[fix_count++]); } else { Mixed.push(NoFixed[nofix_count++]); } } var parent = this.currentItem.get(0).parentNode; var allchild = parent.children; for(var i=0;i<Mixed.length;++i) { parent.removeChild(Mixed[i].item.get(0)); parent.appendChild(Mixed[i].item.get(0)); } }, _returnItems: function(event) { this.containers = [this]; var items = []; var self = this; var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; var connectWith = $.ui.sortable.prototype._connectWith.apply; if(connectWith) { for (var i = connectWith.length - 1; i >= 0; i--){ var cur = $(connectWith[i]); for (var j = cur.length - 1; j >= 0; j--){ var inst = $.data(cur[j], 'sortable'); if(inst && inst != this && !inst.options.disabled) { queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); this.containers.push(inst); } }; }; } for (var i = queries.length - 1; i >= 0; i--) { var targetData = queries[i][1]; var _queries = queries[i][0]; for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { var item = $(_queries[j]); item.data('sortable-item', targetData); // Data for target checking (mouse manager) items.push({ item: item, instance: targetData, width: 0, height: 0, left: 0, top: 0 }); }; }; return items; }, value: function(input) { //console.log("test"); $.ui.sortable.prototype.value.apply(this,arguments); } }); })(jQuery); 

为了以防万一,他的答案被遗弃了

依赖

https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min .js文件

脚本

 function randomColor() { //for a little fun ;) var r = (Math.floor(Math.random()*256)); var g = (Math.floor(Math.random()*256)); var b = (Math.floor(Math.random()*256)); return "#" + r.toString(16) + g.toString(16) + b.toString(16) } $(function() { $("#sortable1").fixedsortable({ fixed: "> .static", //you can use css selector sort: function() { //you can add events as well, without getting confused. for example: $(".static").css("background",randomColor()) //change the fixed items background }, change: function(event,ui) { $(ui.item[0]).css("border","2px solid "+randomColor()) //change the captured border color }, stop: function(event,ui) { $(ui.item[0]).css("border","2px solid #777"); //change the back the css modifications $("#sortable1 > li.static").css("background","#aaa"); } }); $("#sortable2").fixedsortable({ //you can use jQuery object as selector fixed: $("li[foo]").css("background","red") }); $("#sortable3").fixedsortable({ fixed: [2,4], //you can use array of zero base indexes as selector update: function(event, ui) { alert($(this).fixedsortable('toArray')) //the fixedsortable('toArray') also works } }) $("#sortable4").fixedsortable({ fixed: 5 //you can fix a single item with a simple integer }) }); 

HTML

  <body> <div style="width:120px;float:left;"> <ul id="sortable1"> <li><a href="#">oranges</a></li> <li class="static"><a href="#">apples</a></li> <li><a href="#">bananas</a></li> <li><a href="#">pineapples</a></li> <li><a href="#">grapes</a></li> <li class="static"><a href="#">pears</a></li> <li><a href="#">mango</a></li> </ul> <ul id="sortable2"> <li>bananas</li> <li foo="asd">oranges</li> <li foo="dsa">apples</li> <li>pineapples</li> <li>grapes</li> <li>pears</li> <li>mango</li> </ul> </div> <div style="width:120px;float:left;"> <ul id="sortable3"> <li id="fru_1">bananas</li> <li id="fru_2">oranges</li> <li id="fru_3" style="background:#f4f">apples</li> <li id="fru_4">pineapples</li> <li id="fru_5" style="background:#faaba9">grapes</li> <li id="fru_6">pears</li> <li id="fru_7">mango</li> </ul> <ul id="sortable4"> <li>bananas</li> <li>oranges</li> <li>apples</li> <li>pineapples</li> <li>grapes</li> <li style="background:#dada00">pears</li> <li>mango</li> </ul> </div> </body> 

CSS

 ul {margin:10px;} ul#sortable1 > li, ul#sortable2 > li, ul#sortable3 > li, ul#sortable4 > li { display:block; width:100px; height:15px; padding: 3px; background: #aaa; border: 2px solid #777; margin: 1px; } ul#sortable1 > li.static { opacity:0.5; } 

也许这将有助于某人:使用方法“禁用”和“启用”。 HTML示例:

 <ul class="sortable"> <li>You can move me</li> <li data-state="lifeless">You can't move me.</li> </ul> 

脚本:

 $('#sortable').sortable(); $('#sortable').mousedown(function() { if($(this).data('state')=='lifeless') $('#sortable').sortable('disable'); else $('#sortable').sortable('enable'); }); 

现场示例: https : //jsfiddle.net/ozsvar/0ggqtva5/2/