Document.write in Clojurescript? - clojurescript

It's very often convenient to be able to print things in a simple way when debugging.
How do I call document.write in Clojurescript?

Like so:
(.write js/document "hey")

Related

How to turn text into DOM elements using Clojurescript? (And Om?)

In a ClojureScript/Om app, I have a DOM and a string of HTML.
How can I translate that string of HTML into elements I can insert into the DOM?
I've started down the path of parsing the HTML with hickory, planning to then process the hickory data to create DOM elements, but I think there must be a simpler way I'm overlooking.
(I don't need to validate the HTML, I can assume it's safe and valid enough.)
You don't need to parse the HTML string. It's unnecessary overhead. React/Om supports something like DOM's innerHTML property. Just set the prop this way:
(om.dom/div #js {:dangerouslySetInnerHTML #js {:__html "<b>Bold!</b>"}} nil)
If you work with plain DOM without Om, set the innerHTML property like:
(let [div (. js/document getElementById "elId")]
(set! (. div -innerHTML) "<b>Bold!</b>"))
Aleš Roubíček answer is much better. I'll leave this un case it helps somebody.
Hickory offers a as-hiccup function. Hiccup uses Clojure data structures to represent HTML. You could feed those data structures to Clojurescript libraries that follow the same conventions:
Hiccups to generate regular DOM elements.
Sablono to generate React DOM elements and use with Om.
You could also use Kioo/Enfocus and instead of passing a file path, pass the string directly. This would be more direct and instead of using two libraries (Hickory + Sablono) you would use only one. The caveat is that Kioo and Enfocus follow the Enlive style of templating (which is great but has a learning curve) and the docs are focused on file paths and not strings (even though it is possible to pass strings).

Why aren't NodeList / HtmlCollection seqable?

As a newcomer to Clojurescript it appears to me that every Clojurescript project will have some snippet of code like this:
(extend-type js/NodeList
ISeqable
(-seq [array] (array-seq array 0)))
Why isn't this part of the core library?
You have to think that clojurescript is a compiler to javascript as a language, not only browser JavaScript. You can also use it in other platforms like nodejs or with the QT library where NodeList does not exist (because it is part of the Dom api and not the standard language).
If you are looking for a way to create a sequence from a NodeList there is array-seq function.
(array-seq (js/document.querySelectorAll "div"))
With a patch for https://clojure.atlassian.net/browse/CLJS-3199 applied in ClojureScript 1.10.741 (seq (js/document.querySelectorAll "div")) now actually works out of the box.

How to set an attribute of a DOM element in Clojurescript?

I wish to set the "value" property of an "input" element using Clojurescript, but I am having trouble with the syntax of setProperties in goog.com. Has anyone got a working example?
Update
------
This seems to work:
(goog.dom.setProperties
(goog.dom/getElement "element-name")
(clj->js {:value "text"}))
If you need to create throwaway JS objects for use with JS APIs, you can do so directly using js-obj:
(js-obj "value" "text")
;; produces {"value": "text"} in the compiled output
Of course if you already have a ClojureScript map with the appropriate entries, clj->js will be more convenient.
More importantly, you might want to consider switching to a ClojureScript library for DOM manipulation. Several are available:
Luke VanderHart's Domina, which might have been the first one, is used by Enfocus (listed below) and Pedestal;
Prismatic's dommy, notable due to its own merits as well as the very entertaining blog posts about it on Prismatic's blog (which can serve as a great introduction to the benefits of macros: first one, second one, third one);
Creighton Kirkendall's Enfocus, which is in a nutshell an Enlive-like library for ClojureScript, which is awesome;
Kevin Lynagh's Singult, which is a Hiccup-style library for ClojureScript with cool functionality for merging in changes to the DOM, rather than rerendering from scratch.

PREG_REPLACE in MySQL and PREG_REPLACE_EVAL

I'm using this UDF for the PREG_REPLACE function in MySQL and everything seems to be working fine so far. However, my goal now is to find and encode entities inside pre tags in a column. So ultimately I'd like to get this:
<pre>
<strong>Hello World!</strong>
</pre>
To look like this:
<pre>
<strong>Hello World!</strong>
</pre>
I'm using the PREG_REPLACE function to find the contents inside the pre tags like this:
SELECT PREG_REPLACE('/<pre>(.*?)<\\/pre>/sm', '\\1', '<pre><strong>Hello World</strong></pre>');
Now I'd like to replace \\1 with something that would say "replace with ENCODE_ENTITIES('\\1'). Obviously it could be any other function, like UPPER for example, but UPPER('\\1') doesn't give much. I kind of like the idea of PREG_REPLACE_EVAL in PHP's implementation of preg_replace which allows something like this:
preg_replace("/(<\/?)(\w+)([^>]*>)/e",
"'\\1'.strtoupper('\\2').'\\3'",
$html_body);
Any ideas on how to implement something similar in MySQL? Or maybe I'm heading the wrong way? Thanks!
Unless you want to modify the source code for the UDF to add that feature, there's no way to do that in MySQL. I suggest you pick your favorite programming language and write a program to make the update for you, or perhaps ensure that this modification is performed before the data hits the database.

How can I modify a local HTML file in Perl?

Is there a CPAN module or code snippet that I can use to modify local HTML files without using a regExp?
What I want to do :
Change the start tag ( example : <div> to <div id="newtag"> )
Add a tag before another ( example : </head> to <script type="text/javascript"> ...</script></head>
Remove tags
Read the content of a given tag. (<- ok this can be done with an XML / HTML parser.
If you have HTML, and not XHTML, then you don't want to be using an XML parser.
HTML::Parser is the standard HTML parser for Perl. Pretty much everything else is built on top of it.
HTML::TokeParser is an alternative interface to HTML::Parser. It returns things on demand instead of passing everything to callbacks.
HTML::TreeBuilder builds a DOM-like tree from the HTML, which you can then modify.
HTML::TreeBuilder::XPath extends HTML::TreeBuilder with XPath support.
HTML::Query extends HTML::TreeBuilder with jQuery-like selectors.
pQuery is another module that brings more complete jQuery compatibility to HTML::TreeBuilder.
CPAN
XML::XPATH
XML::Xerces
A simple CPAN search returns
XML Search
XPATH
XPATH Tutorial
It sounds like you are not familiar with XPath. Here is a quick tutorial to get you familiar. Its not Perl but it will explain the concepts.