Skip to content

Instantly share code, notes, and snippets.

@bkardell
Last active August 29, 2015 13:56
Show Gist options
  • Save bkardell/9265476 to your computer and use it in GitHub Desktop.
Save bkardell/9265476 to your computer and use it in GitHub Desktop.
object mapping to DOM

We identify HTML :mappable types. All form elements are :mappable, but it should be plausible to create your own.

:mappable types have a .mapToObject(?Object) method and an .mapFromObject(Object) methods

##mapToObject(?Object)

Given

    <input name="foo" value="bar">

I can call:

    var o = document.querySelector("input[name='foo']").maptoObject()

and it will map this into an object:

	{ "foo": "bar" }

I can provide it an existing object:

    var om = document.querySelector("input[name='foo']").mapToObject({"hello": "world"});

and it will set it's mapped values into the provided object:

    { "hello": "world", "foo": "bar" }

The .mapToObject() method can be overridden/provided by custom elements to provide custom mappings.

##mapFromObject(Object) Likewise, :mappable objects have a .mapFromObject(object) which inverts the process. Given an object it can set the values of the element according to the mappings, so, given:

<input name="foo">
<script>
    document.querySelector('input').mapFromObject({ "hello": "world", "foo": "bar" });
</script>

The form will wind up as

    <input name="foo" value="bar">

Just as before, this element can be overridden too. Overriding both would allow you to, for example, create something that mapped to the text content of a span instead of the standard name/value strategy.

##HTMLFormElement HTMLFormElement specifically implments these methods such that it merely iteratates over its children who are mappable, so given:

my-page.html

    <form>
        <input name='pet[0][species]'>
        <input name='pet[0][name]'>
        <input name='pet[1][species]'>
        <input name='pet[1][name]'>
    </form>
    <script>
        $.getJSON("some/service.json").then(function (data) {
            document.querySelector("form").mapFromObject(someServiceData);
        })
    </script>

If the data looked like this:

{
  "pet":  [
      {
          "species":  "Dahut",
          "name":     "Hypatia"
      },
      {
          "species":  "Felis Stultus"
          "name":     "Billie"
      }
  ]
}

It would set all the values indicated by the mappings:

	<form>
	  <input name='pet[0][species]' value='Dahut'>
	  <input name='pet[0][name]' value='Hypatia'>
	  <input name='pet[1][species]' value='Felis Stultus'>
	  <input name='pet[1][name]' value='Billie'>
	</form>

And similarly if I now said:

	var om = document.querySelector("form").mapToObject();

It would walk through those elements and yield output that is identical to the service call above.

##Form Submission Submitting a <form> does something like

	var submittable = { <<submission info like x,y>> };
	var elements = mappableElements.filter(function (element) {
        return <<the result of submittability tests>>;
    });
    elements.forEach(function (element) {
    	submittable.mapToObject(submittable);
	});
	this.serialize(submittable);

serialize(object) relies on another property of HTMLFormElement (plugin style) the .serializer() function which is set automatically according to the enctype attribute, but may be overridden.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment