Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Wanted: JavaScript to create HTML from suitable JSON

1 view
Skip to first unread message

Jonathan Fine

unread,
Mar 27, 2008, 3:06:10 PM3/27/08
to
Hello

I want to provide a mini-help system on a web page, to help the user
when s/he is filling in a form.

I thought I'd hold the help data in JSON format, and translate it to
HTML via JavaScript in response to user actions.

So I'm wanting to translate suitable JSON into HTML elements. I've
looked around a bit and not found anything that does this.

Do you know of anything like this out there, either as JSON to HTML or
as a help system on a web page?

--
Jonathan

slebetman

unread,
Mar 27, 2008, 9:59:12 PM3/27/08
to

I've been using the following code myself when dynamically
constructing HTML strings in javascript. It's not terribly fast but it
works for me:

/* HTML generator: allows you to write structured HTML in JSON
format!
* Basically the format of json is something like:

[
{a:[{href:'foo/bar',className:'bat'},
'link to foo/bar'
]},
'this is some text',
{div:[{id:'mydiv'},[
'this can also be an array',
{span:[{},
'and look! tags are nestable, just like HTML!'
]}
]}
]

*
* which should generate something like:
*

<a href="foo/bar" class="bat">
link to foo/bar
</a>
this is some text
<div id="mydiv">
this can also be an array
<span>
and look! tags are nestable, just like HTML!
</span>
</div>

* inarray is optional. If inarray is specified, this does
* not return a string!
*/
function jsHTML(json,inarray) {
var arr = inarray || [];
for (var x=0; x<json.length; x++) {
var item = json[x];
switch (typeof(item)) {
case 'number':
case 'string':
arr.push(item);
break;
case 'object':
for (var tag in item) {
arr.push('<'+tag);
switch (typeof(item[tag])) {
case 'number':
case 'string':
arr.push('>'+item[tag]);
break;
case 'object':
var attr = item[tag][0];
var body = item[tag][1];
for (var param in attr) {
// Special support for specifying
// inline style using an object:
if (param === 'style') {
arr.push('style="');
jsSTYLE(attr[param],arr);
arr.push('"');
}
else {
var value = attr[param].replace(/\"/g,'\\"');

// Special support for specifying
// 'class' without quotation:
if (param === 'className') {
param = 'class';
}
arr.push(param+'="'+value+'"');
}
}
arr.push('>');
switch (typeof(body)) {
case 'number':
case 'string':
arr.push(body);
break;
case 'object':
jsHTML(body,arr); // nested tag, recurse!
}
}
// Close tag if necessary:
if (!tag.match(/br|dd|dt|embed|hr|img|input/i)) {
arr.push('</'+tag+'>');
}
}
}
}
if (!inarray) {
return arr.join(' ');
}
}

function jsSTYLE(json,inarray) {
if (!inarray) {
return;
}

for (var s in json) {
inarray.push(s+':');
inarray.push(json[s].replace(/\"/g,'\\"')+';');
}
}

Jonathan Fine

unread,
Mar 28, 2008, 3:49:28 AM3/28/08
to
slebetman wrote:

> I've been using the following code myself when dynamically
> constructing HTML strings in javascript. It's not terribly fast but it
> works for me:

Thanks. I've come up with something a bit different. For me, I'm
having data that looks like
data = [null,
["h2", "Hello world"],
["p", "this and that ", ["strong", "more"]],
["div", "this and that ", ["strong", "more"]],
["hr"],
["p", "this and that ", ["tt", "more"]],
]
and then a call such as
append_nodes(wibble, document.body, data)
appends an <h2> and some other elements to the <body>.

The parameter wibble - I don't have a good name for it now, is a
parameter that contains the call-back functions. By the way, my
'wibble' used document.CreateElement etc. In other words, JSON to DOM
rather than JSON to HTML.

So why am I doing it this way?

1. To make the data smaller when stored in memory.
2. To not be tied to generating HTML from the JSON.
3. To keep HTML style information out of the JSON.

One of the things I'll be want to do is create dynamic image tags from
the source. For example, I'll want something like:
tex;\sum_0^n 2^{-n}
to generate an image whose href is
<URL>;tex=%5Csum_0%5En%202%5E%7B-n%7D
where <URL> is (unless the user has other preferences)
http://www.mathtran.org/cgi-bin/mathtran?

My code, if you want to use or view it, is being developed at
http://code.google.com/p/mathtran-javascript/

I found some useful URLs since I posted this message. They are collected at
http://del.icio.us/jonathan.fine/json_to_html

Thank you, slebetman, for sharing your work.

--
Jonathan

Thomas 'PointedEars' Lahn

unread,
Mar 28, 2008, 6:08:51 PM3/28/08
to
slebetman wrote:
> On Mar 28, 3:06 am, Jonathan Fine <jf...@pytex.org> wrote:
>> I want to provide a mini-help system on a web page, to help the user
>> when s/he is filling in a form.
>>
>> I thought I'd hold the help data in JSON format, and translate it to
>> HTML via JavaScript in response to user actions.
>>
>> So I'm wanting to translate suitable JSON into HTML elements. I've
>> looked around a bit and not found anything that does this.
>>
>> Do you know of anything like this out there, either as JSON to HTML or
>> as a help system on a web page?
>
> I've been using the following code myself when dynamically
> constructing HTML strings in javascript. It's not terribly fast but it
> works for me:

A more reasonable and (therefore) more efficient approach follows below.

> /* HTML generator: allows you to write structured HTML in JSON
> format!
> * Basically the format of json is something like:
>
> [
> {a:[{href:'foo/bar',className:'bat'},

Should be `"class"' instead of `className'. The string literal avoids the
reserved word issue and further dictionary lookup.

> 'link to foo/bar'
> ]},
> 'this is some text',
> {div:[{id:'mydiv'},[
> 'this can also be an array',
> {span:[{},
> 'and look! tags are nestable, just like HTML!'
> ]}
> ]}

You forgot a `]' here.

> ]

/**
* Appends DOM nodes, represented by JSON data, to an element node.
*
* @param Element contextNode
* The element node to which the content should be appended
* @param Array aJSON
* An Array object reference returned from JSON evaluation
* @type Element
* @returns a reference to the modified element node.
* @author
* Copyright (c) 2008 Thomas Lahn <cl...@PointedEars.de>
* Distributed under the GNU GPL v2.
*/
function appendFromJSON(contextNode, aJSON)
{
for (var i = 0, len = aJSON.length; i < len; i++)
{
var o = aJSON[i], node;

if (typeof o == "string")
{
node = document.createTextNode(o);
}
else
{
// assuming nobody has tampered with Object.prototype
for (var p in o)
{
node = document.createElement(p);

var attrs = o[p][0];

for (var a in attrs)
{
// or use the attribute property approach,
// but then you need an attribute name dictionary
node.setAttribute(a, attrs[a]);
}

var childNodes = o[p][1];
if (childNodes)
{
if (childNodes.constructor == Array)
{
appendFromJSON(node, childNodes);
}
else
{
var txt = document.createTextNode(childNodes);
node.appendChild(txt);
}
}

break;
}
}

contextNode.appendChild(node);
}
}

You should add the usual feature tests and maybe the associated fallbacks.
However, the above WFM in Firefox 2.0.0.13, Internet Explorer 5.01 to 7.0,
Opera 9.26, and Safari 3.1 (all on Windows XP SP 2).

Test case: http://PointedEars.de/scripts/test/DOM/JSON/json2markup

> *
> * which should generate something like:
> *
>
> <a href="foo/bar" class="bat">
> link to foo/bar
> </a>
> this is some text
> <div id="mydiv">
> this can also be an array
> <span>
> and look! tags are nestable, just like HTML!
> </span>
> </div>

The whitespace is not automatically generated with either solution, of course.


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

slebetman

unread,
Mar 30, 2008, 9:36:47 PM3/30/08
to
On Mar 29, 6:08 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> slebetman wrote:
> > On Mar 28, 3:06 am, Jonathan Fine <jf...@pytex.org> wrote:
> >> I want to provide a mini-help system on a web page, to help the user
> >> when s/he is filling in a form.
>
> >> I thought I'd hold the help data in JSON format, and translate it to
> >> HTML via JavaScript in response to user actions.
>
> >> So I'm wanting to translate suitable JSON into HTML elements. I've
> >> looked around a bit and not found anything that does this.
>
> >> Do you know of anything like this out there, either as JSON to HTML or
> >> as a help system on a web page?
>
> > I've been using the following code myself when dynamically
> > constructing HTML strings in javascript. It's not terribly fast but it
> > works for me:
>
> A more reasonable and (therefore) more efficient approach follows below.
>
> > /* HTML generator: allows you to write structured HTML in JSON
> > format!
> > * Basically the format of json is something like:
>
> > [
> > {a:[{href:'foo/bar',className:'bat'},
>
> Should be `"class"' instead of `className'. The string literal avoids the
> reserved word issue and further dictionary lookup.
>

Both 'class' and className are supported. For JSON there is no problem
since the spec requires everything to be 'quoted' anyway. But I didn't
develop it for use by JSON. I wrote it for keeping my sanity writing
generating chunks of HTML content in javascript. So for my use I tend
not to quote object attributes. Which is why I support className as
well as 'class'. Besides, it feels natural for me to call it className
in javascript since that's the attribute that stores an HTML element's
class.

Thomas 'PointedEars' Lahn

unread,
Mar 30, 2008, 10:36:18 PM3/30/08
to
slebetman wrote:
> [...] Thomas 'PointedEars' Lahn [...] wrote:

>> slebetman wrote:
>>> /* HTML generator: allows you to write structured HTML in JSON
>>> format! * Basically the format of json is something like: [...]
>>> {a:[{href:'foo/bar',className:'bat'},
>> Should be `"class"' instead of `className'. The string literal avoids
>> the reserved word issue and further dictionary lookup.
>
> Both 'class' and className are supported.

Although there is no good reason to, much less a need.

> For JSON there is no problem since the spec requires everything to be
> 'quoted' anyway. But I didn't develop it for use by JSON. I wrote it for
> keeping my sanity writing generating chunks of HTML content in
> javascript. So for my use I tend not to quote object attributes. Which is
> why I support className as well as 'class'. Besides, it feels natural for
> me to call it className in javascript since that's the attribute that
> stores an HTML element's class.

If you had used my much simpler and much more efficient D::createElement()
and N::setAttribute() approach, which you have carefully ignored, instead,
there would not be a need for winding around the issue. For in
implementations that use ECMAScript binding of one of the known DOMs, among
others it has to be `colSpan' instead of `colspan', `maxLength' instead of
`maxlength', and especially `cssFloat' (W3C) *or* `styleFloat' (MSHTML)
instead of `float' which you do not seem to care much about either.

Array.prototype.push() can accept more than one argument, BTW.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

Jonathan Fine

unread,
Mar 31, 2008, 2:41:09 AM3/31/08
to
Thomas 'PointedEars' Lahn wrote:
> Test case: http://PointedEars.de/scripts/test/DOM/JSON/json2markup

Thank you for your contribution. However, the above URL gives me a 404
error.

--
Jonathan

Tuomo Tanskanen

unread,
Mar 31, 2008, 2:52:05 AM3/31/08
to

Thomas 'PointedEars' Lahn

unread,
Mar 31, 2008, 3:05:18 PM3/31/08
to

That is strange, both should work.

Thomas 'PointedEars' Lahn

unread,
Mar 31, 2008, 3:07:46 PM3/31/08
to
Thomas 'PointedEars' Lahn wrote:
> Tuomo Tanskanen wrote:
>> Jonathan Fine wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> Test case: http://PointedEars.de/scripts/test/DOM/JSON/json2markup
>>> Thank you for your contribution. However, the above URL gives me a 404
>>> error.
>> It's really at:
>> http://PointedEars.de/scripts/test/dom/JSON/json2markup.php
>
> That is strange, both should work.

Ahh, it's the wrong case of the `DOM' directory that causes the problem.
Please use

http://PointedEars.de/scripts/test/dom/JSON/json2markup

instead.

0 new messages