diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..c78b779
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
index 487047c..6288512 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
node_modules/
test/node_modules/
.idea/
-pavlov/
-index.html
\ No newline at end of file
+./pavlov
+index.html
diff --git a/PostalAdapter.md b/PostalAdapter.md
new file mode 100644
index 0000000..7a10b38
--- /dev/null
+++ b/PostalAdapter.md
@@ -0,0 +1,76 @@
+# Postal Topology
+
+
+## Map
+ exchange cartographer
+ topic api
+#### Message Properties
+ name template
+ operation "map"
+
+## Apply
+ exchange cartographer
+ topic api
+#### Message Properties
+ name template name
+ template template instance id
+ model object to base the render on
+ operation "apply"
+### Responds With
+ exchange cartographer
+ topic render.{templateId}
+#### Message Properties
+ template template instance id
+ markup the generated DOM
+ operation "render"
+
+## Add
+ exchange cartographer
+ topic api
+### Message
+ template the template instance id
+ id the fully qualified id of the list control to add to
+ model object to create the new item template from
+ operation "add"
+### Responds With
+ exchange cartographer
+ topic render.{templateId}
+#### Message Properties
+ template template instance id
+ parent the fully qualified id for the parent
+ markup the generated DOM for the new item
+ operation "add"
+
+## Update
+ exchange cartographer
+ topic api
+#### Message Properties
+ template the template instance id
+ id the fully qualified id of the control to update
+ model object to update the control template with
+ operation "update"
+### RespondsWith
+ exchange cartographer
+ topic render.{templateId}
+#### Message Properties
+ template template instance id
+ id the fully qualified id of the item
+ markup the generated DOM for the new item
+ operation "update"
+
+## Append Resolver
+ exchange cartographer
+ topic api
+#### Message Properties
+ order "append"
+ operation "resolver"
+ resolver callback in the form of function( name, onSuccess, onFailure )
+
+## Prepend Resolver
+ exchange cartographer
+ topic api
+#### Message Properties
+ order "prepend"
+ operation "resolver"
+ resolver callback in the form of function( name, onSuccess, onFailure )
+ template template instance id
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ce4f9b4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,66 @@
+# Cartographer
+Cartographer is an HTML templating engine that works with plain HTML and simple JSON. It does this by inferring intention based on the structure of the markup and JSON. Cartographer will never place the generated markup on the page, it hands it back to the provided callback.
+
+Though Cartographer's performance should be sufficient for most applications, several trade-offs were made in order to make the advanced features (not provided by the majority of other template engines) possible.
+
+## Philosophy
+I wanted to create a templating engine that would compliment more complex, asynchronous applications in the browser. Cartographer's APIs are built to provide responses to user provided callbacks. It has been designed to be complimentary with other OSS JS Libraries that encourage decoupled application design: (infuser, postal and machina specifically).
+
+## Advanced Features
+* Generate partial templates
+* Nest templates
+* Specify external templates in the markup or the model
+* Generate new markup for new collection items
+* Fully qualified namespacing for elements that map to the model
+* A flexible way to define custom sources for templates
+* Integration with Postal for messaging
+ * all API methods supported through Postal topography
+* Configurable element identifier
+ * The default attribute used to identify the element for Cartographer is "data-id"
+* Configurable template attribute
+ * The default attribute used to specify a replacement template is "data-template"
+
+## Concepts
+Cartographer creates named templates based on the name of the template source. If your source is an external file, the name of the template is the name of the file. If the source of the template is a DOM element then the data-template property would match the template name.
+
+Once the template has been created, it can be used to create instances which must be uniquely identified (more on why later). The rendered instance is give fully qualified, hierarchical namespaces for all of the controls that had a data-id (mapped to a model property).
+
+Partial renders can be done as an add or update. Adding is intended to support rendered a specific item template for a collection when new elements are added to the model that produced the original render. Updates allow you to regenerate the template, starting at any level, in order to get updated markup for the section of the template that should be reproduced.
+
+## API
+
+### Map - cartographer.map(templateName)
+Creates a template from a named HTML source that will be used to generate markup from JSON.
+
+### Apply - cartographer.render( templateName, templateId, model, onMarkup )
+Renders the templateName and assigns the rendered instance templateId. The template instance id becomes the top of the fqn for all controls in the rendered instance. onMarkup is a function with 3 arguments: template id, markup and operation ( included for integration purposes ).
+
+### Add - cartographer.add( templateId, containerControlFqn, model, onMarkup )
+Adding creates a new set of markup for an existing template / model collection. The containerControlFqn is the fully qualified name of the containing list control. The other arguments are like the 'render' call.
+
+### Update - cartographer.update( templateId, targetFqn, model, onMarkup )
+Updating creates a new render at any level in the template hierarchy. The targetFqn is the level of the DOM template where the render should begin.
+
+### Adding Template Resolvers - cartographer.resolver.appendSource|prependSource( resolverFunction )
+Cartographer looks for the HTML using the template name. It searches its resolvers, in order, and by default has resolvers for in-page and infuser. If you glance at template-source.coffee under the spec folder, you'll see that it's trivial to create these and provide markup from any source you like.
+
+You can add a resolver and control when it will be checked by either appending or prepending your resolver to the list.
+
+The resolver has the signature function(name, success, fail). It uses the name argument to search for an HTML template based on the name and calls success with the HTML when it's found or fail when something tanks.
+
+### Changing The Element Id Attribute
+
+By default, Cartographer uses 'data-id' as the means to identify and correlate a DOM element to your model. This can be changed as follows:
+
+ cartographer.config.elementIdentifier
+
+## Examples
+Currently, there aren't a lot of great examples but the unit tests actually show all of the features.
+
+## Dependencies
+
+Cartographer has a number of dependencies which you must either include on your page OR have available via some AMD system (I've only tested it against Require at this point).
+
+If you happen to use require, here are the path aliases it expects:
+
+ 'jQuery', 'underscore', 'infuser', 'DOMBuilder'
\ No newline at end of file
diff --git a/build.json b/build.json
index 27b55c5..113db1d 100644
--- a/build.json
+++ b/build.json
@@ -5,8 +5,19 @@
"ext": "ext",
"lint": {},
"uglify": {},
- "wrap":{
- "prefix": "(function(context) {",
- "suffix": "})(window);"
+ "gzip": {},
+ "hosts": {
+ "/": "./html",
+ "/play": "./play",
+ "/spec": "./spec"
+ },
+ "finalize": {
+ "header-file": "./header.txt"
+ },
+ "name": {
+ "amd.js": "cartographer.amd.js",
+ "browser.js": "cartographer.js",
+ "adapter.js": "postal.adapter.js",
+ "adapter.amd.js": "postal.adapter.amd.js"
}
}
\ No newline at end of file
diff --git a/ext/infuser-0.2.0.js b/ext/infuser-0.2.0.js
new file mode 100644
index 0000000..7f59bc0
--- /dev/null
+++ b/ext/infuser-0.2.0.js
@@ -0,0 +1,188 @@
+define(['jquery', 'trafficcop'],function($,trafficcop) { // You might need to set up a config for require.js for the jquery/trafficcop dependencies to work, or replace it with an absolute path
+ /*
+ infuser.js
+ Author: Jim Cowart
+ License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
+ Version 0.2.0
+ */
+ var hashStorage = {
+ templates: {},
+
+ storeTemplate: function(templateId, templateContent) {
+ this.templates[templateId] = templateContent;
+ },
+
+ getTemplate: function(templateId) {
+ return this.templates[templateId];
+ },
+
+ purge: function() {
+ this.templates = {};
+ }
+ };
+ var scriptStorage = {
+ templateIds: [],
+ storeTemplate: function(templateId, templateContent) {
+ var node = document.getElementById(templateId);
+ if(node === null) {
+ this.templateIds.push(templateId);
+ node = document.createElement("script");
+ node.type = "text/html";
+ node.id = templateId;
+ document.body.appendChild(node);
+ }
+ node.text = templateContent;
+ },
+
+ getTemplate: function(templateId) {
+ return document.getElementById(templateId);
+ },
+
+ purge: function() {
+ for(var i = 0; i < this.templateIds.length; i++) {
+ document.body.removeChild(document.getElementById(this.templateIds[i]));
+ }
+ this.templateIds = [];
+ }
+ };
+ var errorHtml = "
",
+ returnErrorTemplate = function(status, templateId, templatePath) {
+ return errorHtml.replace('{STATUS}', status).replace('{TEMPLATEID}', templateId).replace('{TEMPLATEURL}', templatePath);
+ },
+ errors = [];
+ var helpers = {
+ getTemplatePath: function(templateOptions) {
+ var templateFile = templateOptions.templatePrefix + templateOptions.templateId + templateOptions.templateSuffix;
+ return templateOptions.templateUrl === undefined || templateOptions.templateUrl === "" ?
+ templateFile : templateOptions.templateUrl + "/" + templateFile;
+ },
+ templateGetSuccess: function(templateId, callback) {
+ return function(response) {
+ infuser.store.storeTemplate(templateId, response);
+ callback(infuser.store.getTemplate(templateId));
+ };
+ },
+ templateGetError: function(templateId, templatePath, callback) {
+ return function(exception) {
+ if($.inArray(templateId, errors) === -1) {
+ errors.push(templateId);
+ }
+ var templateHtml = returnErrorTemplate("HTTP Status code: " + exception.status, templateId, templatePath);
+ infuser.store.storeTemplate(templateId, templateHtml);
+ callback(infuser.store.getTemplate(templateId));
+ };
+ },
+ getAjaxOptions: function(templateOptions) {
+
+ }
+ },
+ infuserOptions = ['target','loadingTemplate','postRender','preRender','render','bindingInstruction','useLoadingTemplate','model','templateUrl','templateSuffix','templatePrefix',''];
+ var infuser = {
+ storageOptions: {
+ hash: hashStorage,
+ script: scriptStorage
+ },
+
+ store: hashStorage,
+
+ defaults: {
+ // Template name conventions
+ templateUrl: "",
+ templateSuffix: ".html",
+ templatePrefix: "",
+ // AJAX Options
+ ajax: {
+ "async": true,
+ "dataType": "html",
+ "type": "GET"
+ },
+ // infuse() specific options - NOT used for "get" or "getSync"
+ target: function(templateId) { return "#" + templateId }, // DEFAULT MAPPING
+ loadingTemplate: {
+ content: 'Loading...
',
+ transitionIn: function(target, content) {
+ var tgt = $(target);
+ tgt.hide();
+ tgt.html(content);
+ tgt.fadeIn();
+ },
+ transitionOut: function(target) {
+ $(target).html("");
+ }
+ },
+ postRender: function(targetElement) { }, // NO_OP effectively by default
+ preRender: function(targetElement, template) { }, // NO_OP effectively by default
+ render: function(target, template) {
+ var tgt = $(target);
+ if(tgt.children().length === 0) {
+ tgt.append($(template));
+ }
+ else {
+ tgt.children().replaceWith($(template));
+ }
+ },
+ bindingInstruction: function(template, model) { return template; }, // NO_OP effectively by default
+ useLoadingTemplate: true // true/false
+ },
+
+ get: function(options, callback) {
+ var templateOptions = $.extend({}, infuser.defaults, (typeof options === "object" ? options : { templateId: options })),
+ template;
+ templateOptions.ajax.url = helpers.getTemplatePath(templateOptions);
+ template = infuser.store.getTemplate(templateOptions.ajax.url);
+ if(!template || $.inArray(templateOptions.ajax.url, errors) !== -1) {
+ templateOptions.ajax.success = helpers.templateGetSuccess(templateOptions.ajax.url, callback);
+ templateOptions.ajax.error = helpers.templateGetError(templateOptions.templateId, templateOptions.ajax.url, callback);
+ $.trafficCop(templateOptions.ajax);
+ }
+ else {
+ callback(template);
+ }
+ },
+
+ getSync: function(options) {
+ var templateOptions = $.extend({}, infuser.defaults, (typeof options === "object" ? options : { templateId: options }), { ajax: { async: false } }),
+ template,
+ templateHtml;
+ templateOptions.ajax.url = helpers.getTemplatePath(templateOptions);
+ template = infuser.store.getTemplate(templateOptions.ajax.url);
+ if(!template || $.inArray(templateOptions.ajax.url, errors) !== -1) {
+ templateHtml = null;
+ templateOptions.ajax.success = function(response) { templateHtml = response; };
+ templateOptions.ajax.error = function(exception) {
+ if($.inArray(templateOptions.ajax.url) === -1) {
+ errors.push(templateOptions.ajax.url);
+ }
+ templateHtml = returnErrorTemplate("HTTP Status code: exception.status", templateOptions.templateId, templateOptions.ajax.url);
+ };
+ $.ajax(templateOptions.ajax);
+ if(templateHtml === null) {
+ templateHtml = returnErrorTemplate("An unknown error occurred.", templateOptions.templateId, templateOptions.ajax.url);
+ }
+ else {
+ infuser.store.storeTemplate(templateOptions.ajax.url, templateHtml);
+ template = infuser.store.getTemplate(templateOptions.ajax.url);
+ }
+ }
+ return template;
+ },
+
+ infuse: function(templateId, renderOptions) {
+ var templateOptions = $.extend({}, infuser.defaults, (typeof templateId === "object" ? templateId : renderOptions), (typeof templateId === "string" ? { templateId: templateId } : undefined )),
+ targetElement = typeof templateOptions.target === 'function' ? templateOptions.target(templateId) : templateOptions.target;
+ if(templateOptions.useLoadingTemplate) {
+ templateOptions.loadingTemplate.transitionIn(targetElement, templateOptions.loadingTemplate.content);
+ }
+ infuser.get(templateOptions, function(template) {
+ var _template = template;
+ templateOptions.preRender(targetElement, _template);
+ _template = templateOptions.bindingInstruction(_template, templateOptions.model);
+ if(templateOptions.useLoadingTemplate) {
+ templateOptions.loadingTemplate.transitionOut(targetElement);
+ }
+ templateOptions.render(targetElement, _template);
+ templateOptions.postRender(targetElement);
+ });
+ }
+ };
+ return infuser; });
\ No newline at end of file
diff --git a/ext/infuser.js b/ext/infuser.js
new file mode 100644
index 0000000..d3772b9
--- /dev/null
+++ b/ext/infuser.js
@@ -0,0 +1,188 @@
+(function($, global, undefined) {
+ /*
+ infuser.js
+ Author: Jim Cowart
+ License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
+ Version 0.2.0
+ */
+ var hashStorage = {
+ templates: {},
+
+ storeTemplate: function(templateId, templateContent) {
+ this.templates[templateId] = templateContent;
+ },
+
+ getTemplate: function(templateId) {
+ return this.templates[templateId];
+ },
+
+ purge: function() {
+ this.templates = {};
+ }
+ };
+ var scriptStorage = {
+ templateIds: [],
+ storeTemplate: function(templateId, templateContent) {
+ var node = document.getElementById(templateId);
+ if(node === null) {
+ this.templateIds.push(templateId);
+ node = document.createElement("script");
+ node.type = "text/html";
+ node.id = templateId;
+ document.body.appendChild(node);
+ }
+ node.text = templateContent;
+ },
+
+ getTemplate: function(templateId) {
+ return document.getElementById(templateId);
+ },
+
+ purge: function() {
+ for(var i = 0; i < this.templateIds.length; i++) {
+ document.body.removeChild(document.getElementById(this.templateIds[i]));
+ }
+ this.templateIds = [];
+ }
+ };
+ var errorHtml = "",
+ returnErrorTemplate = function(status, templateId, templatePath) {
+ return errorHtml.replace('{STATUS}', status).replace('{TEMPLATEID}', templateId).replace('{TEMPLATEURL}', templatePath);
+ },
+ errors = [];
+ var helpers = {
+ getTemplatePath: function(templateOptions) {
+ var templateFile = templateOptions.templatePrefix + templateOptions.templateId + templateOptions.templateSuffix;
+ return templateOptions.templateUrl === undefined || templateOptions.templateUrl === "" ?
+ templateFile : templateOptions.templateUrl + "/" + templateFile;
+ },
+ templateGetSuccess: function(templateId, callback) {
+ return function(response) {
+ infuser.store.storeTemplate(templateId, response);
+ callback(infuser.store.getTemplate(templateId));
+ };
+ },
+ templateGetError: function(templateId, templatePath, callback) {
+ return function(exception) {
+ if($.inArray(templateId, errors) === -1) {
+ errors.push(templateId);
+ }
+ var templateHtml = returnErrorTemplate("HTTP Status code: " + exception.status, templateId, templatePath);
+ infuser.store.storeTemplate(templateId, templateHtml);
+ callback(infuser.store.getTemplate(templateId));
+ };
+ },
+ getAjaxOptions: function(templateOptions) {
+
+ }
+ },
+ infuserOptions = ['target','loadingTemplate','postRender','preRender','render','bindingInstruction','useLoadingTemplate','model','templateUrl','templateSuffix','templatePrefix',''];
+ var infuser = {
+ storageOptions: {
+ hash: hashStorage,
+ script: scriptStorage
+ },
+
+ store: hashStorage,
+
+ defaults: {
+ // Template name conventions
+ templateUrl: "",
+ templateSuffix: ".html",
+ templatePrefix: "",
+ // AJAX Options
+ ajax: {
+ "async": true,
+ "dataType": "html",
+ "type": "GET"
+ },
+ // infuse() specific options - NOT used for "get" or "getSync"
+ target: function(templateId) { return "#" + templateId }, // DEFAULT MAPPING
+ loadingTemplate: {
+ content: 'Loading...
',
+ transitionIn: function(target, content) {
+ var tgt = $(target);
+ tgt.hide();
+ tgt.html(content);
+ tgt.fadeIn();
+ },
+ transitionOut: function(target) {
+ $(target).html("");
+ }
+ },
+ postRender: function(targetElement) { }, // NO_OP effectively by default
+ preRender: function(targetElement, template) { }, // NO_OP effectively by default
+ render: function(target, template) {
+ var tgt = $(target);
+ if(tgt.children().length === 0) {
+ tgt.append($(template));
+ }
+ else {
+ tgt.children().replaceWith($(template));
+ }
+ },
+ bindingInstruction: function(template, model) { return template; }, // NO_OP effectively by default
+ useLoadingTemplate: true // true/false
+ },
+
+ get: function(options, callback) {
+ var templateOptions = $.extend({}, infuser.defaults, (typeof options === "object" ? options : { templateId: options })),
+ template;
+ templateOptions.ajax.url = helpers.getTemplatePath(templateOptions);
+ template = infuser.store.getTemplate(templateOptions.ajax.url);
+ if(!template || $.inArray(templateOptions.ajax.url, errors) !== -1) {
+ templateOptions.ajax.success = helpers.templateGetSuccess(templateOptions.ajax.url, callback);
+ templateOptions.ajax.error = helpers.templateGetError(templateOptions.templateId, templateOptions.ajax.url, callback);
+ $.trafficCop(templateOptions.ajax);
+ }
+ else {
+ callback(template);
+ }
+ },
+
+ getSync: function(options) {
+ var templateOptions = $.extend({}, infuser.defaults, (typeof options === "object" ? options : { templateId: options }), { ajax: { async: false } }),
+ template,
+ templateHtml;
+ templateOptions.ajax.url = helpers.getTemplatePath(templateOptions);
+ template = infuser.store.getTemplate(templateOptions.ajax.url);
+ if(!template || $.inArray(templateOptions.ajax.url, errors) !== -1) {
+ templateHtml = null;
+ templateOptions.ajax.success = function(response) { templateHtml = response; };
+ templateOptions.ajax.error = function(exception) {
+ if($.inArray(templateOptions.ajax.url) === -1) {
+ errors.push(templateOptions.ajax.url);
+ }
+ templateHtml = returnErrorTemplate("HTTP Status code: exception.status", templateOptions.templateId, templateOptions.ajax.url);
+ };
+ $.ajax(templateOptions.ajax);
+ if(templateHtml === null) {
+ templateHtml = returnErrorTemplate("An unknown error occurred.", templateOptions.templateId, templateOptions.ajax.url);
+ }
+ else {
+ infuser.store.storeTemplate(templateOptions.ajax.url, templateHtml);
+ template = infuser.store.getTemplate(templateOptions.ajax.url);
+ }
+ }
+ return template;
+ },
+
+ infuse: function(templateId, renderOptions) {
+ var templateOptions = $.extend({}, infuser.defaults, (typeof templateId === "object" ? templateId : renderOptions), (typeof templateId === "string" ? { templateId: templateId } : undefined )),
+ targetElement = typeof templateOptions.target === 'function' ? templateOptions.target(templateId) : templateOptions.target;
+ if(templateOptions.useLoadingTemplate) {
+ templateOptions.loadingTemplate.transitionIn(targetElement, templateOptions.loadingTemplate.content);
+ }
+ infuser.get(templateOptions, function(template) {
+ var _template = template;
+ templateOptions.preRender(targetElement, _template);
+ _template = templateOptions.bindingInstruction(_template, templateOptions.model);
+ if(templateOptions.useLoadingTemplate) {
+ templateOptions.loadingTemplate.transitionOut(targetElement);
+ }
+ templateOptions.render(targetElement, _template);
+ templateOptions.postRender(targetElement);
+ });
+ }
+ };
+ global.infuser = infuser; })(jQuery, window);
\ No newline at end of file
diff --git a/ext/jquery-1.6.4.min.js b/ext/jquery-1.6.4.min.js
deleted file mode 100644
index 628ed9b..0000000
--- a/ext/jquery-1.6.4.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */
-(function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;ca ",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j =0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c ",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML=" ",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="
";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,""," "],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""," "],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>$2>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/test.html b/spec/test.html
new file mode 100644
index 0000000..cafa67a
--- /dev/null
+++ b/spec/test.html
@@ -0,0 +1,415 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/adapter.amd.coffee b/src/adapter.amd.coffee
new file mode 100644
index 0000000..7550360
--- /dev/null
+++ b/src/adapter.amd.coffee
@@ -0,0 +1,2 @@
+define ['postal', 'cartographer'], (postal, cartographer) ->
+ ###import "postal.coffee" ###
\ No newline at end of file
diff --git a/src/adapter.coffee b/src/adapter.coffee
new file mode 100644
index 0000000..98d4223
--- /dev/null
+++ b/src/adapter.coffee
@@ -0,0 +1 @@
+###import "postal.coffee" ###
\ No newline at end of file
diff --git a/src/amd.coffee b/src/amd.coffee
new file mode 100644
index 0000000..2f63b43
--- /dev/null
+++ b/src/amd.coffee
@@ -0,0 +1,3 @@
+define ['jquery', 'underscore', 'infuser', 'DOMBuilder'], ($, _, infuser) ->
+ ###import "cartographer.coffee" ###
+ return cartographer;
\ No newline at end of file
diff --git a/src/browser.coffee b/src/browser.coffee
new file mode 100644
index 0000000..c01bba2
--- /dev/null
+++ b/src/browser.coffee
@@ -0,0 +1 @@
+###import "cartographer.coffee" ###
\ No newline at end of file
diff --git a/src/cartographer.coffee b/src/cartographer.coffee
index 8ba7708..e0b8d2b 100644
--- a/src/cartographer.coffee
+++ b/src/cartographer.coffee
@@ -1,9 +1,5 @@
-###
- cartographer
- author: Alex Robson <@A_Robson>
- License: MIT ( http://www.opensource.org/licenses/mit-license )
- Version: 0.1.0
-###
-
-###import "main.coffee" ####
-###import "template.coffee" ###
\ No newline at end of file
+ ###import "local.coffee" ###
+ ###import "forkJoin.coffee" ###
+ ###import "sourceResolver.coffee" ###
+ ###import "main.coffee" ####
+ ###import "template.coffee" ###
\ No newline at end of file
diff --git a/src/forkJoin.coffee b/src/forkJoin.coffee
new file mode 100644
index 0000000..38ab8f2
--- /dev/null
+++ b/src/forkJoin.coffee
@@ -0,0 +1,36 @@
+
+forkJoin = (work, done, iterations) ->
+ if not iterations
+ iterations = 1
+ total = work.length * iterations
+ list = new Array(total)
+ count = 0
+ onList = (index, result) ->
+ count++
+ list[index] = result
+ if count == total
+ done list
+
+ callCounter = 0
+ for iteration in [0..iterations-1]
+ for fx in work
+ fx ( y ) ->
+ onList callCounter, y
+ callCounter++
+
+queueByArgList = (context, worker, argList) ->
+ count = argList.length
+ list = new Array(count)
+ for index in [0..count-1]
+ list[index] = createCallback context, worker, argList[index]
+ list
+
+queueByFunctionList = (context, workers, args) ->
+ count = workers.length
+ list = new Array(count)
+ for index in [0..count-1]
+ list[index] = createCallback context, workers[index], args
+ list
+
+createCallback = (context, callback, args) ->
+ (x) -> callback.apply(context, args.concat(x) )
\ No newline at end of file
diff --git a/src/lists.coffee b/src/lists.coffee
deleted file mode 100644
index c3fb75c..0000000
--- a/src/lists.coffee
+++ /dev/null
@@ -1,40 +0,0 @@
- eventHandlers =
- click: "onclick"
- dblclick: "ondblclick"
- mousedown: "onmousedown"
- mouseup: "onmouseup"
- mouseover: "onmouseover"
- mousemove: "onmousemove"
- mouseout: "onmouseout"
- keydown: "onkeydown"
- keypress: "onkeypress"
- keyup: "onkeyup"
- select: "onselect"
- change: "onchange"
- focus: "onfocus"
- blur: "onblur"
- scroll: "onscroll"
- resize: "onresize"
- submit: "onsubmit"
-
- modelTargets =
- hide: "hidden"
- title: "title"
- class: "className"
- value: ["value", "textContent"]
-
- modelTargetsForCollections =
- hide: "hidden"
- title: "title"
- value: "value"
- class: "className"
-
- templateProperties =
- id: "id"
- name: "name"
- title: "title"
- className: "class"
- type: "type"
- width: "width"
- height: "height"
- value: "value"
\ No newline at end of file
diff --git a/src/local.coffee b/src/local.coffee
new file mode 100644
index 0000000..2c1165a
--- /dev/null
+++ b/src/local.coffee
@@ -0,0 +1,41 @@
+configuration =
+ elementIdentifier: 'data-id'
+ templateIdentifier: 'data-template'
+
+createChildren = ( iterations, templateInstance, model, modelFqn, id, context, onChildren) ->
+ children = context.childrenToCreate
+ isCollection = iterations > 0
+ if not iterations
+ iterations = 1
+ childId = id
+ childModel = model
+ childFqn = modelFqn
+
+ callList = []
+ for iteration in [0..iterations-1]
+ if id == undefined and isCollection
+ childId = iteration
+ childModel = model[childId]
+ childFqn = "#{modelFqn}.#{childId}"
+ for fx in children
+ callList.push createCallback self, fx, [templateInstance, childModel, childFqn, childId]
+ forkJoin callList, onChildren
+
+createFqn = ( namespace, id, name, filterName ) ->
+ newNs = namespace || ""
+ newId = if id == undefined then "" else id
+ delimiter = if newNs != "" and newId != "" then "." else ""
+ result = "#{newNs}#{delimiter}#{newId}"
+ result
+
+elementTemplate = ( element ) ->
+ element?.attributes[configuration.templateIdentifier]?.value
+
+getActualValue = (value, context) ->
+ if _.isFunction value then value.call(context) else value
+
+getHtmlFromList = (list, html) ->
+ $(html["DIV"]({}, list)).html()
+
+getNestedValue = (value, property) ->
+ if value and value[property] then value[property] else undefined
\ No newline at end of file
diff --git a/src/main.coffee b/src/main.coffee
index b899dc1..6606e46 100644
--- a/src/main.coffee
+++ b/src/main.coffee
@@ -1,29 +1,42 @@
-Cartographer = () ->
- self = this
+class Cartographer
- postal.channel("cartographer").subscribe (m) ->
- if m.map
- self.map m.target, m.namespace
- else if m.apply
- self.apply m.template, m.proxy, m.render, m.error
+ constructor: ->
+ @config = configuration
+ @templates = {}
+ @containerLookup = {}
+ @instanceCache = {}
+ @resolver = resolver
- @templates = {}
+ map: ( name ) ->
+ template = new Template name
+ @templates[name] = template
+ true
- @map = ( target, namespace ) ->
- template = new Template target, namespace
- @templates[template.fqn] = template
+ render: ( name, id, model, onMarkup, onError ) ->
+ self = this
+ @containerLookup[id] = @templates[name]
+ if @templates[name]
+ template = @templates[name]
+ template.render id, model, (id, op, result) ->
+ self.instanceCache[id] = result
+ onMarkup id, op, result
+ else if model.__template__ and id
+ templateName = model.__template__
+ @map templateName
+ @render templateName, id, model, onMarkup, onError
+ else
+ onError id, "render", "No template with #{name} has been mapped"
- @apply = ( template, proxy, render, error ) ->
- templateInstance = @templates[template]
- if templateInstance
- result = templateInstance.apply proxy
- if render
- render( result, templateInstance.fqn )
- else
- $("#" + templateInstance.fqn ).replaceWith( result )
- else if error
- error()
+ add: (id, listId, model, onMarkup) ->
+ if @containerLookup[id]
+ template = @containerLookup[id]
+ template.add listId, model, onMarkup
- self
+ update: (id, controlId, model, onMarkup) ->
+ if @containerLookup[id]
+ template = @containerLookup[id]
+ template.update controlId, model, onMarkup
-context["cartographer"] = new Cartographer()
\ No newline at end of file
+cartographer = new Cartographer()
+
+cartographer
\ No newline at end of file
diff --git a/src/postal.coffee b/src/postal.coffee
new file mode 100644
index 0000000..383aa72
--- /dev/null
+++ b/src/postal.coffee
@@ -0,0 +1,57 @@
+class PostalSetup
+ constructor: ->
+ self = this
+ postal.subscribe "cartographer", "api", (message, envelope) ->
+ operation = message.operation
+ self[operation](message)
+
+ apply: (message) ->
+ name = message.name
+ template = message.template
+ model = message.model
+ cartographer.apply name, template, model, (
+ (id, markup, op) ->
+ postal.publish "cartographer", "render.#{template}",
+ template: template
+ markup: markup
+ operation: "render"
+ ),
+ ( (error) ->
+ postal.publish "cartographer", "render.#{error}",
+ template: template
+ error: error
+ operation: "render"
+ )
+
+ map: (message) ->
+ cartographer.map message.name
+
+ resolver: (message) ->
+ if message.order == "prepend"
+ cartographer.resolver.prependSource message.resolver
+ else
+ cartographer.resolver.appendSource message.resolver
+
+ add: (message) ->
+ templateId = message.template
+ fqn = message.id
+ model = message.model
+ cartographer.add templateId, fqn, model, (id,markup, op) ->
+ postal.publish "cartographer", "render.{templateId}",
+ template: templateId
+ parent: fqn
+ markup: markup
+ operation: "add"
+
+ update: (message) ->
+ templateId = message.template
+ fqn = message.id
+ model = message.model
+ cartographer.update templateId, fqn, model, (id, markup, op) ->
+ postal.publish "cartographer", "render.{templateId}",
+ template: templateId
+ id: fqn
+ markup: markup
+ operation: "update"
+
+setup = new PostalSetup()
\ No newline at end of file
diff --git a/src/sourceResolver.coffee b/src/sourceResolver.coffee
new file mode 100644
index 0000000..88972a7
--- /dev/null
+++ b/src/sourceResolver.coffee
@@ -0,0 +1,52 @@
+class SourceResolver
+
+ constructor: ->
+ @sources = []
+
+ appendSource: (source) ->
+ @sources.push source
+
+ prependSource: (source) ->
+ @sources.unshift source
+
+ resolve: (name, onFound, notFound) ->
+ self = this
+ # iterate through sources until
+ # 1 - the finder returns a template and calls onFound with result
+ # 2 - all sources are exhausted
+ index = 0
+ finder = -> # this list is required, DO NOT REMOVE
+ finder = () ->
+ call = self.sources[index]
+ if call
+ call(
+ name,
+ (x) ->
+ onFound $(x),
+ () ->
+ index++
+ finder()
+ )
+ else
+ notFound()
+ finder()
+
+resolver = new SourceResolver()
+
+# add a page check method as the first source
+resolver.appendSource (name, success, fail) ->
+ template = $( '#' + name + '-template' )
+ if template.length > 0
+ success template[0]
+ else
+ fail()
+
+infuser = infuser || window.infuser
+
+# if infuser is present, add it as a source
+if infuser
+ resolver.appendSource (name, success, fail) ->
+ infuser.get name,
+ (x) -> success x,
+ (x) ->
+ fail()
\ No newline at end of file
diff --git a/src/template.coffee b/src/template.coffee
index 0472dcb..b24231b 100644
--- a/src/template.coffee
+++ b/src/template.coffee
@@ -1,157 +1,279 @@
-Template = (target, namespace) ->
+class Template
+
+ constructor: (@name) ->
self = this
+ @name = name
+ @fqn = ""
+ @html = DOMBuilder.dom
+ @templates = {}
+ @deferredApplyCalls = []
+ @renderTemplate = () ->
+ @ready = false
+ @factories = {}
- ###import "lists.coffee" ####
+ @crawl @name, undefined, {}, (x) ->
+ self.renderTemplate = x
+ self.ready = true
+ if self.deferredApplyCalls.length > 0
+ for call in self.deferredApplyCalls
+ call()
- conditionalCopy = ( source, target, sourceId, targetId ) ->
- val = source[sourceId]
- if val != undefined
- if _.isArray(targetId)
- ( target[x] = val ) for x in targetId
- else
- target[targetId] = val
-
- copyProperties = ( source, target, list ) ->
- ( conditionalCopy source, target, x, list[x] ) for x in _.keys(list)
-
- crawl = ( context, root, namespace, element ) ->
- id = element["id"]
- fqn = createFqn namespace, id
- tag = element.tagName.toUpperCase()
- context = context or root
-
- if element.children != undefined and element.children.length > 0
- createChildren = ( crawl( context, root, fqn, child ) for child in element.children )
-
- call = ( html, model, parentFqn, idx ) ->
- actualId = if id == "" then idx else id
- myFqn = createFqn parentFqn, actualId
- val = if actualId == fqn or actualId == undefined then model else model?[actualId]
- #collection = if val instanceof ArrayWrapper then val else val?.items
- collection = if val.length then val else val?.items
- #if collection and collection instanceof ArrayWrapper
- if collection and collection.length
- list = []
- childFactory = createChildren[0]
- context.template[myFqn + "_add"] = ( newIndex, newModel ) ->
- childFactory( html, newModel, myFqn, newIndex )
-
- for indx in [0..collection.length-1]
- list.push ( call( html, collection, myFqn, indx ) for call in createChildren )
-
- childElement = makeTag( context, html, tag, element, myFqn, actualId, list, root, model )
- context[myFqn] = childElement
- childElement
- else
- controls = ( call( html, val, myFqn ) for call in createChildren )
- childElement = makeTag( context, html, tag, element, myFqn, actualId, controls, root, model )
- context[myFqn] = childElement
- childElement
-
- context.template[fqn] = call
- call
- else
- call = ( html, model, parentFqn, idx ) ->
- actualId = if id == "" then idx else id
- myFqn = createFqn parentFqn, actualId
- val = if actualId == fqn then model else model?[actualId]
- childElement = makeTag( context, html, tag, element, myFqn, actualId, val, root, model )
- context[myFqn] = childElement
- childElement
-
- context.template[fqn] = call
- call
-
- createFqn = ( namespace, id ) ->
- if id == undefined or id == ""
- result = namespace
- else if namespace == undefined or namespace == ""
- result = id
- else
- result = "#{namespace}.#{id}"
- result
+ handleTemplate: ( template, templateId, onTemplate ) ->
+ self = this
+ if self.templates[templateId]
+ onTemplate self.templates[templateId]
+ true
+ else
+ resolver.resolve(
+ template,
+ (x) ->
+ onTemplate(x)
+ ,
+ () -> console.log "Could not resolve tempalte #{template}")
+ true
- makeTag = ( context, html, tag, template, myFqn, id, val, root, model ) ->
- properties = {}
- templateSource = if template.textContent then template.textContent else template.value
- content = if val then val else templateSource
- element = {}
- if id or id == 0
- properties.id = id
+ buildCreateCall: ( element, elementId, elementFqn, childrenToCreate, templates ) ->
+ self = this
+ tag = element.tagName.toUpperCase()
+ context =
+ tag: tag,
+ element: element,
+ elementId: elementId,
+ elementFqn: elementFqn,
+ childrenToCreate: childrenToCreate,
+ templates: templates
- if template
- copyProperties template, properties, templateProperties
+ return ( instance, model, fqn, id, onElement ) ->
+ self.create( instance, model, fqn, id, context, onElement )
+
+ crawl: ( namespace, markup, templates, onDone ) ->
+ self = this
+ if markup?.length and ( not markup.nodeType || markup.nodeType == 1 )
+ if markup.length > 1
+ total = markup.length
+ argList = ([namespace, markup[i], templates] for i in [0..total-1])
+ workQueue = queueByArgList(self, self.crawl, argList)
+ forkJoin workQueue, (callList) ->
+ onDone (instance, model, fqn, id, onElement) ->
+ crawlQueue = queueByFunctionList self, callList, [instance, model, fqn, id]
+ forkJoin crawlQueue, (result) -> onElement result
- if tag == "INPUT"
- if not _.isObject content
- properties.value = content
- element = html[tag]( properties )
+ else self.crawl namespace, markup[0], templates, onDone
+ else
+ if markup?.nodeType and markup.nodeType != 1
+ onDone( () ->
+ arguments[4] markup.nodeValue
+ )
+ else
+ template = if markup then template = elementTemplate markup else namespace
+ elementId = markup?.attributes[configuration.elementIdentifier]?.value
+ elementFqn = namespace + if elementId then ".#{elementId}" else ''
+
+ if template
+ if not templates[template]
+ templates[template] = template
+ self.handleTemplate(
+ template,
+ elementFqn + "." + template,
+ (x) -> self.crawl namespace, x, templates, (f) ->
+ self.factories[template] = f
+ onDone f
+ )
+ else
+ onDone () -> self.factories[template].apply(self, [].slice.call(arguments,0))
else
- element = html[tag]( properties, content )
+ children = markup.childNodes
+ childFunctionsExpected = children.length
- if model?[id]
- if val instanceof Array
- copyProperties model[id], element, modelTargetsForCollections
+ continueProcessing = (contentList) ->
+ factory = self.buildCreateCall markup, elementId, elementFqn, contentList, templates
+ self.factories[elementFqn] = factory
+ onDone( factory )
+
+ if children.length > 0
+ argList = ( [elementFqn, child, templates] for child in children )
+ queue1 = queueByArgList self, self.crawl, argList
+ forkJoin queue1, continueProcessing
else
- copyProperties model[id], element, modelTargets
- setupEvents( model?[id], root, myFqn, element, context )
- element
-
- setupEvents = ( model, root, fqn, element, context ) ->
- if model
- (wireup x, eventHandlers[x], model, root, fqn, element, context ) for x in _.keys(eventHandlers)
-
- subscribe = ( context, channelName ) ->
- if @changeSubscription and @changeSubscription.unsubscribe
- @changeSubscription.ubsubscribe();
- @changesSubscription = postal.channel( channelName ).subscribe (m) ->
- if m.event != "read"
- control = context[m.key]
-
- lastIndex = m.key.lastIndexOf "."
- parentKey = m.key.substring 0, lastIndex
- childKey = m.key.substring ( lastIndex + 1 )
- target = "value"
-
- if childKey == "value" or not control
- control = context[parentKey]
- target = childKey
-
- if m.event == "wrote"
- if control
- if m.info.value.isProxy
- $(context[m.key]).replaceWith context.template[m.key]( self.html, m.info.value.getRoot(), parentKey )
- else
- conditionalCopy m.info, control, "value", modelTargets[target]
-
- else if m.event == "added"
- addName = parentKey + "_add"
- newElement = context.template[addName]( childKey, m.parent )
- $(context[parentKey]).append newElement
-
- wireup = ( alias, event, model, root, fqn, element, context ) ->
- handler = model[alias]
- if handler
- handlerProxy = (x) -> handler.apply(
- model,
- [root, { id: fqn, control: context[fqn], event: event, context: context, info: x } ]
- )
- element[event] = handlerProxy
+ continueProcessing []
+
+ handleModelTemplate: (template, templateInstance, model, modelFqn, id, context, onElement) ->
+ self = this
+ if self.templates[template]
+ self.templates[template]( templateInstance, model, modelFqn, id, onElement )
+ else
+ self.handleTemplate(template, template, (x) ->
+ self.crawl context.elementFqn, x, templates, ( callback ) ->
+ self.templates[template] = callback
+ callback templateInstance, model, modelFqn, id, onElement
+ )
+
+ create: ( templateInstance, model, modelFqn, id, context, onElement ) ->
+ self = this
+ elementId = context.elementId
+ id = elementId || id #set id to the current position or the dom position
+ # is this bound to the model or just structural
+ isBound = elementId != undefined and elementId != ""
+ idForFqn = if isBound then id else ""
+ newFqn = createFqn modelFqn, idForFqn, false, self.name
+
+ # if the element is bound but no model is present, skip this render
+ if isBound and not model[id]
+ onElement ""
+ return
+
+ # does this poisition of the model have a template?
+ modelTemplate = getActualValue model.__template__, model
+
+ # does the member we're on have a template?
+ memberTemplate = getActualValue model[id]?.__template__, model
+ memberValue = getActualValue(
+ getNestedValue(model[id], "__value__" ) ||
+ model[id] ||
+ getNestedValue(model, "__value__"),
+ model)
+
+ # used to advance the model to the next level
+ childModel = if isBound then model[id] else model
+
+ # if there is a template on the model itself
+ # then we parse this element but replace it's children
+ if modelTemplate
+ delete model.__template__
+ self.handleModelTemplate modelTemplate, templateInstance, model, modelFqn, id, context, (x) ->
+ onElement (self.makeTag context.tag, context.element, newFqn, id, isBound, x, model, templateInstance)
+
+ # if there is a template on the member
+ # then we replace/insert an element at the current location
+ else if memberTemplate
+ delete model[id].__template__
+ self.handleModelTemplate modelTemplate, templateInstance, model, modelFqn, id, context, onElement
+
+ #if not memberTemplate
+ else
+ childElements = context?.childrenToCreate.slice(0)
+ childElementCount = childElements.length
+ # are there elements to create under this one?
+ if childElementCount > 0
+
+ # if the value has items
+ collection = getNestedValue(memberValue, "__items__") || memberValue
+ collectionLength = if collection then collection.length else 0
+ isCollection = if collectionLength and not _.isString(collection) then collection
+
+ self.factories[newFqn+"_add"] = (itemIndex, itemModel, onItem) ->
+ newFqn = "#{newFqn}.#{itemIndex}"
+ createChildren 0, templateInstance, itemModel, newFqn, itemIndex, context, onItem
+
+ if isCollection
+ createChildren collectionLength, templateInstance, childModel, newFqn, undefined, context, (list) ->
+ onElement self.makeTag context.tag, context.element, newFqn, id, context.elementId, list, model, templateInstance
+
+ else # the current value is not a collection, but there are still child elements
+ createChildren 0, templateInstance, childModel, newFqn, id, context, (list) ->
+ onElement self.makeTag context.tag, context.element, newFqn, id, context.elementId, list, model, templateInstance
+
+ else # this element has no children, it only holds the value
+ onElement self.makeTag( context.tag, context.element, newFqn, id, isBound, memberValue, model, templateInstance )
+
+ makeTag: (tag, originalElement, fqn, id, hasId, val, model, templateInstance ) ->
+ self = this
+ properties = {}
+ content =
+ if _.isString(val)
+ val
+ else if _.isArray(val)
+ val || val?[id]
else
- element[event] = (x) ->
- if event == "onchange"
- x.stopPropagation()
- context.eventChannel.publish( { id: fqn, model: model, control: context[fqn], event: event, context: context, info: x } )
-
- @apply = (model) ->
- fn = crawl this, model, namespace, @element, @apply
- fn @html, model
- @element = $(target)[0]
- @fqn = createFqn namespace, @element["id"]
- @eventChannel = postal.channel(@fqn + "_events")
- @html = DOMBuilder.dom
- @template = {}
+ val?[id] || val
+ content = if originalElement.children.length == 0 and id == undefined and (_.isObject(val) or _.isArray(val)) then originalElement.textContent else content
+ element = {}
+
+ if hasId
+ properties[configuration.elementIdentifier] = fqn
+ if originalElement["className"]
+ properties["class"] = originalElement["className"]
+ if originalElement["type"]
+ properties["type"] = originalElement["type"]
+ if originalElement["value"]
+ properties["value"] = originalElement["value"]
+ if originalElement["id"]
+ properties["id"] = originalElement["id"]
+ if model?[id]?.class
+ properties["class"] = model[id].class
- subscribe( self, self.fqn + "_model" )
+ if tag == "INPUT"
+ if not _.isObject content
+ properties.value = content
+ element = self.html[tag]( properties )
+ else if tag == "IMG"
+ properties = $.extend(properties, {
+ src: content.src || content || originalElement.src,
+ alt: content.alt || content || originalElement.alt,
+ width: content.width || originalElement.width || "",
+ height: content.height || originalElement.height || ""
+ })
+ element = self.html[tag]( properties )
+ else if tag == "A"
+ link = model[id]?.link || model.link || originalElement.href
+ alt = model[id]?.alt || model.alt || content || originalElement.alt
+ properties = $.extend(properties, {
+ href: link,
+ alt: alt
+ })
+ element = self.html[tag]( properties, content )
+ else
+ element = self.html[tag]( properties, content )
+ element
+
+ render: (id, originalModel, onResult) ->
+ self = this
+ model = $.extend(true, {}, originalModel);
+ if not self.ready
+ self.deferredApplyCalls.push( () -> self.render(id, model, onResult ) );
+ else
+ self.renderTemplate( id, model, id, undefined, (x) ->
+ result = {}
+ if not x.length
+ result = $(x)[0]
+ $(result).attr(configuration.elementIdentifier, id)
+ else
+ result = getHtmlFromList(x, self.html)
+ onResult id, result, "render"
+ )
+
+ update: (fqn, model, onResult) ->
+ self = this
+ lastIndex = fqn.lastIndexOf "."
+ templateId = fqn.split('.')[0]
+ parentKey = fqn.substring 0, lastIndex
+ childKey = fqn.substring ( lastIndex + 1 )
+
+ if self.factories[fqn]
+ self.factories[fqn](
+ templateId
+ model,
+ parentKey,
+ childKey,
+ ((dom) ->
+ newElement = dom
+ onResult fqn, newElement, "update")
+ )
+
+ add: (fqn, model, onResult) ->
+ self = this
+ lastIndex = fqn.lastIndexOf "."
+ templateId = fqn.split('.')[0]
+ parentKey = fqn.substring 0, lastIndex
+ childKey = fqn.substring ( lastIndex + 1 )
- this
\ No newline at end of file
+ addName = fqn + "_add"
+ if self.factories[addName]
+ count = $("[#{configuration.elementIdentifier}=\"#{fqn}\"]").children.length + 1
+ self.factories[addName](
+ count,
+ model,
+ ((dom) ->
+ newElement = getHtmlFromList(dom, self.html)
+ onResult fqn, newElement, "add")
+ )