2009-04-01 12 views
27

Szukam implementacji interfejsu WWW z wieloma elementami, które można wybrać i przeciągnąć, aby je ustawić, w grupach lub pojedynczo. Raczej jak na pulpicie Windows, naprawdę.Czy istnieje wtyczka JQuery, która łączy Draggable i Selectable

Używamy już JQuery, więc dodatki do tego będą pierwszym wyborem. Interfejs użytkownika JQuery Przeciąganie i wybieranie pojedynczo wykonuje wiele z tego, czego chcemy, ale nie działają razem, aby uzyskać pożądany efekt.

Jestem całkowicie przygnębiony przez stronę wtyczki JQ (jej "popularny" algorytm nie wydaje się zbyt użyteczny) i chętnie przyjmuję wskazówki, jak najlepiej omijać tu wiele reinstalacji koła, jak sądzę że ta metafora została już wykonana.

+0

Kod w http://stackoverflow.com/questions/34698117/elements-became-andandly-non-resizable-after-dragging queston zawiera również odpowiedź na to pytanie Jednak kod w odpowiedziach powoduje losową utratę rozmiaru na przeciągnięcie – Andrus

Odpowiedz

19

Też potrzebowałem zrobić to samo i nie chciałem używać rozszerzenia interfejsu z eyecon.ro. Po pewnych badaniach znalazłem Combining Selectables And Draggables Using jQuery UI. Jest ładnie powiedziane, ale aby uruchamiać fragmenty kodu, musisz się w to zagłębić. Udało mi się sprawić, żeby działało. Lekko to zmieniłem, to jest mój sposób na zrobienie tego. Potrzebuje modyfikacji do wykorzystania na poziomie produkcji, ale mam nadzieję, że to pomaga.

// this creates the selected variable 
// we are going to store the selected objects in here 
var selected = $([]), offset = {top:0, left:0}; 

// initiate the selectable id to be recognized by UI 
$("#selectable").selectable({ 
    filter: 'div', 
}); 

// declare draggable UI and what we are going to be doing on start 
$("#selectable div").draggable({ 
    start: function(ev, ui) { 
     selected = $(".ui-selected").each(function() { 
      var el = $(this); 
      el.data("offset", el.offset()); 
     }); 

     if(!$(this).hasClass("ui-selected")) $(this).addClass("ui-selected"); 
     offset = $(this).offset(); 
    }, 
    drag: function(ev, ui) { 
     var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left; 

     // take all the elements that are selected expect $("this"), which is the element being dragged and loop through each. 
     selected.not(this).each(function() { 
      // create the variable for we don't need to keep calling $("this") 
      // el = current element we are on 
      // off = what position was this element at when it was selected, before drag 
      var el = $(this), off = el.data("offset"); 
      el.css({top: off.top + dt, left: off.left + dl}); 
     }); 
    } 
}); 

Style CSS, aby móc zobaczyć, co się dzieje:

#selectable { width: 100%; height: 100%;} 
#selectable div { 
    background: #ffc; 
    line-height: 25px; 
    height: 25px; 
    width: 200px; 
    border: 1px solid #fcc; 
    } 
#selectable div.ui-selected { 
    background: #fcaf3e; 
    } 
#selectable div.ui-selecting { 
    background: #8ae234; 
    } 

HTML Markup:

<div id="selectable"> 
    <div>item 1</div> 
    <div>item 2</div> 
    <div>item 3</div> 
    <div>item 4</div> 
</div> 
+2

główny problem z tym kodem nie pozwala ci sterować kliknięciem, aby dodać dodatkowe elementy. –

+2

To wydaje się pozwalać tylko na przeciąganie wielu zaznaczonych elementów, nie jestem w stanie wybrać żadnego wybieralnego elementu za pomocą jednego kliknięcia (nie mówiąc już o kliknięciu ctrl) – digout

+0

Ten kod powoduje przypadkową utratę rozmiaru podczas przeciągania. To jest opublikowane w http://stackoverflow.com/questions/34698117/elements-became-andandlyly-non-resizable-after-dragging Jak naprawić? – Andrus

4

Zrobiłem pewnych modyfikacji do odpowiedzi udzielonej przez Sinan Yasar. Nie jest doskonały, ale już zachowuje się znacznie bardziej, niż bym chciał.

Jednym z głównych dodatków jest detektor kliknięć, który wywołuje zaznaczenie.

// manually trigger the "select" of clicked elements 
$("#selectable > div").click(function(e){ 
    if (e.metaKey == false) { 
     // if command key is pressed don't deselect existing elements 
     $("#selectable > div").removeClass("ui-selected"); 
     $(this).addClass("ui-selecting"); 
    } 
    else { 
     if ($(this).hasClass("ui-selected")) { 
      // remove selected class from element if already selected 
      $(this).removeClass("ui-selected"); 
     } 
     else { 
      // add selecting class if not 
      $(this).addClass("ui-selecting"); 
     } 
    } 

    $("#selectable").data("selectable")._mouseStop(null); 
}); 

można zobaczyć kompletny pracy przykład tutaj: http://jsfiddle.net/DXrNn/4/

Jest również plugin jquery-ui dostępny że właśnie to robi: http://code.google.com/p/jqdragdropmultiselect/ probleme jest to, że to nie wygląda utrzymane.

edytuj: jeśli zdefiniujesz opcję "filtru" przeciągania, będziesz musiał wywołać selectable.refresh() przed selectable._mouseStop (null).

$("#selectable > div").click(function(e){ 
    ... 
    var selectable = $("#container").data("selectable"); 
    selectable.refresh(); 
    selectable._mouseStop(null); 
    ... 
+2

Bez względu na to, jak bardzo wypróbuję twoje rozwiązanie w jsfiddle, nie mogę pobrać żadnych elementów, tylko wybierz. Chrome 19. – trusktr

+1

@trusktr Spróbuj z 'jQuery 1.8.3' i' jQueryUI 1.9.2' – mraaroncruz

+1

@trusktr z tego powodu http://stackoverflow.com/questions/14366322/error-jquery-ui-draggable-cannot- read-property-msie wydaje się, że potrzebujesz jQueryUI 1.10, aby użyć jQuery EDGE – mraaroncruz

10

To pytanie jest istotne, ale jest stare; więc są odpowiedzi. Here's an updated version od użytkownika @ idFlood jsfiddle, który działa z jQuery 1.9.1 + jQueryUI 1.10.3:

// store selected elements and the offset of the dragged element 
var selected = $([]), offset = {top:0, left:0}; 

$("#selectable > div").draggable({ 
    start: function (event, ui) { 
     var $this = $(this); 

     if ($this.hasClass("ui-selected")) { 
      // if this is selected, attach current offset 
      // of each selected element to that element 
      selected = $(".ui-selected").each(function() { 
       var el = $(this); 
       el.data("offset", el.offset()); 
      }); 
     } else { 
      // if this is not selected, clear current selection 
      selected = $([]); 
      $("#selectable > div").removeClass("ui-selected"); 
     } 
     offset = $this.offset(); 
    }, 

    drag: function (event, ui) { 
     // drag all selected elements simultaneously 
     var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left; 
     selected.not(this).each(function() { 
      var $this = $(this); 
      var elOffset = $this.data("offset"); 
      $this.css({top: elOffset.top + dt, left: elOffset.left + dl}); 
     }); 
    } 
}); 

// enable marquee selecting and deselect on outside click... 
$("#selectable").selectable(); 

// ...but manually implement selection to prevent interference from draggable() 
$("#selectable").on("click", "div", function (e) { 
    if (!e.metaKey && !e.shiftKey) { 
     // deselect other elements if meta/shift not held down 
     // $("#dc-modules .dc-module").removeClass("ui-selected"); 
     $("#selectable > div").removeClass("ui-selected"); 
     $(this).addClass("ui-selected"); 
    } else { 
     if ($(this).hasClass("ui-selected")) { 
      $(this).removeClass("ui-selected"); 
     } else { 
      $(this).addClass("ui-selected"); 
     } 
    } 
}); 

miałem problem z _mouseStop() wezwanie rzuca błąd, więc usunąłem go; oznacza to, że stan nie występuje po kliknięciu, ale wszystkie pozostałe funkcje pozostają nienaruszone.

+0

To rozwiązanie działa bardzo dobrze, ale mam problem z uzyskaniem go do pracy z droppable. Czy jest coś nieodłącznego w rozwiązaniu, które według ciebie może kolidować ze zrzucaniem lub czy powinienem ciągle walić głową w ten kod? –

+0

@ericsoco Ten kod powoduje losowe wypełnianie po przeciągnięciu. Jest to opublikowane w http://stackoverflow.com/questions/34698117/elements-became-andandlyly-non-resizable-after-dragging Jak naprawić? – Andrus

Powiązane problemy