contao / core

Contao 3 → see contao/contao for Contao 4
GNU Lesser General Public License v3.0
492 stars 213 forks source link

Probleme mit Reihenfolge ändern in Chrome Contao 3 #6520

Closed mrmikeeu closed 10 years ago

mrmikeeu commented 10 years ago

Win 8, Chrome Version 31.0.1650.57 m, Contao 3.2.1

Kein drag/drop im Backend, zum Beispiel color picker, Reihenfolge, etc.

leofeyer commented 10 years ago

Wie lässt sich das in der Onlinedemo reproduzieren?

mrmikeeu commented 10 years ago

Versuche CSS zu bearbeiten, zum Beispiel hintergrundfarbe von body tag: color picker geht nicht.

mrmikeeu commented 10 years ago

In Artikel kann ich die Elemente nicht verschieben (in Home zum beispiel)

xchs commented 10 years ago
mrmikeeu commented 10 years ago

Keine JS Fehler, Keine Add-ons/Plugins. Saubere Chrome installation.

Toflar commented 10 years ago

Kann ich nicht reproduzieren.

xchs commented 10 years ago

Ich kann es ebenfalls nicht reproduzieren. Zumindest nicht in den mir vorliegenden Betriebssystemen; Windows 8 verwende ich nicht. Kann mir aber auch nicht vorstellen, dass es BS-spezifisch ist.

mrmikeeu commented 10 years ago

Es gibt andere Meldungen auf das Forum. Habe es auf zwei Windows 8 Systeme. Nur in Chrome. Firefox ist OK.

mrmikeeu commented 10 years ago

Korrektur: auch Opera geht nicht (auch Webkit). Safari geht aber (anderen Fork von Webkit).

Ich nehme an es ist ein bestimmtes Webkit Fork Thema.

HellPat commented 10 years ago

Ich kann es Reproduzieren.

Browser: Chrome (Canary)

Keine Javascript-Fehler in der JS-Konsole.

Toflar commented 10 years ago

Toll, ich kann es nicht reproduzieren. Weder auf Win 8 noch auf 8.1. Genau die gleiche Version von Chrome und Contao. ^^

HellPat commented 10 years ago

Okay... ich teste mal ein paar Browser durch. In den angehakten Browsern klappt alles:

Nachtrag: Der Test lief auf der Online-Demo.

Zeromax commented 10 years ago

Kann bestätigen dass es da Probleme gibt. Hatte mal den Cache und die Einstellungen zurückgesetzt (im Chrome), dann gings wieder. Paar Wochen später wieder nicht... Chrome Bug ;)

aschempp commented 10 years ago

Ich kann das Problem reproduzieren. Mit Chrome 32 (beta) und 33 (dev) funktioniert Drag&Drop nicht.

Das Problem liegt daran, das Chrome ab Version 32 auf Windows 8 denkt, dass Touch-Support vorhanden ist. Das führt zum Problem mit folgender Routines in der assets/contao/core.js

// Map the touch events to mouse events on mobile devices
if (Browser.Features.Touch) (function() {
    delete Element.NativeEvents['mousedown'];
    Element.defineCustomEvent('mousedown', { base:'touchstart' });

    delete Element.NativeEvents['mousemove'];
    Element.defineCustomEvent('mousemove', { base:'touchmove' });

    delete Element.NativeEvents['mouseup'];
    Element.defineCustomEvent('mouseup', { base:'touchend' });
})();

Die Touch-Events werden dabei auf Mouse-Events umgemünzt. Durch deaktivierung dieser Routine geht das Drag&Drop wieder (was natürlich keine Lösung ist). Der nächste Schritt wäre wohl zu testen, ob auf normalen Touch-Geräten ein Mouse-Event verfügbar ist, um nur im Negativfall auch die Verknüpfung herzustellen.

aschempp commented 10 years ago

Ich hatte gerade noch eine Erkenntnis. Durch das Mapping der Events werden die nativen Mouse-Event "gekillt", weshalb natürlich nichts mehr geht. Dass Touch-Events verfügbar sind, bedeutet ja nicht dass keine Mouse-Events mehr benötigt werden (denn moderne Laptops haben teilweise beides).

Ein schön ausführlicher Artikel zum Thema hab ich hier gefunden: http://www.html5rocks.com/en/mobile/touchandmouse/

aschempp commented 10 years ago

PS: wir konnten das Problem in Chrome 32/33 wohl nur reproduzieren, weil die Beta-Version standardmässig Touch-Support anbietet (auch wenn die Platform das nicht kann). Im initialen Ticket stand ja Chrome 31 auf Windows 8, ich gehe mal davon aus @mhenke64 hat ein Gerät mit Touch-Support und Maus?

mrmikeeu commented 10 years ago

Genau, laptop mit touch screen und maus.

leofeyer commented 10 years ago

Das Ersetzen der Mouse-Events stammt aus MooTools-Mobile: https://github.com/cpojer/mootools-mobile/blob/master/Source/Touch/Click.js

aschempp commented 10 years ago

@mhenke64 kannst du bitte mal http://jsfiddle.net/5jgSF/ auf deinem Laptop testen? Welche Ausgabe (im schwarzen Bereich) bekommst du, wenn du einmal mit Maus und einmal per Finger auf den "Hier klicken" Bereich klickst/touchst?

tpk109 commented 10 years ago

Ich habe Win 8.1, Touchscreen, Chrome 31.0.1650.57 m. Das Reihenfolge-Ändern geht im Chrome bei mir nicht. Bei dem jsfiddle kommt für Maus und Touch diesselbe Ausgabe, mousedown mouseup

aschempp commented 10 years ago

Es erscheint keine touchstart und touchend Meldung?

tpk109 commented 10 years ago

Nope, kein touchstart / end

mrmikeeu commented 10 years ago

Maus:

Touch:

aschempp commented 10 years ago

Schade, war ja klar das es nicht so einfach ist :D

tpk109 commented 10 years ago

Könnte man das Problem nicht durch ein Verschieben des Threads lösen? Von hier in die Issue List vom Chrome? :-)

aschempp commented 10 years ago

Das ist kein Issue von Chrome, sondern von Contao.

leofeyer commented 10 years ago

@aschempp Noch andere Ideen, wie man das Problem in den Griff bekommen könnte?

aschempp commented 10 years ago

ja, aber noch nichts gemacht :(

aschempp commented 10 years ago

So, jetzt kümmere ich mich drum :-)

aschempp commented 10 years ago

So, ich habe die Lösung. Wir können (voraussichtlich) nicht einfach die Touch- auf Mouse-Events ummünzen, sondern explizit Touch-Support für MooTools.Sortables + Mootools.Drag einbauen.

Basierend auf der Vorlage von http://stackoverflow.com/questions/7588576/drag-with-mootools-on-mobile habe ich eine Lösung gefunden, welche für meinen Fall mit Chrome Emulated-Touch und auch auf meinem iPhone funktioniert. Die problematische Routine in der contao.js muss durch folgenden Code ersetzt werden:

Class.refactor(Drag,
{
    attach: function(){
        this.handles.addEvent('touchstart', this.bound.start);
        return this.previous.apply(this, arguments);
    },

    detach: function(){
        this.handles.removeEvent('touchstart', this.bound.start);
        return this.previous.apply(this, arguments);
    },

    start: function(event){
        document.addEvents({
            touchmove: this.bound.check,
            touchend: this.bound.cancel
        });
        this.previous.apply(this, arguments);
    },

    check: function(event){
        if (this.options.preventDefault) event.preventDefault();
        var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
        if (distance > this.options.snap){
            this.cancel();
            this.document.addEvents({
                mousemove: this.bound.drag,
                mouseup: this.bound.stop
            });
            document.addEvents({
                touchmove: this.bound.drag,
                touchend: this.bound.stop
            });
            this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
        }
    },

    cancel: function(event){
        document.removeEvents({
            touchmove: this.bound.check,
            touchend: this.bound.cancel
        });
        return this.previous.apply(this, arguments);
    },

    stop: function(event){
        document.removeEvents({
            touchmove: this.bound.drag,
            touchend: this.bound.stop
        });
        return this.previous.apply(this, arguments);
    }
});

Class.refactor(Sortables,
{
    initialize: function(lists, options){
        options.dragOptions = Object.merge(options.dragOptions || {}, { preventDefault: (options.dragOptions && options.dragOptions.preventDefault) || Browser.Features.Touch });
        return this.previous.apply(this, arguments);
    },

    addItems: function(){
        Array.flatten(arguments).each(function(element){
            this.elements.push(element);
            var start = element.retrieve('sortables:start', function(event){
                this.start.call(this, event, element);
            }.bind(this));
            (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvents({
                mousedown: start,
                touchstart: start
            });
        }, this);
        return this;
    },

    removeItems: function(){
        return $$(Array.flatten(arguments).map(function(element){
            this.elements.erase(element);
            var start = element.retrieve('sortables:start');
            (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvents({
                mousedown: start,
                touchend: start
            });

            return element;
        }, this));
    },

    getClone: function(event, element){
        if (!this.options.clone) return new Element(element.tagName).inject(document.body);
        if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);

        var clone = this.previous.apply(this, arguments);
        clone.addEvent('touchstart', function(event){
            element.fireEvent('touchstart', event);
        });

        return clone;
    }
});

Es stellt sich nun lediglich die Frage, ob dies in die contao.js gehört oder besser gleich in die mootools.js gepackt werden sollte, damit die Funktion auch im Frontend zur Verfügung steht?

leofeyer commented 10 years ago

Implementiert in ecedc88a0cd5bb608dcbddff1af006b6ab4c492c. Hab es in die "MooTao"-Klasse eingefügt, in der schon andere Contao-spezifische MooTools-Anpassungen enthalten sind :)

@aschempp Bin immer wieder beeindruckt von Deinen JavaScript-Kenntnissen!

aschempp commented 10 years ago

Danke :-)