Jak sprawić, by element div interfejsu użytkownika jQuery „draggable ()” można było przeciągać na ekran dotykowy?

112

Mam interfejs użytkownika jQuery, draggable()który działa w przeglądarkach Firefox i Chrome. Koncepcja interfejsu użytkownika polega w zasadzie na kliknięciu, aby utworzyć element typu „post-it”.

Zasadniczo klikam lub stukam div#everything(100% wysoki i szeroki), który nasłuchuje kliknięć i wyświetla się wejściowy obszar tekstowy. Dodajesz tekst, a kiedy skończysz, zapisuje go. Możesz przeciągać ten element dookoła. To działa w normalnych przeglądarkach, ale na iPadzie, z którym mogę przetestować, nie mogę przeciągać elementów. Jeśli dotknę, aby zaznaczyć (następnie lekko się ściemni), nie mogę go przeciągnąć. W ogóle nie przeciągnie się w lewo ani w prawo. I można przeciągnąć w górę lub w dół, ale nie jestem przeciągając osobnika div, jestem przeciągając całą stronę.

Oto kod, którego używam do przechwytywania kliknięć:

$('#everything').bind('click', function(e){
    var elem = document.createElement('DIV');
    STATE.top = e.pageY;
    STATE.left = e.pageX;
    var e = $(elem).css({
        top: STATE.top,
        left: STATE.left
    }).html('<textarea></textarea>')
    .addClass('instance')
    .bind('click', function(event){
        return false;
    });
    $(this).append(e);
});

A oto kod, którego używam do „zapisania” notatki i przekształcenia wejściowego div w zwykły display div:

$('textarea').live('mouseleave', function(){
    var val = jQuery.trim($(this).val());
    STATE.content = val;
    if (val == '') {
        $(this).parent().remove();
    } else {
        var div  = $(this).parent();
        div.text(val).css({
            height: '30px'
        });
        STATE.height = 30;
        if ( div.width() !== div[0].clientWidth || div.height () !== div[0].clientHeight ) {
            while (div.width() !== div[0].clientWidth || div.height () !== div[0].clientHeight) {
                var h = div.height() + 10;
                STATE.height = h;
                div.css({
                    height: (h) + 'px'
                });     // element just got scrollbars
            }
        }
        STATE.guid = uniqueID()
        div.addClass('savedNote').attr('id', STATE.guid).draggable({
            stop: function() {
                var offset = $(this).offset();
                STATE.guid = $(this).attr('id');
                STATE.top = offset.top;
                STATE.left = offset.left;
                STATE.content = $(this).text();
                STATE.height = $(this).height();
                STATE.save();
            }
        });
        STATE.save();
        $(this).remove();
    }
});

Mam ten kod, kiedy ładuję stronę z zapisanymi notatkami:

$('.savedNote').draggable({
    stop: function() {
        STATE.guid = $(this).attr('id');
        var offset = $(this).offset();
        STATE.top = offset.top;
        STATE.left = offset.left;
        STATE.content = $(this).text();
        STATE.height = $(this).height();
        STATE.save();
    }
});

Mój STATEobiekt obsługuje zapisywanie notatek.

Onload, to jest cała treść HTML:

<body> 
    <div id="everything"></div> 
<div class="instance savedNote" id="iddd1b0969-c634-8876-75a9-b274ff87186b" style="top:134px;left:715px;height:30px;">Whatever dude</div> 
<div class="instance savedNote" id="id8a129f06-7d0c-3cb3-9212-0f38a8445700" style="top:131px;left:347px;height:30px;">Appointment 11:45am</div> 
<div class="instance savedNote" id="ide92e3d13-afe8-79d7-bc03-818d4c7a471f" style="top:144px;left:65px;height:80px;">What do you think of a board where you can add writing as much as possible?</div> 
<div class="instance savedNote" id="idef7fe420-4c19-cfec-36b6-272f1e9b5df5" style="top:301px;left:534px;height:30px;">This was submitted</div> 
<div class="instance savedNote" id="id93b3b56f-5e23-1bd1-ddc1-9be41f1efb44" style="top:390px;left:217px;height:30px;">Hello world from iPad.</div> 

</body>

Tak więc moje pytanie brzmi naprawdę: jak mogę to poprawić na iPadzie?

Nie jestem ustawiony na interfejs użytkownika jQuery, zastanawiam się, czy to jest coś, co robię źle z interfejsem jQuery lub jQuery, lub czy mogą istnieć lepsze ramy do wykonywania elementów draggable () kompatybilnych z wieloma platformami / wstecznie pracować dla interfejsów użytkownika z ekranem dotykowym.

Bardziej ogólne komentarze na temat pisania komponentów interfejsu użytkownika, takich jak ten, również byłyby mile widziane.

Dzięki!


AKTUALIZACJA: udało mi się po prostu draggable()powiązać to z moim wywołaniem interfejsu użytkownika jQuery i uzyskać odpowiednią możliwość przeciągania na iPadzie!

.touch({
    animate: false,
    sticky: false,
    dragx: true,
    dragy: true,
    rotate: false,
    resort: true,
    scale: false
});

Plugin jQuery dotykowy załatwiło sprawę!

artlung
źródło
1
Coś mnie ciekawi: czy możesz przeciągnąć element div dwoma lub trzema palcami? Wiem, że czasami trzeba używać wielu palców, aby przewijać osadzone treści w mobilnym Safari, więc może to być to samo w przypadku treści „do przeciągania”.
Walter Mundt,
Walter Mundt dzięki! Nie próbowałem żadnych odmian palców, spróbuję, gdy dostanę to w dłonie!
artlung
1
dwa lub trzy palce faktycznie zapobiegały niezamierzonemu przewijaniu „całej strony”, ale nie powodowały zmian w przypadku przeciągania.
artlung
Niestety, ta technika wydawała mi się nie działać. :(
blaster
@blaster Będziesz musiał spojrzeć na niektóre inne odpowiedzi, aby znaleźć inne możliwe rozwiązania
artlung

Odpowiedzi:

138

Po zmarnowaniu wielu godzin natknąłem się na to!

jquery-ui-touch-punch

Tłumaczy zdarzenia dotknięcia jako zdarzenia kliknięcia. Pamiętaj, aby załadować skrypt po jquery.

Mam to działające na iPadzie i iPhonie

$('#movable').draggable({containment: "parent"});
ctrl-alt-dileep
źródło
2
To rozwiązanie działa świetnie, kolejna odpowiedź, którą zmęczyłem, była
wadliwa
Mała wskazówka: działa świetnie, chociaż jeśli przeciągany element pokryty warstwami, jak obraz z maską nad nim, nie jest aktywowany, ale rozwiązaniem będzie add pointer-events: none; na górnych warstwach.
Adler
To świetne i proste rozwiązanie, wystarczy użyć wtyczki i kontynuować pracę z funkcją przeciągania JQuery. Perfekcyjnie, dzięki!
prawie początkujący
Zapobiegnie to klikalnym elementom w przeciąganych elementach.
Abdul Sadik Yalcin
61

Uwaga: ta odpowiedź została napisana w 2010 roku, a technologia szybko się rozwija. Aby uzyskać nowsze rozwiązanie, zobacz odpowiedź @ ctrl-alt-dileep poniżej .


W zależności od potrzeb możesz wypróbować wtyczkę jQuery touch ; można spróbować przykład tutaj . Przeciąganie na moim iPhonie działa dobrze, podczas gdy jQuery UI Draggable nie.

Alternatywnie możesz wypróbować wtyczkę, chociaż może to wymagać napisania własnej funkcji , którą można przeciągać.

Na marginesie: wierzcie lub nie, słyszymy coraz większe zainteresowanie na temat tego, jak urządzenia dotykowe, takie jak iPad i iPhone, powodują problemy zarówno w witrynach internetowych, które używają funkcji: najedź / onmouseover, jak i treści, które można przeciągać.

Jeśli interesuje Cię podstawowe rozwiązanie tego problemu, to użycie trzech nowych zdarzeń JavaScript; ontouchstart, ontouchmove i ontouchend. Apple faktycznie napisał artykuł o ich zastosowaniu, który można znaleźć tutaj . Uproszczony przykład można znaleźć tutaj . Te zdarzenia są używane w obu wtyczkach, z którymi się łączyłem.

vonconrad
źródło
2
Super super! Wszystko, co musiałem zrobić, to połączyć się .touch({ animate: false, sticky: false, dragx: true, dragy: true, rotate: false, resort: true, scale: false });z moim istniejącym draggable()połączeniem i działa to wspaniale! Nadal muszę opracować wszystkie zdarzenia, którymi chcę się zająć, aby uzyskać prawidłowy przepływ pracy, ale wtyczka jQuery touch załatwiła sprawę!
artlung
4
wydaje się, że wtyczka nie jest już dostępna na jquery.com. nadal możesz znaleźć javascript tutaj manifestinteractive.com/iphone/touch/js/jquery.touch.js
bjelli
1
Heh, teraz brakuje również wtyczki z manifestinteractive.com. Spróbuj tego: plugins.jquery.com/files/jquery.touch.js.txt
Ian Hunter
5
ta odpowiedź jest już nieaktualna. zobacz odpowiedź @ ctrl-alt-dileep poniżej (jquery-ui-touch-punch), aby uzyskać odpowiedź z 2012 roku
bjelli
1
@bjelli Dzięki za wskazanie tego. Zaktualizowałem odpowiedź o ostrzeżenie. :)
vonconrad
7

jQuery ui 1.9 zajmie się tym za Ciebie. Oto demo pre:

https://dl.dropbox.com/u/3872624/lab/touch/index.html

Po prostu wyjmij plik jquery.mouse.ui.js, umieść go pod ładowanym plikiem jQuery ui i to wszystko, co powinieneś zrobić! Działa również w przypadku sortowania.

Ten kod działa świetnie, ale jeśli otrzymujesz błędy, zaktualizowaną wersję jquery.mouse.ui.js można znaleźć tutaj:

Sortowanie Jquery-ui nie działa na urządzeniach dotykowych opartych na systemie Android lub IOS

thatmiddleway
źródło
3
To świetnie, że mają do czynienia z tym 1.9. FWIW, znalazłem wersję kodu w tym demo, która zawierała błędy i nie działała tak dobrze. Ktoś opublikował bardziej poprawną wersję tego pytania: stackoverflow.com/questions/6745098/ ... która działa lepiej dla mnie.
asgeo1
Zaktualizowałem moją odpowiedź, aby rozwiązać ten problem. Nie otrzymałem jeszcze żadnych błędów w moim przypadku użycia z oryginałem.
thatmiddleway
1
Link do Dropbox nie działa.
BerggreenDK
2

Zmagałem się wczoraj z podobnym problemem. Miałem już "działające" rozwiązanie wykorzystujące draggable jQuery UI razem z jQuery Touch Punch, o których wspominałem w innych odpowiedziach. Jednak użycie tej metody powodowało dla mnie dziwne błędy w niektórych urządzeniach z Androidem, dlatego zdecydowałem się napisać małą wtyczkę jQuery, która może przeciągać elementy HTML za pomocą zdarzeń dotykowych, zamiast używać metody emulującej fałszywe zdarzenia myszy.

Wynikiem tego jest jQuery Draggable Touch, która jest prostą wtyczką jQuery do przeciągania elementów, której głównym celem są urządzenia dotykowe za pomocą zdarzeń dotykowych (takich jak touchstart, touchmove, touchend itp.). Nadal ma rezerwę, która używa zdarzeń myszy, jeśli przeglądarka / urządzenie nie obsługuje zdarzeń dotykowych.

Cześć, stary
źródło
Cześć Heyman, Niezła robota. Dzięki za udostępnienie. Czy to zadziała również dla jQuery z możliwością zmiany rozmiaru?
Haris
1

Możesz spróbować użyć jquery.pep.js :

jquery.pep.js to lekka wtyczka jQuery, która zamienia dowolny element DOM w obiekt do przeciągania. Działa w większości przeglądarek, od starych do nowych, od dotyku do kliknięcia. Zbudowałem go, aby zaspokoić potrzebę, w której przeciąganie interfejsu jQuery UI nie spełniało, ponieważ nie działało na urządzeniach dotykowych (bez hakowania).

Strona internetowa , link do GitHub

martynas
źródło
1
Dzięki @martynas, sprawdzę to!
artlung