In have been working with ASP.NET MVC lately. As part of this, I’ve been moving to pure JavaScript pages without viewstate.
Take, for example this very simple timesheet. The user can add and delete rows without saving to the database or even going back and forth with the web server. One option is to cleverly name all the text fields so that they can be properly associated with database records. In other cases, you might want to save the contents of div’s, span’s or even attributes of HTMLelements. One way to handle this is to keep cleverly named hidden fields in sync with the contents of those HTMLelements.
Here is a jQuery plugin that allows you to convert an HTML element and selected sub-elements, and their properties and attributes into XML which you can then post to the server in a hidden field. Simply add “decorator” attributes to the elements from which you want to get data:
- data-extract-method – calls the named jQuery method on the element to get the element value
- data-extract-name – the name of the XML element to create
- data-extract-property – gets the value of the named property of the element
- data-extract attribute – gets the value of the named attribute
For example, this HTML
<html>
<head>
<title>Test</title>
<script src="/lib/jqueryUI/jquery-ui-1.9.0/js/jquery-1.8.2.js" type="text/javascript"></script>
<script src="~/Scripts/extractState.js"></script>
</head>
<body>
<div id="main" data-extract-name="root">
<p data-extract-name="item">
<input type="text" data-extract-name="name" data-extract-method="val" value="Bob" />
<input type="checkbox" data-extract-name="chk" data-extract-property="checked" />
<span data-extract-name="age" data-extract-attribute="class">50</span>
</p>
<p data-extract-name="item">
<input type="text" data-extract-name="name" data-extract-method="val" value="Alice" />
<input type="checkbox" data-extract-name="chk" data-extract-property="checked" />
<span data-extract-name="age" data-extract-attribute="class">25</span>
</p>
</div>
<textarea id="xx"></textarea>
<script>
$("#xx").on("click", function () {
var m = $("#main");
var v = $.extractState(m);
$(this).val("<" + v[0].nodeName + ">" + v.html() + "</" + v[0].nodeName + ">")
});
</script>
</body>
</html>
will return this result in the textarea:
<root>
<item>
<name>
<val>Bob</val>
</name>
<chk>
<checked>
</checked>
</chk>
<age>
<class>gray</class>
</age>
</item>
<item>
<name>
<val>Alice</val>
</name>
<chk>
<checked>
</checked>
</chk>
<age>
<class>black</class>
</age>
</item>
</root>
<!--A few words of caution: be very careful of your xml output names. Don't call an element xml or use hyphens or it won't work in IE.-->