UNPKG

raptor

Version:

RaptorJS provides an AMD module loader that works in Node, Rhino and the web browser. It also includes various sub-modules to support building optimized web applications.

278 lines (238 loc) 10.2 kB
/* * Copyright 2011 eBay Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * The {@link raptor/render-context/Context} class represents a "rendering context" * suitable for rendering HTML to a writer. A context object is required when rendering * a template and the context object contains a reference to an underlying writer object that is * used to capture the rendered output. */ define.Class( 'raptor/render-context/Context', ['raptor'], function(raptor, require) { "use strict"; var forEachEntry = raptor.forEachEntry, escapeXmlAttr = require('raptor/xml/utils').escapeXmlAttr, StringBuilder = require('raptor/strings/StringBuilder'), createError = raptor.createError, nextUniqueId = 0, _classFunc = function(className, name) { var Clazz = require(className), func = Clazz[name] || (Clazz.prototype && Clazz.prototype[name]); if (!func) { throw createError(new Error('Helper function not found with name "' + name + '" in class "' + className + '"')); } return func; }; /** * */ var Context = function(writer) { this.writer = writer; this.w = this.write; this.listeners = {}; this.attributes = {}; }; Context.classFunc = _classFunc; var proto = { /** * Returns the attributes object associated with the context. * * The attributes object is just a regular JavaScript Object that can be used to store arbitrary data. * * @returns {Object} The attributes object. */ getAttributes: function() { return this.attributes; }, /** * Returns the value of an attribute associated with the context * * @returns {Object} The attribute value. */ getAttribute: function(name) { return this.attributes[name]; }, /** * Returns a auto-incrementing unique ID that remains unique across multiple context objects. * @returns {Number} The unique number */ uniqueId: function() { return 'c' + nextUniqueId++; }, /** * Outputs a string to the underlying writer. If the object is null then nothing is written. If the object is not a string then it is converted to a string using the <code>toString</code> method. * * @param str {String|Object} The String (or Object) to write to the underlying writer. */ write: function(str) { if (str !== null && str !== undefined) { if (typeof str !== 'string') { str = str.toString(); } this.writer.write(str); } return this; }, /** * Returns the string output associated with the underling writer by calling <code>this.writer.toString()</code> * * @returns {String} The String output */ getOutput: function() { return this.writer.toString(); }, /** * * Temporarily swaps out the underlying writer with a temporary buffer and invokes the provided function to capture the output and return it. * * After the function has completed the old writer is swapped back into place. The old writer will remain untouched. * Internally, this method uses the {@link raptor/render-context/Context.prototype#swapWriter} method. * * @param func {Function} The function to invoke while the old writer is swapped out * @param thisObj {Object} The "this" object ot use for the provided function * @returns {String} The resulting string output. */ captureString: function(func, thisObj) { var sb = new StringBuilder(); this.swapWriter(sb, func, thisObj); return sb.toString(); }, /** * Temporarily swaps out the underlying writer with the provided writer and invokes the provided function. * * After the function has completed the old writer is swapped back into place. The old writer will remain untouched. * * @param newWriter {Object} The new writer object to use. This object must have a "write" method. * @param func {Function} The function to invoke while the old writer is swapped out * @param thisObj {Object} The "this" object ot use for the provided function * * @returns {void} */ swapWriter: function(newWriter, func, thisObj) { var oldWriter = this.writer; try { this.writer = newWriter; func.call(thisObj); } finally { this.writer = oldWriter; } }, createNestedContext: function(writer) { var context = require('raptor/render-context').createContext(writer); context.attributes = this.getAttributes(); return context; }, /** * * @param handler * @param input */ invokeHandler: function(handler, input) { if (typeof handler === 'string') { handler = require(handler); } var func = handler.process || handler.render; func.call(handler, input, this); }, getFunction: function(className, name) { if (!this._helpers) { this._helpers = {}; } var key = className + ":" + name, helper = this._helpers[key]; if (!helper) { helper = this._helpers[key] = _classFunc(className, name).bind(this); } return helper; }, getHelperObject: function(className) { if (!this._helpers) { this._helpers = {}; } var Helper = this._helpers[className] || (this._helpers[className] = require(className)); return new Helper(this); }, isTagInput: function(input) { return input && input.hasOwnProperty("_tag"); }, renderTemplate: function(name, data) { require("raptor/templating").render(name, data, this); return this; }, attr: function(name, value, escapeXml) { if (value === null || value === true) { value = ''; } else if (value === undefined || value === false || (typeof value === 'string' && value.trim() === '')) { return this; } else { value = '="' + (escapeXml === false ? value : escapeXmlAttr(value)) + '"'; } this.write(' ' + name + value); return this; }, /** * * @param attrs */ attrs: function(attrs) { if (arguments.length !== 1) { this.attr.apply(this, arguments); } else if (attrs) { forEachEntry(attrs, this.attr, this); } return this; }, /** * Helper function invoke a tag handler */ t: function(handler, props, body, dynamicAttributes, namespacedProps) { if (!props) { props = {}; } props._tag = true; if (body) { props.invokeBody = body; } if (dynamicAttributes) { props.dynamicAttributes = dynamicAttributes; } if (namespacedProps) { raptor.extend(props, namespacedProps); } this.invokeHandler(handler, props); return this; }, c: function(func) { var output = this.captureString(func); return { toString: function() { return output; } }; } }; // Add short-hand method names that should be used in compiled templates *only* proto.a = proto.attrs; proto.f = proto.getFunction; proto.o = proto.getHelperObject; proto.i = proto.renderTemplate; Context.prototype = proto; return Context; });