Updated
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
// Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @fileoverview Provides a soy renderer that allows registration of
|
||||
* injected data ("globals") that will be passed into the rendered
|
||||
* templates.
|
||||
*
|
||||
* There is also an interface {@link goog.soy.InjectedDataSupplier} that
|
||||
* user should implement to provide the injected data for a specific
|
||||
* application. The injected data format is a JavaScript object:
|
||||
* <pre>
|
||||
* {'dataKey': 'value', 'otherDataKey': 'otherValue'}
|
||||
* </pre>
|
||||
*
|
||||
* To use injected data, you need to enable the soy-to-js compiler
|
||||
* option {@code --isUsingIjData}. The injected data can then be
|
||||
* referred to in any soy templates as part of a magic "ij"
|
||||
* parameter. For example, {@code $ij.dataKey} will evaluate to
|
||||
* 'value' with the above injected data.
|
||||
*
|
||||
* @author henrywong@google.com (Henry Wong)
|
||||
* @author chrishenry@google.com (Chris Henry)
|
||||
*/
|
||||
|
||||
goog.provide('goog.soy.InjectedDataSupplier');
|
||||
goog.provide('goog.soy.Renderer');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.soy');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new soy renderer. Note that the renderer will only be
|
||||
* guaranteed to work correctly within the document scope provided in
|
||||
* the DOM helper.
|
||||
*
|
||||
* @param {goog.soy.InjectedDataSupplier=} opt_injectedDataSupplier A supplier
|
||||
* that provides an injected data.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper;
|
||||
* defaults to that provided by {@code goog.dom.getDomHelper()}.
|
||||
* @constructor
|
||||
*/
|
||||
goog.soy.Renderer = function(opt_injectedDataSupplier, opt_domHelper) {
|
||||
/**
|
||||
* @type {goog.dom.DomHelper}
|
||||
* @private
|
||||
*/
|
||||
this.dom_ = opt_domHelper || goog.dom.getDomHelper();
|
||||
|
||||
/**
|
||||
* @type {goog.soy.InjectedDataSupplier}
|
||||
* @private
|
||||
*/
|
||||
this.supplier_ = opt_injectedDataSupplier || null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template into a single node or a document fragment.
|
||||
* Delegates to {@code goog.soy.renderAsFragment}.
|
||||
*
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
* @return {!Node} The resulting node or document fragment.
|
||||
*/
|
||||
goog.soy.Renderer.prototype.renderAsFragment = function(template,
|
||||
opt_templateData) {
|
||||
return goog.soy.renderAsFragment(template, opt_templateData,
|
||||
this.getInjectedData_(), this.dom_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template into a single node. If the rendered HTML
|
||||
* string represents a single node, then that node is returned.
|
||||
* Otherwise, a DIV element is returned containing the rendered nodes.
|
||||
* Delegates to {@code goog.soy.renderAsElement}.
|
||||
*
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
* @return {!Element} Rendered template contents, wrapped in a parent DIV
|
||||
* element if necessary.
|
||||
*/
|
||||
goog.soy.Renderer.prototype.renderAsElement = function(template,
|
||||
opt_templateData) {
|
||||
return goog.soy.renderAsElement(template, opt_templateData,
|
||||
this.getInjectedData_(), this.dom_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template and then set the output string as the
|
||||
* innerHTML of the given element. Delegates to {@code goog.soy.renderElement}.
|
||||
*
|
||||
* @param {Element} element The element whose content we are rendering.
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
*/
|
||||
goog.soy.Renderer.prototype.renderElement = function(element, template,
|
||||
opt_templateData) {
|
||||
goog.soy.renderElement(
|
||||
element, template, opt_templateData, this.getInjectedData_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template and returns the output string.
|
||||
*
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
* @return {string} The return value of rendering the template directly.
|
||||
*/
|
||||
goog.soy.Renderer.prototype.render = function(template, opt_templateData) {
|
||||
return template(opt_templateData || {}, undefined, this.getInjectedData_());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the injectedParams map if necessary and calls the configuration
|
||||
* service to prepopulate it.
|
||||
* @return {Object} The injected params.
|
||||
* @private
|
||||
*/
|
||||
goog.soy.Renderer.prototype.getInjectedData_ = function() {
|
||||
return this.supplier_ ? this.supplier_.getData() : {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An interface for a supplier that provides Soy injected data.
|
||||
* @interface
|
||||
*/
|
||||
goog.soy.InjectedDataSupplier = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the injected data. Implementation may assume that
|
||||
* {@code goog.soy.Renderer} will treat the returned data as
|
||||
* immutable. The renderer will call this every time one of its
|
||||
* {@code render*} methods is called.
|
||||
* @return {Object} A key-value pair representing the injected data.
|
||||
*/
|
||||
goog.soy.InjectedDataSupplier.prototype.getData = function() {};
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @fileoverview Provides utility methods to render soy template.
|
||||
*/
|
||||
|
||||
goog.provide('goog.soy');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.dom.TagName');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template and then set the output string as
|
||||
* the innerHTML of an element. It is recommended to use this helper function
|
||||
* instead of directly setting innerHTML in your hand-written code, so that it
|
||||
* will be easier to audit the code for cross-site scripting vulnerabilities.
|
||||
*
|
||||
* @param {Element} element The element whose content we are rendering into.
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
* @param {Object=} opt_injectedData The injected data for the template.
|
||||
*/
|
||||
goog.soy.renderElement = function(element, template, opt_templateData,
|
||||
opt_injectedData) {
|
||||
element.innerHTML = template(
|
||||
opt_templateData || goog.soy.defaultTemplateData_, undefined,
|
||||
opt_injectedData);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template into a single node or a document
|
||||
* fragment. If the rendered HTML string represents a single node, then that
|
||||
* node is returned (note that this is *not* a fragment, despite them name of
|
||||
* the method). Otherwise a document fragment is returned containing the
|
||||
* rendered nodes.
|
||||
*
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
* @param {Object=} opt_injectedData The injected data for the template.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
|
||||
* create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
|
||||
* @return {!Node} The resulting node or document fragment.
|
||||
*/
|
||||
goog.soy.renderAsFragment = function(template, opt_templateData,
|
||||
opt_injectedData, opt_domHelper) {
|
||||
var dom = opt_domHelper || goog.dom.getDomHelper();
|
||||
return dom.htmlToDocumentFragment(
|
||||
template(opt_templateData || goog.soy.defaultTemplateData_,
|
||||
undefined, opt_injectedData));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Renders a Soy template into a single node. If the rendered
|
||||
* HTML string represents a single node, then that node is returned. Otherwise,
|
||||
* a DIV element is returned containing the rendered nodes.
|
||||
*
|
||||
* @param {Function} template The Soy template defining the element's content.
|
||||
* @param {Object=} opt_templateData The data for the template.
|
||||
* @param {Object=} opt_injectedData The injected data for the template.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
|
||||
* create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
|
||||
* @return {!Element} Rendered template contents, wrapped in a parent DIV
|
||||
* element if necessary.
|
||||
*/
|
||||
goog.soy.renderAsElement = function(template, opt_templateData,
|
||||
opt_injectedData, opt_domHelper) {
|
||||
var dom = opt_domHelper || goog.dom.getDomHelper();
|
||||
var wrapper = dom.createElement(goog.dom.TagName.DIV);
|
||||
wrapper.innerHTML = template(
|
||||
opt_templateData || goog.soy.defaultTemplateData_,
|
||||
undefined, opt_injectedData);
|
||||
|
||||
// If the template renders as a single element, return it.
|
||||
if (wrapper.childNodes.length == 1) {
|
||||
var firstChild = wrapper.firstChild;
|
||||
if (firstChild.nodeType == goog.dom.NodeType.ELEMENT) {
|
||||
return /** @type {!Element} */ (firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, return the wrapper DIV.
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Immutable object that is passed into templates that are rendered
|
||||
* without any data.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.soy.defaultTemplateData_ = {};
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @fileoverview Provides test helpers for Soy tests.
|
||||
*/
|
||||
|
||||
goog.provide('goog.soy.testHelper');
|
||||
goog.setTestOnly('goog.soy.testHelper');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Fake Soy-generated template functions.
|
||||
//
|
||||
|
||||
var example = {};
|
||||
|
||||
|
||||
example.textNodeTemplate = function(opt_data, opt_sb, opt_injectedData) {
|
||||
assertNotNull(opt_data);
|
||||
assertNotUndefined(opt_data);
|
||||
return goog.string.htmlEscape(opt_data.name);
|
||||
};
|
||||
|
||||
|
||||
example.singleRootTemplate = function(opt_data, opt_sb, opt_injectedData) {
|
||||
assertNotNull(opt_data);
|
||||
assertNotUndefined(opt_data);
|
||||
return '<span>' + goog.string.htmlEscape(opt_data.name) + '</span>';
|
||||
};
|
||||
|
||||
|
||||
example.multiRootTemplate = function(opt_data, opt_sb, opt_injectedData) {
|
||||
assertNotNull(opt_data);
|
||||
assertNotUndefined(opt_data);
|
||||
return '<div>Hello</div><div>' + goog.string.htmlEscape(opt_data.name) +
|
||||
'</div>';
|
||||
};
|
||||
|
||||
|
||||
example.injectedDataTemplate = function(opt_data, opt_sb, opt_injectedData) {
|
||||
assertNotNull(opt_data);
|
||||
assertNotUndefined(opt_data);
|
||||
return goog.string.htmlEscape(opt_data.name) +
|
||||
goog.string.htmlEscape(opt_injectedData.name);
|
||||
};
|
||||
|
||||
|
||||
example.noDataTemplate = function(opt_data, opt_sb, opt_injectedData) {
|
||||
assertNotNull(opt_data);
|
||||
assertNotUndefined(opt_data);
|
||||
return '<div>Hello</div>';
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Test helper functions.
|
||||
//
|
||||
|
||||
/**
|
||||
* Retrieves the content of document fragment as HTML.
|
||||
* @param {Node} fragment The document fragment.
|
||||
* @return {string} Content of the document fragment as HTML.
|
||||
*/
|
||||
function fragmentToHtml(fragment) {
|
||||
var testDiv = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
testDiv.appendChild(fragment);
|
||||
return elementToInnerHtml(testDiv);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the content of an element as HTML.
|
||||
* @param {Element} elem The element.
|
||||
* @return {string} Content of the element as HTML.
|
||||
*/
|
||||
function elementToInnerHtml(elem) {
|
||||
var innerHtml = elem.innerHTML;
|
||||
if (goog.userAgent.IE) {
|
||||
innerHtml = innerHtml.replace(/DIV/g, 'div').replace(/\s/g, '');
|
||||
}
|
||||
return innerHtml;
|
||||
}
|
||||
Reference in New Issue
Block a user