 I'm going to be talking about integrating Ember into existing sites. I'm James Croft. I occasionally tweet. I occasionally blog. And I work at a company called Minified, where a small company that helped clients develop new products. And we've been using Ember for quite a while. This was a blog post I wrote back in the early days of Ember, just as a framework was emerging back when it was called Sproutcore 2. So, we've built a few things at Minified using Ember from apps where JavaScript-only web apps, where everything's built in Ember, to sites where we've just built small parts of it in Ember, where we've integrated Ember into existing sites. So, first I'm going to talk about this debate that keeps rear in its head between progressive enhancement and JavaScript-only web apps. So, on one side you've got people arguing that sites should be accessible without JavaScript for delivering the base content of the site. On the other side you've got people arguing that the sort of web is moved on and we can treat the browser as a runtime. And JavaScript-only web apps can offer experiences that normal sites can't offer. And it's often presented as this like pit-your-side type argument. And Ember's clearly targeting itself as a framework for building these JavaScript-only web apps. But the problem is not everything's a good fit to be a JavaScript-only web app. So, in this talk, instead of talking in the abstract about these things, I'm going to walk through a case study of a site that's not a good fit to be a JavaScript-only web app, but a site that I've used Ember on and I'll show you how and where I'm using Ember and where it's helping me out. I mean, you could even say that I was using Ember to progressively enhance the site. So, the site I'm talking about is Endless Rotation. It's a site project of mine. And this is a music discovery site for DJs. And it's all based around the concept of DJ charts. So every month DJs will often produce top tens of the tracks that they're liking that month. And they do it to give recognition to the artists that produce those tracks and build some hype about the track. And Endless Rotation is a place that DJs can come and chart that music. And it breaks away from this 10 per month format. And the DJs can chart as many or as few tracks as they like. And I use that chart data to drive a recommendation engine to suggest similar tracks. And this site isn't a good fit to be a JavaScript-only web app. So this is what the site looks like. This is the page for a particular track. And you've got a list of which DJs charted the track. You've got an embedded player so you can click the play button and the YouTube video will start playing off that track. And then down here we've got this section where you can explore tracks that we think are similar. So this is a publicly accessible site where I'm delivering content. And it needs to be crawlable to be indexed. A lot of the traffic comes from Google because DJs often chart tracks before they've been released. And no one's written much about them on the web yet. So it ranks quite highly. So that's a source of traffic that I'm not willing to use. And I don't think JavaScript-only web apps are indexable by Google just yet. I think maybe if you build them in a certain way. But people have come up to solutions with this indexing problem. So this is a discourse which is a forum site written in Ember. And they've got around this indexing problem by using this no script tag. So if you visit discourse with JavaScript turned off then this is the view that you see. It's server rendered HTML that lives between these no script tags. If you visit with JavaScript enabled then your browser will just ignore everything between those no script tags. Ember will boot up and render this version of the site. So that's one solution but it sort of seems a bit like double work to me. You're rendering things on the server and then you're throwing all that away and then rendering everything again on the client. You might get some reuse out of your templates depending on how you've set things up. But if not you've got this sort of keeping things in sync between server and client. It's not a solution that I particularly wanted to use. But other people are coming up with the solutions for indexing JavaScript-only web apps. Some people are running JavaScript runtimes on the server, pre-rendering the content, pre-rendering the site and serving that up. And I think you can structure your JavaScript web apps in such a way that search engines can start indexing them now or something recently about Yahoo might be indexing some Ember app. But the thing is with endless rotation, like all the solutions are valid but at the end of the day it's a sort of site that I just wanted to be server rendered. I didn't want to enforce a JavaScript runtime just for delivering simple content. Just delivering simple content down but there are trade-offs. I've essentially split the page into what I class as essential and non-essential content. You outright won't get some of the functionality if you visit endless rotation with JavaScript turned off but I'm fine with that. So this is the track page and then this is the track page with JavaScript turned off. So you see that you don't get the embedded player and you don't get that section where we were showing you the similar tracks. That's not really the main content of the site. Those are just links off to other pages. There's no new content there. But the core content of what makes up the site is which DJs were chatting on which tracks and that's all still accessible with JavaScript turned off. So given I've got this starting point of server rendered HTML, where does Ember fit in and why am I using Ember at all? Well, as a starting point let's consider this track player. So each page has this play button and if you click the play button then an embedded YouTube video pops up and starts playing the track. Likewise, if you're on a page that lists a lot of different tracks, they've all got play links by the side and you can click those and the associative video load and start playing the track. Now you might think that we don't need Ember just for simple functionality like that, just for loading and playing a YouTube video, but over time this track player has evolved and turned into more of a playlist manager where you can cue multiple tracks. It keeps track of the currently playing track. It allows you to reorder tracks, save playlists, remove tracks and I've got more functionality planned for it. When you're building more complex JavaScript functionality like this it's nice to be able to lean on the Ember framework because there's a lot of good stuff in Ember. There's a lot of good stuff in the core Ember object model, like bindings, observers, computer properties and the run loop that buffers these changes for you and things. This is what first attracted me to Ember in the first place was this object model that I could build things on. Back then there wasn't the router which rendered the templates for you and things. You just sort of created things with this base object model and built your stuff out from there. With the question of that track player, how would we build that? Well, this could be one approach. I apologise for the coffee script here, but I've defined a track player component and when it's inserted into the DOM this setup player function runs. This will create an instance of the YouTube player and then we've just got this observer that's observing the video ID property of the track and whenever that changes we'll load the new track into the player. We've also defined a track controller and in our template we can just wire up this component such that the track property is bound to the track controller. All that needs to happen to start playing a video is that we change the content of the track controller. We give the track controller an object with a video ID property and the video will start playing. How do we populate the content of that track controller? Well, if we had an Ember app we'd most likely do something like this. At some point we'd have a list of tracks. I'm saying here that they'd be in the tracks controller and we could loop over each track in that controller and render out a list element and this play link. We're using the handlebars action helper to attach an action to the play link such that when that link is clicked this play track event will fire and we can handle that action somewhere in that application either in a controller or in a route. Here I'm handling it in the application route and I'm just setting the content of the track controller. That will make our video start playing. The problem is, on Ember's rotation Ember isn't rendering these links. Ember isn't rendering these play links so we can't use this action helper where the links are rendered by the server and are on the page and rendered before Ember even initializes. This is the HTML that the server is serving up. Similar, we've got this play link and we've given it a couple of extra attributes like the artist and the title giving it a classic play. Just on the JavaScript on the page we can define an event handler for this play link such that when it's clicked we can pull the data off that link we can look up the video idea on YouTube we can create our track and then all we need to do is get our track into the application we need to populate the content of that track controller. One solution would be this. Because we're outside the confines of our Ember app here all we can see about our Ember app is this app global variable. This is our only route into our Ember app and from that we can get the container and look up the track controller and then we can set the content of the track controller. That does what we want we're using this double underscore container and we know this is bad because Tom Dale said every time they see someone using this double underscore container they'll just add another pair of underscores but from outside the confines of our Ember app that's the only way that we can grab a handle on the track controller but there's a workaround in this case so this is our event handler and we can just pick up this code and move it into the confines of our Ember app we can put it in an initialiser and in the initialiser we have access to our container and this is a guilt free container there's no underscores here so we can do the same thing we can look up the track controller on the container and then we can just populate the content of that track controller. So in this case we've found a workaround we've just been able to pick up our code and move it into our Ember app and everything's happy but I've been in situations where you can't just pick up your code and move everything into Ember and I have had to go in through this underscored container before so in this case we haven't solved the problem of how to get data into our application from the outside world but we have found a workaround so if you think where we are now if you click this play button the track will start playing but as soon as we click one of these links the browser is going to request the new page and load the new page and we're going to lose that playing track and that doesn't make for a very good user experience we want that track to continue playing so click around the browser on the site so the solution to this is to like only load the content that has changed and a way of doing that is by using PJAX so PJAX was originally developed for GitHub and using the file browser and if you click around the file browser there you'll see that the whole page isn't reload just the section that's changed loads it does this by hijacking all the links on the page and when you click them instead of changing the window location it will fire off an XHR to the server and the server will deliver back only the content that has changed and then they change that in the browser so I wanted to put this in there because for those of you who don't know TurboLinks is basically a rebranded version of PJAX DHH came along and rebranded PJAX as TurboLinks and made it a default in every Rails project which like it... TurboLinks like totally has a bad ret and for the record it definitely shouldn't be on by default in a Rails app however, using the right place like PJAX or TurboLinks like it can be effective and you speak to people and most people like GitHub's file browser experience but if you told any Ember Dev that you were building a new app using TurboLinks like you should expect a few snidey remarks but here I am using Ember and TurboLinks like side by side so just don't tell any Ember core people but in this case it's a solution to our problem we've started the track playing and now we can click around the site and we're not having a full page refresh the track will continue playing so you can browse around you started to track playing you can click a link you don't lose the track playing but you see the new content and every link you click we're just changing this section of the page so now our Ember application is long lived we've taken our Ember application outside of the... we're making it long lived outside the browser's normal request response of the entire page so there's just one piece remaining which is like this section explore similar tracks so this is like a paginated tabs list where when you click these tabs or move to the next pages we're grabbing content from the server so given that we're serving up this section via PJAX how do we make this section? so one way you could do it would be and the PJAX response that you're serving up you could have some JavaScript there that manually created a view and here creating an instance of the controller and passing that to the view and then just appending that view to the page and this is the way that you used to do things back back before there was a Ruto like back in the early days of Ember you just create these instances of your view and put them on the page where you were going to use them but if you do this now you'll get this warning that's saying that your view doesn't have a container so every instance of a view now needs a container so we could give our view our container like this but again if someone catches you doing that we're soon going to end up in this situation like with this API but we've basically hit upon the same problem again there's no way to access objects within our Ember application without going through the container and using the container from outside the context of your apps discouraged another way to do it is rather than create the instance of the view yourself you could look up the view on the container and that will create the fresh instance of the view with you create the fresh instance of the view for you so then you're not coupled to the naming of the view so it's like a win for dependency injection but it doesn't get you away from the underscore container likewise instead of creating the track controller here you could look up the track controller through the container and that would return you the instance of that and I haven't found a way around this yet so I've just been using this double underscore container in my code because there's actually no way to reach in to the reach into an Ember app from outside and create instances of things or change the data in there so in working through this case study we've ended up with this hybrid site we've got a server rendered site that has some Ember enhancements and uses PJAX or turbo links if you want to cause a reaction so that the Ember components are long lived and are not lost in the normal browser request response behaviour so the point is that Ember's got this great object model there's some really great stuff in there that makes it useful not just for building single page applications it can be really useful to lean on that object model when you're building complex JavaScript behaviours it seems that Ember's targeting itself solely at being a framework for JavaScript-only web apps apps where Ember's front and centre in the application and everything is done through Ember but hopefully I've shown you a case where Ember isn't a good fit for the whole application but that it can still be used to build parts of your app where it makes sense and you don't have to use the whole of Ember you can just ignore the bits that you don't need and just use the bits that you do need to enhance your sites and hopefully when Ember's fully split out into the ES6 modules it'll become much easier to pick and choose the bits of Ember that you need one area where I think Ember could be improved is when working with code that lives outside the confines of the Ember app I'm still not convinced about the double underscore in the container it means that there's no real route into the Ember app if you want to grab a handle on something inside it you may find yourself going through the container which they're discouraging maybe they just need to expose a common way of passing messages into the Ember app like Twitter's flight framework does it encourages building these highly decoupled components that communicate by sending and listening for events maybe Ember needs something like that because when you're using Ember as part of your application and not the whole of it you want to build things that are decoupled and you don't want to be reaching in by going through your double underscore container all the time so finally it's not possible yet but hopefully one day Ember will be able to work with existing content on the page rather than needing to render everything itself from scratch so then you'd be able to serve up these server rendered HTML and Ember wouldn't need to throw up all and re-render everything itself it could just sort of see what's there and come in and take over and enhance what's there and that's it, so if you've got any questions I'll be happy to answer I'm always using apps on the score, container on the score you showed us an example of using an initializer so in that same initializer you could just set those instances to some way where you could reuse them so you could have like an Ember.globals or something object where you set those instances that you cared about and then that creates this sort of single API for where you can grab instances that you've chosen so you're saying in the initializer look up the things I need from the container that's the point of the container the container is where your dependencies are injected into and that's where you go to look up your things so I don't want to introduce another content I'm actually happy enough using the container in that way it's just I guess I don't necessarily think that it should be discouraged because I think there are valid use cases for it so I'm happy enough sort of accessing the container like that in certain circumstances I think, I guess what you hinted at was that it's a private API and that variable name could change that's definitely something that you're opening yourself up to if you do that but I think there are other ways of doing it from what I've presented here other ways of getting data into the app but I just wanted to walk through some cases where I think it made sense that you wanted to do something from outside the Ember wall and show that they're discouraging it but I think there are valid use cases for it any more I was aiming to demonstrate the choices that I'd made along the way and that is the way that I would still build it now I want server rendered HTML when it's a publicly accessible site delivering content I just want that to be server rendered I want that to be served up so that it works without JavaScript so that it works when I've just got multiple reasons for wanting that server rendered HTML served up but then I wanted the experience where you could browse around the application whilst having this track playing and if it was a site with no JavaScript you'd lose it every new page you navigated to so the solution to that was PJAX and Ember came in when I wanted to start building more complex behaviour so basically I would do things the same way if I'd rebuilt it so the question was how much of a window I think I've had using Ember over just plain jQuery and things and the answer to that is like a lot I've become so accustomed to using this object model that Ember offers and things like the computer properties and the bindings allow you just to start working in higher and higher level abstractions as you build out your code and start achieving much more complicated behaviour than I personally would get to if I just started throwing some jQuery together and yeah, like I say, that's an object model that I like, I'm familiar with it and I like to lean on that whenever I start doing anything complex so for something simple like clicking a link and having a YouTube video that's fine just in jQuery but as soon as it started becoming this like incurring multiple tracks and reordering and sharing those playlists becoming like a playlist manager that's when Ember really starts to shine with its object model Well done So is the answer like some sort of HTML markup that has embedded data in it so actually like the HTML is readable but like Ember data could like side load Yeah, I don't know how Ember would come in and start working with the content that was already there and just sort of slot in but apparently Angular works with existing content on the page I don't know how they do it I haven't looked into Angular so much but I guess whatever data you've got on the page that isn't marked up in a way that could easily be pulled out like you would need to add in via data attributes or whatever like you need to make sure that data is there I guess All right, thank you