1
votes

I'm not so much looking for specific code but rather overall approaches for dealing with the following situation: A user can, by way of click and drag, create a new div wrapped text (lets call it a text node). I want to somehow save the state of the user modified DOM.

Check my JSBin sample to see exactly what I mean.

The code's been extracted from my Ember project but this is what it does:

  1. The Click to edit area is just an Ember view
  2. When you drag it to the workspace, Click to edit is cloned and all Ember bindings are lost (which is totally fine)

So after a user adds one or many text nodes to the workspace I end up with something like this:

<div class="workspace">
  <div class="text" style="top: 86px; left: 141px;">Text Node 1</div>
  <div class="text" style="top: 99px; left: 100px;">Text Node 2</div>
  <div class="text" style="top: 10px; left: 44px;">Text Node 3</div>
</div>

tl;dr (get to the **cking question already)

How would I save this information so I can faithfully recreate the users changes on another page?

Some ideas

  1. On route change, loop through every DOM element with the .text class and create an object which store the DOM text and style attributes? I'd then have to create a 'build' type function that loops through the objects and recreates those DOM elements on a given page.
  2. On route change, loop through every DOM element and save each one into an array as a jQuery object. 'Rebuilding' would just be a question of looping each item in the array and appending to the DOM.

In closing, what do you think? Ideas, criticisms & past experiences are very much welcome.

1

1 Answers

2
votes

Looping through the DOM to extract the state would be useful to try things out but would get messy once you start having multiple types of objects, optional attributes, etc.

What you have is essentially a Canvas that contains different types of objects. Each object is displayed with a different UI depending on its attributes.

The objects on the Canvas are shapes with some manner of polymorphism. Eg:- Rectangle > Shape, Note > Shape, etc.

A Shape would be a basic data structure that hold common data for a shape, like x,y coordinates, dimensions, so on.

The subclasses like Note would have a label attribute that stores the text for that note. Similarly other shapes would store additional data that they need.

Each Shape needs to provide some way to serialize and deserialize data into JSON. For instance, if I do shape = new Note(); shape.deserialize({ ... }), it would populate the shape with data from the json.

On the flip side, if I do shape.serialize() it will return a JSON representation of the data of the shape. Eg:- { x: 10, y: 10, label: 'test', width: 100, height: 100 }.

Now you need a corresponding view object that displays this shape. Each shape could have a ShapeView that given a shape object as data, renders it on the DOM.

Then a CanvasView using a CollectionView would given an array of shapes, display the shape using it's View and then put it at the correct position.

All this gives you a Canvas model that stores the state of the canvas. And a corresponding CanvasView that renders the state for that model. So at any point in time you can call canvasModel.serialize() which gives you some json that holds the state of the canvas. You can save this to the server.

And later use canvasModel.deserialize() to restore the canvas to a previous state.

This is the gist of a simple editor. This stuff is the foundation of most games. Usually the CanvasView is very smart, drawing on stuff on screen, doing scrolling, animation, etc.