Перемещение элементов в районе одного дива.
Всем привет!
<div id="intro"> <div id="one" style="background:url(images/nemo.jpg )" title="1"><h1>HELLO ONE </h1></div> <div id="two" style="background:url(images/walle.jpg )"title="2"><h1>HELLO ONE </h1></div> <div id="three" style="background:url(images/nemo.jpg )"title="3"><h1>HELLO ONE </h1></div> </div> Как видите есть div с вложенными дивами, и у меня есть необходимость в перемещении их по порядку. Например нужна такая комбинация <div id="intro"> <div id="one" style="background:url(images/nemo.jpg )" title="1"><h1>HELLO ONE </h1></div> <div id="three" style="background:url(images/nemo.jpg )"title="3"><h1>HELLO ONE </h1></div> <div id="two" style="background:url(images/walle.jpg )"title="2"><h1>HELLO ONE </h1></div> </div> То есть второй и третий поменялись местами. Что я предпринял: // Получаем перечень вложенных дивов var div = document.getElementById('intro') var elems = div.getElementsByTagName('div') // Изменяется расположенеи дивов внутри главного дива. var first = elems[0].id; $(first).prependTo( '#intro' ); Предположил что ошибка в коде (смесь jquery & javascript) , предпринял попытку которая точно не имеет ошибок $('#one).prependTo( '#intro' )? аналогично. Я думал насчет удаление и вставки , но хотелось бы более элегантное что то и менее трафикопоглащающее. Если коротко то я хочу чтобы: а б в >> б а в >> в а б >> и т.д. Есть еще вариант с четвертым дивом, в который все будет копировать, но все равно остается вопрос над перемещением, а именно вставкой между существующих div . Благодарен за помощь. |
$('div#intro #three').prependTo( 'div#intro #two' ); |
Цитата:
a b c >> c b a а вот для такого варианта a b c >> b c a и c a b И желательно без дополнительных блоков! И ВОТ ЕЩЕ БЕДА КАКАЯ , после $('div#intro #three').prependTo( 'div#intro #two' ); визуально блоки меняют место , но не меняют расположения в html разметке. Об этом мне говорит var div = document.getElementById('intro') var elems = div.getElementsByTagName('div') |
Если я правильно всосал проблему
То для установки одного обьекта относительно другого, лучше использовать after - для установки после и before - для установки перед <div id="intro"> <div id="one" style="background:url(images/nemo.jpg )" title="1"><h1>HELLO 1 </h1></div> <div id="two" style="background:url(images/nemo.jpg )"title="3"><h1>HELLO 2 </h1></div> <div id="three" style="background:url(images/walle.jpg )"title="2"><h1>HELLO 3 </h1></div> </div> <script src="http://yandex.st/jquery/1.6.3/jquery.min.js"></script> <script> $("#three").after($("#one")); // ставим one после three 1 2 3 -> 3 1 2 $("#three").after($("#two")); // ставим two после three 3 1 2 -> 3 2 1 </script> |
Продолжая кумекать, сваял функцию рокировки любых 2х элементов.
В качестве параметров получает два селектора. И меняет эти два обьекта местами. Алгоритм прост как валенок. 1) Клонируем id2 2) вставляем клона после id1 3) заменяем оригинал id2 элементом id1. Готово ! )) события повешанный на элементы должны остаться привязанными как и были, тобиш непотеряются несмотря на перестановку. <div id="intro"> <div id="one" style="background:url(images/nemo.jpg )" title="1"><h1>HELLO 1 </h1></div> <div id="two" style="background:url(images/nemo.jpg )"title="3"><h1>HELLO 2 </h1></div> <div id="three" style="background:url(images/walle.jpg )"title="2"><h1>HELLO 3 </h1></div> </div> <script src="http://yandex.st/jquery/1.6.3/jquery.min.js"></script> <script> function rokir(id1,id2){ id1=$(id1); id2=$(id2); id2.after(id1.clone(true)); id1.replaceWith(id2); } rokir("#three","#one"); // 1 2 3 -> 3 2 1 меняем 3 и 1 rokir("#two","#one"); // 3 2 1 -> 3 1 2 меняем 2 и 1 </script> Единственное назначение clone здесь, это сохранить местоположение за id2 чтобы знать куда переместить id1. Возможно реализовать её и без clone, можно запомнить позицию за счёт соседних элементов, но алгоритм будет и сложнее и почти наверняка медленнее. upd: За счёт соседей не круто. Круто за счёт порядковой позиции в родителе узнать позицию index(селектор), получить элемент по номеру get(N). Но особого смысла всё равно не вижу. |
Хотел бы узнать, а зачем вам такое надо, просто из любопытсва
|
Обьясняю зачем это нужно.
Это слайдер и столкнулся с ситуацией что существующий не совсем мне подходят (грубо говоря там используется масса не нужного для работы ,а может я не способен разобраться с написанным и т.д. , да и свое ближе) и мне захотелось чтобы дойдя до показа последнего элемента из списка , то есть дива 3 , я не прокручивал все до первого дива , а перемещал див 1 за див 3. И соответственно наоборот если прокрутка идет в противоположную сторону. ЕСЛИ вЫ ТАКОЙ уже встречали. то все равно сог |
Немного поразмыслив с ответом DjDiablo , пришел к выводу что это не совсем то что мне надо, элементы перемещаются как нужно, но сразу происходит прыжок изображений в виду использования float для всех дивов.
Так что пришел к выводу что лучше сделать длинную ленту из всех блоков и уже когда вдруго слайдер подойдет к последнему блоку, перекинуть опять в центр ленты. Думаю будет незаметно. Хотя нет, лучше обнулять смещение влево.!!! |
Интересная задача.
Но я не уверен что её можно решить только одними манипуляциями с DOM. Выглядеть наверняка будет криво. Возможно более разумно следить за координатами самостоятельно. То есть управлять слайдами при помощи координат а не средствами html вёрстки вроде позиционирования относительно левого элемента. В этом случае мы прокручиваем не родителя слайдов а перемещать сами слайды. При этом если слайд выходит за какие то границы в меньшую сторону перебрасываем его в конец, если наоборот то в начало. Так как мы некрутим родителя, нет риска что он закончится, и его ненадо никуда перематывать. // вот крайне грубый набросок, чтобы было яснее о чём я говорю. var slides[ ]; // массив со слайдами // x-координата по X // link=$(слайд) //slidewidth -ширина слайда //slideBreak - расстояние между слайдами // инициализация плагина function init(cont){ // здесь мы перебираем в цикле содержимое cont и заполняем массив slides // все слайды являются дочерними элементами, Div Conteiner var i=0 cont.find(">div").each(function(){ slides[i]={}; slides[i].link=this; // предварительно расставляем слайды в контейнере slides[i].x= i*(slideWidth+slideBreak); // другие полезные действия //увеличиваем счётчик. i=i+1; }) // вычисляем константы. //ширина контейнера слайдов = (Ширина слайда+расстояние между слайдами) * кол-во слайдов conteiner.hight= (slidewidth+slidebreak)*slides.length; // ширина контейнера слайдов //позиционирование контейнера в view = (ширина контейнера - ширина ВИДИМОЙ ОБЛАСТИ)/2 conteiner.pos= (conteiner.width-view.width)/2; //позиционируем контейнер внутри view. // через метод css надо полагать. } //s-Насколько нужно сместить слайдеры. function render(s){ // перебор слайдов. // c целью добавления к координатам смещения и и перемещения элементов dom по новым координатам. For(i=0;i<slides.length;i++){ slides[i].x+=s; //прибавляем смещение. //вышли за контейнер справа. перекидываем слайд влево. ( с поправкой на вылет за предел) if (slides[i].x)>conteiner.width) slider[i].x=slides[i].x-conteiner.width; //вышли за экран. слева перекидываем слайд вправо. ( с поправкой на вылет за предел) if (slides[i].x)<0) slider[i].x=conteiner.width+slides[i].x; slides[i].link.css("left",slides[i].x); //устанавливаем координаты } } } Если визуальная область просмотра меньше ширины всех слайдов. То conteiner, может быть дочерним элементом ,элемента view который наделён свойством hidden. Допустим область просмотра (view) по ширине всего 500px, а conteiner со слайдами занимает 1500. Значит conteiner Внутри view надо отпозиционировать в -500 px. Чтобы в видимую зону (view) попала центральная часть. Так как всё содержимое вращается по кругу, то оно неприменно попадёт в зону видимости. Всё что я здесь написал это скорее псевдокод, чтобы направить мысли в русло )) |
Мне кажется что у меня решение немного проще.
Делаю длинный div с слайдами (slider-intro) . Он обернут другим дивом с overflow:hidden (slider). И еще пару кнопочек есть , но это пустяк. И кликая по кнопке лево\право слайды меняются местами. Осталась вот какая проблема. Если скажем клацать "тихо-мирно", то все работает ок, но если начать клацать как бешеный , то не милисекунды видно , то что не нужно видеть. То есть нужна проверка , перемещаются сечас слайды или нет, а потом запускать анимацию, короче говоря анимация не должна запускаться по идет смена слайдов и хотелось бы без присваивания иддентификатора , то есть без переменных . а более правильно. Живой пример тут>> http://duvanov.net/slider.html Привожу ниже код слайдера. #slider { width:600px; height:300px; overflow:hidden; margin:0; padding:0; margin-top:100px; left:100px; } #slider-intro { width:1800px; /* БЕРЕТСЯ КАК СУММА ВСЕ ПОЛЕЙ*/ height:300px; background:#DDD; float:left; padding:0; left:-600px; } div { position:relative; float:left; width:600px; height:300px; background:#06F; } <body> <div id="slider"> <div id="slider-intro"> <div id="one" style="background:url(images/nemo.jpg )" title="1"><h1> ONE </h1></div> <div id="two" style="background:url(images/walle.jpg )"title="2"><h1> two </h1></div> <div id="three" style="background:url(images/nemo.jpg )"title="3"><h1>THREE </h1></div> </div> </div> <button id="left">«</button> <button id="right">»</button> </body> $(document).ready(function() { $("#right").click(function(){ $("#slider-intro").animate({"left": "+=600px"}, "slow", function() { permutation('lefor'); }); }); $("#left").click(function(){ $("#slider-intro").animate({"left": "-=600px"}, "slow", function() { permutation('left'); }); }); function permutation(trend) { // Получаем перечень вложенных дивов var div = document.getElementById('slider-intro'); var elems = div.getElementsByTagName('div'); // Изменяется расположенеи дивов внутри главного дива. var first = elems[0].id; var name = '#'+first; var middle = elems[1].id; var name1 = '#'+middle; var last = elems[2].id; var name2 = '#'+last; $("#slider-intro").css('left','-600px'); if(trend=="left") { $(name2).after($(name)); }else { $(name).after($(name2)); // А вот как это не делать 2 раза? $(name2).after($(name)); } } }); |
Часовой пояс GMT +3, время: 11:14. |