Невозможно уронить перетаскиваемое место, где два сбрасываемых предмета касаются друг друга - PullRequest
1 голос
/ 09 июня 2011

Кажется, что при использовании двух сбрасываемых пользовательских интерфейсов jquery, которые соприкасаются друг с другом, сбрасываемые события запускаются неправильно.Если при перетаскивании перетаскиваемого элемента из одного из элементов в на ниже его на следующий элемент событие out вызывается для первого элемента dropbleable, но событие over не вызывается для второго.Если вы уроните в этот момент, событие сброса не будет запущено.

Пример лучше.Попробуйте эту скрипку (протестировано в IE7,8,9 и Chrome11).Убедитесь, что журнал консоли вашего браузера открыт.Если вы перетаскиваете перетаскиваемый элемент через первый ряд, а затем медленно перетаскиваете его ко второму ряду, вы вскоре увидите в журнале, что событие out для первого ряда инициировано, а событие over для второго ряда - нет.Если вы отбрасываете, когда это происходит, событие сброса не запускается.

Кажется, что это просто 1-пиксельная линия между строками, которая вызывает проблему.При перетаскивании еще одного пикселя событие over вызывается, и событие drop работает правильно.

Мне это кажется ошибкой, но я не могу найти никого другого, кто использовал бы строки таблицы в качестве dropables исообщил о проблеме.Я разработал таблицу, чтобы вы могли видеть, что строки действительно находятся на одном уровне без пробелов между ними.

Это большая проблема для меня, потому что в нашем приложении строки таблицы представляют собой вложенные жадные атрибуты.Поэтому, если пользователь отбрасывает, когда это происходит, вместо этого на самом деле отбрасывается падение.

Кроме того, мы предоставляем обратную связь пользователю в перетаскиваемом помощнике в виде значка и сообщения, которое изменяется в зависимости отна сбросе вы закончили.Когда вы перетаскиваете между строками, он на мгновение мерцает, так как думает, что вы не слишком сбрасываетесь, когда вы на самом деле.

Мои вопросы:

  1. Есть ли какие-либо исправления или обходные путидля этой проблемы?
  2. Должен ли я сообщить об этом как об ошибке?

Обновление

@ davin,

Мы закончили тем, что изменили сопротивлениефункция в $ .ui.ddmanager для исправления порядка событий.Наша проблема заключалась в том, что мы вложили жадные каплиКогда вы переместились из одной из этих вложенных таблиц сброса в другую снизу вверх, событие over фактически сработало бы для родителя последним, что привело бы к плохим вещам.

Поэтому мы добавили логику, чтобы в основном проверить, перемещается ли изодно вложенное жадное в другое, и если это так, не запускать родительские события.

Не слишком ли много было бы попросить вас просмотреть это очень быстро и убедиться, что наша логика имеет смысл?Есть два логических изменения.Если мы перешли от жадного ребенка к жадному ребенку:

  1. Не отменять parentInstance.greedyChild
  2. Не запускать событие parentInstance._over.

Вот кодПосмотрите строки, связанные с переменным замыкания isParentStateChanged, который мы добавили:

    drag: function(draggable, event) {

    //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
    if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);

    var isParentStateChanged = false;

    //Run through all droppables and check their positions based on specific tolerance options
    $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {

        if(this.options.disabled || this.greedyChild || !this.visible) return;
        var intersects = $.ui.intersect(draggable, this, this.options.tolerance);

        var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
        if(!c) return;

        var parentInstance;
        if (this.options.greedy && !isParentStateChanged) {
            var parent = this.element.parents(':data(droppable):eq(0)');
            if (parent.length) {
                parentInstance = $.data(parent[0], 'droppable');
                parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
            }
        }

        // we just moved into a greedy child
        if (parentInstance && c == 'isover') {
            isParentStateChanged = true;

            parentInstance['isover'] = 0;
            parentInstance['isout'] = 1;
            parentInstance._out.call(parentInstance, event);
        }

        this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
        this[c == "isover" ? "_over" : "_out"].call(this, event);

        // we just moved out of a greedy child
        if (parentInstance && c == 'isout') {

            if (!isParentStateChanged) {
                parentInstance['isout'] = 0;
                parentInstance['isover'] = 1;
                parentInstance._over.call(parentInstance, event);
            }
        }
    });

}

Ответы [ 3 ]

3 голосов
/ 09 июня 2011

Это не ошибка как таковая, это особенность.Это все вопрос определений.Вы определили допуск ваших указателей для предметов, которые могут быть помечены, согласно документам:

указатель : указатель мыши перекрывает пометку

Когда указатель мыши находится в точке (10,10), а верхний левый угол окна заканчивается в (10,10), это перекрывается?Это зависит от вашего определения.Определение jQueryUI - сильное неравенство или сильное перекрытие ( см. соответствующий код ).Это имеет смысл (для меня), так как я не в поле, если я только на краю, поэтому я не хотел бы, чтобы событие запускалось.

Хотя, если для ваших целей вам требуется слабоенеравенство в условии перекрытия (т.е. слабое перекрытие), вы можете изменить эту строку кода в вашем источнике или переопределить ее, добавив:

$.ui.isOverAxis = function( x, reference, size ) {
    return ( x >= reference ) && ( x <= ( reference + size ) );
};

Рабочий пример: http://jsfiddle.net/vwLhD/8/

Имейте в виду, что со слабым неравенством возникают другие препятствия на пути: ваше событие out сработает после вашего события over, поэтому у вас может быть два события over до того, как сработает один out.Это не так сложно, но вам нужно убедиться, что вы имеете дело с этим делом.

ОБНОВЛЕНИЕ:

Важно отметить, что если вы добавите код Iвставленный выше, он повлияет на все другие виджеты пользовательского интерфейса в области $, если это важно.Возможно, подузел $ мог бы этого избежать.

В любом случае, у меня есть второй обходной путь, который полностью решит вышеуказанную проблему, и теперь при каждом движении мыши указатель находится внутри или вне каждого элемента исключительно:

$.ui.isOverAxis2 = function( x, reference, size ) {
    return ( x >= reference ) && ( x < ( reference + size ) );
};
$.ui.isOver = function( y, x, top, left, height, width ) {
    return $.ui.isOverAxis2( y, top, height ) && $.ui.isOverAxis( x, left, width );
};

Рабочий пример: http://jsfiddle.net/vwLhD/10/

По сути, я сделал верхнее условие слабым неравенством, а нижнее - сильным.Таким образом, границы полностью соседствуют.Теперь события происходят практически идеально.Почти и не полностью, потому что плагин по-прежнему проходит по порядку в буксируемых элементах, поэтому, если я перетаскиваю сверху вниз, порядок запуска хорош, потому что сначала он обнаруживает, что я покинул верхний элемент, а затем обнаруживает, что я вошел внижний элемент, в то время как при перетаскивании снизу вверх порядок стрельбы меняется на противоположный - сначала стреляет, входя в верхний, и только потом оставляя нижний.

Разница между этим и предыдущим обходным решением заключается в том, что даже в половине случаевпорядок не хороший, все происходит в один тик, то есть овер-аут или аут-аут всегда вместе, пользователь никогда не может застрять, как в исходном случае и первом обходном пути.

Вы можете дополнительно отточитьэто должно быть абсолютно идеально, если изменить код пользовательского интерфейса для циклического перебора элементов вначале в соответствии с теми, над которыми наведена мышь, и только затем с остальными (в функции $.ui.ddmanager).Таким образом, мышь уйдет всегда первым.В качестве альтернативы вы можете поменять порядок и получить обратный порядок;все, что подходит вам лучше.

Это определенно решит вашу проблему полностью.

0 голосов
/ 25 июня 2014

У меня была эта проблема с проектом, над которым я работал.

Мое решение состояло в том, чтобы проверить, как далеко было перетаскиваемое окно над каждым предметом. Если перетаскиваемость составляет 50% от верхней капли, тогда я предполагаю, что пользователь хочет сбросить верхнюю каплю.

Похоже на дно.

Для этого я изменил $ .ui.intersect;

добавленные переменные - hw = droppable.proportions.width / 2, hh = droppable.proportions.height / 2, lhw = l + hw, thh = t + hh

затем добавьте несколько операторов if

// going down
if(y2 < b && y2 >= thh){}

// going up
if(y1 > t && y1 <= thh){}

// covered
if(y1 <= t && y2 >= b){}
0 голосов
/ 09 июня 2011

Звучит так, как будто вы отбрасываете между строками, что означает, что вы опускаетесь на стол. У вас свернуты границы стола? css border-collapse: collapsed;

...