feat: imp move cursor up down by position

This commit is contained in:
Weihua Lu
2021-06-09 02:21:57 +08:00
committed by Tienson Qin
parent fe3fa70fc9
commit 237857aafe
4 changed files with 141 additions and 33 deletions

View File

@@ -0,0 +1,116 @@
(ns frontend.util.cursor
(:require ["/frontend/caret_pos" :as caret-pos]
[cljs-bean.core :as bean]
[clojure.string :as string]
[frontend.util :as util]
[goog.dom :as gdom]
[goog.object :as gobj]))
(defn- closer [a b c]
(let [a-left (or (:left a) 0)
b-left (:left b)
c-left (or (:left c) js/Number.MAX_SAFE_INTEGER)]
(if (< (- b-left a-left) (- c-left b-left))
a
c)))
(defn mock-char-pos [e]
{:left (.-offsetLeft e)
:top (.-offsetTop e)
:pos (-> (.-id e)
(string/split "_")
second
int)})
(defn get-caret-pos
[input]
(when input
(try
(let [pos ((gobj/get caret-pos "position") input)]
(bean/->clj pos))
(catch js/Error e
(js/console.error e)))))
(defn move-cursor-to [input n]
(.setSelectionRange input n n))
(defn move-cursor-up [input]
(let [elms (-> (gdom/getElement "mock-text")
gdom/getChildren
array-seq)
cusor (-> input
(util/get-caret-pos)
(select-keys [:left :top :pos]))
chars (->> elms
(map mock-char-pos)
(group-by :top))
tops (sort (keys chars))
tops-p (partition-by #(== (:top cusor) %) tops)
prev-t (-> tops-p first last)
lefts
(->> (get chars prev-t)
(partition-by (fn [char-pos]
(<= (:left char-pos) (:left cusor)))))
left-a (-> lefts first last)
left-c (-> lefts last first)
closer
(if (> 2 (count lefts))
left-a
(closer left-a cusor left-c))]
(move-cursor-to input (:pos closer))))
(defn move-cursor-down [input]
(let [elms (-> (gdom/getElement "mock-text")
gdom/getChildren
array-seq)
cusor (-> input
(util/get-caret-pos)
(select-keys [:left :top :pos]))
chars (->> elms
(map mock-char-pos)
(group-by :top))
tops (sort (keys chars))
tops-p (partition-by #(== (:top cusor) %) tops)
next-t (-> tops-p last first)
lefts
(->> (get chars next-t)
(partition-by (fn [char-pos]
(<= (:left char-pos) (:left cusor)))))
left-a (-> lefts first last)
left-c (-> lefts last first)
closer
(if (< (count lefts) 2)
left-a
(closer left-a cusor left-c))]
(move-cursor-to input (:pos closer))))
(comment
;; previous implementation of up/down
(defn move-cursor-up
"Move cursor up. If EOL, always move cursor to previous EOL."
[input]
(let [val (gobj/get input "value")
pos (.-selectionStart input)
prev-idx (string/last-index-of val \newline pos)
pprev-idx (or (string/last-index-of val \newline (dec prev-idx)) -1)
cal-idx (+ pprev-idx pos (- prev-idx))]
(if (or (== pos (count val))
(> (- pos prev-idx) (- prev-idx pprev-idx)))
(move-cursor-to input prev-idx)
(move-cursor-to input cal-idx))))
(defn move-cursor-down
"Move cursor down by calculating current cursor line pos.
If EOL, always move cursor to next EOL."
[input]
(let [val (gobj/get input "value")
pos (.-selectionStart input)
prev-idx (or (string/last-index-of val \newline pos) -1)
next-idx (or (string/index-of val \newline (inc pos))
(count val))
nnext-idx (or (string/index-of val \newline (inc next-idx))
(count val))
cal-idx (+ next-idx pos (- prev-idx))]
(if (> (- pos prev-idx) (- nnext-idx next-idx))
(move-cursor-to input nnext-idx)
(move-cursor-to input cal-idx)))))