I'm learning Perl and using Dancer as a web framework.
I've got two views (tt files) which should share the same navigation.
So, it would be great to start learning how to manage templates for navigation and footers.
I've read the documentation for the Template Toolkit and I've done the following:
I've changed the config.yml file to:
#template: "simple"
template: "template_toolkit"
engines:
template_toolkit:
start_tag: '[%'
end_tag: '%]'
I've defined the templates in the .pm file:
package proyecto;
use Dancer ':syntax';
our $VERSION = '0.1';
get '/' => sub {
template 'index';
};
get '/menu' => sub {
template 'menu';
};
true;
There is a link in the index template directing the visitor to the menu template:
<li class="active">< a href="/menu">Menu <span class="sr-only"></span></a></li>
I would like to reuse the navigation code from index.tt into menu.tt, so I've wrapped the navigation code in index.tt with the following:
[% BLOCK navigation %]
#my nav code
[% END %]
To finally include that code in the menu.tt file, I've written the following (where the navigation code should be):
[% navigation = 'index.tt' %]
[% INCLUDE navigation %]
The files index.tt and menu.tt are located in the folder views. But it seems it's not that easy! =( Any suggestion on how to reuse code from one file to another which is located in the same directory?
This is what layouts are for. The idea is that content common to all pages (e.g. header, footer, navbar) goes in the layout and content specific to each page goes in templates called views. Views are called "partials" in other frameworks because they only contain the content for part of the page.
If you use the dancer command line utility to set up your application, the default layout is views/layouts/main.tt and looks something like this:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=<% settings.charset %>" />
<title>Foo</title>
<link rel="stylesheet" href="<% request.uri_base %>/css/style.css" />
</head>
<body>
<% content %>
<div id="footer">
Powered by Dancer <% dancer_version %>
</div>
</body>
</html>
The <% content %> section is replaced with the specified view when you call template 'view';. (In your case, you'll need to change <% and %> to [% and %] since you're using the Template Toolkit-style delimiters.)
For example, if views/index.tt is:
<h1>Hello, World!</h1>
calling template 'index'; in a route renders the following:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Foo</title>
<link rel="stylesheet" href="http://www.example.com/css/style.css" />
</head>
<body>
<h1>Hello, World!</h1>
<div id="footer">
Powered by Dancer 1.3202
</div>
</body>
</html>
Note that there's already a footer section; you just have to add elements for a header and navbar.
If this is new development, you should really be using Dancer2 instead of Dancer (fortunately, layouts and views are the same in both).
The [% INCLUDE %] directive's argument can be interpreted in one of two ways.
The name of another template file
The name of a block that is defined in the current template file (or in another template file which has included the current template file).
All of which means that your current plan won't work. menu.tt won't see any block defined inside index.tt.
There are a couple of better solutions though.
Firstly, consider moving the navigation code into a third, separate, template file. You can then INCLUDE this template into both index.tt and menu.tt.
Secondly, you can use Dancer's "layout" feature. This is a template that is wrapped around your view templates. Typically the layout template contains the navigation and all standard page furniture (like headers and footers). It also contains a [% content %] directive. When a view is rendered, the rendered version is dropped into the layout template in the location of the [% content %] directive. See the Layouts section in Dancer::Tutorial for more information.
p.s. I see you're using Dancer. I'd highly recommend switching to Dancer2.
Related
I want to render some javascript snippet with sapui5. I am trying to use Text control but when I use that I cannt format javascript text to show up properly.Is there a way to do that?
You can use the HTML core control to embed html/javascript: https://sapui5.hana.ondemand.com/sdk/#docs/api/symbols/sap.ui.core.HTML.html
Or create a custom control
All other SAPUI5 controls are protected against XSS and forgery attacks so they won't accept any javascript code.
I also suggest that you use sap.ui.core.HTML to embed HTML in your sapui5 view. However to get your code formatted correctly (for example it shall be indented correctly) you can use the markdown-js library. See this example:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>Render javascript source code in sapui5</title>
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.ui.commons"></script>
<script src="markdown.js"></script>
<script>
$.get("markdown.md", function(data) {
var mdView = new sap.ui.core.HTML({
content: markdown.toHTML(data)
});
mdView.placeAt("uiArea");
}, "html");
</script>
</head>
<body class="sapUiBody">
<div id="uiArea"></div>
</body>
</html>
markdown.md:
# Markdown
To produce a code block in Markdown, simply indent every line of the block by at least 4 spaces or 1 tab.
for (i=0; i < 10; i++) {
if (true) {
console.log("Hello World!");
}
}
If you want to test this example in you Chrome browser, do the following:
Download markdown-browser-*.tgz from markdown-js and place the contained markdown.js together with the above index.html and markdown.md in some folder.
Start Chrome with parameter --allow-file-access-from-files and drop the index.html on the Chrome browser window.
In the interest of DRY, I have 3 page types in my SPA: (1)Layout, (2)Index, and (3)XXXX (view).
Layout has the body related tags, Index the nav system, and XXXX the relative content. Here is the code:
Layout.ejs:
<!DOCTYPE>
<html>
<head>
<title>Index Page</title>
<% include ../includes/styles%>
<script type="text/javascript" src="/vendor/jquery/dist/jquery.min.js" ></script>
</head>
<body>
</body>
<% include ../includes/scripts%>
</html>
Index.ejs:
<% include ../includes/layout %>
<h1>This is where the nav bar goes</h1>
<div data-ng-view></div>
View pages not important for this problem.
What I noticed is that my sccript tags from layout are above the body's children DOMs, not at all what I wanted.
What I wanted is:
----- body
--- content
----- scripts
What must I do in layout.ejs to keep the script tags at the bottom of the final html page?
ejs-locals does not support Express 4.x.
I opted for creating a custom engine.
I an a newsletter app, i send a view as a template of mail.
Inside the view there a variable that hold the content taken from a form.
I try to apply different inline style to the view, but no one worked.
This is the view, now there is only one style (color:blue) to test css:
<html>
<body style="color:blue;">
{{ $content }}
</body>
</html>
How can i do to style this view, and send a mail with the proper css style?
Thank you
You can do styling like this,
<!DOCTYPE html>
<html>
<body>
<p style="font-style:italic">
{{ $content }}
</p>
</body>
</html>
It works for me.
Is this possible? Basically, I have HTML file A, which I want to include in HTML files B, C, D, and E. All of them will be displayed within my iOS app. No internet involved -- everything will be on the device.
actually its possible
here is how its done
tell me if i am wrong
first file test.html has following contents
<html><body><object type="text/html" data="test2.html">
<p>if object inclusion faile this takes over</p>
</object></body></html>
and test2.html has this code
<div>blah</div>
Try open it in firefox and it should display blah
if its IE then use this code in your test.html
<html><body>
<object classid="clsid:25336920-03F9-11CF-8FD0-00AA00686F13" data="test2.html">
<p>if object inclusion faile this takes over</p>
</object>
</body></html>
hope this helps
you can also have simple IE detection check like this
<!--[if IE]>
<html><body>
<object classid="clsid:25336920-03F9-11CF-8FD0-00AA00686F13" data="test2.html">
<p>if object inclusion faile this takes over</p>
</object>
</body></html>
<![endif]-->
<!--[if !IE]>
<!-- place your other code here -->
<![endif]-->
There is no standard or magic way, but you would have to do it yourself with some native code. It shouldn't be too hard.
For example, imagine some files like this:
index.html
<div id="content">
<% include1.html %>
</div>
include1.html
<h1>Hello World!</h1>
You could write native code to load the index.html file, and search for these special tags, and replace those tags with the content in the named html file that is also on the device. You can then pass the HTML as a string to a webview to load and display.
I want to include certain .js and .css files only on pages that need them.
For example, my EditorTemplate DateTime.ascx needs files anytimec.js and anytimec.css.
That template is applied whenever I use either the EditorFor or EditorForModel helper methods in a view for a model with a DateTime type value.
My technique:
I've put this condition into the <head> section of my master page. It checks for a DateTime type property in the ModelMetadata.
<% if (this.ViewData.ModelMetadata.Properties.Any(p => p.ModelType == typeof(DateTime))) { %>
<link href="../../Content/anytimec.css" rel="stylesheet" type="text/css" />
<script src="../../Scripts/anytimec.js" type="text/javascript"></script>
<% } %>
This has two problems:
Fails if I have nested child models of type DateTime
Unnecessarily triggered by views without EditorFor or EditorForModel methods (example: DisplayForModel)
How can I improve this technique?
Personally, I would use a partial view and an ASP Content Placeholder.
In the Views/Shared have a partial view EditorScripts.ascx which contains the tags defining the scripts to be included in your editing pages.
Then put a placeholder in the Site.Master <head> tag, something like this:
<asp:ContentPlaceHolder ID="HeadContent" runat="server" />
The, in any view that you want/need the scripts, put this code:
<asp:Content ContentPlaceHolderID="HeadContent" runat="server">
<% Html.RenderPartial("EditorScripts"); %>
</asp:Content>
This isn't a perfect solution and isn't as dynamic as you would like. The reason for using a partial view is that if you decide to update or add more scripts to those views, then you only have to update it in one location.
Another way would be to have a Editor.Master page that contains these scripts and other editor specific things then have that master use the Site.Master as it's master page. Then all editor views would have the Editor.Master as their master page.
HTH
I think the telerik web asset manager allows you to accomplish what you want and is open source.