Hi there,

I've continued to mess around with json-template.js to see whether I
could get the DOM-node relative node lookup to work, as I want to use
it in a project. I got it working, and for future reference, here are
the relevant snippets. This code is assuming a version of
json-template with the hooks I proposed earlier built in. I also need
some way to generate a contex based on a path into the JSON structure
- since this uses the _ScopedContext interface to stay compatible and
since this is a private interface, the path to lookup function code
would need to be inside json-template.js, though the path parsing code
could be separated out.

The logic to transform JSON structures so that they contain path
information. paths look like this: '.foo.bar|3, which would be
data_dict['foo']['bar'][3]. (the syntax could easily be altered)

var _transform_paths_dict_helper = function(data_dict, path) {
  var key;
  var value;

  data_dict['_path'] = path;

  for (key in data_dict) {
    value = data_dict[key];
    if (_is_array(value)) {
      _transform_paths_array_helper(value, path + '.' + key);
    } else if (typeof value === 'object') {
      _transform_paths_dict_helper(value, path + '.' + key);
    }
  }
};

var _transform_paths_array_helper = function(data_array, path) {
  var i;
  var value;
  for (i = 0; i < data_array.length; i++) {
    value = data_array[i];
    if (_is_array(value)) {
      _transform_paths_array_helper(value, path + '|' + i);
    } else if (typeof value === 'object') {
      _transform_paths_dict_helper(value, path + '|' + i);
    }
  }
};

var _is_array = function(obj) {
  return Object.prototype.toString.apply(obj) === '[object Array]';
};

Hooks to generate the hidden <div></div> sections into the HTML when
going into a {.section} and going into a {.repeated section}, so that
the code can later look up the path information in the generated HTML
DOM. It also sets up the JSON transformation logic to add in the _path
information, which the insertion logic neds.

var HtmlIdHooks = function() {
  return {
     transformData: function(data_dict) {
        _transform_paths_dict_helper(data_dict, '');
        return data_dict;
     },
     beforeSection: function(lookup, write, name) {
       write('<div class="json-template-path" style="display:none"
id="' + lookup('_path') + '"></div>');
     },
     afterSection: function(lookup, write, name) {
     },
     beforeRepeatedSection: function(lookup, write, name, index) {
       write('<div class="json-template-path" style="display:none"
id="' + lookup('_path') + '"></div>');
     },
     afterRepeatedSection: function(lookup, write, name, index) {
     }
  };
};

Given a data_dict (the JSON structure), a path (of the structure
defined before), we create a function that returns a lookup function
appropriate to location in the JSON structure. This is the bit that
hooks into _ScopedContext, so cannot be a plugin unlike the rest. We
could however implement a simple path resolution algorithm that takes
a list of objects, and thus keep the path parsing logic out of the
core.

var get_lookup = function(data_dict, path, undefined_str) {
  var steps = path.split('.');
  var context = _ScopedContext(data_dict, {'undefined_str': undefined_str});
  for (var i = 0; i < steps.length; i++) {
    var parts = steps[i].split('|');
    if (parts.length >= 2) {
      var key = parts[0];
      var indexes = parts.slice(1);
    } else {
      var key = parts[0];
      var indexes = [];
    }
    if (key == '') {
      continue;
    }
    context.PushSection(key);
    for (var j = 0; j < indexes.length; j++) {
      for (var x = 0; x < parseInt(indexes[j]) + 1; x++) {
        context.next();
      }
    }
  }
  return function(name) {
    return context.Lookup(name);
  };
};

Given data_dict and a HTML DOM node, find a lookup function. This
builds on the previous logic, and sniffs the path from the HTML (which
got inserted previously).

var get_node_lookup = function(data_dict, node, undefined_str) {
  var parent = node;
  while (parent !== null) {
    var sibling = parent;
    while (sibling !== null) {
      if (sibling.getAttribute('class') == 'json-template-path') {
        var path = sibling.getAttribute('id');
        return get_lookup(data_dict, path, undefined_str);
      }
      sibling = sibling.previousSibling;
    }
    parent = parent.parentNode;
  }
  return undefined_str;
};

So, to use this in javascript, you can write something like this:

var lookup = get_node_lookup(data_dict, my_element)

var a = lookup('a')
var b = lookup('b')
var c = lookup('b.c')

The idea is that if you want to set up event handlers after expanding
a JSON template, you can easily retrieve information from the
underlying JSON without having to serialize it to HTML first, and
without having to embed javascript event handlers within the template.

The only code proposed for inclusion in json-template.js are:

* three hooks (or more): the data transformation one, and one hook for
{.section} and another for {.repeated section}

* a way to turn path information into a lookup function that uses
_ScopedContext internally (but doesn't expose it).

All the other code can be in an extension.

The main thing missing are a lot of tests. I'd like to write tests for
this, but the verifier.py testing protocol lacks the infrastructure to
do this. I'd probably be easier to write these tests as javascript
only tests anyway, but we don't have infrastructure for that yet
either as far as I know.

Regards,

Martijn

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "JSON 
Template" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/json-template?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to