我有一个页面与无序的列表在两列.当我点击一个,它放大,所以只有一列,它有一个空格,所以我想要移动下一个李,所以不会有这样的空间.
图片点击之前显示div(它们不是空的,我刚刚删除了这个目的的内容),点击div与li index 1之后怎么改变,以及我如何用索引1和2交换li.
我找到一些解决方案,但没有什么对我有用.我结束了:
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() ); } }
解决方法
实现这一工作的诀窍在意识到,活跃元素的新位置应该是从现在的位置开始的“先行者”.
要找到一个第一行的元素,只需要查找一个元素:
>第一个孩子,或
>具有比之前的兄弟姐妹更小的左偏移(至少在ltr上下文中). (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.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),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,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,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>