延迟:on-click事件以查看是否触发:on-double-click事件的简单方法是什么?
[:div {:on-click (fn [e]
;; listen to double-click event, within 500ms,
;; if so on-double-click-fn,
;; if not, on-click-fn
)
:on-double-click (fn [e]
;; on-click-fn
)}]谢谢!
第一次尝试:
(defn sleep [timeout]
(let [maxtime (+ (.getTime (js/Date.)) timeout)]
(while (< (.getTime (js/Date.)) maxtime))))
[:div {:on-click (fn [e] (sleep 500) (print "single-clicked"))
:on-double-click (fn [e] (print "double-clicked"))}]第二次尝试:
(def state (atom {:click-count 0}))
(defn handle-click [e click-fns-map]
(swap! state update :click-count inc)
(sleep 500)
(let [click-count (get @state :click-count)]
(swap! state assoc :click-count 0)
(cond
(= click-count 1) ((:on-single-click click-fns-map) e)
(> click-count 1) ((:on-double-click click-fns-map) e)))))
[:div
{:on-mouse-down
(fn [e]
(handle-click e {:on-single-click #(print "single-click")
:on-double-click #(print "double-click")}))}]
;;=> "single-click"
;;=> "single-click"编辑:
基于Taylor Wood's answer,这里是一个抽象,它为您包装html元素args并覆盖:on-click和:on-double-click。
(defn ensure-single-double-click
[{:keys [on-click on-double-click] :as args}]
(let [waiting? (atom false)]
(merge
args
{:on-click (fn [e]
(when (compare-and-set! waiting? false true)
(js/setTimeout
(fn [] (when @waiting?
(on-click %)
(reset! waiting? false)))
300)))
:on-double-click (fn [e]
(reset! waiting? false)
(on-double-click %))})))
[:a (ensure-single-double-click
{:style {:color "blue"} ;; this works
:on-click #(print "single-click")
:on-double-click #(print "double-click")})
"test"]发布于 2019-12-08 19:25:53
Taylor Wood's answer很接近,但compare-and-set!并没有保护我不受三次点击(甚至更多的点击!)的影响,因为如果在500 is内发生三次点击,waiting?将在第三次左右再次设置为false,并安排第二次超时。我认为这意味着技术上每一次奇数点击都会有一个新的超时。
幸运的是,click事件附带了一个名为detail的属性,该属性被设置为连续单击的次数。我找到它了here。以下内容应该解决OP的问题,而不允许三次单击:
:on-click
(fn [e]
; This prevents the click handler from running
; a second, third, or other time.
(when (-> e .-detail (= 1))
(reset! waiting? true))
; Wait an appropriate time for the double click
; to happen...
(js/setTimeout
(fn []
; If we are still waiting for the double click
; to happen, it didn't happen!
(when @waiting?
(single-click-fn %)
(reset! waiting? false)))
500)))
:on-double-click #(do (reset! waiting? false)
(double-click-fn %))尽管三重点击可能听起来有些异国情调,但它们确实起到了一定的作用:选择一整行文字,所以我不想让用户错过这种能力。
其余部分是对那些有兴趣让文本选择工作的元素的增编,这些元素只需一次点击就可以收听。我是从谷歌来的,想知道该怎么做,所以也许能帮上忙。
我遇到的一个挑战是,我的应用程序要求用户可以执行双击,而不首先释放第二次单击;有点像“一次半点击”。为什么?因为我正在监听span上的单击,用户很可能执行双击来选择一个完整的单词,但接着按下第二次单击并拖动鼠标,以便在原始单词旁边选择其他单词。问题是双击事件处理程序只有在用户释放第二次单击之后才会触发,因此waiting?没有按时设置为false。
我使用:on-mouse-down处理程序解决了这个问题:
:on-click
(fn [e]
; This prevents the click handler from running
; a second, third, or other time.
(when (-> e .-detail (= 1))
(reset! waiting? true))
; Wait an appropriate time for the double click
; to happen...
(js/setTimeout
(fn []
; If we are still waiting for the double click
; to happen, it didn't happen!
(when @waiting?
(single-click-fn %)
(reset! waiting? false)))
500)))
:on-double-click #(double-click-fn %)
:on-mouse-down #(reset! waiting? false)请记住,:on-click和:on-double-click处理程序只在发布时触发(并且处理程序按鼠标向下、单击、双击的顺序启动),这使:on-mouse-down处理程序有机会将waiting?设置为false,如果用户尚未释放鼠标,则需要将其设置为false,因为他不会触发:on-double-click事件处理程序。
请注意,现在您甚至不需要在双击处理程序中将waiting?设置为false,因为鼠标向下的处理程序在运行双击处理程序时已经完成了该操作。
最后,在我的特定应用程序中,用户可能希望在不触发单击处理程序的情况下选择文本。为了做到这一点,他将点击一段文字,在不释放鼠标的情况下,拖动光标来选择更多的文本。当游标被释放时,不应该触发单击事件。因此,我必须另外跟踪用户是否在松开鼠标(一种“半点击”)之前在任何时候做出选择。在这种情况下,我不得不向组件的状态添加一些东西(一个名为selection-made?的布尔原子和一个名为selection-handler的事件处理程序函数)。这种情况依赖于对选择的检测,而且由于选择是在双击下进行的,因此不需要再检查事件的细节属性来防止三次或更多的单击。
整个解决方案看起来是这样的(但是请记住,这是专门针对文本元素的,因此只是OP要求的一个补充):
(defn component
[]
(let [waiting? (r/atom false)
selection-made? (r/atom false)
selection-handler
(fn []
(println "selection-handler running")
(when (seq (.. js/document getSelection toString))
(reset! selection-made? true)))]
(fn []
[:div
; For debugging
[:pre {} "waiting? " (str @waiting?)]
[:pre {} "selection-made? " (str @selection-made?)]
; Your clickable element
[:span
{:on-click
(fn [e]
(println "click handler triggered")
; Remove the selection handler in any case because
; there is a small chance that the selection handler
; was triggered without selecting any text (by
; holding down the mouse on the text for a little
; while without moving it).
(.removeEventListener js/document "selectionchange" selection-handler)
(if @selection-made?
; If a selection was made, only perform cleanup.
(reset! selection-made? false)
; If no selection was made, treat it as a
; simple click for now...
(do
(reset! waiting? true)
; Wait an appropriate amount of time for the
; double click to happen...
(js/setTimeout
(fn []
; If we are still waiting for the double click
; to happen, it didn't happen! The mouse-down
; handler would have set waiting? to false
; by now if it had been clicked a second time.
; (Remember that the mouse down handler runs
; before the click handler since the click handler
; runs only once the mouse is released.
(when @waiting?
(single-click-fn e)
(reset! waiting? false)))
500))))
:on-mouse-down
(fn [e]
; Set this for the click handler in case a double
; click is happening.
(reset! waiting? false)
; Only run this if it is a left click, or the event
; listener is not removed until a single click on this
; segment is performed again, and will listen on
; every click everywhere in the window.
(when (-> e .-button zero?)
(js/console.log "mouse down handler running")
(.addEventListener js/document "selectionchange" selection-handler)))
:on-double-click #(double-click-fn %)}
some content here]])))发布于 2018-02-25 02:10:42
有一种方法可以做到:
(defn slow-link [text single-click-fn double-click-fn]
(let [waiting? (atom false)]
[:a {:on-click #(when (compare-and-set! waiting? false true)
(js/setTimeout (fn [] (when @waiting?
(single-click-fn %)
(reset! waiting? false)))
500))
:on-double-click #(do (reset! waiting? false)
(double-click-fn %))}
text]))
[slow-link "Test" #(prn "single-click") #(prn "double-click")]这将启动一个JS定时器,该定时器将在500 JS之后执行给定的函数。该函数检查超时结束时是否仍然是waiting?,如果是,则执行single-click-fn。如果我们不是waiting?,这意味着双击事件已经发生,请将waiting?重置为false,并调用double-click-fn。
:on-click处理程序使用compare-and-set只在我们还没有处于waiting?状态时才采取行动,避免了三次/四次单击时的一些活跃行为,等等。
https://stackoverflow.com/questions/48969496
复制相似问题