reitit.frontend - HTML5Router does not prevent anchor click as should on matching route - clojurescript

if we choose HTML5Router or Fragment router - in both cases reitit should prevent default anchor click behavior
however, ignore-anchor-click function here is never called
https://github.com/metosin/reitit/blob/0.5.18/modules/reitit-frontend/src/reitit/frontend/history.cljs#L109
because a few lines below goog.events/listen is missing true 4th arg - so browser first captures click and never gets to document.click
https://github.com/metosin/reitit/blob/0.5.18/modules/reitit-frontend/src/reitit/frontend/history.cljs#L124
is
(gevents/listen js/document goog.events.EventType.CLICK ignore-anchor-click))
should be - then all works
(gevents/listen js/document goog.events.EventType.CLICK ignore-anchor-click true))
question
is there a way to change this behavior without PR or forking?

solution
copy function code from reitit.frontent.history
using history ref unsubscribe and resubscribe
(let [history (Yzma.frontend.easy/start! _ _ _)]
(goog.events/unlistenByKey (:click-listen-key history))
(goog.events/listen
js/document
goog.events.EventType.CLICK
(fn [event]
(when-let [element (Yzma.frontend.history/closest-by-tag
(Yzma.frontend.history/event-target event) "a")]
(let [uri (.parse goog.Uri (.-href element))]
(when (Yzma.frontend.history/ignore-anchor-click?
(.-router history) event element uri)
(.preventDefault event)
(let [path (str (.getPath uri)
(when (.hasQuery uri)
(str "?" (.getQuery uri)))
(when (.hasFragment uri)
(str "#" (.getFragment uri))))]
(.pushState js/window.history nil "" path)
(Yzma.frontend.history/-on-navigate history path)))))) true))

Related

Turn vimscript key mapping into function

I am trying to make a function in vimscript that will activate on every cursor movement in visual mode, i.e. it will automatically highlight all the matches of the current visual selection.
The mapping from https://vi.stackexchange.com/questions/20077/automatically-highlight-all-occurrences-of-the-selected-text-in-visual-mode:
xnoremap <silent> <cr> "*y:silent! let searchTerm = '\V'.substitute(escape(#*, '\/'), "\n", '\\n', "g") <bar> let #/ = searchTerm <bar> echo '/'.#/ <bar> call histadd("search", searchTerm) <bar> set hls<cr>
works perfectly for me but I am failing to implement it into function. This is what I tried:
function! HighlightVisual(mode)
if mode()=~#"^[vV\<C-v>]"
call feedkeys('"*y')
let searchTerm = '\V'.substitute(escape(#*, '\/'), "\n", '\\n', "g")
let #/ = searchTerm
echo '/'.#/
call histadd("search", searchTerm)
set hls
endif
endfunction
autocmd CursorMoved * call HighlightVisual(mode())
However, it is not working.
What am I doing wrong? I think the function is terminated each time a call is invoked but have no idea how to workaround that.
I have made it work. Firstly, I found from https://vi.stackexchange.com/questions/28404/vim-does-not-call-functions-correctly-when-wrapped-in-another-function that "Vim doesn't like updating Screen too often" so redraw was necessary after set hls. And secondly, y was forcing normal mode and gv was moving cursor triggering the autocmd CursorMoved inside the function thus making an infinite loop. I made a workaround by set eventignore=CursorMoved and resetting it back at the end of function. I am saving selected word to register h (as in highlight) but you can choose any by changing "hy and #h. Moreover, I added highlight toggle when not needed. So, if somebody wants to use the feature of automatically highlighting visual matches, here is the code:
function! HighlightVisual(mode)
if mode()=~#"^[vV\<C-v>]"
set eventignore=CursorMoved
normal "hy
normal gv
let searchTerm = '\V'.substitute(escape(#h, '\/'), "\n", '\\n', "g")
let #/ = searchTerm
call histadd("search", searchTerm)
set hls
redraw
set eventignore=""
endif
endfunction
autocmd CursorMoved * :call HighlightVisual(mode())
vnoremap <silent> <ESC> :<C-u>set nohlsearch<CR>
; just copy-paste it in your .vimrc/init.vim.
Big thanks to trusktr as I used his answer in https://vi.stackexchange.com/questions/20077/automatically-highlight-all-occurrences-of-the-selected-text-in-visual-mode to build my function I wanted for sooo long.
Happy coding!

"Autosave" Functionality in ClojureScript

I'd like to add an "autosave" feature to a Reagent form in a ClojureScript function. In Clojure, I usually make something out of a ScheduledExecutorService. Since that isn't available in ClojureScript, I came up with the following.
(def delay-handle (atom nil))
(defn clear-autosave-delay! []
(.clearTimeout js/window #delay-handle))
(defn start-autosave-delay!
[doc-save-fn delay-ms page-map-atom]
(reset! delay-handle (.setTimeout js/window doc-save-fn delay-ms page-map-atom)))
(defn change-watcher!
[doc-save-fn page-map-atom]
(let [delay (* 1000 (get-in #page-map-atom [:options :editor_autosave_interval]))]
(when (pos? delay)
(clear-autosave-delay!)
(start-autosave-delay! doc-save-fn delay page-map-atom))))
I put the change-watcher! function in the Reagent :on-change handlers for the input controls. Whenever a change occurs, it resets the delay. If the delay expires, the doc-save-fn is called to do the save.
It seems to work Ok, but isn't very "Clojuresque." Is there a more idiomatic way to write this?​
Use debouncer for this issue. It's pretty simple and does same
(goog.functions.debounce auto-save-action 1000)

How to Switch Tags in Hoplon

If I have the following code and a function to switch from 'p' tag to 'h1' tag:
(def switch-tag (cell p))
And later on in the hlisp
((cell= switch-tag) "Text goes here")
How come when I switch to the h1 tag nothing seems to happen.
I have been unable to solve this your way. Here is a workaround:
(page "index.html")
(def key! (cell true))
(defelem my-elem [_ [child]]
(cell= (if key! (h1 child) (p child))))
(html
(body
(button :click #(swap! key! not) "test")
(my-elem "this is a test")))

Normal instance method calls within a clojure doto

I'm setting up a swing UI in clojure and have a block like:
(doto main-frame
(.setUndecorated true)
(.setExtendedState Frame/MAXIMIZED_BOTH)
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.setVisible true)
)
But now I want to call
(.setBackground (.getContentPane main-frame) Color/BLACK)
before I set the frame visible, is there a nicer way to do this than ending the doto and using the (.instanceMember instance args*) syntax?
If you really want a single doto, then maybe this will do:
(doto main-frame
(.setUndecorated true)
(.setExtendedState Frame/MAXIMIZED_BOTH)
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(-> (.getContentPane) (.setBackground Color/BLACK))
(.setVisible true))
The above relies on the fact that doto is not confined to Java methods, it just inserts its first argument (evaluated) as first argument of every form that follows.
I'd go with ending the doto though as the above is not very readable. Alternatively, maybe just define a set-background-on-content-pane function (that obviously takes the main-frame) and use that in the doto:
(defn set-bg-on-frame [fr color] (.setBackground (.getContentPane fr) color))
(doto main-frame
.
.
.
(set-bg-on-frame Color/BLACK)
(.setVisible true))

Image Processing, extending JPanel and Simulating Classes in Clojure

there! I'm building an image-processing application in swing/clojure, and right now I need to develop an image panel in which I can click and compute data. Thanks to coobird, I now have a good idea on how to do it in Java, but I still don't get many issues on its integration with Clojure.
Let's take a look at how coobird suggested me doing. First, we should extend a class in Java. In clojure, we do this with the proxy macro, so we'd have something like this:
(def painting-panel
(proxy [JPanel] []))
The next step is to create the class constructor and set some variables.
I can define functions after the second argument of proxy, but how can I create the constructor? Is painting-panel the name of this class (therefore the name of the function I should create)?
How can I deal with class variables? Should I define them with a let, like I did?
Are this and super available for me to use, like I did below?
(def painting-panel
(let [background-image (Image.)
point-clicked (Point.)]
(proxy [JPanel] []
(paintComponent [g]
(do ((.paintComponent super) g)
(doto g
(.drawImage background-image 0 0 nil)
(.fillRect (.x point-clicked) (.y point-clicked) 1 1))))
(painting-panel []; constructor?
((.addMouseListener this)
(proxy [MouseAdapter] []
(mouseClicked [e]
(do
(def point-clicked (.getPoint e))
(.repaint this)))))))))
Suggestions and code corrections are also welcome!
Thank you!
proxy actually creates an instance tada! You don't need to create a constructor.
Yes, but consider using a clojure ref instead. Also using def like that on the second last line is nasty! it creates a global binding for point-clicked when your logic relies on the lexically scoped one created by let.
(proxy-super paintComponent g), and yes "this" is available
This works for me:
(let [click (ref nil)
panel (proxy [javax.swing.JPanel] []
(paintComponent [g]
(proxy-super paintComponent g)
(.drawImage g (.getImage
(javax.swing.ImageIcon. "play.png"))
0 0 (.getWidth this) (.getHeight this) nil)
(if #click
(.fillRect g (:x #click) (:y #click) 10 10))))]
(.addMouseListener panel
(proxy [java.awt.event.MouseAdapter] []
(mouseClicked [e]
(let [p (.getPoint e)]
(dosync (ref-set click {:x (.x p), :y (.y p)})))
(javax.swing.SwingUtilities/invokeLater #(.repaint panel)))))
(doto (javax.swing.JFrame.)
(.setContentPane panel)
(.setSize 200 200)
(.show)))