hi, yes a realtime version of what medium (or google docs) is sort of what I’m after.
I can do it in javascript and that might be a better solution honestly, but my goal is to try to avoid javascript as much as possible (mainly for my own learning). It’s definitely necessary for the window selection api, but I’m hoping that’s all I use it for.
The challenge that I’ve run into so far is that just given highlights (structs that define start and ends of a highlight), constructing the ui with eex is difficult, so I had to create a second data structure that made this easier that I called a chunk for now.
defmodule Qda.Chunk do
defstruct content: "", highlight: false
def chunkify(content, highlights), do: chunkify(content, 0, highlights)
def chunkify("", _offset, _highlights), do: []
def chunkify(suffix, _offset, []), do: [%__MODULE__{content: suffix, highlight: false}]
def chunkify(content, offset, highlights) do
[ highlight | tail ] = highlights
{prefix, highlight_start} = String.split_at(content, highlight.start_offset - offset)
{highlighted_content, suffix} = String.split_at(highlight_start, highlight.end_offset - highlight.start_offset)
case prefix do
"" -> []
str -> [%__MODULE__{content: str, highlight: false}]
end
++ [%__MODULE__{content: highlighted_content, highlight: true}]
++ chunkify(suffix, String.length(prefix) + String.length(highlighted_content) + offset, tail)
end
end
There I have a function that given some text and some highlights, computes the chunks for the document. Then in my eex I can do something like this to render all the chunks (with the selections bolded):
<div id="contents" phx-hook="DocumentContents">
<%= for chunk <- @chunks do %>
<%= if chunk.highlight == true do %>
<b><%= chunk.content %></b>
<% else %>
<span><%= chunk.content %></span>
<% end %>
<% end %>
</div>
If I add a new chunk, will live view know not to push the other chunks down the wire (and not rerenader the other parts of the dom)?
Is this the right way to approach the problem? I’m new to elixir + phoenix, so if anyone has suggestions, I’d love to hear them! Thanks 