/* * jQuery Taconite plugin - A port of the Taconite framework by Ryan Asleson and * Nathaniel T. Schutta: http://taconite.sourceforge.net/ * * Examples and documentation at: http://malsup.com/jquery/taconite/ * Copyright (c) 2007 M. Alsup * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * Thanks to Kenton Simpson for contributing some good ideas! * * @author: M. Alsup * @version: 2.0.9 (3/14/2007) * @requires jQuery v1.0.4 or later */ (function($) { // add 'replace' and 'replaceContent' plugins (conditionally) if (typeof $.fn.replace == 'undefined') $.fn.replace = function(a) { return this.after(a).remove(); }; if (typeof $.fn.replaceContent == 'undefined') $.fn.replaceContent = function(a) { return this.empty().append(a); }; /** * Processes a Taconite XML command document. * @name taconite * @param Document|String command document */ $.taconite = $.xmlExec = function(xml) { $.taconite.impl.process(xml); } $.taconite.version = [2,0,9]; // major,minor,point revision nums $.taconite.debug = 0; // set to true to enable debug logging to Firebug $.taconite.lastTime = 0; // processing time for most recent document $.taconite._httpData = $.httpData; // original jQuery httpData function // auto-detection method (replaces jQuery's httpData method when auto-detection is enabled) $.httpData = $.taconite.detect = function(xhr, type) { var ct = xhr.getResponseHeader('content-type'); $.taconite.log('[AJAX response] content-type: ', ct, '; status: ', xhr.status, ' ', xhr.statusText, '; has responseXML: ', xhr.responseXML != null); var data = $.taconite._httpData(xhr, type); // call original method if (data && data.documentElement) { var root = data.documentElement.tagName; $.taconite.log('XML document root: ', root); if (root == 'taconite') { $.taconite.log('taconite command document detected'); $.taconite(data); } } else $.taconite.log('httpData: response is not XML (or not "valid" XML)'); return data; }; // allow auto-detection to be enabled/disabled on-demand $.taconite.enableAutoDetection = function(b) { // reset jQuery's httpData method $.httpData = b ? $.taconite.detect : $.taconite._httpData; }; $.taconite.log = function() { if (!$.taconite.debug || !window.console || !window.console.log) return; if (!$.taconite.log.count++) $.taconite.log('Plugin Version: ' + $.taconite.version.join('.')); window.console.log('[taconite] ' + [].join.call(arguments,'')); }; $.taconite.log.count = 0; $.taconite.impl = { trimHash: {wrap:1}, // convert string to xml document convert: function(s) { var doc; $.taconite.log('attempting string to document conversion'); try { if (window.ActiveXObject) { doc = new ActiveXObject('Microsoft.XMLDOM'); doc.async = 'false'; doc.loadXML(s); } else { var parser = new DOMParser(); doc = parser.parseFromString(s, 'text/xml'); } } catch(e) { if (window.console && window.console.error) window.console.error('[taconite] ERROR parsing XML string for conversion: ' + e); throw e; } var ok = doc && doc.documentElement && doc.documentElement.tagName != 'parsererror'; $.taconite.log('conversion ', ok ? 'successful!' : 'FAILED'); return doc; }, process: function(xml) { if (typeof xml == 'string') xml = this.convert(xml); if (!xml || !xml.documentElement) { $.taconite.log('$.taconite invoked without valid document; nothing to process'); return; } try { var t = new Date().getTime(); // process the document $.taconite.impl.process1(xml.documentElement.childNodes); $.taconite.lastTime = (new Date().getTime()) - t; $.taconite.log('time to process response: ' + $.taconite.lastTime + 'ms'); } catch(e) { if (window.console && window.console.error) window.console.error('[taconite] ERROR processing document: ' + e); throw e; } }, process1: function(commands) { for(var i=0; i < commands.length; i++) { if (commands[i].nodeType != 1) continue; // commands are elements var cmdNode = commands[i], cmd = cmdNode.tagName; if (cmd == 'eval') { var js = (cmdNode.firstChild ? cmdNode.firstChild.nodeValue : null); $.taconite.log('invoking "eval" command: ', js); if (js) $.globalEval(js); continue; } var q = cmdNode.getAttribute('select'); var jq = $(q); if (!jq[0]) { $.taconite.log('No matching targets for selector: ', q); continue; } var a = []; if (cmdNode.childNodes.length > 0) { for (var j=0,els=[]; j < cmdNode.childNodes.length; j++) els[j] = this.createNode(cmdNode.childNodes[j]); a.push(this.trimHash[cmd] ? this.cleanse(els) : els); } else { // remain backward compat with pre 2.0.9 versions var n = cmdNode.getAttribute('name'); var v = cmdNode.getAttribute('value'); if (n !== null) a.push(n); if (v !== null) a.push(v); // @since: 2.0.9: support arg1, arg2, arg3... for (var j=1; true; j++) { v = cmdNode.getAttribute('arg'+j); if (v === null) break; a.push(v); } } if ($.taconite.debug) { var arg = els ? '...' : a.join(','); $.taconite.log("invoking command: $('", q, "').", cmd, '('+ arg +')'); } jq[cmd].apply(jq,a); } }, cleanse: function(els) { for (var i=0, a=[]; i < els.length; i++) if (els[i].nodeType == 1) a.push(els[i]); return a; }, createNode: function (node) { var type = node.nodeType; if (type == 1) return this.createElement(node); if (type == 3) return this.fixTextNode(node.nodeValue); if (type == 4) return document.createTextNode(node.nodeValue); return null; }, fixTextNode: function(s) { if ($.browser.msie) s = s.replace(/\n/g, '\r'); return document.createTextNode(s); }, createElement: function (node) { var e, tag = node.tagName.toLowerCase(); if ($.browser.msie && (tag == 'input' || tag == 'button')) { var type = node.getAttribute('type'); if (type == 'radio' || type == 'checkbox') return document.createElement(''); else if (tag == 'button') e = document.createElement('