在ClojureScript中,延迟`:on-click`事件并仅在未触发`:on-double-click`事件时触发

leo*_*bot 2 clojure clojurescript reagent

:on-click如果:on-double-click事件被触发,有什么简单的方法来延迟事件首先查看?

[:div {:on-click "listen to double-click event, within 500ms, 
             if so on-double-click-fn, 
             if not, on-click-fn"
       :on-double-click "on-click-fn"}]
Run Code Online (Sandbox Code Playgroud)

谢谢!

第一次尝试:

(defn sleep [timeout]
  (let [maxtime (+ (.getTime (js/Date.)) timeout)]
    (while (< (.getTime (js/Date.)) maxtime))))

[:div {:on-click #(do (sleep 500) (print "single-clicked"))
       :on-double-click #(print "double-clicked")}]
Run Code Online (Sandbox Code Playgroud)

第二次尝试:

(def state (atom {:click-count 0}))

(defn handle-click [e click-fns-map]
  (do (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"
Run Code Online (Sandbox Code Playgroud)

编辑:

基于已接受的答案,这里是一个抽象包装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 #(when (compare-and-set! waiting? false true)
                   (js/setTimeout (fn [] (when @waiting?
                                           (on-click %)
                                           (reset! waiting? false)))
                                 300))
      :on-double-click #(do (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"]
Run Code Online (Sandbox Code Playgroud)

Tay*_*ood 6

这是一种方法:

(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")]
Run Code Online (Sandbox Code Playgroud)

这将启动一个JS计时器,它将在500ms后执行给定的函数.该函数检查waiting?在超时过去时我们是否还在进行另一次单击,如果是,则执行single-click-fn.如果我们不是waiting?那个意味着双击事件已经发生,重置waiting?false并调用double-click-fn.

:on-click处理器使用compare-and-set,如果我们在一个很没有只采取行动waiting?的状态,避免了三/四击等一些活泼的行为