It is natural for javascript to operate with mutable references, so you'll have to introduce them sooner or later (not necessarily IORef
s, maybe some kind of lookup table living in state monad).
If most of operations on DOM will be performed from javascript, then it is better to select data structure natural for it.
Don't try to use pure data structure only for purity itself. Otherwise you'll finish with hand-made emulation of RAM :) Your task looks imperative for me, so why not to use all the imperative features haskell provides?
I don't think zippers, as Niklas B. suggested, can help you a lot. Usually they have only one "cursor", where you can mutate. (AFAIK in theory any number of cursors are possible, but in practice it is mostly unusable)