How to use JST with underscore.js? - javascript

I'm having troubles using variables that would normally be no problem with understand.js, but seemingly when you combine JST with underscore.js it seems to struggle.
var something= SD.defaultView.extend({
el: 'page',
template: JST['app/www/js/templates/sex.ejs'],
data: {
header: 'some information!!!',
image: '/img/path.jpg'
},
render: function () {
var compiled = _.template(this.template(), this.data); //I pass in the complied JST template
this.$el.html(compiled);
}
});
JST File rendered
this["JST"]["app/www/js/templates/sex.ejs"] = function (obj) {
obj || (obj = {});
var __t, __p = '', __e = _.escape;
with (obj) {
__p += ((__t = ( header )) == null ? '' : __t) + '<sexform>Hello There</sexform>';
}
return __p
};
Error
ReferenceError: header is not defined - templates.js (line 21)
...obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p +=((__t = ( header )...
sex.ejs
<%= header %><sexform>Hello There</sexform>
Background Information
As expected, header is not available at the time of the reader, which is happening via grunt file with each change to my JST templates. I feel I must be implement JST's the wrong way.
But, to me this seems like the correct way of doing everything.
Of course, I am trying to use variables with underscore inside of sex.ejs
All of this code can be seen here: http://m.sexdiaries.co.uk/#wank
NB:
I can assure that this is safe for work and contains no images, even though as misleading as the url is its really not adult material, its an educational app.

You have this to define the view's template:
template: JST['app/www/js/templates/sex.ejs'],
And JST contains functions (which is, more or less, the whole point of using JST-style precompiled templates):
this["JST"]["app/www/js/templates/sex.ejs"] = function (obj) {
Then you do this:
var compiled = _.template(this.template(), this.data);
// function call ----------------------^^
Two things are wrong there:
You've already called _.template to compile the template.
this.template is the compiled template function that expects to be fed this.data.
The fix is quite simple:
var compiled = this.template(this.data);

Related

requirejs and ByteBuffer

im an javascript newbie and google didnt helps:
I tryed to load ByteBuffer.js in an require.js module:
define(['js/ByteBufferAB'], function (ByteBufferAB) {
var MessageBase = function () {
this._version = 0; // unsinged int 16 bits
this._dataType = "";
};
MessageBase.prototype.toBytes = function () {
//console.log( new ByteBufferAB(58));
var headerBytes = new ByteBufferAB(58); // <-- here comes the error
headerBytes.clear();
return headerBytes;
};
return MessageBase;
});
with the same syntax math.js is properly loaded.
But with ByteBufferAB.js the following error comes:
Uncaught TypeError: undefined is not a function
What am I doing wrong?
Thank you for your help
In your define call you refer to the module as js/ByteBufferAB so RequireJS looks for a module named js/ByteBufferAB. However, the module defines itself as ByteBuffer:
/* AMD */ else if (typeof define === 'function' && define["amd"])
define("ByteBuffer", ["Long"], function(Long) { return loadByteBuffer(Long); });
Because the module name is hardcoded, you need to have a mapping like this in your paths in the configuration you give to RequireJS:
ByteBuffer: "js/ByteBufferAB"
and you need to refer to the module as ByteBuffer in your define call.
None of this would be required if the developers for this library had not hardcoded a name but they have, and so here we are.

How to compile inline HTMLBars templates?

I have an inline template (template in JavaScript) that I used to compile like so (where temp is a Handlebars string):
var template = Handlebars.compile(temp);
template({model: results}); // Gets the HTML
I'm trying to use HTMLBars instead, but can't quite figure it out. I did the following:
var template = Ember.HTMLBars.compile(temp);
template({model: results}); // Throws an error that template isn't a function
How do I go about getting the HTML back from the HTMLBars template. I also tried:
var template = Ember.HTMLBars.compile(temp);
Ember.HtmlBars.template(template, {model: results});
Which doesn't error, but also doesn't use the model when rendering the HTML. I think I'm close, but can't quite figure out how to inject the model.
HTMLBars doesn't produce functions like Handlebars did. Handlebars was a string templating language: you compile a string to a template function, then run that function to produce a string. HTMLBars compiles a string into a template but the template doesn't produce a string, it produces DOM nodes. The simple answer is that you're not going to be able to do the same things with HTMLBars as you did with Handlebars. I suggest either adding another string templating library to your code (maybe Handlebars), or letting a view handle the HTMLBars template as seen in this question.
And if you're curious, here's what an HTMLBars template object looks like after being compiled (gotten from a JSBin console dump):
[object Object] {
blockParams: 0,
build: function build(dom) {
var el0 = dom.createDocumentFragment();
var el1 = dom.createTextNode("");
dom.appendChild(el0, el1);
var el1 = dom.createTextNode("");
dom.appendChild(el0, el1);
return el0;
},
cachedFragment: null,
hasRendered: false,
isHTMLBars: true,
isMethod: false,
isTop: true,
render: function render(context, env, contextualElement) {
var dom = env.dom;
var hooks = env.hooks, content = hooks.content;
dom.detectNamespace(contextualElement);
var fragment;
if (env.useFragmentCache && dom.canClone) {
if (this.cachedFragment === null) {
fragment = this.build(dom);
if (this.hasRendered) {
this.cachedFragment = fragment;
} else {
this.hasRendered = true;
}
}
if (this.cachedFragment) {
fragment = dom.cloneNode(this.cachedFragment, true);
}
} else {
fragment = this.build(dom);
}
if (this.cachedFragment) { dom.repairClonedNode(fragment,[0,1]); }
var morph0 = dom.createMorphAt(fragment,0,1,contextualElement);
content(env, morph0, context, "foo");
return fragment;
}
}

how to assign function to marionette.template

As per I know, marionette.template accept either jquery selector or compiled template string.
If I write code like in the following way, working fine
exports.ProductInfoView=Backbone.Marionette.ItemView.extend({
domInfo:{
mainTemplateId:"tagProductListTpl",
tableTemplateId:"taginfoViewTpl"
},
template:commomFunctions.templateCompilation("tagProductListTpl",""),
onRender:function(){
this.templatingProductInformation();
},
modelEvents:{
"change:currentJson":"templatingProductInformation"
},
templatingProductInformation:function(){
console.log(this.el);
//this.el.innerHTML=commomFunctions.templateCompilation(this.ui.mainTemplateId,"");
}
});
Note :commonFunctions.templateCompilation() accept templateId as first argument and data as second argument. It will compile handlebars template and it return compiled template.
If I assign that return value to template, working fine.
I want to make data for templating,so I am passing function to template like in the following way.
exports.ProductInfoView=Backbone.Marionette.ItemView.extend({
domInfo:{
mainTemplateId:"tagProductListTpl",
tableTemplateId:"taginfoViewTpl"
},
template:function(){
return commomFunctions.templateCompilation("tagProductListTpl","");
},
onRender:function(){
this.templatingProductInformation();
},
modelEvents:{
"change:currentJson":"templatingProductInformation"
},
templatingProductInformation:function(){
console.log(this.el);
//this.el.innerHTML=commomFunctions.templateCompilation(this.ui.mainTemplateId,"");
}
});
This way also working fine, If you observer I hard coded templateId("tagProductListTpl") inside function.But I don't want like that. I want to use like this.domInfo.mainTemplateId instead of hard coding. that way it's not working fine.
It's throwing error. I know it's out of scope. but how can I achive this.
can anyone help me.
Thanks.
I will advise you to rewrite Marionette.TemplateCache.prototype.compileTemplate which is responsible for template compilation. Look at this post, there almost the same issue.
Marionette.TemplateCache.prototype.compileTemplate = function (yourRawTemplate) {
// In case if template is function
if (_.isFunction(yourRawTemplate)) {
return yourRawTemplate;
} else {
return Handlebars.compile(yourRawTemplate);
}
};
And if you loading template files from remote server you also need to rewrite Backbone.Marionette.TemplateCache.prototype.loadTemplate. Here example:
Marionette.TemplateCache.prototype.loadTemplate = function ( templateId ) {
var template = '',
templateUrl = 'path_to_your_template/' + templateId + '.html';
// Loading template synchronously.
Backbone.$.ajax( {
async : false,
url : templateUrl,
success : function ( templateHtml ) {
template = templateHtml;
}
} );
return template;
};

Object not defined or null

I wrote a JavaScript file named global.js that has the following contents:
;
var Globals =
{
function getAppRoot() {
if (typeof (jQuery) !== "undefined")
return $("#ApplicationRoot").attr("href");
};
appRoot : getAppRoot();
};
Then in my HTML file (ASP.NET MVC project), I included my JavaScript file like so:
<link rel = "home" id = "ApplicationRoot"
href = "#Url.Content("~/")" />
<script src = "#Url.Content("~/Scripts/jquery-1.8.3.js")"
type="text/javascript"></script>
<script src = "#Url.Content("~/Scripts/global.js")"
type = "text/javascript"></script>
And then, in the HTML file, inside a SCRIPT tag, I write:
$(document).ready(
function() {
alert("Globals.appRoot = " + window.Globals.appRoot);
} );
However, when I run the code, it tells me that Globals is undefined.
UPDATE
Thank you, all. I just noticed that I'd forgotten the equal to sign (assignment operator) for one.
Another important thing that I observe now (which I wasn't fully sure of) is: I am assuming from your comments that an object declaration like so:
var foo = { /* cannot have anything that does not adhere to the bar : gar syntax? */ }
ANOTHER UPDATE
The thing is: if I made appRoot a method by doing so:
var Globals =
{
appRoot : function() { }
};
or like so:
var Globals =
{
appRoot : function getAppRoot() { }
}
The client would have to invoke appRoot with a set of following parenthesis. I would like for appRoot to be a property instead of a method. How do I do that?
FINAL UPDATE
I now have changed my code to read as follows:
// globals.js
// I understand that the starting semi-colon is not
// required. I'd left it in for reasons that it is used
var Globals =
{
appRoot : $("#ApplicationRoot").attr("href");
};
// inside the HTML file in $(document).ready();
if (tyepof(Globals) == "undefined" || Globals == null)
alert("Globals is either undefined or null");
else
alert("Globals.appRoot = " + Globals.appRoot);
I get the alert message Globals is either undefined or null.
ANSWER
Okay, finally. Thanks for all your help. I had another minor syntax error in the object declaration/initialization of the Globals object.
Since appRoot was a member of the object, and I was using the object initializer syntax, I should not have terminated the declaration of appRoot with a semi-colon. Instead, I should either have used a comma or just left it without any terminating character since it was the last (and the only member of Globals).
You need to re-write your globals.js, something like this should work:
var Globals = {
appRoot : function() {
if (typeof (jQuery) !== "undefined") {
return $("#ApplicationRoot").attr("href");
}
}
};
Your global.js should look more like this:
//; << not needed
var Globals = /*equal to missing*/
{
appRoot : function getAppRoot() {
if (typeof (jQuery) !== "undefined")
return $("#ApplicationRoot").attr("href");
}
};

Knockout Template with jQote2

I've started looking into using Knockout for my team's use; I've been very pleased with the framework so far, with the exception of its ties to the jQuery Templates plugin, whose syntax I hate. Additionally (and more importantly), we've been using jQote2 for our client-side templating, so I wanted to look into creating a template engine that uses it.
I'm having difficulty with the renderTemplate function; the jQote2 library doesn't seem to know how to locate the variables passed in through the data argument. Has anyone dealt with this sort of thing before? I'm assuming it's more of a jQote2 quirk than anything with how Knockout renders its templates...
The code:
jqoteTemplateEngine = function () {
var templates = {};
this.createJavaScriptEvaluatorBlock = function (script) {
return '<%= ' + script + ' %>';
}
this.getTemplateNode = function (template) {
var templateNode = document.getElementById(template);
if (templateNode == null)
throw new Error("Cannot find template with ID of " + template);
return templateNode;
}
this.renderTemplate = function(templateId, data, options) {
var renderedMarkup = jQuery.jqote(templates[templateId], data);
return ko.utils.parseHtmlFragment(renderedMarkup);
}
this.rewriteTemplate = function (template, rewriterCallback) {
var templateNode = this.getTemplateNode(template);
templates[template] = rewriterCallback(templateNode.text);
}
this.isTemplateRewritten = function (templateId) {
return templateId in templates;
}
};
jqoteTemplateEngine.prototype = new ko.templateEngine();
ko.setTemplateEngine(new jqoteTemplateEngine());
The Gist: http://gist.github.com/1341737
I would take a look at KO 1.3. It is in beta, but is quite stable. Two important things in 1.3. There is now a native template engine, so you could choose to avoid having any dependency on an external template engine (and even jQuery). The control-flow bindings with anonymous templates make this much simpler option.
Secondly, it simplified the way that custom template engines are defined. So, if you still want to use an external engine, then it is a bit easier to get it working.
Basically, you only need to define a renderTemplate method and a createJavaScriptEvaluatorBlock if you want to be able to data-bind to variables available to the template engine. The rest is defined on a ko.templateEngine base "class".
So, your engine might simply look like:
ko.jqoteTemplateEngine = function() {};
ko.jqoteTemplateEngine.prototype = new ko.templateEngine();
ko.jqoteTemplateEngine.prototype.createJavaScriptEvaluatorBlock = function(script) {
return '<%= ' + script + ' %>';
};
ko.jqoteTemplateEngine.prototype.renderTemplateSource = function(templateSource, bindingContext, options) {
var templateText = templateSource.text();
return ko.utils.parseHtmlFragment($.jqote(templateText, bindingContext.$data));
};
ko.setTemplateEngine(new ko.jqoteTemplateEngine());
Here is a sample in use: http://jsfiddle.net/rniemeyer/yTzcF/

Categories