/*
 * @name JSHTML
 * @version 1.1
 * ---
 * @author James Padolsey http://james.padolsey.com
 * @copyright James Padolsey
 * ---
 * @description
 *    JSHTML provides a simple way of introducing enhanced
 *    markup into your HTML documents. Markup found in HTML
 *    comments between the specified delmiters (+ preceeding flag)
 *    will be replaced with actual markup in the same position.
 * ---
 * @config
 *    ~ flag : A string used to signify JSHTML block.
 *    ~ delimiters : 2-part array containing delimiters, each one
 *                   signifies the beginning and end of the block.
 *    ~ fragmentCallback : Function fires on each new fragment.
 *                         ('this' refers to fragment)
 *    ~ template : By default an empty object. JSHTML can replace
 *                 text wrapped in { and } within the JSHTML block.
 *                 (a primative templating system)
 *                 e.g. JSHTML.config.template.location = 'page.html';
 *                      ...
 *                      <!-- JSHTML {{ <a href="{location}">Blah!</a> }} -->
 * ---
 * @example
 *    HTML:
 *      <div id="normal">
 *          <!-- JSHTML {
 *              <span id="control">
 *                  This span only appears when JS is enabled
 *              </span>
 *          } -->
 *      </div>
 *    JavaScript:
 *      JSHTML.parse(); //< Only call once the DOM is fully loaded!
 */

var JSHTML = {
    config : {
        flag : 'JSHTML',
        delimiters : ['{{','}}'],
        fragmentCallback : function(){},
        template : {}
    },
    parse : function() {
        var config = this.config,
            flagRegex = new RegExp(
                '\\s*?' + config.flag + '\\s*?'
                + config.delimiters[0] + '(.+)'
                + config.delimiters[1] + ''
            ),
            context = arguments[0] || document.documentElement,
            nodes = context.childNodes,
            nLen = nodes.length,
            current, match,
            makeFrag = function(str) {
                var tempDiv = document.createElement('div'),
                    frag = document.createDocumentFragment(),
                    replacement = function($0, $1) {
                        return config.template[$1] || $0;
                    },
                    node;
                tempDiv.innerHTML = str.replace(/^\s+|\s+$/g,'')
                                       .replace(/\{(.+?)\}/g, replacement);
                while (node = tempDiv.firstChild) {
                    frag.appendChild(node);
                }
                try { config.fragmentCallback.call(frag); }
                catch(e) {
                    setTimeout(function(){ throw new Error(e); }, 0);
                }
                return frag;
            };
        while (nLen--) {
            current = nodes[nLen];
            if (current.nodeType !== 8) {
                arguments.callee.call(this, current);
                continue;
            }
            match = flagRegex.exec(current.data.replace(/[\n\r]/g,''));
            if (!match) { continue; }
            current.parentNode.replaceChild(makeFrag(match[1]), current);
        }
    }
};

