I have group of pages on site that is statically generated using nanoc; each group represents one document kind and has it's own template. Each group template is a little different. For example, main template:
<html>
<body>
<--header-->
<--news-->
<--content-->
<--sidebar-->
</body>
</html>
And then some other template maybe will not have news section, but will have the footer:
<html>
<body>
<--header-->
<--content-->
<--sidebar-->
<--footer-->
</body>
</html>
and so on. What would be better thing to do:
[A] to have one master template and then to have a flag to turn on/off certain imports
or
[B] to have many smaller templates that include common chunks of html?
I have a relatively large site on nanoc, and I do [B], mostly. I have a fairly complex nested hierarchy of layouts. Article pages are something like this (not these actual tags, I'm just using pseudo-xml to indicate how the layouts are nested):
<default>
<content>
<article>
<post> <!-- or image, or link, or quote, or ... -->
<%= yield %>
</post>
</article>
</content>
</default>
While a tag or archive page would be:
<default>
<content>
<list>
<%= yield %>
</list>
</content>
</default>
Every page on my site uses the default layout. Most pages use content, with the exception of a few pages that are "chromeless"… Everything else is some combination of these or other layouts. I think I've got about 25 layouts in total :)
Related
When using HTML5, do you have to have a main element when creating a web page and if so, what is the maximum amount you can use?
The correct answer is the 'C'
look at:
http://www.w3schools.com/tags/tag_main.asp
I believe it is expected that the main element serve as diversionary element, like the header, nav, and footer. So I think it should really only be used once per page. Using markup similar to this.
<html>
<head>
</head>
<body>
<header>
<!-- Page Title -->
</header>
<nav>
<!-- Primary Menu -->
</nav>
<main>
<!-- Primary Content -->
</main>
<footer>
<!-- Stuff at the Bottom -->
</footer>
</body>
</html>
I'm using the linkedIn fork of Dust with Node.JS & Express.
My template hierarchy is having:
1 layout template - The base template
1 Page template - This is the template that will be rendered
Optional number of partials - Might be included by the page template
layout.dust (layout template):
<html>
<head>
<script src="/js/layout.js"></script>
<link rel="stylesheet" href="/css/layout.css">
<script src="/js/home.js"></script>
<link rel="stylesheet" href="/css/home.css">
<script src="/js/sidebar.js"></script>
<link rel="stylesheet" href="/css/sidebar.css">
<script src="/js/widget.js"></script>
<link rel="stylesheet" href="/css/widget.css">
</head>
<body>
{+content}{/content}
</body>
</html>
home.dust (page template):
{>layout/}
{<content}
<div>
{>sidebar/}
</div>
<div>
{>widget/}
</div>
{/content}
When the user visits the website homepage, then home.dust will be rendered, and the user will see a page with the sidebar and some widget. The content of sidebar.dust and widget.dust is irrelevant.
As you can see in layout.dust, there are 4 sets of JavaScript and CSS included in the head section, one for each of the templates and partials. My problem is finding a way to automatically include each asset into the layout (without hardcoding). Ideally I would like to be able to just do this:
{#scripts}
<script src="{.}"></script>
{/scripts}
Different pages may require different assets.
How can I push each script source path into the context of layout.dust?
What do other developers do, do they just hardcode them?
I'd be adding all scripts to the head of the layout without pushing any from the pages that extend from this layout. I'm not sure how knowledgeable you are on javascript minification but it's common practice to bundle all (or most) of your javascript assets into one file and serve them up to the user with a single HTTP request. This speeds up your page a lot; checkout what Google has to say about it here.
It's not hard because there are a few tools to do this for you automatically. You could go for an asset manager or Grunt.
ASSET MANAGER:
There are a few on npm. I found one called Express Asset Manager and another called Asset Pipeline.
GRUNT:
Use contrib-uglify and contrib-concat to handle you minification. There are plenty of others that you should find useful. You can do the exact same thing with all of your CSS too.
Obviously in development you don't really want to try to debug minified code so you can do something like the following:
{?production}
<script src="production-minified-script.js"></script>
{:else}
{#scripts}
<script src="{.}"></script>
{/scripts}
{/production}
where production is a variable passed to your template from process.env.NODE_ENV. To avoid manually adding in each script, you could pass them in as an array by
STILL WANT TO ADD FROM OTHER PAGES?
If you still want to add from other pages, add in a block to your head below your main scripts, something like:
{+otherScripts}{/otherScripts}
I recently upgraded the version of Heist I'm using. It was mostly an arbitrary decision and I'm still seeing the consequences of that action, mostly in terms of more pleasing code structure.
But, I was relying pretty heavily on the "apply" tag inside my templates in order to bring in boilerplate components, like my site header and menus. For me, a typical template looks like this:
<html>
<head>
<title> <PageTitle /> </title>
<link rel="stylesheet" type="text/css" href="/styles/style.css" />
<link rel="alternate" type="application/rss+xml" title="${PageTitle} Feed" href="http://www.savannidgerinel.com/rss" />
</head>
<body class="center">
<apply template="header" />
<div id="content">
<h1><PageTitle /></h1>
<ul>
<PageMetadata />
</ul>
<PageContent />
</div>
</body>
</html>
And, I'm now loading the templates like this:
setup_heist template_dir = do
templates <- Heist.loadTemplates template_dir
hs <- Heist.initHeist (Heist.HeistConfig [] [] [] [] templates)
return hs
This is not too much different from how I used to load templates (still using the loadTemplates function), but it is a different way of setting up the Heist state that I'm not accustomed to.
But, now none of the apply tags have any effect. My "included" templates just never load and within the resulting HTML I see this:
<apply template='header'></apply>
The apply tag is a splice just like any other. It doesn't have any special status other than that it is included with Heist. Therefore, you have to bind that splice in your HeistConfig. If you are using interpreted templates, then you can do it like this:
HeistConfig defaultInterpretedSplices [] [] [] templates
If you are using compiled templates, then use this:
HeistConfig [] defaultLoadTimeSplices [] [] templates
I've added the following code to the selected transformation of a News List webpart:
<%# Register Src="~/CMSAdminControls/ContentRating/RatingControl.ascx" TagName="RatingControl" TagPrefix="cms" %>
<cms:RatingControl ID="elemRating" runat="server" Enabled="true" RatingType="Stars" ExternalValue='
<%# Convert.ToString(CMS.GlobalHelper.ValidationHelper.GetDouble(Eval("DocumentRatingValue"), 0)/((CMS.GlobalHelper.ValidationHelper.GetDouble(Eval("DocumentRatings"), 0) == 0?1:CMS.GlobalHelper.ValidationHelper.GetDouble(Eval("DocumentRatings"), 1)))) %>' />
The rest of the selected transformation is the same as the default.
According to the Kentico documentation this should add the webpart to the details page of a news item.
For some reason the input tag is getting rendered as follows:
<input type="hidden" name="p$lt$zoneContent$pageplaceholder$pageplaceholder$lt$News$NewsList$repItems$ctl00$ctl00$elemRating$RatingControl$elemRating_RatingExtender_ClientState" id="p_lt_zoneContent_pageplaceholder_pageplaceholder_lt_News_NewsList_repItems_ctl00_ctl00_elemRating_RatingControl_elemRating_RatingExtender_ClientState" value="0">
note the type="hidden" attribute. This causes the control not to render and I'm not sure where to fix this.
As mentioned in my comment. The is actually just used to store the value. Below that, it renders some extra content that will not display unless some CSS classes are carried over from the CMSDesk.css.
You can either copy the necessary CSS classes into your own CSS, or just import the CMSDesk.css file where necessary to make sure the rating elements are displaying.
How would I output the title of an entry in ExpressionEngine and display it in the browser's title bar?
Here is the content of my page's header:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test Site</title>
<link rel="stylesheet" href="{stylesheet=site/site_css}" type="text/css" media="screen" />
</head>
What I need is for each page to display the title of the entry in my browser's title bar — how can I achieve that?
Part of UPDATED Code:
Here is how i have done it :
{exp:channel:entries channel="news_articles" status="open|Featured Top Story|Top Story" limit="1" disable="member_data|trackbacks|pagination"}
{embed="includes/document_header" page_title=" | {title}"}
<body class="home">
<div id="layoutWrapper">
{embed="includes/masthead_navigation"}
<div id="content">
<div id="article">
<img src="{article_image}" alt="News Article Image" />
<h4>{title}</h4>
<h5><span class="by">By</span> {article_author}</h5>
<p>{entry_date format="%M %d, %Y"} -- Updated {gmt_edit_date format="%M %d, %Y"}</p>
{article_body}
{/exp:channel:entries}
</div>
What do you think?
Another relatively new way to tackle it is using the Stash add-on and a template partials approach. This method knocks you down to one embed, and has the added advantage of giving you a centralized "wrapper" template - one for each major page layout, basically. The example below assumes you've simply added custom fields to handle any entry-specific meta data you're looking to inject into the header. With this idea in mind, here's a simplified view of the basic structure I've been applying recently:
In your template you apply EE tags to determine the logic of what gets sent to the inside-wrapper
{embed="embeds/.inside-wrapper"}
{exp:channel:entries channel="channel_name" limit="1" dynamic="yes" disable="whatever|you|can|live|without"}
{!-- ENTRY SEO META DATA --}
{exp:stash:set name="entry_seo_title" scope="site"}{cf_channelprefix_seo_title}{/exp:stash:set}
{exp:stash:set name="entry_seo_description" scope="site"}{cf_channelprefix_seo_description}{/exp:stash:set}
{exp:stash:set name="entry_seo_keywords" scope="site"}{cf_channelprefix_seo_keywords}{/exp:stash:set}
{!-- ENTRY/PAGE CONTENT --}
{exp:stash:set name="entry_body_content" parse_tags="yes" parse_conditionals="yes" scope="site"}
Your page content here
{/exp:stash:set}
{/exp:channel:entries}
And then in your wrapper template, which would ultimately contain all your wrapping HTML but could be chunked into snippets. for something like the header since it would be shared with other wrapper templates, for example:
<html>
<head>
<title>{exp:stash:get name="entry_seo_title"}</title>
<meta name="description" content="{exp:stash:get name="entry_seo_description"}" />
<meta name="keywords" content="{exp:stash:get name="entry_seo_keywords"}" />
</head>
<body>
{exp:stash:get name="entry_body_content"}
</body>
</html>
If you want to show just the name of your ExpressionEngine site (as defined in CP Home > Admin > General Configuration) use the site name global variable:
<title>{site_name}</title>
If you want to display just the current entry title from a given channel use the following:
<title>
{exp:channel:entries channel="channel_name" limit="1" dynamic="yes"}
{title}
{/exp:weblog:entries}
</title>
Many Web Developers will use an Embed Variable with an Embedded Template to pass the `{entry_title} to a global embed template, allowing for a dynamic page title:
{embed="includes/header" title="{exp:channel:entries channel="{channel_name}"}{title}{/exp:channel:entries}"}
If you're using EE2, the SEO Lite Module takes care of all the hard work for you with a single line of code:
<html lang="en">
<head>
<meta charset="utf-8" />
{exp:seo_lite url_title="{url_title}"}
</head>
Other solutions include the Low Title Plugin (EE1, EE2).
One addition to Ryan's embed method (which is definitely the most flexile method): chances are you can wrap most of your page in an {exp:channel:entries} tag when viewing an individual entry, avoiding the additional (and expensive) channel:entries call. So it would look more like this:
{exp:channel:entries channel="channel_name" limit="1"}
{embed="includes/header" title="{title}"}
<h1>{title}</h1>
{page_content}
{embed="includes/footer"}
{if no_results}{redirect="404"}{/if}
{/exp:channel:entries}
NSM Better Meta is a more complete way to pass channel meta data to the tag.
For smaller sites, I use the String plugin.
https://devot-ee.com/add-ons/string
Very simple syntax.