要让它起作用的诀窍是意识到活动元素的新位置应该是其当前位置的“第一行”。
要查找第一行的元素,只需查找以下元素之一:
- 第一个子元素;
- 具有左偏移小于其前一个兄弟(至少在从左到右的语境中)。(`candidate.offset().left < candidate.prev().offset().left`)
因此,以下内容将起作用:
- 在激活(点击)时,记录当前位置,并查找下一个“第一行”的元素(包括单击的元素)。
- 交换这两个元素。
- 在取消激活时,将每个活动元素移回其原始位置。
为了方便使用,我已将原始答案重写为 jQuery 插件。由于我找不到一个好名字,它目前被称为 `foobar`。
用法:
$('.wrapper').foobar({
elements: 'li',
triggerOn: '.toggle',
activeClass: 'active',
onActivate: function ($el) {
console.log('activating', $el);
},
onDeactivate: function ($el) {
console.log('de-activating', $el);
}
});
插件:
(function ($, pluginName) {
'use strict';
$.fn[pluginName] = function (options) {
var settings = $.extend(true, {}, $.fn[pluginName].defaults, options);
if (null === settings.triggerOn) {
throw 'the `triggerOn` must be set.';
}
if (null === settings.elements) {
settings.elements = settings.triggerOn;
}
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);
}
});
});
};
$.fn[pluginName].defaults = {
triggerOn: null,
elements: null,
event: 'click',
activeClass: 'active',
onActivate: function () {},
onDeactivate: function () {}
};
function reset($elements, activeIndicator, onDeactivate)
{
$elements
.filter(function () {
return $(this).hasClass(activeIndicator);
})
.each(function () {
deactivate($(this), $elements, activeIndicator, onDeactivate);
})
;
}
function deactivate($el, $elements, activeIndicator, onDeactivate)
{
var originalIndex = $el.index();
$el.removeClass(activeIndicator).insertBefore(
$elements.eq(originalIndex)
);
onDeactivate($el);
}
function activate($el, $elements, activeIndicator, onActivate)
{
$el
.insertAfter(
$elements.eq(findSuitablePosition($elements, $el.index()))
)
.addClass(activeIndicator)
;
onActivate($el);
}
function findSuitablePosition($elements, originalIndex)
{
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');
以下内容是关于it技术的,如果您愿意使用jQuery,以下代码可以帮助您实现目标。虽然这种方法比较复杂,但是它适用于超过两列的情况。请注意,代码样式易于跟踪。此外,以下是演示链接:
http://plnkr.co/edit/8ARXgq2pLSzm9aqHI8HL?p=preview
$('.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();
$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)
{
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>