Как предотвратить перекрытие нескольких ручек в слайдере пользовательского интерфейса jQuery?

Я хочу иметь ползунок пользовательского интерфейса jQuery с двумя дескрипторами, значения которых можно задавать независимо друг от друга.

Я также хочу, чтобы они были оформлены так, чтобы одна ручка находилась «сверху» ползунка, а другая — снизу.

Проблема в том, что когда два дескриптора имеют одно и то же значение, пользовательский интерфейс jQuery считает, что один из дескрипторов все еще находится «сверху», поэтому один из маркеров необходимо переместить, прежде чем можно будет настроить другой. Если верхний маркер установлен на значение, то нижний маркер перемещается на то же значение, верхний маркер не может быть перемещен до тех пор, пока нижний маркер не будет удален первым. Сценарий сложно описать, поэтому ниже есть ссылка на скрипку.

Есть ли способ указать пользовательскому интерфейсу jQuery, что дескриптор, который я нажимаю, является тем, который я хочу активно перемещать?

Ссылка на JS Fiddle здесь: https://jsfiddle.net/rqpndLsL/

Как устроен мой слайдер:

$('.slider').slider({
    min: 0,
  max: 400,
  step: 50,
  values: [200, 200],
  range: false,
})

person Anne Lee    schedule 09.11.2016    source источник
comment
Фактическая проблема заключается в значениях min и max, причина, по которой нижний обработчик не может двигаться, заключается в том, что логически Max не может быть меньше минимального значения.   -  person Nikhil Nanjappa    schedule 09.11.2016
comment
Минимальное и максимальное значения предназначены для установки диапазонов для самого ползунка — насколько высоко или низко может двигаться любая ручка. Я удалил эти значения, и проблема не устранена.   -  person Anne Lee    schedule 09.11.2016
comment
Проверьте этот Fiddle.   -  person Nikhil Nanjappa    schedule 09.11.2016
comment
Все еще не работает. Если вы перетащите верхнюю ручку поверх нижней ручки, а затем попытаетесь переместить нижнюю ручку, вместо этого она переместит верхнюю. Это происходит, когда два дескриптора имеют одинаковое значение. В вашем примере сложно сделать две ручки одинаковыми, потому что шаг установлен на 1, но если вы измените его на что-то вроде 500, проблему будет легче увидеть.   -  person Anne Lee    schedule 09.11.2016
comment
Хм, хорошо... теперь добавлен новый тег - jquery-ui-slider. Надеюсь, что попаду к нужным людям с экспертным мнением.   -  person Nikhil Nanjappa    schedule 10.11.2016
comment
Мне удалось найти решение, которое сработало для меня. Я разместил его ниже и отмечу как ответ через 24 часа — взгляните, если вам интересно. Спасибо за помощь!   -  person Anne Lee    schedule 10.11.2016


Ответы (1)


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

Глядя на API jQuery, похоже, что активный дескриптор вычисляется на основе некоторого расстояния, когда я хотел просто дескриптор, на который нажимают.

Я переопределил событие jQuery UI _mouseCapture и настроил его так, чтобы оно реагировало на клики. Также требовалось некоторое жесткое определение класса CSS, чтобы определить, какой дескриптор является активным.

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

// Create the slider.
var slider = $('.slider').slider({//OPTIONS HERE});

// Get the slider and replace the _mouseCapture function with a custom one.
slider.data('ui-slider')._mouseCapture = function(event) {
  var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
        that = this,
        o = this.options;

  if ( o.disabled ) {
    return false;
  }

  this.elementSize = {
    width: this.element.outerWidth(),
    height: this.element.outerHeight()
  };
  this.elementOffset = this.element.offset();

  // Get the element that the click was triggered on and set that to closestHandle. There was a bunch of distance calculation here previously - that has been removed.
  currentHandle = $(event.toElement);
  closestHandle = currentHandle;
  // 'custom-handle-1' is a custom class I give to the left slider handle
  // I know that my sliders will only have 2 values (so index will either be 0 or 1 always).
  if (closestHandle.hasClass('custom-handle-1')) {
    index = 0;
  }
  else {
    index = 1;
  }

  allowed = this._start( event, index );
  if ( allowed === false ) {
    return false;
  }
  this._mouseSliding = true;

  this._handleIndex = index;

  this._addClass( closestHandle, null, "ui-state-active" );
  closestHandle.trigger( "focus" );

  offset = closestHandle.offset();
  mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
  this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
    left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
    top: event.pageY - offset.top -
      ( closestHandle.height() / 2 ) -
      ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
      ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
      ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
  };

  if ( !this.handles.hasClass( "ui-state-hover" ) ) {
    this._slide( event, index, normValue );
  }
  this._animateOff = true;
  return true;
};

Недостатком является то, что это может быть несовместимо с будущими версиями пользовательского интерфейса jQuery, но это проблема будущего (в настоящее время это 1.12.1).

person Anne Lee    schedule 10.11.2016
comment
Хм, приятно .... Это больше похоже на решение JQuery, чем на UI Slider, что может быть плохо, как вы упомянули. Но, честно говоря, я предполагаю, что для этой проблемы вам пришлось пойти нетрадиционным путем, поскольку библиотека не предоставила его. По крайней мере, вы нашли хорошее решение. Ваше здоровье - person Nikhil Nanjappa; 14.11.2016