Assemble: Multiple points of content insertion in layout? - handlebars.js

All assemble users who uses layouts knows that "{{> body }}" marks the point of insertion of contents of any page who uses the layout. But is it possible to define multiple points of insertions, instead of tossing everything at where the {{> body }} is?
For instance, in my page I would like to define a specific piece of javascript, but I like that custom javascript to be at the very bottom of the page along with out javascript tags. If it only puts everything where the {{> body }} is, this is not possible, since the script will just be appended to the content.
In other words, it would be useful to have {{> script }} or even customizable tags marking different points of insertion, and in the page using the layout, these tags are specifically defined.
Above is my ideal use case, does anyone know if assemble supports anything like this?

#Xavier_Ex check out the assemble handlebars helper repo https://github.com/assemble/example-layout-helpers
And this particular pull request https://github.com/assemble/handlebars-helpers/pull/75
We added some layout helpers about a month ago that allow you to "extend" a layout and include different content sections. Notice that you'll have to include your layout as a partial in the assemble gruntfile setup for this to work properly...
assemble: {
options: {
flatten: true,
assets: 'docs/assets',
partials: ['src/includes/*.hbs', 'src/layouts/*.hbs'],
layout: false,
data: ['src/data/*.{json,yml}', 'package.json']
},
pages: {
src: 'src/*.hbs',
dest: 'docs/'
}
}
Layout (default.hbs)...
<!DOCTYPE html>
<html lang="en">
<head>
{{#block "head"}}
<meta charset="UTF-8">
<title>{{title}} | {{site.title}}</title>
<link rel="stylesheet" href="{{assets}}/{{stylesheet}}.css">
<link rel="stylesheet" href="{{assets}}/github.css">
{{/block}}
</head>
<body {{#is stylesheet "bootstrap"}}style="padding-top: 40px;"{{/is}}>
{{#block "header"}}
{{! Navbar
================================================== }}
{{> navbar }}
{{/block}}
{{! Subhead
================================================== }}
<header class="{{#is stylesheet "bootstrap"}}jumbotron {{/is}}{{#is stylesheet "assemble"}}masthead {{/is}}subhead">
<div class="container">
<div class="row">
<div class="col col-lg-12">
<h1> DOCS / {{#if title}}{{ uppercase title }}{{else}}{{ uppercase basename }}{{/if}} </h1>
</div>
</div>
</div>
</header>
{{! Page content
================================================== }}
{{#block "body"}}
<div class="container">
<div class="panel panel-docs">
{{> body }}
</div>
</div>
{{/block}}
{{#block "script"}}
<script src="{{assets}}/highlight.js"></script>
<script src="{{assets}}/holder.js"></script>
{{/block}}
</body>
</html>
Some page
{{#extend "default"}}
{{#content "head"}}
<link rel="stylesheet" href="assets/css/home.css" />
{{/content}}
{{#content "body"}}
<h2>Welcome Home</h2>
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
{{/content}}
{{#content "script"}}
<script src="assets/js/analytics.js"></script>
{{/content}}
{{/extend}}
Hope this helps.

Related

Express Handlebars append page content to partial page

I am new to express-handlebars and finding difficulty in understanding it.
my layout
views
-layouts
-mainlayout.hbs
-partials
-header.hbs(it contains main menu)
-footer.hbs
-patialpage.hbs
pagecontent.hbs
my main page
<div>
{{body}}
</div>
this is my partial page
{{>header}}
<div>
<div>Side Bar Menu</div>
<div>Page Content Here</div>
</div>
{{>footer}}
this is my content
<div>This Content to be append in partial page</div>
You just did in the wrong sequence.
You tried to append the page content to a partial.
In the main layout you define the look of your page.
partials are e.g. parts of this layout (e.g. navbar, footer, ...)
Your main could look like:
<div>
{{> header}}
{{body}}
{{> footer}}
</div>
this means: on each side the header and the footer partial will be loaded and in between, inside {{body}} there will be the rendered view.
example of a main.handlebars file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>title</title>
</head>
<body>
{{!-- navbar partial --}}
{{> _navbar}}
{{!-- flash messages --}}
{{> _flashmessages}}
{{!-- placeholder for rendered views --}}
{{{body}}}
</body>
</html>
then you can render a view based on this main layout.
example with just a text rendered
// Index Route
app.get('/', (req, res) => {
res.send("Hello world");
});
});
example with the view index.handlebars rendered to the {{body}} part of the page
// Index Route
app.get('/', (req, res) => {
res.render('index');
});

Embedding an R htmlwidget into existing webpage

I am trying to embed an R htmlwidget into an existing webpage -- a webpage that already has bootstrap and styling applied. For example, consider the following webpage (note where the widget should be placed):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>This is a test.</p>
<!-- htmlwidget should go here. -->
<p>A closing paragraph.</p>
</body>
</html>
I can create and save a datatable widget like so:
library(htmlwidgets)
library(datatable)
d1 <- datatable(mtcars, filter = "top")
saveWidget(d1, file = "widget_file.html")
The generated widget_file.html (even for this modest widget) contains a lot of code. Is there an easy way to embed this into an existing webpage/template?
I have been successful using <iframe src="widget_file.html"> but I'm wondering if there is a better way? Moreover, is there a way to separate pieces/dependencies (e.g. json data) from the widget_file.html so they can be placed in other folders?
Note: I created the htmlwidget tag, but I believe there should be a synonymous htmlwidgets tag.
The htmlwidget-Package offers a way to save the pieces for the widget separately as follows:
library(dygraphs)
d1 <- dygraph(nhtemp, main = "New Haven Temperatures") %>%
dyRangeSelector(dateWindow = c("1920-01-01", "1960-01-01"))
saveWidget(d1, file = "widget_file.html", selfcontained = FALSE)
Which results in the following files/dirs:
widget_file.html
widget_file_files
/dygraphs-1.1.1
..
/dygraphs-binding-0.6
..
/htmlwidgets-0.5
..
/jquery-1.11.1
..
/moment-2.8.4
..
/moment-timezone-0.2.5
..
And widget_file.html reads as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="widget_file_files/htmlwidgets-0.5/htmlwidgets.js"></script>
...
<script src="widget_file_files/dygraphs-binding-0.6/dygraphs.js"></script>
</head>
<body style="background-color:white;">
<div id="htmlwidget_container">
<div id="htmlwidget-2956" style="width:960px;height:500px;" class="dygraphs"></div>
</div>
<!-- THE JSON DATA -->
<script type="application/json" data-for="htmlwidget-2956">
{THE JSON DATA YOU WERE LOOKING FOR}
</script>
<!-- THE JSON DATA -->
<script type="application/htmlwidget-sizing" data-for="htmlwidget-2956">{Widget-Styling-Json}
</script>
</body>
</html>
So you can edit your html as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- Begin of scripts to run the widget -->
<script src="widget_file_files/htmlwidgets-0.5/htmlwidgets.js"></script>
<script src="widget_file_files/jquery-1.11.1/jquery.min.js"></script>
<link href="widget_file_files/dygraphs-1.1.1/dygraph.css" rel="stylesheet" />
<script src="widget_file_files/dygraphs-1.1.1/dygraph-combined.js"></script>
<script src="widget_file_files/moment-2.8.4/moment.js"></script>
<script src="widget_file_files/moment-timezone-0.2.5/moment-timezone-with-data.js"></script>
<script src="widget_file_files/dygraphs-binding-0.6/dygraphs.js"></script>
<!-- End of scripts to run the widget -->
<!-- Begin Widget styling -->
<script type="application/htmlwidget-sizing" data-for="htmlwidget-2956">{"viewer":{"width":450,"height":350,"padding":10,"fill":true},"browser":{"width":960,"height":500,"padding":40,"fill":true}}</script>
<!-- End widget Styling -->
<!-- Begin Data for the widget-->
<script type="application/json" data-for="htmlwidget-2956">{"x":{"attrs":{"title":"New Haven Temperatures","labels":["year","V1"],"legend":"auto","retainDateWindow":false,"axes":{"x":{"pixelsPerLabel":60}},"showRangeSelector":true,"dateWindow":["1920-01-01T00:00:00Z","1960-01-01T00:00:00Z"],"rangeSelectorHeight":40,"rangeSelectorPlotFillColor":" #A7B1C4","rangeSelectorPlotStrokeColor":"#808FAB","interactionModel":"Dygraph.Interaction.defaultModel"},"scale":"yearly","annotations":[],"shadings":[],"events":[],"format":"date","data":[["1912-01-01T00:00:00Z","1913-01-01T00:00:00Z","1914-01-01T00:00:00Z","1915-01-01T00:00:00Z","1916-01-01T00:00:00Z","1917-01-01T00:00:00Z","1918-01-01T00:00:00Z","1919-01-01T00:00:00Z","1920-01-01T00:00:00Z","1921-01-01T00:00:00Z","1922-01-01T00:00:00Z","1923-01-01T00:00:00Z","1924-01-01T00:00:00Z","1925-01-01T00:00:00Z","1926-01-01T00:00:00Z","1927-01-01T00:00:00Z","1928-01-01T00:00:00Z","1929-01-01T00:00:00Z","1930-01-01T00:00:00Z","1931-01-01T00:00:00Z","1932-01-01T00:00:00Z","1933-01-01T00:00:00Z","1934-01-01T00:00:00Z","1935-01-01T00:00:00Z","1936-01-01T00:00:00Z","1937-01-01T00:00:00Z","1938-01-01T00:00:00Z","1939-01-01T00:00:00Z","1940-01-01T00:00:00Z","1941-01-01T00:00:00Z","1942-01-01T00:00:00Z","1943-01-01T00:00:00Z","1944-01-01T00:00:00Z","1945-01-01T00:00:00Z","1946-01-01T00:00:00Z","1947-01-01T00:00:00Z","1948-01-01T00:00:00Z","1949-01-01T00:00:00Z","1950-01-01T00:00:00Z","1951-01-01T00:00:00Z","1952-01-01T00:00:00Z","1953-01-01T00:00:00Z","1954-01-01T00:00:00Z","1955-01-01T00:00:00Z","1956-01-01T00:00:00Z","1957-01-01T00:00:00Z","1958-01-01T00:00:00Z","1959-01-01T00:00:00Z","1960-01-01T00:00:00Z","1961-01-01T00:00:00Z","1962-01-01T00:00:00Z","1963-01-01T00:00:00Z","1964-01-01T00:00:00Z","1965-01-01T00:00:00Z","1966-01-01T00:00:00Z","1967-01-01T00:00:00Z","1968-01-01T00:00:00Z","1969-01-01T00:00:00Z","1970-01-01T00:00:00Z","1971-01-01T00:00:00Z"],[49.9,52.3,49.4,51.1,49.4,47.9,49.8,50.9,49.3,51.9,50.8,49.6,49.3,50.6,48.4,50.7,50.9,50.6,51.5,52.8,51.8,51.1,49.8,50.2,50.4,51.6,51.8,50.9,48.8,51.7,51,50.6,51.7,51.5,52.1,51.3,51,54,51.4,52.7,53.1,54.6,52,52,50.9,52.6,50.2,52.6,51.6,51.9,50.5,50.9,51.7,51.4,51.7,50.8,51.9,51.8,51.9,53]]},"evals":["attrs.interactionModel"]}</script>
<!-- End Data for the widget-->
</head>
<body>
<p>This is a test.</p>
<div id="htmlwidget_container">
<div id="htmlwidget-2956" style="width:960px;height:500px;" class="dygraphs"></div>
</div>
<p>A closing paragraph.</p>
</body>
</html>
This will leave you with the json-data hardcoded within the html-document (see my ).
If you want to load the data dynamically you can use e.g.
json_dat <- readLines("widget_file.html")[18]
cat(sub("</script>","",sub('<script type=\"application/json\" data-for=.*\">', "", json_dat)), file = "./widget_file_files/my_data.json")
To save the json-data as ./widget_file_files/my_data.json and then load it within the html. If you are using PHP you can do:
<script type="application/json" data-for="htmlwidget-2956">
<?php include('widget_file_files/my_data.json'); ?>
</script>
If you want to use a pure JS solution maybe have a look at http://api.jquery.com/jquery.getjson/ and the widget_file_files/htmlwidgets-0.5/htmlwidgets.js-File how the json-data is bound at the moment...
P.S.:
As this question got a lot of attention already you could also contact the package developer and ask him to further "un-selfcontain" the "selfcontained" option in htmlwidgets:::saveWidget: Meaning to save the json-data separately and include it e.g. via jquery.getjson

unable to load a dicom image using cornerstone

I am trying to load a dicom image using cornerstone library. I get an error - uncaught exception: loadImage: no image loader for imageId.
I have my image file named as image-1.dcm. What am I doing wrong?
Here is my code:
<!DOCTYPE HTML>
<html>
<head>
<!-- twitter bootstrap CSS stylesheet - not required by cornerstone -->
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>
jsminimal/index.html
</h1>
This is an example of the minimal use of cornerstone driven by javascript
<br>
<br>
In this example, javascript is used to image enable a div.
<br>
<br>
<div id="dicomImage" style="width:512px;height:512px;">
</div>
</div>
</body>
<!-- cornerstone depends on jQuery so it must be loaded first-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- include the cornerstone library -->
<script src="cornerstone-master/dist/cornerstone.js"></script>
<!-- include special code for these examples which provides images -->
<script src="cornerstone-master/example/exampleImageIdLoader.js"></script>
<script>
$(document).ready(function() {
var imageId = 'image-1';
var element = document.getElementById('dicomImage');
cornerstone.enable(element);
cornerstone.loadImage(imageId).then(function(image) {
cornerstone.displayImage(element, image);
});
});
</script>
</html>
You need to use the cornerstoneWADOImageLoader to loader DICOM P10:
https://github.com/chafey/cornerstoneWADOImageLoader

Context of {{title}} in master template when using multiple data/json files using assemble

I am using assemble.io for a simple static web site but am having issues with the {{title}} tag. Here is a rough overview of the issue.
Here is my layout.hbs:
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<!-- the body tag is used to "pull in" content from pages -->
{{> body }}
</body>
</html>
I have 2 json files for data:
foo1.json
{
"title": "Hello world I am title 1"
}
foo2.json
{
"title": "I am a different title"
}
And I have 2 pages:
foo1.hbs
{{#foo1 }}
{{> module1 }}
{{> module2 }}
{{> module3 }}
{{/foo1 }}
foo2.hbs
{{#foo2 }}
{{> module1 }}
{{> module2 }}
{{> module3 }}
{{/foo2 }}
My gruntfile.js snippet:
options: {
layout: "src/responsive/layouts/layout.hbs",
partials: 'src/responsive/modules/**/*.hbs',
data: 'src/responsive/data/**/*.json',
flatten: false
},
pages: {
expand: true,
cwd: 'src/responsive/pages',
src: '**/*.hbs',
dest: 'src/'
}
When I run 'grunt assemble' I get no page title. I think this has something to do with context as if I change {{title}} in layout.hbs to be {{foo1.title}} or {{foo2.title}} it works but then both pages get the same title as they share this template.
How can I make the context of {{title}} in layout.hbs work for all json files being passed in?
A.
#Adi I setup a repo here containing the structure that you described.
I just changed this code in layout.hbs and it's working as expected.
<!DOCTYPE html>
<html>
<head>
<title>{{page.title}}</title>
</head>
<body>
<!-- the body tag is used to "pull in" content from pages -->
{{> body }}
</body>
</html>
If you have a repo we can look at, it might help track down the issue.
Hope this helps.

#RenderSection in nested razor templates

My problem is I can't seem to use #RenderSection from a nested template when #RenderSection is defined in the base template. Currently, I have a nested base template which is linked to a child template which is then used in the view pages. When I define the #RenderSection in the base template and render it in the view pages it throws an error.
Here's the exact problem.
I want to create a RenderSection to allow me to insert custom scripts.
My base template....
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
#RenderSection("HeaderContent", false) // The region of the header scripts (custom css)
</head>
<body>
#RenderBody()
</body>
</html>
I then skip the child template as I do not want to put any custom head code in there and apply it to the page itself..
#section HeaderContent {
<script>alert("hi");</script>
}
My problem is that I cant seem to add custom head code in to the base template from my normal pages.
The following sections have been defined but have not been rendered for the layout page ~/Views/Shared/OneColLayer.cshtml": "HeaderContent.
Do I need to include a pointer to the base template in the view page?
#{
Layout = "~/Views/Shared/BaseTemplate.cshtml";
}
My new base template
<head>
<link rel="stylesheet" type="text/css" href="#Url.Content("~/content/layout.css")" />
<link rel="stylesheet" type="text/css" href="#Url.Content("~/content/global.css")" />
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/js/fadeInFadeOut.js")"></script>
<title>#ViewBag.Title</title>
#RenderSection("HeaderContent", false)
</head>
<body>
#RenderBody()
</body>
my new child template
#{
Layout = "~/Views/Shared/BaseTemplate.cshtml";
}
#RenderSection("HeaderContent", false)
#RenderBody()
my view
#{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/OneColLayer.cshtml";
}
#section HeaderContent {
<h1>Left Content</h1>
}
<div>my view content</div>
the content gets placed in the oneCol template now the base template.
results...
<div id="Content">
<h1>Left Content</h1>
</div>
You need to specify the sections that are allowed to pass through in the middle template.
BaseTemplate.cshtml
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
#RenderSection("HeaderContent", false) #* The region of the header scripts (custom css) *#
</head>
<body>
#RenderBody()
</body>
</html>
EDIT
your new child template
#{
Layout = "~/Views/Shared/BaseTemplate.cshtml";
}
#section HeaderContent {
#RenderSection("HeaderContent", false)
}
#RenderBody()
If you put the render section inside of a section from the base template, it will render that section in the correct place on the base template.
View.cshtml -> uses MiddleLayout.cshtml as it's layout
#section HeaderContent
{
<!-- header content that will now render -->
}
<!-- page content -->

Resources