Knockoutjs один и двойной щелчок
Я хочу, чтобы иметь возможность привязывать одно и двух кликов к диапазону текста. Я знаю, что могу использовать
data-bind ="event: { dblclick: doSomething }
для двойного щелчка, но мне также нужна возможность выполнять другую функцию одним кликом. Любые предложения?
Ответы
Ответ 1
Во-первых, я бы не рекомендовал привязку 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
});
Изменить: см. также предложение Niko относительно поддержки одиночных и двойных кликов. В принципе, следует подсчитать количество кликов вручную и соответствующим образом вызвать различные функции. Я предположил, что jQuery обрабатывает это для вас, но, к сожалению, этого не делает.
Ответ 2
<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);
}
});
}
};
Здесь - демонстрация.
Ответ 3
Вышеупомянутые ответы были очень полезны, но не дали точного решения, я считаю, что OP был после: простая привязка Knockout, которая позволяет использовать эксклюзивные события с одним и двумя кликами. Я знаю, что сообщение было год назад, но я нашел эту статью, когда собираюсь сделать то же самое сегодня, поэтому я отправляю сообщение, если этот ответ полезен кому-то другому.
Нижеприведенный пример, похоже, соответствует требованию OP и может сэкономить время на некоторое время (отказ от ограниченного кроссбраузерного тестирования). 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 - я просто объединил два решения.
Ответ 4
@madcapnmckay дал отличный ответ,
ниже - модифицированная версия, использующая ту же идею, что и двойной щелчок. И, используя последнюю версию нокаута, 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);
}
});
}
};
Ответ 5
Вот мое решение для программирования на вопрос:
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>