knockoutjs одиночный и двойной клик

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

data-bind ="event: { dblclick: doSomething }

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

5 ответов


во-первых, я бы не рекомендовал click привязка по всем. Вместо этого вы должны использовать "click" и "dblclick" обработчики событий в jQuery:

$(someParentElement).on('click', 'your span selector', function (event) {
    var myViewModelFragment = ko.dataFor(this);
    // your code here
});

$(someParentElement).on('dblclick', 'your span selector', function (event) {
    var myViewModelFragment = ko.dataFor(this);
    // your code here
});

Edit: см. также Нико!--10--> относительно поддержки как одиночных, так и двойных кликов. В основном, вы должны подсчитать количество кликов вручную и вызовите различные функции соответственно. Я предполагал, что jQuery обрабатывает это для вас, но, к сожалению, это не так.


<div data-bind="singleClick: clicked, event : { dblclick: double }">
    Click Me
</div>

это отфильтрует одиночные клики, которые также являются двойными кликами.

ko.bindingHandlers.singleClick= {
    init: function(element, valueAccessor) {
        var handler = valueAccessor(),
            delay = 200,
            clickTimeout = false;

        $(element).click(function() {
            if(clickTimeout !== false) {
                clearTimeout(clickTimeout);
                clickTimeout = false;
            } else {        
                clickTimeout = setTimeout(function() {
                    clickTimeout = false;
                    handler();
                }, delay);
            }
        });
    }
};

здесь демо.


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

приведенный ниже пример, похоже, соответствует требованию OPs и может сэкономить кому-то время (отказ от ответственности: ограниченное кросс-браузерное тестирование). JSFiddle:http://jsfiddle.net/UxRNy/

кроме того, есть вопросы о том, следует ли использовать это в первую очередь (мобильные браузеры, замедление страницы, доступность и т. д.)- но это другой пост (например,https://ux.stackexchange.com/questions/7400/should-double-click-be-avoided-in-web-applications)

пример использования:

<div data-bind="singleOrDoubleClick: { click: singleClick, dblclick: doubleClick }">
    Click or double click me...
</div>

обязательные:

ko.bindingHandlers.singleOrDoubleClick= {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var singleHandler   = valueAccessor().click,
            doubleHandler   = valueAccessor().dblclick,
            delay           = valueAccessor().delay || 200,
            clicks          = 0;

        $(element).click(function(event) {
            clicks++;
            if (clicks === 1) {
                setTimeout(function() {
                    if( clicks === 1 ) {
                        // Call the single click handler - passing viewModel as this 'this' object
                        // you may want to pass 'this' explicitly
                        if (singleHandler !== undefined) { 
                            singleHandler.call(viewModel, bindingContext.$data, event); 
                        }
                    } else {
                        // Call the double click handler - passing viewModel as this 'this' object
                        // you may want to pass 'this' explicitly
                        if (doubleHandler !== undefined) { 
                            doubleHandler.call(viewModel, bindingContext.$data, event); 
                        }
                    }
                    clicks = 0;
                }, delay);
            }
        });
    }
};

выше было собрано из сочетание примеров выше и примеров отсюда:https://gist.github.com/ncr/399624 - я просто объединил два решения.


@madcapnmckay предоставил отличный ответ, ниже приведена измененная версия, использующая ту же идею, чтобы обеспечить двойной щелчок. И используя последнюю версию knockout, vm передается обработчику как контекст. Это может работать в то же время с одним щелчком мыши.

<div data-bind="doubleClick: clicked">
    Double click Me
</div>

--

ko.bindingHandlers.doubleClick= {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var handler = valueAccessor(),
            delay = 200,
            clickTimeout = false;

        $(element).click(function() {
            if(clickTimeout !== false) {
                handler.call(viewModel);
                clickTimeout = false;
            } else {        
                clickTimeout = setTimeout(function() {
                    clickTimeout = false;
                }, delay);
            }
        });
    }
};

вот мое программное решение вопроса:

var ViewModel = function() {
  var self = this;
  this.onSingleClick = function() {
    self.lastTimeClicked = undefined;
    console.log('Single click');
  };

  this.onDoubleClick = function() {
    console.log('Double click');
  };

  this.timeoutID = undefined;

  this.lastTimeClicked = undefined;
  this.clickDelay = 500;
  this.clickedParagraph = function(viewModel, mouseEvent) {
    var currentTime = new Date().getTime();
    var timeBetweenClicks = currentTime - (viewModel.lastTimeClicked || currentTime);
    var timeToReceiveSecondClick = viewModel.clickDelay - timeBetweenClicks;

    if (timeBetweenClicks > 0 && timeBetweenClicks < viewModel.clickDelay) {
      window.clearTimeout(viewModel.timeoutID); // Interrupt "onSingleClick"
      viewModel.lastTimeClicked = undefined;
      viewModel.onDoubleClick();
    } else {
      viewModel.lastTimeClicked = currentTime;
      viewModel.timeoutID = window.setTimeout(viewModel.onSingleClick, timeToReceiveSecondClick);
    }
  };
};

ko.applyBindings(new ViewModel(), document.getElementById("myParagraph"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<p id="myParagraph" data-bind="click: clickedParagraph">Click me</p>

каждый "двойной щелчок" создается из двух щелчков мыши. Если есть "двойной щелчок", мы должны убедиться, что обработчик событий для первого одиночного щелчка не выполняется (вот почему я использую window.setTimeout & window.clearTimeout). При настройке таймеров мы также должны учитывать, что первый щелчок по элементу может быть уже двойным щелчком.

в моем коде я поставил clickDelay до 500ms. Таким образом, два клика в пределах 500 мс распознаются как "двойной щелчок". Вы также можете увеличить это значение, чтобы проверить поведение моего