Param:
'<div class="someclass">' + somecontent + '</div>' + somecontent2
Template:
<div>{{ param }}</div>
And in browser I have:
<div class="someclass"> somecontent </div>somecontent2
How to isolate .someclass, that it render as a dom element, not text?
I think all Html elements are escaped by default. To return un-escaped Html use the triple mustache:
<div>{{{param}}}</div>
I would suggest using partial templates for this.
<script id="main" type="text/html">
<div>{{>partial}}</div>
</script>
<script id="partial" class="partial" type="text/html">
<div class="someclass">{{somecontent}}</div>{{somecontent2}}
</script>
Then just call the main template with your data as normal:
html = ich.main({
somecontent: 'content',
somecontent2: 'content2'
});
Related
Hello I have this code using HTML
<div class="abc">
<div class="12" id="hour"></div>
</div>
And I want to use javascript like this :
$('#hour').empty();
$('#hour').text(begin+ " \n "+end);
The problem is that I have no a new line for the variable end...
Do you have any ideas to solve this problem ?
Thank you !
Since you are adding that context in a HTML page inside a <div>, suggested way is to use html() function instead of text(). Then, you can use <br/> to add a new line. So, when this entire content is rendered as a HTML, then <br/> will add a new line. This also defines the difference between text() and html() function.
var begin = 'begin';
var end = 'end';
$('#hour').empty();
$('#hour').html(begin + "<br/> " + end);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="abc">
<div class="12" id="hour"></div>
</div>
Use html() instead of text() and <br> instead of \n
$('#hour').empty();
$('#hour').html('begin'+ "<br>"+'end');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="abc">
<div class="12" id="hour"></div>
</div>
I am trying to simplify my HTML file, and I have very long scripts that consist of just HTML (templates) that I'd like to move to their own external files. This is easy for me to do when the <script> tags involve functions, but in my case it's just straight HTML. In the new external file, how do I properly type up those HTML tags? See below.
<script type="text/template7" id="myStuffTemplate">
{{#each results}}
<div class="list-block media-list">
<ul>
<li>
<a href="#" class="item-link item-content">
<div class="item-media"><img src={{this.pictures['1']}} width="80" height="80px"></div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">{{this.name}}</div>
</div>
<div class="item-text">{{this.description}}</div>
</div>
</a>
</li>
</ul>
</div>
{{else}}
<div style="text-align:center">
<h1>Nothing yet!</h1>
<h2>Upload things you're willing to trade so you can start trading!</h2>
</div>
{{/each}}
</script>
That's the script within the HTML File. I'd like that moved into its own external file. How can one go about doing this? And do I reference it just like every other file when I link it? eg.:
<script type="text/template7" src="js/views/mystuff.js" id="myStuffTemplate"></script>
Thanks in advance.
This is not a script, it's a template made with either handlebars or moustache templates.
You can't "source" them with <script src="..."> like you can with Javascript, but they can be stored externally, then loaded and processed at runtime. This needs to be done asynchronously through an AJAX call. For example, assuming you were using jQuery, you could achieve it with the following:
// request the template
$.get('templates/products.hbs', function(rawTemplate) {
// once received, convert the raw template to a handlebars template
var template = Handlebars.compile(rawTemplate);
// compile the template with your context 'data' and set it on an element with an id
$('#someTargetId').html(template(data));
}, 'html'); // <-- tell jquery to load the file as html
Just be warned, even small templates will take some time to load, so there will be a delay between your page loading and the template loading then being displayed.
First of all, consider using a framework like Angular.js or React.js however this should work for you:
Let's suppose that you want to put that inside a div with id=items:
<div id="items"> Your code... </div>
In the html file add this, just before the <body> closing tag:
<script type="text/javascript" src="code.js"></script>
to include your code and this
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
to include jQuery.
Create a code.js file and put the following code inside:
$(document).ready( function() {
var myCode = "{{#each results}}" +
"<div class="list-block media-list">" +
"<ul>" +
"<li>" +
"<a href="#" class="item-link item-content">" +
"<div class="item-media"><img src={{this.pictures['1']}} width="80" height="80px"></div>" +
"<div class="item-inner">" +
"<div class="item-title-row">" +
"<div class="item-title">{{this.name}}</div>" +
"</div>" +
"<div class="item-text">{{this.description}}</div>" +
"</div>" +
"</a>" +
"</li>" +
"</ul>" +
"</div>" +
"{{else}} " +
"<div style="text-align:center">" +
"<h1>Nothing yet!</h1>" +
"<h2>Upload things you're willing to trade so you can start trading!</h2>" +
"</div>" +
"{{/each}}";
$( "#items" ).html( myCode );
} );
In my mustache template I do have something like:
<div {{attr}}="{{attrVal}}"></div>
Rendering this using
Mustache.render(template, {attr : 'data-test', attrVal : 'test'})
does produce
<div ="test"></div>
I expect to get something like
<div data-test="test"></div>
Isn't it possible to render attribute name inside of a tag using Mustache?
UPDATE
I figured out the problem. I define my HTML Mustache Templates inside custom <template> tags in my document. For example:
<template id='myTemplate'>
<div {{dataAttr}}="{{dataAttrValue}}"></div>
</template>
When getting the template using document.querySelector("#myTemplate").innerHTML the browser does convert the {{dataAttr}} to {{dataattr}} because attributes are case insensitiv. So calling
Mustache.render(
document.querySelector("#myTemplate").innerHTML,
{ dataAttr : 'data-attr', dataAttrValue : 'test'}
);
Results in
<div ="test"></div>
Hope this code snippet will help you..
var template = document.querySelector("#template").innerHTML;
//Mustache.parse(template); // optional, speeds up future uses
var rendered = Mustache.render(template, {
attr: "data-test",
attrVal: "test"
});
document.querySelector("#target").innerHTML = rendered;
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.2.1/mustache.js"></script>
<body>
<div id="target">Loading...</div>
<template id="template" >
<textarea style="width:300px">
<div {{attr}}="{{attrVal}}"></div>
</textarea>
</template>
</body>
I head the same problem Try the single [']:
<template id='myTemplate'>
<div {{dataAttr}}='{{dataAttrValue}}'></div>
</template>
.....
You can also try using to_html method for the expected output.
const HTML = Mustache.to_html(template, {attr : 'data-test', attrVal : 'test'});
document.getElementById("myTemplate").innerHTML = HTML;
const template = `
<div {{attr}}="{{attrVal}}">
</div>
`
const HTML = Mustache.to_html(template, {attr : 'data-test', attrVal : 'test'});
document.getElementById("myTemplate").innerHTML = HTML;
console.log(document.getElementById("myTemplate").innerHTML);
<html>
<head>
</head>
<body>
<template id='myTemplate'>
</template>
<div id="display-output"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.1.0/mustache.min.js"></script>
</body>
</html>
I have some content on my site that doesn't format well because different browsers/screens render the font-size a little differently. To counteract this, I'm attempting to use Angular to get the height of some <p> tags, and if they're taller than my layout allows, lower their font size.
The <p> tags I'm trying to manipulate are contained in a directive which generates multiple content boxes based on some JSON.
I have created this directive:
spaModule.directive ("resizeParagraph", function() {
return function (scope, element, attrs) {
while (element.height() > 400) {
element.css("font-size", (parseInt(element.css("font-size")) -1 + "px"));
}
}
});
This is the directive which creates those boxes (this works):
<div ng-repeat="data in homeCtrl.homeData" class="content-box">
<img class="content-image" ng-src="images/home/{{ data.imageSrc }}"/>
<div class="sub-content">
<h1>
{{ data.heading }}
</h1>
<p resize-paragraph class="large-text">
{{ data.body }}
</p>
<a ng-href="#/{{ data.linkUrl }}" class="box-link">
{{ data.linkValue }}
</a>
</div>
</div>
I'm at home creating custom directives with a source URL, but this is my first go at creating a logical attribute-based directive.
What have I done wrong?
Try adding jQuery, before loading angular.js. In this post, it is written that Angular is using its own library jqLite to substitute for jQuery when the jQuery library is not included. jqLite does not include a height() function. To be able to use height(), you have to include the full jQuery library.
Just add <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script> before the line where you include angular.js.
I tested it with the following code:
<style type="text/css">
.large-text {
font-size: 600px;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script>
<script src="angular.js"></script>
<script type="text/javascript">
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.homeCtrl = {};
$scope.homeCtrl.homeData = [
{
heading: 'Heading',
body: 'Body',
linkValue: 'LinkValue'
}
];
});
app.directive("resizeParagraph", function() {
return function (scope, element, attrs) {
while (element.height() > 100) {
element.css("font-size", (parseInt(element.css("font-size")) -1 + "px"));
}
}
});
</script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="data in homeCtrl.homeData" class="content-box">
<img class="content-image" ng-src="images/home/{{ data.imageSrc }}"/>
<div class="sub-content">
<h1>
{{ data.heading }}
</h1>
<p resize-paragraph class="large-text">
{{ data.body }}
</p>
<a ng-href="#/{{ data.linkUrl }}" class="box-link">
{{ data.linkValue }}
</a>
</div>
</div>
</div>
EDIT
After some testing, I found the reason why it is not working as expected. The function inside the directive is called, before the expression {{data.body}} is executed in the template. It means that at the moment the directive is called, the text inside the paragraph is literally {{data.body}}. What you want is to postpone the execution of the directive after the expression has been executed. You can do it as follows:
app.directive("resizeParagraph", function() {
return function (scope, element, attrs) {
scope.$watch(name, function () {
while (element.height() > 50) {
element.css("font-size", (parseInt(element.css("font-size")) -1 + "px"));
}
})
}
});
I can also confirm that element.height() and element.context.offsetHeight return the same value. The height of the element in px. So, it doesn't matter which of the two you'll use.
I hope this helps.
I am rendering different kinds of attributes within the same html element in the following manner:
Javascript:
var dataAttribute = {
value:function(){ return 1;}
}
var listAttribute = {
value:function(){ return "<div>My Arbitrary HTML
<div>1</div>
<div>2</div>
<div>3</div>
</div>";}
}
var attributes = [dataAttribute,listAttribute]
HTML:
<div ng-repeat="attribute in attributes"> {{ attribute.value() }} </div>
How do I get the html in the listAttribute to render as HTML and not as text, while still retaining the ability to render the normal data of the dataAttribute?
You just should not. Use ng-switch directive if you want to render different things based on properties of items in your collection. ( in worst case use series of ng-if inside your ng-repeat)
Do not invent another templating engine if you already using angular, you are just confusing yourself.
Little more explanation here. You already have code that generates that html somewhere. It really better by angular directives.
<div ng-repeat="attribute in attributes" ng-switch="attribute.type">
<div ng-switch-default> {{ attribute.value() }} </div>
<div ng-switch-when="table"><my-table data='attribute.value()'></my-table></div>
<div ng-switch-when="list"><my-list data='attribute.value()'></my-list></div>
</div>
And set of directives
.directive('myTable', myTable).directive('myList', myList)
will hold all the logic to produce html from the data.
I.E. don't mix layout and data in one structure.
The solution was a combination of #vittore and #YOU's answers:
Javascript:
var dataAttribute = {
value:function(){ return 1;},
type:'data'
}
var listAttribute = {
value:function(){ return "<list-directive></list-directive>";},
type:'list'
}
var attributes = [dataAttribute,listAttribute]
HTML:
<div ng-repeat="attribute in attributes" ng-switch="attribute.type">
<div ng-switch-default> {{ attribute.value() }} </div>
<div ng-switch-when="list" ng-bind-html="attribute.value()"></div>
</div>
Thanks!