Mixing "real" JavaScript code in with your templates (i.e. tossing a <script>
into a template, not simple bits of JavaScript for putting the template together) generally doesn't work out that well. You'll usually have an easier time if you separate the concerns: HTMLish things go in the template, functionality is hooked up in the view.
I'm not that familiar with amChart but many charting (and mapping) libraries will need to know a few important things about their target element before they can do any work. In particular, they'll usually want to know where it is on the page and how big it is and those won't be know until the <div>
has been rendered to the page. In a Backbone app, that generally won't be true until someone has render
ed a view and appended its el
to the page:
var v = new View;
// We don't know the position or size of anything yet.
v.render();
// We still don't know.
$('body').append(v.el);
// Now the size and position are available but we might have to
// pass control back to the browser first.
You're facing the added difficulty of amChart apparently wanting the id
of something in the DOM that it should draw into:
chart.write("chartdiv");
But document.getElementById('chartdiv')
won't return anything useful until after render
has been called and after someone has done a x.append(v.el)
(or equivalent).
If you're expecting someone to immediately your view's el
to the page right after calling render
then you can queue up some code to run after the browser gets control back (and hence has time to figure out the size and position of things and make document.getElementById('chartdiv')
do something useful) by using setTimeout
with a timeout of zero:
render: function() {
var _this = this;
var chartData = ....
// Do normal rendering and template stuff.
setTimeout(function() {
var chart = new AmCharts.AmSerialChart();
chart.dataProvider = chartData;
//...
chart.write("chartdiv");
}, 0);
return this;
}
You can also use _.defer
(which is little more than setTimeout(..., 1)
) if you want to be a little more explicit about it.
There might be some amChart-specific stuff to deal with but hopefully this will take care of the hard parts.
BTW, that AmCharts.ready
call you mentioned in the comments probably doesn't work that well with single-page apps because it is probably equivalent to $(document).ready()
and that only fires when a page is loaded (i.e. only once for the duration of a single-page app). There might be other events you can use instead but you should be able to use the existing Backbone view structure instead of relying on document-ready events.