Sortowalne elementy z zapisem kolejności

Opublikowano 10.7.2010  w JavaScript » 13 komentarzy
move

Wyobraźmy sobie sytuację, że mamy na swojej stronie kilka rubryczek ustawione w jednym rzędzie i w każdej jest zawartość która zainteresuje inne osoby np: sidebar z listami ostatnich wpisów osobno dla różnych kategorii. I teraz możemy mieć dylemat którą tematykę dać na górę a którą ukryć niżej. Jest jednak rozwiązanie: możemy pozwolić użytkownikom aby sami ustalali kolejność która później będzie przywracana przy każdym wczytaniu strony.

jQuery i wtyczki

Pisanie skryptu zaczynamy od pobrania jQuery i dołączenia do swojego kod, tak samo musimy zrobić z jQuery UI gdyż tam znajduję się plugin Sortable na którym oprzemy nasz skrypt. Gdy już to mamy możemy napisać kod html:

<div class="box">
   <div id="m" class="element">matematyka</div>
   <div id="f" class="element">fizyka</div>
   <div id="c" class="element">chemia</div>
   <div id="i" class="element">informatyka</div>
   <div id="e" class="element">ekonomia</div>
</div>

Box to nasz pojemnik z divami które będziemy sortować. Każdy z tych elementów musi mieć inne ID by skrypt mógł je rozpoznawać. Poniżej zaś kod JavaScript który uruchomi sortowanie:

$(".box").sortable({ items: '.element' });

W tym momencie będzie już działać sortowanie ale po odświeżeniu wszystkie elementy wrócą na swoje miejsce. Aby móc zapisać kolejność będziemy musieli skorzystać z mechanizmu ciastek. Aby ułatwić sobie ich obsługę skorzystamy z dwóch specjalnych funkcji które można skopiować stąd. Przyda się również wtyczka w jQuery do sortowania elementów DOM. Użyjemy qsort którą można pobrać tutaj. Gdy już wszystko podepniemy do naszej strony możemy zacząć pisać nasz skrypt.

Szczypta naszego kodu

Najpierw napiszemy kod do zapisywania kolejności. Aby to zrobić musimy do wcześniej napisanego wywołania funkcji sortable dopisać parę dodatkowych linijek.

$(".box").sortable({
   items: '.element',
   update: function(event, ui){
      var k = $(".box").sortable("toArray");
      var ks = k.toString();
      SetCookie('kolejnosc', ks, 30);
   }
});

Skorzystaliśmy tu z zdarzenia update które jest wywoływane zawsze gdy zmieniona zostanie kolejność elementów. Podpięta funkcja anonimowa najpierw uruchamia metodę toArray by wtyczka sortable zwróciła tablicę id kolejnych elementów, następnie otrzymana tablica jest serializowana by na końcu otrzymany ciąg został zapisany do ciasteczka.

Teraz pozostał nam jeszcze do napisania skrypt który po wczytaniu strony będzie ustawiał elementy w odpowiedniej kolejności. Oto i on:

if(GetCookie('kolejnosc')){
   var kol = GetCookie('kolejnosc').split(',');
   for(var j=0;j<kol.length;j++){
      $('#'+kol[j]).attr('value',j);
   }
   $('.element').qsort({attr: "value"});
   SetCookie('kolejnosc', kol, 30);
}

Powyższą instrukcję należy wywołać gdy cała strona jest już załadowana. Skrypt działa następująco: najpierw sprawdzamy czy istnieje ciasteczko, jeśli tak to wyciągamy z niego informacje i deserializujemy je do tablicy. Następnie w pętli kolejnym sortowalnym elementom nadajemy value o wartości takiej jaką powinno zajmować miejsce. Gdy to już mamy zrobione uruchamiamy funkcję qsort i na końcu przedłużamy żywotność ciasteczka.

Cały skrypt  z dokładnymi komentarzami można skopiować tutaj a strona z gotowym efektem jest do zobaczenia w tym miejscu.

Otagowano: , , ,

13 odpowiedzi do tego artykułu

  1. A gdybym teraz chciał zrobić z tego moduł edycji menu w moim cmsie. Tak abym mógł blokowo przestawiać pozycje. To jak zrobić teraz zapis do bazy danych?? Tzn chodzi mi o rozpisanie pętli, która będzie sprawdzała nowa pozycje i przy każdym przebiegu zapisywała ja do bazy danych.

    • Elektryk

      Zamiast zapisywać wartość zmiennej ks do ciasteczka użyj funkcji ajax() udostępnianej przez jQuery by wysłać ciąg do pliku php na serwerze.

  2. Szczerze mówiąc nigdy nie miałem styczności z ajaxem, dlatego też pytam się o takie rzeczy. Może mógłbyś pomóc jakimś tutorialem, lub przykładem, który ułatwił by mi przerobienie tego oto kodu.

    • Elektryk

      Piszę z pamięci ale będzie to wyglądać mniej więcej tak, że zamiast linijki która zapisuje dane do ciacha wstaw to:
      $.ajax({ url: "plik_php_który_zapisze_dane.php", data: "dane="+ks, type: "POST"});
      Przesłane informacje będziesz mógł wyciągnąć z $_POST['dane']

  3. Hmm zrobiłem tak:

    plik menu.php

    echo ”;
    for($i=0;$i<$IleWynikow;$i++)
    {
    echo '’.$Wynik[$i]['menu_tytul'].”;
    }

    echo ”;

    oraz jeszcze cos takiego, aby sprawdzić czy cokolwiek przekazuje ajax:

    $zrob=$_GET['zrob'];

    mysql_query(‘SET NAMES utf8′); // A ja nie to zamiast utf8 daje utf-8

    if($zrob=”poukladaj”){

    echo $_POST['dane'];

    }

    w pliku naszkod.js zrobiłem coś takiego:

    $(„.box”).sortable({
    items: ‘.element’,
    update: function(event, ui){
    //metoda toArray zwraca tablicę z ID kolejnych elementów
    var k = $(„.box”).sortable(„toArray”);
    //konwertujemy tablicę do pojedynczego ciągu
    var ks = k.toString();
    $.ajax({ url: „administrator.php?zarzadzaj=menu$zrob=poukladaj”, data: „dane=”+ks, type: „POST”});
    }
    });

    Niestety nic się nie dzieje, poukładam sobie bloki i nic :/

    • Elektryk

      Nie możesz przesyłać danych POST na adres z informacjami GET.
      $.ajax({ url: „administrator.php”, data: „zarzadzaj=menu&zrob=poukladaj&dane=”+ks, type: „POST”});
      po za tym zamiast ampersantu miałeś dolara. Ale my się chyba nie zrozumieliśmy. Bo ty chcesz zrobić tak, że użytkownik po ustawieniu elementów musi przeładować stronę by to zapisać? Wtedy jest prościej. Po prostu tworzysz formularz z przyciskiem i ukrytym elementem o danym id np ‘zapamietaj’ i zamiast kodu z ajaxem który Ci kazałem wstawić dajesz:
      document.getElementById(‘zapamietaj’).value=ks;
      Przy wysłaniu formularza ta informacja też się wyślę.

  4. Hmm nie mogę zrozumieć tylko jakim sposobem przekazać do zapytania aktualizujacego w bazie danych które id menu jest edytowane

    to jest fragment pliku menu.php:

    http://wklej.to/HCI7

    a to naszkod.js:

    http://wklej.to/TYeu

    Nie wiem jak skonstruować to że naszkod.js przekazuje do php menu_id oraz nową wartość pozycji

    • Elektryk

      Jeszcze raz: tu masz plik JS: http://wklej.org/id/362881/ a tak ma wyglądać formularz który wyśle dane do pliku php po kliknięciu http://wklej.org/id/362883/ Zrezygnowaliśmy z ajaxu. tak będzie prościej. Teraz wszystko działa tak, że po aktualizacji kolejności skrypt zmienia wartość ukrytego pola formularza a ten formularz (i to pole) jest wysłane po kliknięciu submita.

  5. Problem z tego co widzę leży w pliku naszkod.js, gdy wywalę ostatnią linię tą:
    document.getElementById(‘zapamietaj’).value=ks;
    To elementy się przesuwają, jednak gdy wklejam tak jak podałeś to elementy są nieruchome,

    Dla pewności jeszcze raz przesyłam kod php i js
    http://wklej.org/id/362893/
    http://wklej.org/id/362894/

    • Elektryk

      Ojej, głupi błąd, w tym kodzie co psuje zamiast apostrofów daj cudzysłowy :)

  6. Dokładnie, już to wczoraj zauważyłem i działa ;) Dzięki wielkie. Fajny blog i na pewno będę go odwiedzał ;)

    Pozdrawiam

  7. Zrób z tych komentarzy osobny artykuł. Mam też pytanie: jak zrobić coś takiego, z sortowaniem i przekładaniem do folderów? Np. miałbym foldery i chciałbym do folderów przekładać, np. produkty w sklepie internetowym. Da się takie coś zrobić?

    Proponuję artykuł nt. układanie menu góra / dół w jQuery i zapisem do bazy PHP.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

*

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Markup Controls
Emoticons Smile Grin Sad Surprised Shocked Confused Cool Mad Razz Neutral Wink Lol Red Face Cry Evil Twisted Roll Exclaim Question Idea Arrow Mr Green