我有一个包含两列无序列表的页面。点击一个之后,它会放大,所以它只有一列,并且行上有一个空格,所以我想在它之前移动下一个li,所以不会有那个空格。
图片显示点击之前的div(它们不是空的,我只是为了这个目的删除了内容),点击带有li索引1的div后它如何变化以及我想如何将li与索引1和2。
我找到了一些解决方案,但没有任何对我有用。我最终得到了:
function swap(n) {
var l = n.ancestor("li.msg-box-wrapper");
var m = n.ancestor("#doubleColumnList").all("li.msg-box-wrapper");
var k = m.indexOf(n.ancestor("li.msg-box-wrapper"));
if ((k%2 != 0)) {
$(l).before( $(l).next() );
}
}
答案 0 :(得分:12)
让这个工作起作用的技巧是,意识到活动元素的新位置应该是“first-in-line”从它的当前位置开始。
要查找第一行的元素,只需查找以下元素:
candidate.offset().left < candidate.prev().offset().left
)以下内容将起作用:
(点击)记下当前位置,
取消激活时,只需将每个活动元素移回原位即可。
为了易于使用,我将原来的答案重写为jquery插件。由于我找不到一个好名字,它目前被称为foobar
。
<强>使用强>:
// '.wrapper' is the element containing the *toggle-able* elements.
$('.wrapper').foobar({
// the element-selector
elements: 'li',
// the toggle-selector (if a *deeper* element should be used to toggle state)
triggerOn: '.toggle',
// indicates an active element
activeClass: 'active',
// get's called on activation [optional]
onActivate: function ($el) {
console.log('activating', $el);
},
// get's called on de-activation [optional]
onDeactivate: function ($el) {
console.log('de-activating', $el);
}
});
插件:
(function ($, pluginName) {
'use strict';
/**
* Plugin behavior
*/
$.fn[pluginName] = function (options) {
var settings = $.extend(true, {}, $.fn[pluginName].defaults, options);
// triggerOn-selector is required
if (null === settings.triggerOn) {
throw 'the `triggerOn` must be set.';
}
// without an element-selector
if (null === settings.elements) {
// use triggerOn-selector as default
settings.elements = settings.triggerOn;
}
// apply behavior to each element in the selection
return this.each(function() {
var
$wrapper = $(this),
$elements = $wrapper.find(settings.elements)
;
$wrapper.on(settings.event, settings.triggerOn, function () {
var
$el = $(this).closest(options.elements),
isActive = $el.hasClass(settings.activeClass)
;
reset($elements, settings.activeClass, settings.onDeactivate);
if (!isActive) {
activate($el, $elements, settings.activeClass, settings.onActivate);
}
});
});
};
/**
* Plugin defaults
*/
$.fn[pluginName].defaults = {
// required
triggerOn: null,
// defaults
elements: null,
event: 'click',
activeClass: 'active',
onActivate: function () {},
onDeactivate: function () {}
};
/**
* Reset all currently active elements
*
* @param {jQuery} $elements
* @param {String} activeIndicator
* @param {Function} onDeactivate
*/
function reset($elements, activeIndicator, onDeactivate)
{
$elements
.filter(function () {
return $(this).hasClass(activeIndicator);
})
.each(function () {
deactivate($(this), $elements, activeIndicator, onDeactivate);
})
;
}
/**
* Deactivate the given element by moving it back to it's original position and removing the active-indicator.
*
* @param {jQuery} $el
* @param {jQuery} $elements
* @param {String} activeIndicator
* @param {Function} onDeactivate
*/
function deactivate($el, $elements, activeIndicator, onDeactivate)
{
var originalIndex = $el.index();
$el.removeClass(activeIndicator).insertBefore(
$elements.eq(originalIndex)
);
onDeactivate($el);
}
/**
* Activate the given element by moving it to a suitable position while applying the required indicator.
*
* @param {jQuery} $el
* @param {jQuery} $elements
* @param {String} activeIndicator
* @param {Function} onActivate
*/
function activate($el, $elements, activeIndicator, onActivate)
{
$el
.insertAfter(
$elements.eq(findSuitablePosition($elements, $el.index()))
)
.addClass(activeIndicator)
;
onActivate($el);
}
/**
* @param {jQuery} $elements
* @param {Number} originalIndex
*/
function findSuitablePosition($elements, originalIndex)
{
// short-circuit simple case
if (0 === originalIndex) {
return originalIndex;
}
var
candidateIndex = originalIndex,
lim = $elements.length,
$candidate
;
for (; candidateIndex < lim; candidateIndex += 1) {
$candidate = $elements.eq(candidateIndex);
if ($candidate.offset().left < $candidate.prev().offset().left) {
return candidateIndex;
}
}
throw 'could not find a suitable position.';
}
})(jQuery, 'foobar');
演示:http://plnkr.co/edit/8ARXgq2pLSzm9aqHI8HL?p=preview
原始回答:
如果您愿意使用jQuery,以下内容将会起作用。
它比需要的要复杂一点,但这种方式也适用于两列以上。请注意代码样式是可以轻松遵循的。
$('.wrapper').each(function () {
var $wrapper = $(this);
$wrapper.on('click', 'li', function () {
var
$el = $(this),
isOpen = $el.is('.open')
;
reset();
if (!isOpen) {
open($el);
}
});
function open($el)
{
var originalIndex = $el.index();
// note index and move to suitable position
$el
.data('original-index', originalIndex)
.insertAfter(
$wrapper.find('li').eq(findSuitablePosition(originalIndex))
)
.addClass('open')
;
}
function reset()
{
$wrapper.find('.open').each(function () {
var
$el = $(this),
originalIndex = $el.data('original-index')
;
$el.removeClass('open').insertBefore(
$wrapper.find('li').eq(originalIndex)
);
});
}
function findSuitablePosition(originalIndex)
{
// short-circuit simple case
if (0 === originalIndex) {
return originalIndex;
}
var
$candidates = $wrapper.find('li'),
candidateIndex = originalIndex,
lim = $candidates.length,
candidate
;
for (; candidateIndex < lim; candidateIndex += 1) {
candidate = $candidates.eq(candidateIndex);
if (candidate.offset().left < candidate.prev().offset().left) {
return candidateIndex;
}
}
throw 'could not find a suitable position.';
}
});
ul {
list-style: none;
margin: 0;
padding: 5px 10px;
width: 300px;
border: 1px solid #ccc;
overflow: hidden;
font-family: sans-serif;
margin-bottom: 5px;
}
li {
float: left;
margin: 10px 5px;
padding: 3px;
border: 1px solid #ccc;
box-sizing: border-box;
}
ul li.open {
width: calc(100% - 10px);
height: 40px;
border-color: green;
}
.two li {
width: calc(50% - 10px);
}
.three li {
width: calc(33% - 10px);
}
.four li {
width: calc(25% - 10px);
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<ul class="wrapper two">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<ul class="wrapper three">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
<ul class="wrapper four">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</ul>
答案 1 :(得分:3)
如果你想要一个不使用jQuery的答案,这就是一个这样的解决方案:
var list = document.getElementById('list');
var listItems = list.children;
function select(e) {
// Remove the selected class from the previously selected list item
var selectedEl = document.querySelector('.selected');
if (selectedEl) {
selectedEl.classList.remove('selected');
}
// Add the selected class to the current list item
var targetEl = e.target;
targetEl.classList.add('selected');
// Find the current li's position in the node list
var targetPosition = Array.prototype.indexOf.call(listItems, targetEl);
// If it is in an odd position, and there is a sibling after it
// move that sibling before it
if (targetPosition % 2 > 0 && targetEl.nextElementSibling) {
list.insertBefore(targetEl.nextElementSibling, targetEl);
}
}
// Add click listeners
for(var i = 0, len = listItems.length; i < len; i++) {
listItems[i].addEventListener('click', select);
}
&#13;
ul {
position: relative;
width: 400px;
}
li {
text-align: center;
float: left;
display: block;
height: 20px;
width: 190px;
margin: 5px;
background: red;
}
.selected {
width: 390px;
}
&#13;
<ul id="list">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
&#13;
解决方案的关键是使用单击的列表项作为参考节点调用Node.insertBefore。
答案 2 :(得分:0)
您可以使用jquery轻松完成此操作。
我为你制作了一个JSFiddle here
这个想法是定义类,一个用于小型,一个用于大型矩形。比onclick的一个小,设置所有小和点击大。 如果有必要,请重新排序列表。
HTML
<ul class="container">
<li class="small item">1</div>
<li class="small item">2</div>
<li class="small item">3</div>
<li class="small item">4</div>
<li class="small item">5</div>
<li class="small item">6</div>
</ul>
CSS
.container{
width: 130px;
list-style-type: none;
}
.small{
margin: 5px;
width: 50px;
height: 20px;
background-color: red;
float: left;
}
.big{
margin: 5px;
width: 110px;
height: 60px;
background-color: red;
float: left;
}
Jquery的:
$(function(){
//ON LI CLICKED
$(".small").click(function() {
//LI REMOVE BIG ONE
$( ".item" ).removeClass( "big" ).addClass( "small" );
//ADD BIG CLASS
$(this).removeClass( "small" ).addClass( "big" );
//IF NECESSARY THAN REORDER
if($( "li" ).index( $(this) )%2==1){
alert("reorder");
//CHANGE INDEX OF LI
$(this).siblings().eq(1).after(this);
}
});
});
答案 3 :(得分:0)
你可以检查被点击的元素是否在奇数位置,然后在它之前插入下一个元素。检查一下 -
$('.box').on('click', function() {
if($(this).index()%2 != 0) {
$(this).next().insertBefore($(this));
}
$('.box').removeClass('fullwidth');
$(this).addClass('fullwidth');
});
更新: 添加了sorter()
功能,对原始位置的所有div
进行排序。
$('.box').each(function(i) {
$(this).attr('i', i);
});
function sorter() {
for(var x=0; x<$('.box').length; x++) {
$('.box').each(function() {
if($(this).attr('i') > $(this).next().attr('i')) {
$(this).insertAfter($(this).next());
}
});
}
}
在点击.box
时首先调用它。