HTML5 & RDFa-lite semantic templating engines

If you’re writing a webapp using rdfa-lite, It makes sense to consider using rdfa markers in the DOM based template engine.

While working on round-trip html5 <-> Rdfa-lite query and editing, I’ve been struck by the primitive feeling of html template languages. {{mustache}} ,  <%escapes%> <–%ssi escapes %–> all work the same way as C preprocessor macros – string concatenation style – which ignores the underlying structure that we’re working with.

Thankfully, HTML5 is changing everything – it has / will have a template tag

Along the way to finding that, I came across Weld.js (dead?), Transparency or Plates and Pure and not forgetting Knockout.js.

None of them quite goes where I want – as they either use class/id, or their own data- attributes.

What I’m after, is leveraging the already existing semantic annotations of existing (or template tag) elements to add new ones.

For example, I might have the following Link menu, and then want to dynamically add others from a remote query

     <ul id="page-list">
         <template id="page-item-template" style="display:none;">
            <li  typeof="WebPage" resource="/">
                <a property="url" href="/" tabindex="-1" id="index">
                    <span property="name">Home</span></a>
             </li>
          </template>
             <li typeof="WebPage" resource="/">
                  <a property="url" href="/" tabindex="-1" id="index">
                    <span property="name">Home</span></a>
             </li>
             <li  typeof="WebPage" resource="/SvenDowideit.html">
                  <a property="url" href="/SvenDowideit.html" tabindex="-1" id="SvenDowideit">
                    <span property="name">Sven Dowideit</span></a>
             </li>
        </ul>

The following works for browsers that don’t support the new HTML5 template tag:

var node = document.querySelector('#page-list [typeof=WebPage]').cloneNode(true);
node.querySelector('[property=name]').textContent = 'TODO';
node.querySelector('[property=url]').href = '/TODO.html';
document.querySelector('#page-list').appendChild(node);

A nice start, but to me, there’s still something not right with the addressing scheme –
which is where some of the above template engines use the @ symbol to denote that the value should be set on the named attribute.

something like this might work

var node = document.querySelector('#page-list [typeof=WebPage]').cloneNode(true);
node.render( {
    '[property=name]@textContent':  'TODO',
    '[property=url]@href': '/TODO.html'
});
document.querySelector('#page-list').appendChild(node);
but setting up the relationships beforehand, and making the clone implicit
var template = getTemplate('#page-list [typeof=WebPage]', {
   name: '[property=name]@textContent',
   url:  '[property=url]@href'
});
document.appendChild(template([
 {name: 'Sven Dowideit', url: '/SvenDowideit.html'},
 {name: 'TODO', url: '/TODO.html'}
]);

Which looks an awful lot like Weld.js’ (and the inverse of Pure?) API. And, should be trivial to implement using Transparancy.

in the process of thinking it through, I wrote a simplistic version that deserves replacing when I’m thinking about something else:

        getTemplate: function(templateSelector, map) {
            if (this.Template === undefined) {
                var template = document.querySelector(templateSelector);
                var template_map = {};

                for (var key in map) {
                    var address = map[key].match(/^([^@]*)@?(.*)?$/);
                    template_map[key] = {
                        node: address[1] || '*',
                        attr: address[2] || 'textContent'
                    }
                }                
                this.Template = function(values) {
                    var new_elements = [];
                    for (var idx in values) {
                        var elem = template.cloneNode(true)                
                        for (var key in values[idx]) {
                            if (template_map[key] !== undefined) {
                                var node =  elem.querySelector(template_map[key].node);
                                //TODO: detect if key is a method, and call it?
                                if (template_map[key].attr === 'textContent') {
                                    node.textContent = values[idx][key];
                                } else {
                                    node.setAttribute(template_map[key].attr, values[idx][key]);
                                }
                            }
                        }
                        //TODO: if it where a real template tag, apparently there would be an elem.content
                        new_elements.push(elem.children[0]);
                    }
                    return new_elements;
                };
            }
            return this.Template;
        }}

TodoMVC written using backbone-forms

I’ve been working on some bootstrap instant edit userinterface ideas, and while integrating hallo.js, I was reading about backbone.js and the VIE create.js RDF form generators.

This lead me to backbone-forms, which auto-creates the backbone view from a model schema…

So to try it out, I wrote a TodoMVC example using backbone-forms – moving almost the entire code into the view.

MongoDB had a server-side query JOIN

When I developed the Foswiki MongoDB integration, I worked out a really ‘nifty’ way to do cross database and collection JOINs .

When I developed the Foswiki MongoDB integration, I worked out a really ‘nifty’ way to do cross database and collection JOINs .

but, it’s finally been broken in MongoDB 2.2 – with the removal of the global lock.

So we’re going to have to restrict the foswiki MongoDB plugin to version 2.0.

 

So, you’re curious?

On reason I decided to use MongoDB as a target for foswiki adhoc queries, was the backup of writing $where clauses in javascript. I’ve used them when the Perl-isms in foswiki’s query results could not be magically matched – string and number duplicity for example.

and one facility that MongoDB’s javascript has, is to call db.getSisterDB(‘someotherdbname’);

so for (a very simplified) example:

db.current.find({$where : "db.getSisterDB(this.otherDB).current.findOne({topic: this.otherTopic}).value == 'what are you looking at'"});

yes, this is not SELECT JOIN, just WHERE JOIN – but it’s exactly what we needed.

 

 

Zero overhead Client-Side error logging with Apache

Thanks to a tweet by a Brisbane local (Bruce) I was continuing to mull the disconnect I have from external web traffic tracking tools. I prefer to reduce the number of requests needed to serve my users – and zero requests are always fastest.

I’ve been messing with Apache CustomLog formats to debug session and performance issues in foswiki, and so given a hammer, wondered why not apply it to more things.

Then comes Bruce’s link to Client-Side Error Logging With Google Analytics, a continuation of You Really Should Log Client-Side Errors – and I wondered…

What if I put the client error into the next user request made to the server?

the javascript:

function logError(details) {
    $.cookie('clientError', details);
}
window.onerror = function(message, file, line) {
  logError(file + ':' + line + '\n\n' + message);
};
$(document).ajaxError(function(e, xhr, settings) {
  logError(settings.url + ':' + xhr.status + '\n\n' + xhr.responseText);
});
$.cookie('clientError', null);

the apache CustomLog settings:

#add a Client Error log
 LogFormat  "%h %l \"%r\" %u %t %>s %{clientError}C" clientError
 CustomLog ${APACHE_LOG_DIR}/clientError_local_log clientError

and the result:

192.168.1.51 - "GET /~sven/core/pub/System/JQueryPlugin/plugins/foswiki/jquery.foswiki.js?version=2.01 HTTP/1.1" - [07/Apr/2012:16:18:26 +1000] 304 -
 192.168.1.51 - "GET /~sven/core/pub/System/TwistyPlugin/jquery.twisty.js?version=1.6.0 HTTP/1.1" - [07/Apr/2012:16:18:26 +1000] 304 -
 192.168.1.51 - "GET /~sven/core/bin/view/Sandbox/TestClientSideLogging HTTP/1.1" - [07/Apr/2012:16:18:31 +1000] 200 http%3A%2F%2F192.168.1.51%2F~sven%2Fcore%2Fbin%2Fview%2FSandbox%2FTestClientSideLogging%3A1%0A%0Acall_me%20is%20not%20defined
 192.168.1.51 - "GET /~sven/core/pub/System/TwistyPlugin/twisty.css?version=1.6.0 HTTP/1.1" - [07/Apr/2012:16:18:32 +1000] 304 -
 192.168.1.51 - "GET /~sven/core/pub/System/JQueryPlugin/plugins/livequery/jquery.livequery.js?version=1.1.1 HTTP/1.1" - [07/Apr/2012:16:18:32 +1000] 304 -

This way we get super fast, no extra traffic client error tracking.

 

(If someone has the apache-foo to get the right SetEnvIF or RewriteCond to only log when an error is defined, please help – I tried, but failed.)

Google’s DataWiki experiment

Google Labs has just added DataWiki – it looks like one of the features Foswiki (and its parent) have been doing for 10 years…

Google Labs has just added a GoogleAppEngine based Java application called – DataWiki.

So far, project information is very minimal, but it looks like one of the features Foswiki (and its parent) have been doing for 10 years…

The timing is excellent, as I’ve been working with others in the Foswiki Community to improve Foswiki’s mashup-ability:

enable easy input/output from a variety of endpoints, e.g. via Twitter, ODK or SMS from a remote location

Right now we’re working on a proper REST API for foswiki data – enabling us to retrieve and save changes to datasets in formats that are convenient to the external endpoints – and to simplify the development to dynamic visualisation and editing tools for complex data.

Perhaps what we’re looking at is a combination of the acquired and shut down JotSpot, and a response to Yahoo Pipes 🙂

Foswiki is an extremely mature (10 years) DataWiki capable enterprise wiki, with significant traction in workplaces around the world, and a strong, motivated developer and user community.

New Dynamic jquery mb.Menus for foswiki

I’ve just started work adding Matteo Bicocchi’s rather stunning mb.Components – starting with mb.Menu. Along the way, adding foswiki Macro’s to make it simpler for us to use, I’ve also made some changes to the code (which hopefully I can get integrated into an mb.Menu release) that I have attached to the live demo.

Here’s the all important Screenie:

I’ve been working on a Foswiki User administration user interface again

This iteration I’ve been working using the HTTPDUserAdminContrib – as having the users and groups in the database makes it hard to work on.

UserManagementUI

Hopefully there’ll be time to use and extend it for foswiki 1.1

firefox 3.x on debian amd64

I’ve been running a firefox 3.0 pre-release build for ages now, and finally thought I’d upgrade – (it turns out) mozilla do not provide 64 bit binaries. The i686 build that you can download from getfirefox.org does not work on my debian amd64 system – but not everything is lost.

As I’m a developer, I’m reasonably happy to play with nightly builds – and so – http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/ has what I need – today its firefox-3.1a2pre.en-US.linux-x86_64.tar.bz2.

Unziped into my non-debian firefox dir, and runs seemingly fine, except that the firefox addins won’t run, as they are scared of firefox versions that they have not been tested on 🙂

That too can be solved – edit the application.ini file, and replace the Version=3.1a2pre with Version=3.0.1 or whatever the release is that your addons are willing to work on.

so far, only VMWare’s addon won’t run – perhaps I need to set the Version lower, as it worked on Minefield 3.0pre.

http://packages.debian.org/search?keywords=iceweasel&searchon=names&suite=testing&section=all tells me that 3.0.1 is in amd64 debian testing since July 2008

VMWare’s addon to give console access won’t run in the 3.0.1 debian version either – talk about disappointing. The 3.1 nightly build seems to feel faster too, so I suspect I’ll be running that most of the time, and will look to migrate away from VMWare over time.

Adding Web 2.0 interface JavaScript to TWiki

While updating the YahooUserInterfaceContrib in TWiki to the just releases 2.2 version, I started to work with the BETA DataTable module.

Firstly, I’ve had to fix TWiki to put the headers and footers into the correct thead and tfoot HTML sections, and then there are the ‘tiny buglets’ 🙂

  1. sometimes the yui component initialises with only part of the html table
  2. yui hides all rows in the thead and tfoot section (so you loose the spreadsheet calculations we do in TWiki)
  3. you have to hand define the table header elements at the moment, rather than having an option to ‘autodetect’ their names, and possible sorty-ness

But it is a nice begining. I’ll be doing further work on it in TWiki (especially in the BugsContrib, and its derived task manager), and i’m planning on replacing the Catalyst DBIx paging with the dataTable Paging in mySpending.