How to load multiple templates with HandlebarJS - javascript

I am currently building a small Handlebars.js application. I have no prior experience and as I'm learning as I'm going along, I've been running in to a few issues.
My first issue is loading templates.
Currently I have functions like this for every single template I need to load
var populateDocs = function() {
var srcContent = $( '#docs-template' ).html(),
contentTemplate = Handlebars.compile( srcContent ),
htmlContent = contentTemplate( content.getItem( 'docs' ) );
$( '#docs' ).append( htmlContent );
};
I am reading templates from a content.json file so once this file is ready, I call multiple functions to populate each template.
content.onReady(
function() {
populateFooter();
populateHomework();
populateDocs();
populateContact();
generateTabs();
}
);
My question is. Is there a way I can load all these templates without having to call each function for each template?

I rather think the best you can do is to proceduralise things better.
If all the populateXxx() functions follow the same pattern as populateDocs() (or can be made to do so), then you can write :
var populate = function(id) {
$('#'+id).append(Handlebars.compile($('#'+id+'-template').html())(content.getItem(id)));
};
content.onReady(function() {
populate('footer');
populate('homework');
populate('docs');
populate('contact');
generateTabs();
});
or
content.onReady(function() {
['footer', 'homework', 'docs', 'contact'].forEach(populate);
generateTabs();
});

Related

Loading WordPress Posts on a html page

I am trying to load posts outside WordPress on a static html page. So far I have a working example using React, http://v2.wp-api.org/ and https://github.com/mzabriskie/axios. This working example using react currently displays the posts properly but it is fragile and there is no fall back. Codepen example here, https://codepen.io/krogsgard/pen/NRBqPp/
I use this example to get my feed source using axios axios.get(this.props.source). Then I use the examples react function to grab my latest three posts, including titles and images and load them into a static html page via
render: function render() {
return React.createElement(
"div",
{ className: "post-wrapper" },
this.state.posts.map(function (post) {
return React.createElement(
"div",
{ key: post.link, className: "post" },
React.createElement(
"h2",
{ className: "post-title" },
React.createElement("a", {
href: post.link,
dangerouslySetInnerHTML: { __html: post.title.rendered }
})
),
post.featured_media ? React.createElement(
"a",
{ href: post.link },
React.createElement("img", { src: post._embedded['wp:featuredmedia'][0].source_url })
) : null
);
})
);
}
My blog's source wp json is
React.render(React.createElement(App, { source:
"myBlogURL.com/wp-json/wp/v2/posts/?_embed&per_page=3" }),
document.querySelector("#blog-post"));
Which correctly loads my latest 3 blog posts into the <div id="blog-posts">
I'm looking for a vanilla js way to do this with some fallback helpers. In case I forget to include the featured image to a post, the posts will not fail to load. Any ideas or examples would greatly be appreciated!
You are working way to hard for this. Wordpress CMS is designed for stuff like this. You are able to display posts in the form of a RSS feed by categories, tags and other taxonomies. pretty easily
• If you are not too good with code, you can find many widgets that'll take care of most of the work.
• If you need to do it yourself, below should get you there with JSON / jQuery.
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js'></script>
<script type="text/javascript">
var MYBLOG_LIMIT = 3;
var MYWRAPPER_CLASS = 'homeblog';
var WP={open:function(b){var a={posts:function(){var d=MYBLOG_LIMIT;var e=0;var c={all:function(g){var f=b+"/api/get_recent_posts/";f+="?count="+d+"&page="+e+"&callback=?";jQuery.getJSON(f,function(l){var k=l.posts;for(var j=0;j<k.length;j++){var h=k[j];h.createComment=function(i,m){i.postId=h.id;a.comments().create(i,m)}}g(k)})},findBySlug:function(f,h){var g=b+"/api/get_post/";g+="?slug="+f+"&callback=?";jQuery.getJSON(g,function(i){h(i.post)})},limit:function(f){d=f;return c},page:function(f){e=f;return c}};return c},pages:function(){var c={findBySlug:function(d,f){var e=b+"/api/get_page/";e+="?slug="+d+"&callback=?";jQuery.getJSON(e,function(g){f(g.page)})}};return c},categories:function(){var c={all:function(e){var d=b+"/api/get_category_index/";d+="?callback=?";jQuery.getJSON(d,function(f){e(f.categories)})}};return c},tags:function(){var c={all:function(e){var d=b+"/api/get_tag_index/";d+="?callback=?";jQuery.getJSON(d,function(f){e(f.tags)})}};return c},comments:function(){var c={create:function(f,e){var d=b+"/api/submit_comment/";d+="?post_id="+f.postId+"&name="+f.name+"&email="+f.email+"&content="+f.content+"&callback=?";jQuery.getJSON(d,function(g){e(g)})}};return c}};return a}};
var blog = WP.open('https://www.fldtrace.com');
blog.posts().all(function(posts){
for(var i = 0; i < posts.length; i++){
jQuery('.'+MYWRAPPER_CLASS).append(function(){
return (posts[i].thumbnail) ? '<a class="lastpost_title" href="'+posts[i].url+'">
<h4>'+posts[i].title+'</h4>
</a><img src="'+posts[i].thumbnail+'"/>' : '<a href="'+posts[i].url+'">
<h4>'+posts[i].title+'</h4>
</a>';
});
}
});
</script>
<div class="homeblog">
</div>
You need to configure the next options
var MYBLOG_LIMIT = 1; will define how many posts will show. By default
is 1. var MYWRAPPER_CLASS = ‘homeblog’; – the class name of HTML
element where the post(s) will be shown. var blog =
WP.open(‘https://www.fldtrace.com/’); – this should link to your blog
main domain (mandatory) by default, will be shown the post thumbnail
and title both linked. The rest is CSS customization, including
adjusting the thumbnail size.
Read more here at source article.

Facing issue with Mouse Event

I am new to web development, so I am taking a Pluralsight course called "Building a Web App with ASP.NET Core RC1, MVC 6, EF7 & AngularJS" by Shawn Wildermuth. In his jQuery module, Shawn has this piece of code that works flawlessly for him:
var main = $("#main");
main.on("mouseenter", function() {
main.style = "background-color: #888;";
});
main.on("mouseleave", function() {
main.style = "";
});
I have a div with id="main" on my index.html page, js file is referenced, other jQuery functionality in the same file works, I just can't get this piece of code to work. I know it is not significant, but at this point it is personal. Any suggestions are helpful. Thank you!
As style is a property of native DOM element and main is a jQuery object. You can use .css() and .removeAttr() jQuery method to get the desired result.
var main = $("#main");
main.on("mouseenter", function() {
main.css("background-color": "#888");
});
main.on("mouseleave", function() {
main.removeAttr('style');
});
You can't access the style property like this. Try the following:
var main = $("#main");
main.mouseenter(function() {
main.css("background-color", "#888");
});
main.mouseleave(function() {
main.css("background-color", "none");
});
Try this:
var main = document.getElementById("main");
main.onmouseenter=function(){
main.setAttribute('style', 'background-color:#888;');
};
main.onmouseleave=function(){
main.removeAttribute("style")
};

Backbone.Marionette Layout: Access region.layout.view directly

I have a Marionette application which as more than 1 region.
App.addRegions({
pageRegion: '#page',
contentsRegion :'#contents'
});
As part of App.pageRegion, I add a layout.
App.ConfiguratorLayout = Marionette.Layout.extend({
template: '#configurator-page',
regions: {
CoreConfiguratorRegion: '#Core-Configurator-Region',
SomeOtherRegion:'#someOtherregion'
}
});
This layout is rendered before the application starts.
App.addInitializer(function() {
var configLayout = new App.ConfiguratorLayout();
App.pageRegion.show(configLayout);
});
Later on in the application, I just need to change the contents of the configLayout.
I am trying to achieve something like this.
App.pageRegion.ConfiguratorLayout.CoreConfiguratorRegion.show(someOtherLayout);
Is there a way to do this besides using DOM selector on the $el of App.pageRegion.
App.pageRegion.$el.find('#...')
Instead of in an app initializer, move the configLayout initialization code into a controller that can keep a reference to it and then show() something in one of its regions.
// pseudocode:
ConfigController = Marionette.Controller.extend({
showConfig: function() {
var layout = new App.ConfiguratorLayout();
App.pageRegion.show(configLayout);
var someOtherLayout = new App.CoreConfiguratorLayout();
layout.coreConfiguratorRegion.show(someOtherLayout);
// ... maybe create and show() some views here?
}
});
App.addInitializer(function() {
var controller = new ConfigController();
// more likely this would be bound to a router via appRoutes, instead of calling directly
controller.showConfig();
});

Common data between js modules in IE8

I have a web app made of several jsp files, several of which make use of common jscript modules. My problem is that I am having difficulties accessing common data between the jscript modules in IE8.
For example - In a jsp file:
<script for="window" event="onload">
// My globals.
myGlobals = new Object();
// Attach it to the window for maximum availability.
window.myGlobals = myGlobals;
// Add some fields to it.
// List is actually built from external data so cannot be included from external file.
myGlobals.filters = [
'Filter-Women',
'Filter-Men',
'Filter-Girls',
'Filter-Boys',
];
myGlobals.filtered = '';
</script>
and in a separate js file:
function filter(f) {
for (var i = 0;i < myGlobals.filters.length;i++){
if ( 'Filter-'+f == myGlobals.filters[i] ) {
filterIn(document.getElementById(myGlobals.filters[i]));
} else {
filterOut(document.getElementById(myGlobals.filters[i]));
}
}
myGlobals.filtered = f;
}
function filterIn(e) {
e.classList.add('filterselected');
}
function filterOut(e) {
e.classList.remove('filterselected');
}
and in my jsp - the list is also built from the same external data as above:
<div class="filterbuttons">
<a id="Filter-Women" onclick="filter('Women')">WOMEN</a>
<a id="Filter-Men" onclick="filter('Men')">MEN</a>
<a id="Filter-Girls" onclick="filter('Girls')">GIRLS</a>
<a id="Filter-Boys" onclick="filter('Boys')">BOYS</a>
</div>
Now this all works fine in Firefox but customer also needs this to work in IE8. There, the myGlobals structure is not available, not even from the window. Any ideas?
Problem solved!
Change:
<script for="window" event="onload">
to just plain:
<script>
and everything works fine again.

jquery templating - import a file?

I'm working with backbone.js, but as far as I've seen, it doesn't care what templating system you use. Currently I'm trying out mustache.js, but I'm open to other ones. I'm a little annoyed though with the way I have to put a template into a string:
var context = {
name: this.model.get('name'),
email: this.model.get('email')
}
var template = "<form>Name<input name='name' type='text' value='{{name}}' />Email<input name='email' type='text' value='{{email}}' /></form>";
var html = Mustache.to_html(template, context);
$(this.el).html(html);
$('#app').html(this.el);
I'd like if I could load it from a different file or something somehow. I want to be able to have template files in order to simplify things. For example, if I put it all in a string, I can't have breaks (well I can have html breaks, but that's not the point). After the line starts to get very long, it becomes unmanageable.
Tips?
Updated (4/11/14):
As answered by OP below:
Unfortunately, the jQuery team has moved the templating functionality out of jQuery Core. The code is still available as a library here: github.com/BorisMoore/jquery-tmpl and here: github.com/borismoore/jsrender
Original Answer:
I just used this a couple of hours ago:
http://api.jquery.com/category/plugins/templates/
It's an official jQuery plugin(i.e. the devs endorse it).
This is the function you need to use for loading templates from things other than strings: http://api.jquery.com/template/
Here's the code to have a template in HTML:
<script id="titleTemplate" type="text/x-jquery-tmpl">
<li>${Name}</li>
</script>
___________
// Compile the inline template as a named template
$( "#titleTemplate" ).template( "summaryTemplate" );
function renderList() {
// Render the movies data using the named template: "summaryTemplate"
$.tmpl( "summaryTemplate", movies ).appendTo( "#moviesList" );
}
It's in a <script> tag, because that's not visible by default.
Note the type="text/x-jquery-tmpl". If you omit that, it will try to parse it as JavaScript(and fail horribly).
Also note that "loading from a different file" is essentially the same as "reading a file" and then "loading from a string".
Edit
I just found this jQuery plugin - http://markdalgleish.com/projects/tmpload/ Does exactly what you want, and can be coupled with $.tmpl
I have built a lightweight template manager that loads templates via Ajax, which allows you to separate the templates into more manageable modules. It also performs simple, in-memory caching to prevent unnecessary HTTP requests. (I have used jQuery.ajax here for brevity)
var TEMPLATES = {};
var Template = {
load: function(url, fn) {
if(!TEMPLATES.hasOwnProperty(url)) {
$.ajax({
url: url,
success: function(data) {
TEMPLATES[url] = data;
fn(data);
}
});
} else {
fn(TEMPLATES[url]);
}
},
render: function(tmpl, context) {
// Apply context to template string here
// using library such as underscore.js or mustache.js
}
};
You would then use this code as follows, handling the template data via callback:
Template.load('/path/to/template/file', function(tmpl) {
var output = Template.render(tmpl, { 'myVar': 'some value' });
});
We are using jqote2 with backbone because it's faster than jQuery's, as you say there are many :)
We have all our templates in a single tpl file, we bind to our template_rendered so we can add jquery events etc etc
App.Helpers.Templates = function() {
var loaded = false;
var templates = {};
function embed(template_id, parameters) {
return $.jqote(templates[template_id], parameters);
}
function render(template_id, element, parameters) {
var render_template = function(e) {
var r = embed(template_id, parameters);
$(element).html(r);
$(element).trigger("template_rendered");
$(document).unbind(e);
};
if (loaded) {
render_template();
} else {
$(document).bind("templates_ready", render_template);
}
}
function load_templates() {
$.get('/javascripts/backbone/views/templates/templates.tpl', function(doc) {
var tpls = $(doc).filter('script');
tpls.each(function() {
templates[this.id] = $.jqotec(this);
});
loaded = true;
$(document).trigger("templates_ready");
});
}
load_templates();
return {
render: render,
embed: embed
};
}();
They look like
<script id="table" data-comment="generated!!!!! to change please change table.tpl">
<![CDATA[
]]>
</script>

Categories

Resources