HTML startapp view inside Graphics.element.container - elm

I am trying to place my html view in the middle of a container.
Unfortunately, container gives output of type Graphics.Element.Element whereas html view must be of the type, Html.Html.
And also, the html element constructors like div, checkbox, button, body return type is Html whereas, container needs a Graphics.Element parameter.
This is an erroneous html view, which i would like to make it work,
view : Signal.Address Action -> Model -> Element
view address model =
container 1000 1000 middle <|
toForm <|
div []
[ button [ onClick address Decrement ] [text "-"]
, div [ countStyle ] [ text (toString model ) ]
, button [ onClick address Increment ] [ text "+" ]
]
It has two buttons, one div all placed in the middle of a 1000 * 1000 container.

The elm-html package has a fromElement that can be used to create an Html from an Element.
I will say though, the idea with elm-html is to allow for a more "normal" flow of rendering HTML and using CSS to style it. While it would work to take your Html, convert it to an to either a Form or Element, use a collage or container to move it to the center of some area, and then convert back to Html, I'd probably recommend against it. If you're using HTML, just render that and style it (either with an external stylesheet or withHtml.Attributes).

Related

JSON content shows a blank window for Tiptap-Vuetify?

Background
I'm using tiptap-vuetify to implement a message/chat UI where users see an editable Tiptap instance for creating new messages as well as several uneditable Tiptap instances (one for each already-sent message in the thread the user is viewing).
I have the editable instance output data in JSON format, which I store in my database in a JSONB field.
Problem
When I load the JSON for sent messages from the database, only plaintext messages show up; if I applied any kind of styling (bold, italics, lists, etc.), nothing at all shows up.
The code I'm using for the uneditable Tiptap instances is this:
<tiptap-vuetify
v-model="message.content"
:editor-properties="{ editable: false }"
output-format="json"
/>
Here's a screenshot of the message object (and message.content) for the "bold asdf" example above:
When i was looking in the documentation -> Get started
I see that the content is HTML.
As it usually is inside any tiptap.
Your content data is an object with alot of nested data. I don't think the plugin/component can handle that type of format.
Try save your data as HTML to your .json and there for also fetch the data as HTML from your .json.
Example:
{
messages: [
{
"id": 1,
"content": "<p>foo bar</p>"
},
{
"id": 2,
"content": "<p>hello world</p>"
},
]
}
(New to answer questions on stackoverflow)
I figured out the fix:
I didn't realize I needed to include the :extensions prop for all of the HTML features I wanted to use (bold, italic, etc.) in the editor that would render the HTML. I thought those extensions were just used to add the toolbar buttons, but they are also used to render the JSON that those buttons produce.
To then hide the toolbar, I just used the example toolbar-slot code from the readme, and the toolbar was gone.
Here's the working code:
<tiptap-vuetify
v-model="message.content"
:extensions="extensions"
:editor-properties="{ editable: false }"
>
<template #toolbar="{ buttons }">
<pre>{{ buttons }}</pre>
</template>
</tiptap-vuetify>

How do I save an svg image

Let's say I have made an svg image in Elm:
svg [ viewBox "0 0 100 100" ] [ circle [ cx "60", cy "60", r "50" ] [] ]
How do I go about saving that image?
Just embedding it in html and right clicking doesn't work; and I can't find any other way to use it.
edit:
The "best" I've gotten so far is to use inspect mode and copy the generated html, save that as a file manually. This was enough to unblock me currently. Obviously that could be scripted with JavaScript, but I'm looking for an Elm solution.
The actual usecase I have is that I generate an identicon in Elm; like for instance Phace; my own package though, since the images should make sense in my app.
I want to be able to save the actual image, rather than the data used to generate it. Converting it to a png would be fine for this, though I prefer an svg.
You can use elm-svg-string instead of the official SVG library and produce the string version of the SVG. You can then take the string version, encode it with Url.percentEncode and use it as the href for a download link and as src for an image in order to display it for preview purposes
module Main exposing (main)
import Browser
import Html exposing (Html, a, br, div, img, text)
import Html.Attributes exposing (download, href, src)
import Svg.String as Svg exposing (Svg)
import Svg.String.Attributes as Attr exposing (attribute, viewBox)
import Url
someSvg : Svg.Html msg
someSvg =
Svg.svg
[ attribute "xmlns" "http://www.w3.org/2000/svg"
, viewBox "0 0 100 100"
]
[ Svg.circle
[ Attr.cx "60"
, Attr.cy "60"
, Attr.r "50"
, Attr.style "fill: red; stroke: blue"
]
[]
]
asString : String
asString =
someSvg
|> Svg.toString 2
asData =
"data:image/svg+xml;utf8," ++ Url.percentEncode asString
main =
div []
[ text <| asString
, br [] []
, a [ download "image.svg", href asData ]
[ img [ src asData ] [] ]
]
In the above example, clicking on the image will result in the image being downloaded.

A way to detect a click anywhere but a specific control?

In my app the user can click on a div to highlight it. Is there a way to detect that they've clicked somewhere away from the div? I'd like to unhighlight selected things when this happens. I tried adding an onclick to the big div that contains everything else, but that doesn't really work as desired. IIRC the big div onclick always happens after the contained div onclick, so you can't ever select anything.
You can do this by adding a on "click" event to both the divs and then in the inner div, use onWithOptions to stop the propagation of the event. Here's some (untested) code:
onClickStop msg =
onWithOptions "click"
{ stopPropagation = True, preventDefault = False }
(Json.succeed msg)
view _ =
div [ onClick Clicked ]
[ div [ onClickStop NoOp ] []
]
When the user clicks inside the nested div, the event will be ignored and its propagation to its parent will be cancelled. Only when the user clicks outside the inner div will the Clicked message will be sent to update.

How do I retrieve text from an html element?

How do I get the caption from a button?
decorateOn : String -> Html Msg -> Html Msg
decorateOn selectedCaption button =
if button.text == selectedCaption then
button [ class "selectedNavigationButton" ] []
else
button [ class "navigationButton" ] []
button does not have a field named text. - The type of button
is:
Html Home.Msg
Which does not contain a field named text.
Note, I realize that the "button" is really of type Html Msg.
You need to turn your thinking on its head. Rather than seeing what is in the button text, you need to set the text at the same stage as setting the class. So that gives you something like
decorateOn : String -> Html Msg -> Html Msg
decorateOn selectedCaption button =
if selectedCaption == "the selected value" then
button [ class "selectedNavigationButton" ] [text selectedCaption ]
else
button [ class "navigationButton" ] [text selectedCaption]
You can't get the text from a button without resorting to hacks involving ports and JavaScript. Moreover, you can't really inspect anything about the Elm Virtual DOM from within Elm.
Instead, try to refactor your app so that you can get the information from your model.

I want JAWS to tell the user what kind of node they are in while navigating the dijit.Tree

We have a dijit.Tree that indicates a node type by using an icon. The icon is a unique indicator that tells the person this node is a "book" or a "DVD" or a "magazine" for example.
dijit renders the icon as a background image in CSS which we know screen readers do not see.
I tried overriding the getTooltip method to provide a tooltip saying "book" or "DVD". It successfully adds the "title" attribute to the "dijitTreeRow". If I mouse over the node, I see the text. This is not ever focused on when the user moves down to get from one node to the next.
When navigating the tree, the up and down arrows traverse the nodes. The span with the visible text is focused on and that string is read. You can see the dotted line focus as well as hear this with JAWS in the most basic of examples: https://dojotoolkit.org/reference-guide/1.10/dijit/Tree.html
What I have not been able to figure out is how to create an indicator that the screen reader will pick up on that will read "Book" alongside "The Great Gatsby".
Does anyone have any tips on how they made this dijit widget accessible for the screen reader when the images are an indicator that should be heard by the blind user?
The tree supports HTML labels, via setting the labelType property on the model you give it.
Assuming you don't want to change the store data (or override the getLabel method), you can reimplement dijit/Tree.getLabel and produce the HTML label, and wrap it with a span with an aria-label.
(code lifted from the dijit.Tree reference).
var myModel = new ObjectStoreModel({
store: myStore,
labelType: "html", // Hack to tell the tree node to render as HTML
query: {id: 'world'}
});
var tree = new Tree({
model: myModel,
getLabel: function(item) {
var label = this.model.getLabel(item);
// dojo.string
return dstring.substitute("<span aria-label='dvd ${0}'>${0}</span>", [label]);
}
});
If your data might contain HTML-ish characters that you don't want to render, escape the characters in getLabel too.