Dust.js and tables - javascript

I am new to Dust.js and am trying to iterate a JSON object with records and render each of them into a row within a table. Below is the script, I am using to render the table, but am running into issues, I guess while rendering, especially the template argument of the render function. Appreciate if I could be pointed in the right direction
<div id="dustPlaceholder"></div>
<script id="goalTemplate">
<table id="dustGoals">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{#friends}
<tr>
<td>{name}</td>
<td>{age}</td>
</tr>
{/friends}
</tbody>
</table>
</script>
</div>
<script type="text/javascript">
var src = document.getElementById("goalTemplate").innerHTML;
var compiled = dust.compile(src);
dust.render("goalTemplate", { friends: [ { name: "Moe", age: 37}]},
function(err, out) {
document.getElementById('dustPlaceholder').innerHTML = out;
});
</script>

You need to include the entire Dust.js library if you are going to be rendering on the client, so you need to include the dust-full-0.3.0.min.js. Additionally,
<script src="dust-full-0.3.0.min.js"></script>
Also, what is "goalTemplate"?
Also what are you compiling? There are no variables in there. You need to compile the actual HTML - the content in the DIV tag. So everything including the div tags belong in the src variable.
Also, you must assume a name to the compiled template so it can be accessed. I'm really confused what you were doing before, but this example should work:
<script src="dust-full-0.3.0.min.js"></script>
<script type = "text/javascript">
var source = "<div id="dustPlaceholder"></div>
<script id="goalTemplate">
<table id="dustGoals">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{#friends}
<tr>
<td>{name}</td>
<td>{age}</td>
</tr>
{/friends}
</tbody>
</table>
</script>
</div>";
var compiled = dust.compile(src, goalTemplate);
dust.render("goalTemplate", { friends: [ { name: "Moe", age: 37}]},
function(err, out) {
document.getElementById('dustPlaceholder').innerHTML = out;
});
</script>

Related

Trying to highlight a substring with JavaScript

I want to write a JS function which will, within an element (a td), find a substring, and highlight it. It only needs to work for the first occurrence of the substring within the element. I am just trying to highlight some keywords on my blog.
Here is what I have tried so far -
JavaScript
function highlight(s, search) {
return s.replace(new RegExp(
search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi'
), '<b>$&</b>');
}
Note the object['highlight'] is an object I have access to in my Ruby on Rails code.
HTML
<div>
<table>
<thead>
<tr>
<th>...</th>
</tr>
</thead>
<tbody>
<tr>
<td class="test">This element contains text to be highlighted</td>
<script>highlight($('test').html(), <% object['highlight'].first %>)</script>
</tr>
</tbody>
</table>
</div>
When I try to run this code, nothing is highlighted.
Can anyone see what I have done incorrectly here ?
Thanks
Have a look at mark.js. It can highlight keywords/terms or custom regular expressions. It is also available as jQuery plugin.
DEMO: JSFIDDLE
var context = document.querySelector(".test");
var instance = new Mark(context);
// "text" is '<% object['highlight'].first %>'
instance.mark("text");
mark{
background: yellow;
color: black;
}
<div>
<table>
<thead>
<tr>
<th>...</th>
</tr>
</thead>
<tbody>
<tr>
<td class="test">This element contains text to be highlighted</td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdn.rawgit.com/julmot/mark.js/6.1.0/dist/mark.min.js"></script>
You have to append the text back on to the td.
<table>
<thead>
<tr>
<th>...</th>
</tr>
</thead>
<tbody>
<tr>
<td class="test">
This element contains text to be highlighted
<script>highlight('.test', '<%= object['highlight'].first %>')</script>
</td>
</tr>
</tbody>
</table>
Javascript part
<script>
function highlight(s, search) {
text = $(s).html();
modifiedText = s.replace(new RegExp(
search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi'
), '<b>$&</b>');
$(s).html(modifiedText);
}
</script>
Edit:
Even though this might answer the OP's question, this is not recommended. It would be better to use any libraries like this or this

requirejs define is not defined

I'm trying to implement knockoutjs and requirejs to my asp.net mvc app.
So, here's what I have.
Views/Shared/_Layout.cshtml
<html>
<body>
#RenderBody()
<script src="~/Scripts/require.js" data-main="/Scripts/app/main"></script>
#RenderSection("scripts", required: false)
</body>
<html>
Scripts/main.js
require.config({
baseUrl: '/Scripts',
paths: {
ko: '/Scripts/knockout-3.3.0'
}
});
Views/Product/Index.cshtml (one of my views)
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Status</th>
</tr>
</thead>
<tbody data-bind="foreach: products">
<tr>
<td data-bind="text: $data.product"></td>
</tr>
</tbody>
</table>
<script src="~/Scripts/app/product.js"></script>
#section scripts {
// Some scripts here
}
Scripts/app/product.js
define(['ko'], function (ko) {
var data = [
{ name: 'Product1' },
{ name: 'Product2' }
];
var Product = function () {
this.name = ko.observable()
};
var productVm = {
products: ko.observableArray([]),
load: function() {
for (var i = 0; i < data.length; i++) {
productVm.products.push(new Product()
.name(data[i].name));
}
}
}
productVm.load();
ko.applyBindings(productVm);
});
Just in case you need to see my folder structure
Solution
- Scripts
-- app
--- product.js
-- require.js
-- knockout-3.3.0.js
- Views
-- Product
--- Index.cshtml
-- Shared
--- _Layout.cshtml
Then, once I navigate to my products index page. I got a define is not define error. What am I missing?
Include following in your main.js
require(["app/product"], function () {
});
And modify index.html as follows
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Status</th>
</tr>
</thead>
<tbody data-bind="foreach: products">
<tr>
<td data-bind="text: $data.name"></td>
</tr>
</tbody>
</table>
#section scripts {
}
If you intend to use RequireJS for multi page application, then also read this.

How do I loop over a JSON array with handlebars.js in a Shopify store?

I'm making a GET request to /cart.js. It returns the following JSON data:
{
"token":"118aa66ff7cc99c7fb4524f07bd305a4",
"note":null,
"attributes":{
},
"total_price":771,
"total_weight":0,
"item_count":3,
"items":[
{
"id":903858951,
"title":"Aarts Frambozen op siroop",
"price":211,
"line_price":211,
"quantity":1,
"sku":"wi195688",
"grams":0,
"vendor":"Aarts",
"properties":null,
"product_id":385866167,
"variant_id":903858951,
"gift_card":false,
"url":"/products/aarts-frambozen-op-siroop?variant=903858951",
"image":"https://cdn.shopify.com/s/files/1/0656/8697/products/AHI_434d50303234343731_dRevLabel_1_Rendition_LowRes_JPG.jpeg?v=1413443204",
"handle":"aarts-frambozen-op-siroop",
"requires_shipping":true
},
{
"id":903852739,
"title":"AH Aardappelschijfjes spek en ui",
"price":211,
"line_price":211,
"quantity":1,
"sku":"wi202676",
"grams":0,
"vendor":"AH",
"properties":null,
"product_id":385862935,
"variant_id":903852739,
"gift_card":false,
"url":"/products/ah-aardappelschijfjes-spek-en-ui?variant=903852739",
"image":"https://cdn.shopify.com/s/files/1/0656/8697/products/AHI_434d50303038363632_dRevLabel_2_Rendition_LowRes_JPG.jpeg?v=1413442904",
"handle":"ah-aardappelschijfjes-spek-en-ui",
"requires_shipping":true
},
{
"id":903852571,
"title":"AH Aardappelen iets kruimig voordeelzak",
"price":349,
"line_price":349,
"quantity":1,
"sku":"wi127728",
"grams":0,
"vendor":"AH",
"properties":null,
"product_id":385862819,
"variant_id":903852571,
"gift_card":false,
"url":"/products/ah-aardappelen-iets-kruimig-voordeelzak?variant=903852571",
"image":"https://cdn.shopify.com/s/files/1/0656/8697/products/AHI_434d50303233343335_dRevLabel_1_Rendition_LowRes_JPG.jpeg?v=1413442897",
"handle":"ah-aardappelen-iets-kruimig-voordeelzak",
"requires_shipping":true
}
],
"requires_shipping":true
}
What I'd like to do is iterator over the items and show the id, title and quantity.
Here's what I'm trying:
<script class="foobar" charset="utf-8" type="text/x-handlebars-template">
<div>
{{#items}}
<thead>
<th>Id</th>
<th>Title</th>
<th>Qty</th>
</thead>
<tbody>
<tr>
<td>{{id}}</td>
<td>{{title}}</td>
<td>{{quantity}}</td>
</tr>
</tbody>
{{/items}}
</div>
</script>
<script charset="utf-8">
var source = $(".foobar").html();
var template = Handlebars.compile(source);
var jqxhr = $.getJSON( "/cart.js", function() {
console.log( "success" );
})
$('body').append(template(jqxhr.responseJSON));
</script>
But this returns:
Id Title Qty
Without any data. I know the GET request is working, because console.log(jqxhr.responseJSON); prints the correct data.
What am I doing wrong and what could I try next?
Edit:
I think I'm handling the Ajax response wrongly.
JSFiddle: http://jsfiddle.net/narzero/4fn3f6sg
Edit 2:
It might be worth mentioning that I'm running the code on a Shopify store.
The way you're looping over the data you've provided should work, but I see a minor mistake with the ajax call which would in fact make you think you're code isn't working.
You have to return your results in the complete callback of your code since you're using ajax, and ajax is asynchronous.
$.getJSON( "/cart.js", function(data) {
$('body').append(template(data));
});
I'm not sure if it was on purpose or not, but you're table is not complete.
<script class="foobar" charset="utf-8" type="text/x-handlebars-template">
<div>
<table>
<thead>
<th>Id</th>
<th>Title</th>
<th>Qty</th>
</thead>
<tbody>
{{#items}}
<tr>
<td>{{id}}</td>
<td>{{title}}</td>
<td>{{quantity}}</td>
</tr>
{{/items}}
</tbody>
</table>
</div>
</script>
I solved this problem by adding the tags {% raw %} {% endraw %} inside the handlebar script class, like so:
<script class="foobar" type="text/x-handlebars-template">
{% raw %}
<div>
<thead>
<th>Id</th>
<th>Title</th>
<th>Qty</th>
</thead>
<tbody>
{{#items}}
<tr>
<td>{{id}}</td>
<td>{{title}}</td>
<td>{{quantity}}</td>
</tr>
</tbody>
{{/items}}
</div>
{% endraw %}
</script>
When using {% raw %} it makes sure that no liquid will be parsed within these tags.
Thanks for the help guys.

Mustache Template with Nested Array of Objects

Could use a little help figuring out why my Mustache template isn't rendering properly. I'm very confused why the following isn't working. I'm sure it's a minor stupid mistake of mine or something...
var tableRows = [
{name: 'name1',
values: ['1','2','3']},
{name: 'name2',
values: ['1','2','3']},
{name: 'name3',
values: ['1','2','3']}
];
var template = $('#mustache-template').html();
$('#target').append(Mustache.render(template, {rows: tableRows}));
HTML Template:
<div id="mustache-template">
<table>
<tbody>
{{#rows}}
<tr class="">
<td>{{name}}</td>
{{#values}}
<td>{{.}}</td>
{{/values}}
</tr>
{{/rows}}
</tbody>
</table>
</div>
I'm expecting a table with each array item being its own row, but instead I'm getting this:
[object Object]
Here's a jsFiddle to illustrate: http://jsfiddle.net/gF9ud/
The problem is that the browser handles your template as an invalid table element. It's not a good idea to store your templates on a page like that, use <script type="text/template"> to wrap them:
<script id="mustache-template" type="text/template">
<table>
{{#rows}}
<tr class="">
<td>{{name}}</td>
{{#values}}
<td>{{.}}</td>
{{/values}}
</tr>
{{/rows}}
</table>
</script>
http://jsfiddle.net/zHkW5/
Another solution that I found works is to comment out the mustache like so:
<div id="mustache-template">
<table>
<tbody>
<!-- {{#rows}} -->
<tr class="">
<td>{{name}}</td>
{{#values}}
<td>{{.}}</td>
{{/values}}
</tr>
<!-- {{/rows}} -->
</tbody>
</table>
</div>
For me, it rendered exactly as I had hoped. I think the browser kind of freaks seeing code between tr tags.

Javascript code is not created inside MVC3 Razor foreach loop !!?

Here is code fragment:
#foreach (var item in Model)
{
<table>
<thead>
<tr>
<th>Column1</th>
<th>Column2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Value1</td>
<td>Value2</td>
</tr>
</tbody>
<table>
<script type="text/javascript">
$(function () { $("table").highchartTable(); });
</script>
}
Why javascript code is not created inside MVC3 Razor foreach loop ?
There must be multiple javasctipt codes created.
However, the resulting HTML doesnt have javascript at all.
Any ideas ??
Thank you.

Categories