An example of bootstrapping dynamic data onto the page, and then exposing it for programmatic access with rttc.compile()
. This makes it possible to expose our view locals in our client-side js for access in the browser. This example uses Sails.js, but is equally applicable for Hapi or Express.
UPDATE: Check out balderdashy/sails#3522 and https://github.com/mikermcneil/expose-locals-to-browser-xss-test-app
Let's assume you are building a website about vampires.
In your view template (pages/all-vampires.ejs
), you might write:
<div class="topbar">
<span>Logged in as <%= me.name %></span>
</div>
<div class="vampire-list-component" is="vampire-list-component">
<h2>All known vampires in the Los Angeles area:</h2>
<ul class="vampire-list">
<% _.each(vampires, function (vampire){ %>
<li data-vampire-username="<%=vampire.username%>">
<span><%= vampire.name %></span>
<button is="summon-btn">Summon</button>
</li>
<% }); %>
</ul>
</div>
<%
// If present, expose the `dataToExposeToBrowserJs` local to client-side js as `window.SAILS_LOCALS`:
if(typeof dataToExposeToBrowserJs !== undefined) { %>
<script type="text/javascript">
window.SAILS_LOCALS = <%- dataToExposeToBrowserJs %>;
</script>
<% } %>
<script type="text/javascript">
// * * (normally the code in this second script block would be in a separate client-side js file) * *
// When the summon button is clicked, trigger the `summon` function for this vampire.
$('[is="vampire-list-component"]').on('click', '[is="summon-btn"]', function whenSummonButtonIsClicked(e) {
// Look up the clicked vampire in SAILS_LOCALS
var clickedVampire = _.find(window.SAILS_LOCALS.vampires, {
username: $(e.currentTarget).closest('[data-vampire-username]').attr('data-vampire-username')
});
// Call its summon function
// (obviously the summon function has to contain logic which runs in the browser)
var summoningStatusReport = clickedVampire.summon(window.SAILS_LOCALS.me.name);
// Will log:
// > At last, the browser! I am born again! Thanks, Rupert.
//
// Or:
// > ...
// And return:
// > { mood: 'hungry' }
// Or:
// > { mood: 'brooding' }
});
</script>
using EJS on the server, and provided some data as a view local (as well as providing access to rttc
):
var SOME_WATCHER = { name: 'Rupert Giles', hobbies: ['dirty dancing'], favoriteVampire: 'angelus' };
var SOME_VAMPIRES = [
{
username: 'angelus',
name: 'Angelus',
hobbies: ['taiji'],
summon: function noteThatRttcCompilePreservesFunctionNamesIfProvided(){
console.log('...');}
return {mood: 'brooding'};
},
{
username: 'darla',
name: 'Darla',
hobbies: ['torture'],
summon: function (yourName){
console.log('At last, the browser! I am born again! Thanks, '+ yourName+ '.');
return {mood: 'hungry'};
}
}
];
return res.view('pages/my-sweet-page', {
watcher: SOME_WATCHER,
vampires: SOME_VAMPIRES,
dataToExposeToBrowserJs: require('rttc').compile({
watcher: SOME_WATCHER,
vampires: SOME_VAMPIRES,
otherStuff: {like: 'this'},
orMaybe: [ { 'even another function': function (){ console.log('like this'); } } ]
}
})
UPDATE: Check out balderdashy/sails#3522 and https://github.com/mikermcneil/expose-locals-to-browser-xss-test-app