Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Перемещение элементов в районе одного дива. (https://javascript.ru/forum/jquery/21442-peremeshhenie-ehlementov-v-rajjone-odnogo-diva.html)

Duda.Ml1986@gmail.com 09.09.2011 13:04

Перемещение элементов в районе одного дива.
 
Всем привет!
<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 .

Благодарен за помощь.

Триви 09.09.2011 13:30

$('div#intro #three').prependTo( 'div#intro #two' );

Duda.Ml1986@gmail.com 09.09.2011 15:46

Цитата:

Сообщение от Триви (Сообщение 125735)
$('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')

DjDiablo 10.09.2011 11:35

Если я правильно всосал проблему

То для установки одного обьекта относительно другого, лучше использовать
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>

DjDiablo 10.09.2011 12:07

Продолжая кумекать, сваял функцию рокировки любых 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). Но особого смысла всё равно не вижу.

Виктор Кон 10.09.2011 13:39

Хотел бы узнать, а зачем вам такое надо, просто из любопытсва

Duda.Ml1986@gmail.com 10.09.2011 15:21

Обьясняю зачем это нужно.
Это слайдер и столкнулся с ситуацией что существующий не совсем мне подходят (грубо говоря там используется масса не нужного для работы ,а может я не способен разобраться с написанным и т.д. , да и свое ближе) и мне захотелось чтобы дойдя до показа последнего элемента из списка , то есть дива 3 , я не прокручивал все до первого дива , а перемещал див 1 за див 3. И соответственно наоборот если прокрутка идет в противоположную сторону.

ЕСЛИ вЫ ТАКОЙ уже встречали. то все равно сог

Duda.Ml1986@gmail.com 10.09.2011 15:35

Немного поразмыслив с ответом DjDiablo , пришел к выводу что это не совсем то что мне надо, элементы перемещаются как нужно, но сразу происходит прыжок изображений в виду использования float для всех дивов.

Так что пришел к выводу что лучше сделать длинную ленту из всех блоков и уже когда вдруго слайдер подойдет к последнему блоку, перекинуть опять в центр ленты. Думаю будет незаметно.

Хотя нет, лучше обнулять смещение влево.!!!

DjDiablo 10.09.2011 16:57

Интересная задача.

Но я не уверен что её можно решить только одними манипуляциями с 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) попала центральная часть. Так как всё содержимое вращается по кругу, то оно неприменно попадёт в зону видимости.

Всё что я здесь написал это скорее псевдокод, чтобы направить мысли в русло ))

Duda.Ml1986@gmail.com 10.09.2011 19:42

Мне кажется что у меня решение немного проще.

Делаю длинный 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">&laquo;</button> <button id="right">&raquo;</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.