Ember template and Google AdSense - ember.js

What is the appropriate way to include a Google AdSense banner in an Ember (Handlebars) template?
Say I have a template for a view that looks like this:
<script type="text/x-handlebars" data-template-name="myPageWithBanner">
<div id="mainContent">
Lorem ipsum main content
</div>
<div id="banner">
//Normally I would insert a script tag here, but that is not possible
</div>
</script>
Do I need to do this from code using pre-compiled templates, or is there a way I am not aware of?

I don't have a Google AdSense account, so I can't test this. But there are several major problems here:
You can't include a <script> tag inside a Handlebars template, not even if you use CDATA.
Google AdSense requires the AdSense JavaScript to appear verbatim in your page, or it's a TOS violation.
According to this StackOverflow answer, AdSense on AJAX sites is poorly supported at the moment.
The Google AdSense crawler won't be able to see any content on your page, so I doubt that ad-targeting is going to work. But see below for some things which might help crawlers.
But I'm going to assume, for the sake of simplicity, that you can discuss TOS issues directly with Google, and I'll just try to solve the technical problems. First, based on this StackOverflow answer, here's one possible solution that allows you to serve up Google's script verbatim:
<script type="text/x-handlebars">
<h1>Ember AdSense</h1>
{{outlet}}
<div id="ads"></div>
</script>
<script type="text/x-handlebars" data-template-name="index">
<p>Hello, world!</p>
</script>
<div id="ads-load" style="display: none">
<!--
Apparently this needs to appear verbatim, exactly as Google gave it to
you, or it's a TOS violation.
-->
<script type="text/javascript"><!--
google_ad_client = "ca-pub-XXXXXXXXXX";
/* Test Ad */
google_ad_slot = "XXXXXX";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
Then when our main template loads, we use jQuery to move the ads into our application template:
window.App = Ember.Application.create();
// Explicitly declare the view class for our application view.
App.ApplicationView = Ember.View.extend({
// Called once the view is rendered.
didInsertElement: function () {
$('#ads-load').appendTo("#ads").css("display", "block");
}
});
As for allowing the Google crawler to see you content, Google has official advice for AJAX applications, but I don't know whether that works with the AdSense crawler. Alternatively, if you're using pushState to update your displayed URLs, then you need to make sure that each of those URLs can be rendered by your server when requested by a crawler. (The Discourse forum software does exactly this.)
Please let me know if it gets you any closer.

Related

How to append Ember.View Properly

I have recently decided to do a major upgrade with my javascript libraries and have ran into a perplexing issue with appending Ember.Views. I have been researching this issue for several hours now and have tried many things but nothing has worked.
What I want to do is quite simple: Extend Ember.View, manually create a new instance of this extended view and then append it to a div. In a much earlier version (ember.js 1.5) this was extremely straightforward. Now (ember.js 1.9) attempting the same thing results in an error.
Container was not found when looking up a views template. This is most
likely due to manually instantiating an Ember.View. See:
http://git.io/EKPpnA
Here is a very simple example that demonstrates this: http://jsfiddle.net/81dhm3ta/
html
<body>
<script data-template-name="main" type="text/x-handlebars">
Main
</script>
<div id="main" style="text-align: center;"></div>
</body>
javascript
$(document).ready(function () {
App = Ember.Application.create();
App.MainView = Ember.View.extend({
templateName: 'main',
});
App.view = App.MainView.create();
App.view.appendTo("#main");
});
Can someone show me the simplest way to do this properly?
App.view is neither a D0M element or jQuery object that you can simply append to a div. It is an Ember object of type View.
In the link given by the error, you are clearly told that you can't create views like you did in your snippet. Dynamic views must be instantiated within a parent view or directly through the container (not recommended).
Your life will be much easier if you add views within a template by just using the view helper:
<script type="text/x-handlebars" data-template-name="index">
{{view 'main'}}
</script>

EmberJS: How to position the application template

I'm running into a problem. I need App.rootElement = "body", because views and components will be used all over the place. I do not want to put the entire page in a handlebars template, due to SEO and other concerns. The main application template will exist somewhere in the center of the page:
<h1>Header markup</h1>
<script type="text/x-handlebars">
<h2>Application Template</h2>
{{outlet}}
</script>
<h1>Footer markup</g1>
However, when the page is rendered, this template is appended to the end of the body, instead of staying where the template script has been placed. (see jsbin exmaple) Is there any way to tell Ember to render the application template where it is in the markup?
One hacky solution I've found is to manually move the containing element in didInsertElement, but that seems a little heavy handed and not something that would be considered a best practice. (see jsbin example)
The script tag doesn't have anything to do with placement, if you want it to live somewhere create a div tag, id it, and change the rootElement to that div tag.
<script type="text/x-handlebars">
<h2>Application Template</h2>
{{outlet}}
</script>
...
<h1>Header markup</h1>
<div id='foo'></div>
<h1>Footer markup</h1>
App.rootElement = '#foo';

child template rendering in wrong routes in ember when clicking browser back/forward button

One of my child template is rendering in all routes/links when I click on the browser back/forward button. My route is defined as :
this.resource('analytics', {path: '/analytics'}, function(){
this.resource('analyticsRuns', {path: ':exerciseRunId/analyticsRuns'},function(){
this.resource('analyticsRun',{path: ':runId'});
});
});
and my templates are as follows :
<script type="text/x-handlebars" data-template-name="analytics">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="analytics/index">
some content in analytics index
</script>
<script type="text/x-handlebars" data-template-name="analyticsRuns">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="analyticsRuns/index">
some content in analytics runs index
</script>
<script type="text/x-handlebars" data-template-name="analyticsRun">
some content in analytics run index
</script>
My templates are more complex than these but I wanted to give you a gist of what issue I am facing. So when I go from analytics to analyticsRuns and to browser back , then there are no issues, but when I go from analytics -> analyticsRuns -> analyticsRun and then go back to analytics using browser back button, the analyticsRuns template shows up after the analytics template is rendered. Now if I do forward, the analyticsRuns template seems to be appended in all the other routes. I am not sure if I am defining my handlebars wrong which is causing this issue, or maybe the problem lies somewhere else. But if you have any suggestion on how to avoid this issue then I would appreciate it a lot.
In my app setup, "analytics" is not actually a parent resource. Analytics just provides a filter value to "analyticsRuns" by which the master/parent data is loaded.
Thanks,
Dee
I don't know if this will be help to others, but in my case the problem was due to bad HTML markup(I was missing a closing div in one of the templates).

Examples on how to render a template in emberjs v1.0.0-pre.4?

I am missing something very fundamental to being able to render templates in emberjs. I found a few examples online..
github.com/elucid/ember-tunes
github.com/emberjs/examples
I'm still not able to get my stuff working. These are also using a previous version of emberjs.
ember-yii.sk.hj.cx/site/app seemed promising as well but, I was still not able to get my stuff working.
Does anyone know of examples specific to v1.0.0-pre.4 ?
I'm trying to render a header, body, and footer as separate outlets. Here is the body of app.html:
<div id="main">
<script type="text/x-handlebars" data-template-name="app">
<header>
{{outlet header}}
</header>
<section>
{{outlet body}}
</section>
<footer>
{{outlet footer}}
</footer>
</script>
</div>
What I'm not understanding is how to render templates within the 3 {{outlet}} placeholders.
I watched various EmberJS "tutorials", read the documentation. This is why I believe I'm missing something very fundamental.
Any help, guidance, or direction to helpful examples will be very appreciated.
#akshayrawat has provided an absolute gold mine at: https://gist.github.com/akshayrawat/4701510 This is literally a list of 1.0.0-pre4 EmberJS resources.
#trek, one of the core EmberJS contributors created his own version of the Todos app at: https://github.com/trek/ember-todos-with-build-tools-tests-and-other-modern-conveniences
I found this particularly useful when I was trying to figure out how to use multiple {{outlet}} placeholders.
Ps: The peepcode screencast on EmberJS costs 12 USD.. but it is really good and based on Embe 1.0.0-pre4

Getting the content rendered inside a #each ember template helper, without the #each content binding

/START description of why
I'm doing a 'load more' type of interaction: user gets at bottom of a page, I load more content.
As I'm using a plugin that formats content in a 'pinterest-style' (masonry), I need to take the output of a rest call, formatted using an ember view, and i'm doing something like:
<div id="list">
</div>
<div id="hidden" style="display:none">
{{#each item in App.itemsController}}
test {{item.id}}
<br />
{{/each}}
</div>
What I want to do is, load the content in the hidden div, and then pass its HTML generated content to the plugin to process in my formatted list view.
If I just copy the #hidden content, the Ember scripts get in, and on subsequent 'load more', content is inserted in the #list, in addition of going in the #hidden div.
That's because I copied the entire handlebars.
So I get rid of the container tag, the one I supposed was wrapping the controller content binding, but even when stripping it from the content I pass to #list, the #list still auto-updates when a 'load more' is called.
I know that's a dirty hackish thing, but in order to improve performance in the client I must take a similar route.
/END description of why
//ACTUAL QUESTION ;)
Given this background, the question is, stripping the container metamorph script tags (like the ones here below), and just take the content inside them, shouldn't get rid of the auto-updating content functionality?
<script id="metamorph-X-start" type="text/x-placeholder"></script>
//ALL THE CONTENT
<script id="metamorph-X-end" type="text/x-placeholder"></script>
Inside those, I just have the actual content generated, like:
<script id="metamorph-9-start" type="text/x-placeholder"></script>
test <script id="metamorph-59-start" type="text/x-placeholder"></script>2873<script id="metamorph-59-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-9-end" type="text/x-placeholder"></script>
<script id="metamorph-10-start" type="text/x-placeholder"></script>
test <script id="metamorph-60-start" type="text/x-placeholder"></script>2872<script id="metamorph-60-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-10-end" type="text/x-placeholder"></script>
The alternative is programmatically render the template inside a variable and process that, which is surely a better way of doing this, but I just wonder how the #each binding works internally as I thought the metamorph was doing that.
Have you looked into using a CollectionView and calling the plugin through the didInsertElement callback?
e.g.
MyList = Ember.CollectionView.extend({
itemViewClass: 'App.ListItem',
didInsertElement: function(){
view.$().jqueryPlugin({ ... })
}
})