Przeciąganie divów w javascript

0

**Cześć! :D **

Wpadłem ostatnio interesujące repozytorium : https://github.com/atlassian/react-beautiful-dnd
Jest tam bardzo ciekawa aplikacja napisana w React'ie gdzie można przeciągać i upuszczać.
Zastanawiam się co powinienem wiedzieć żeby móc napisać coś podobnego w czystym javascriptcie ?

1

Zacząłbym od tego: https://www.w3schools.com/howto/howto_js_draggable.asp

Myślę, że następnie należałoby zaimplementować przyciąganie do odpowiedniego miejsca na liście jakoś w zależności od położenia w pionie w stosunku do brzegów poszczególnych elementów listy oraz samej listy (w poziomie położenie nie miałoby znaczenia, bo element byłby przyciągany na całej szerokości strony).


UPDATE:
Jeśli istotna jest obsługa klawiatury (jak widzę na obrazku pod załączonym linkiem do GitHuba), to należałoby dodatkowo zaimplementować obsługę naciśnięcia jakiegoś klawisza (i przyciągania elementu po puszczeniu) dla elementu aktywnego (nie wiem dokładnie, jak ustalana jest aktywność elementu na stronie oraz kolejność przeskakiwania klawiszem tab). Działałoby to chyba podobnie, tylko zamiast myszy byłaby klawiatura.

Piszę tak ogólnie, bo kodu pod załączonym przeze mnie linkiem nie czytałem dokładnie.


UPDATE 2: Ten fragment z W3Schools wydaje mi się najważniejszy:

function elementDrag(e) {
    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

UPDATE 3: Acha, no i oczywiście nie można zapomnieć (jak ja to właśnie zrobiłem ;) ) o przesunięciu w dół elementów poniżej górnej linii przeciąganego elementu (albo powyżej dolnej, w zależności od kierunku przeciągania). Bo inaczej przesunięty element zakryje inne elementy.


UPDATE 4: Jeszcze pozostała kwestia tzw. stacking context dla poszczególnych elementów: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context. Tylko o tym wspominam, bo tak ogólnie to się prosto załatwia przez dodanie z-index (jak w tym przykładzie W3Schools). Ale być może w przypadku większej liczby elementów na stronie robiłoby to różnicę, albo na przykład, gdyby były dwie takie listy z przeciąganiem obok siebie. Choć z-index może przyjmować bardzo dużo wartości (===duże liczby; więc zazwyczaj można coś przenieść na górę innych elementów), to jednak nie polecam korzystania tylko z niego, dlatego że byłoby to trochę jak zamiatanie pod dywan czegoś, po co można się schylić. CSS posiada algorytm wyznaczania pozycji elementów na osi z i raczej poznałbym sam algorytm dokładnie, gdybym miał obsługiwać bardziej złożone sytuacje.

0

Ogromne dzięki!

Mam do tego pytania:

  1. Dla czego w: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_draggable
    element #mydivheader posiada w ogóle atrybut z-index ?
  2. Czy istnieje jakiś konkretny powód żeby wartości z-index były tak wysokie (9, 10) skoro równie dobrze to mogło być 1?
  3. [link 1.] W " function dragMouseDown(e) " nie rozumiem zapisu e = e || window.event;
0
  1. Dla czego w: https://www.w3schools.com/how[...]?filename=tryhow_js_draggable
    element #mydivheader posiada w ogóle atrybut z-index?

To jest dobre pytanie. Jak sam widzisz, po jego usunięciu działa chyba jak przedtem. Przy CSS twórcy tego przykładu napisali: "The only important style is position: absolute, the rest is up to you", z czego wnioskuję, że być może chodziło im pierwotnie właśnie o zrobienie listy z przeciąganymi elementami? Wtedy – najprawdopodobniej, bo są inne metody – poszczególne elementy musiałby jakoś odróżniać swoją kolejność na stosie (stacking order). Jeden miałby z-index: 9, a drugi z-index: 10.

  1. Czy istnieje jakiś konkretny powód żeby wartości z-index były tak wysokie (9, 10) skoro równie dobrze to mogło być 1?

Ekspertem nie jestem, ale w mojej opinii logika tak nakazuje. Biorąc pod uwagę projekt dużej (pod)strony, z jednej strony – możesz mieć dużo elementów z explicite nadanymi wartościami z-index i trzeba być pewnym, że będą się odróżniać; z drugiej strony – mogą być one również nadane implicite przez przeglądarkę, to znaczy przez stacking order oraz stacking context (odsyłam do załączonego przeze mnie linku do MDN).

Z trzeciej strony – można też założyć, że wartości powinny być semantycznie zrozumiałe i do zapamiętania (o ile zakładane jest ręczne utrzymanie kodu CSS), więc nawet jeżeli to nie spowoduje wymogu, żeby były małe – tak jak Ty najpewniej oczekiwałeś – to przynajmniej powinny kręcić się wokoło wielokrotności liczby 10, np. 10, 20, 100, 500, 1000.

  1. W " function dragMouseDown(e) " nie rozumiem zapisu e = e || window.event;

Dokładnie nie wiem, czemu akurat tutaj tak napisano, ale znalazłem, jak mi się wydaje, odpowiedź na ten temat na SO:

(...)
However Internet Explorer doesn't pass event to handler. Instead you can use window.event object which is being updated immediately after the event was fired. So the crossbrowser way to handle events:

node.onclick = function(e) {
e = e || window.event;
// also there is no e.target property in IE.
// instead IE uses window.event.srcElement
var target = e.target || e.srcElement;
// Now target refers to node. And you can, for example, modify node:
target.style.backgroundColor = '#f00';
}


Choć same pytanie i odpowiedź dotyczą trochę czego innego, to jednak – <u>oczywiście jeśli autor miał rację, podając taki przykład kodu, bo ja nie znam obsługi zdarzeń aż tak dobrze</u> – to chodziłoby tutaj o to, że w Internet Explorerze (być może w jego starszych wersjach? Sprawdź, może MDN będzie mieć informacje o kompatybilności tej funkcji) zdarzenia (lub: niektóre zdarzenia) nie są przypisywane do handlerów, tylko do globalnego obiektu `window.event`. U nas powodowałoby to, że obiekt `e` będzie "pusty". Skoro tak, to trzeba sprawdzić, który z tych obiektów jest ustawiony (czyli, przy okazji, z jaką przeglądarką mamy do czynienia). Pamiętaj, że operator `||` sprawdza, czy którakolwiek wartość może być przekonwertowana na `false` – a w JS takimi mogą być `0`, `-0`, `null`, `false`, `Nan`, `undefined` oraz pusty ciąg znaków `""` (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean). U nas prawdopodobnie chodzi albo o `undefined`, albo może o `null`. Dla jasności możesz jeszcze przeczytać: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers oraz https://stackoverflow.com/questions/35936365/javascript-what-exactly-is-parameter-eevent-and-why-pass-it-to-javascript-fun#

---
Mam nadzieję, że nie zamieszałem i wszystko brzmi logicznie. Gdyby były jakiś nieścisłości w stosunku do innych źródeł, napisz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1